From a06a9519e471a96612826d121a3e10dcc9cba3f9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 31 Aug 2011 16:35:20 +0200 Subject: [PATCH] linux: remove nouveau patch Signed-off-by: Stephan Raue --- ....0.4-110-nouveau_drm_update-20110726.patch | 12781 ---------------- 1 file changed, 12781 deletions(-) delete mode 100644 packages/linux/patches/linux-3.0.4-110-nouveau_drm_update-20110726.patch diff --git a/packages/linux/patches/linux-3.0.4-110-nouveau_drm_update-20110726.patch b/packages/linux/patches/linux-3.0.4-110-nouveau_drm_update-20110726.patch deleted file mode 100644 index 47476db8b2..0000000000 --- a/packages/linux/patches/linux-3.0.4-110-nouveau_drm_update-20110726.patch +++ /dev/null @@ -1,12781 +0,0 @@ -diff -Naur linux-3.0/drivers/gpu/drm/drm_gem.c linux-3.0.patch/drivers/gpu/drm/drm_gem.c ---- linux-3.0/drivers/gpu/drm/drm_gem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/drm_gem.c 2011-07-26 07:03:44.396050644 +0200 -@@ -211,6 +211,8 @@ - idr_remove(&filp->object_idr, handle); - spin_unlock(&filp->table_lock); - -+ if (dev->driver->gem_close_object) -+ dev->driver->gem_close_object(obj, filp); - drm_gem_object_handle_unreference_unlocked(obj); - - return 0; -@@ -227,7 +229,8 @@ - struct drm_gem_object *obj, - u32 *handlep) - { -- int ret; -+ struct drm_device *dev = obj->dev; -+ int ret; - - /* - * Get the user-visible handle using idr. -@@ -248,6 +251,15 @@ - return ret; - - drm_gem_object_handle_reference(obj); -+ -+ if (dev->driver->gem_open_object) { -+ ret = dev->driver->gem_open_object(obj, file_priv); -+ if (ret) { -+ drm_gem_handle_delete(file_priv, *handlep); -+ return ret; -+ } -+ } -+ - return 0; - } - EXPORT_SYMBOL(drm_gem_handle_create); -@@ -402,7 +414,12 @@ - static int - drm_gem_object_release_handle(int id, void *ptr, void *data) - { -+ struct drm_file *file_priv = data; - struct drm_gem_object *obj = ptr; -+ struct drm_device *dev = obj->dev; -+ -+ if (dev->driver->gem_close_object) -+ dev->driver->gem_close_object(obj, file_priv); - - drm_gem_object_handle_unreference_unlocked(obj); - -@@ -418,7 +435,7 @@ - drm_gem_release(struct drm_device *dev, struct drm_file *file_private) - { - idr_for_each(&file_private->object_idr, -- &drm_gem_object_release_handle, NULL); -+ &drm_gem_object_release_handle, file_private); - - idr_remove_all(&file_private->object_idr); - idr_destroy(&file_private->object_idr); -diff -Naur linux-3.0/drivers/gpu/drm/drm_irq.c linux-3.0.patch/drivers/gpu/drm/drm_irq.c ---- linux-3.0/drivers/gpu/drm/drm_irq.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/drm_irq.c 2011-07-26 07:03:44.396050644 +0200 -@@ -397,13 +397,16 @@ - /* - * Wake up any waiters so they don't hang. - */ -- spin_lock_irqsave(&dev->vbl_lock, irqflags); -- for (i = 0; i < dev->num_crtcs; i++) { -- DRM_WAKEUP(&dev->vbl_queue[i]); -- dev->vblank_enabled[i] = 0; -- dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i); -+ if (dev->num_crtcs) { -+ spin_lock_irqsave(&dev->vbl_lock, irqflags); -+ for (i = 0; i < dev->num_crtcs; i++) { -+ DRM_WAKEUP(&dev->vbl_queue[i]); -+ dev->vblank_enabled[i] = 0; -+ dev->last_vblank[i] = -+ dev->driver->get_vblank_counter(dev, i); -+ } -+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - } -- spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - - if (!irq_enabled) - return -EINVAL; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/Makefile linux-3.0.patch/drivers/gpu/drm/nouveau/Makefile ---- linux-3.0/drivers/gpu/drm/nouveau/Makefile 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/Makefile 2011-07-26 07:03:44.402050716 +0200 -@@ -21,16 +21,17 @@ - nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ - nv84_crypt.o \ - nva3_copy.o nvc0_copy.o \ -- nv40_mpeg.o nv50_mpeg.o \ -+ nv31_mpeg.o nv50_mpeg.o \ - nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ -- nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ -- nv50_cursor.o nv50_display.o \ - nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ - nv04_crtc.o nv04_display.o nv04_cursor.o \ -+ nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ -+ nv50_cursor.o nv50_display.o \ -+ nvd0_display.o \ - nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o \ - nv10_gpio.o nv50_gpio.o \ - nv50_calc.o \ -- nv04_pm.o nv50_pm.o nva3_pm.o \ -+ nv04_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ - nv50_vram.o nvc0_vram.o \ - nv50_vm.o nvc0_vm.o - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_bios.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bios.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bios.c 2011-07-26 07:03:44.405050752 +0200 -@@ -135,13 +135,14 @@ - int i; - - if (dev_priv->card_type >= NV_50) { -- uint32_t vbios_vram = (nv_rd32(dev, 0x619f04) & ~0xff) << 8; -- -- if (!vbios_vram) -- vbios_vram = (nv_rd32(dev, 0x1700) << 16) + 0xf0000; -+ u64 addr = (u64)(nv_rd32(dev, 0x619f04) & 0xffffff00) << 8; -+ if (!addr) { -+ addr = (u64)nv_rd32(dev, 0x1700) << 16; -+ addr += 0xf0000; -+ } - - old_bar0_pramin = nv_rd32(dev, 0x1700); -- nv_wr32(dev, 0x1700, vbios_vram >> 16); -+ nv_wr32(dev, 0x1700, addr >> 16); - } - - /* bail if no rom signature */ -@@ -295,6 +296,11 @@ - if (dev_priv->card_type < NV_50) - return reg; - -+ if (reg & 0x80000000) { -+ BUG_ON(bios->display.crtc < 0); -+ reg += bios->display.crtc * 0x800; -+ } -+ - if (reg & 0x40000000) { - BUG_ON(!dcbent); - -@@ -303,7 +309,7 @@ - reg += 0x00000080; - } - -- reg &= ~0x60000000; -+ reg &= ~0xe0000000; - return reg; - } - -@@ -3220,6 +3226,49 @@ - return 1; - } - -+static void -+init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) -+{ -+ const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; -+ u32 r, s, v; -+ -+ /* Not a clue, needs de-magicing */ -+ r = nv50_gpio_ctl[gpio->line >> 4]; -+ s = (gpio->line & 0x0f); -+ v = bios_rd32(bios, r) & ~(0x00010001 << s); -+ switch ((gpio->entry & 0x06000000) >> 25) { -+ case 1: -+ v |= (0x00000001 << s); -+ break; -+ case 2: -+ v |= (0x00010000 << s); -+ break; -+ default: -+ break; -+ } -+ -+ bios_wr32(bios, r, v); -+} -+ -+static void -+init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) -+{ -+ u32 v, i; -+ -+ v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); -+ v &= 0xffffff00; -+ v |= (gpio->entry & 0x00ff0000) >> 16; -+ bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); -+ -+ i = (gpio->entry & 0x1f000000) >> 24; -+ if (i) { -+ v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); -+ v &= 0xffffff00; -+ v |= gpio->line; -+ bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); -+ } -+} -+ - static int - init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) - { -@@ -3234,7 +3283,6 @@ - - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; -- const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; - int i; - - if (dev_priv->card_type < NV_50) { -@@ -3247,33 +3295,20 @@ - - for (i = 0; i < bios->dcb.gpio.entries; i++) { - struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; -- uint32_t r, s, v; - - BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); - - BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", - offset, gpio->tag, gpio->state_default); -- if (bios->execute) -- pgpio->set(bios->dev, gpio->tag, gpio->state_default); - -- /* The NVIDIA binary driver doesn't appear to actually do -- * any of this, my VBIOS does however. -- */ -- /* Not a clue, needs de-magicing */ -- r = nv50_gpio_ctl[gpio->line >> 4]; -- s = (gpio->line & 0x0f); -- v = bios_rd32(bios, r) & ~(0x00010001 << s); -- switch ((gpio->entry & 0x06000000) >> 25) { -- case 1: -- v |= (0x00000001 << s); -- break; -- case 2: -- v |= (0x00010000 << s); -- break; -- default: -- break; -- } -- bios_wr32(bios, r, v); -+ if (!bios->execute) -+ continue; -+ -+ pgpio->set(bios->dev, gpio->tag, gpio->state_default); -+ if (dev_priv->card_type < NV_D0) -+ init_gpio_unknv50(bios, gpio); -+ else -+ init_gpio_unknvd0(bios, gpio); - } - - return 1; -@@ -4466,8 +4501,8 @@ - } - - int --nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, -- uint32_t sub, int pxclk) -+nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, -+ struct dcb_entry *dcbent, int crtc) - { - /* - * The display script table is located by the BIT 'U' table. -@@ -4557,22 +4592,22 @@ - return 1; - } - -- if (pxclk < -2 || pxclk > 0) { -+ if (pclk < -2 || pclk > 0) { - /* Try to find matching script table entry */ - for (i = 0; i < otable[5]; i++) { -- if (ROM16(otable[table[4] + i*6]) == sub) -+ if (ROM16(otable[table[4] + i*6]) == type) - break; - } - - if (i == otable[5]) { - NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " - "using first\n", -- sub, dcbent->type, dcbent->or); -+ type, dcbent->type, dcbent->or); - i = 0; - } - } - -- if (pxclk == 0) { -+ if (pclk == 0) { - script = ROM16(otable[6]); - if (!script) { - NV_DEBUG_KMS(dev, "output script 0 not found\n"); -@@ -4580,9 +4615,9 @@ - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk == -1) { -+ if (pclk == -1) { - script = ROM16(otable[8]); - if (!script) { - NV_DEBUG_KMS(dev, "output script 1 not found\n"); -@@ -4590,9 +4625,9 @@ - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk == -2) { -+ if (pclk == -2) { - if (table[4] >= 12) - script = ROM16(otable[10]); - else -@@ -4603,31 +4638,31 @@ - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk > 0) { -+ if (pclk > 0) { - script = ROM16(otable[table[4] + i*6 + 2]); - if (script) -- script = clkcmptable(bios, script, pxclk); -+ script = clkcmptable(bios, script, pclk); - if (!script) { - NV_DEBUG_KMS(dev, "clock script 0 not found\n"); - return 1; - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } else -- if (pxclk < 0) { -+ if (pclk < 0) { - script = ROM16(otable[table[4] + i*6 + 4]); - if (script) -- script = clkcmptable(bios, script, -pxclk); -+ script = clkcmptable(bios, script, -pclk); - if (!script) { - NV_DEBUG_KMS(dev, "clock script 1 not found\n"); - return 1; - } - - NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); -- nouveau_bios_run_init_table(dev, script, dcbent); -+ nouveau_bios_run_init_table(dev, script, dcbent, crtc); - } - - return 0; -@@ -5186,7 +5221,7 @@ - load_table_ptr = ROM16(bios->data[bitentry->offset]); - - if (load_table_ptr == 0x0) { -- NV_ERROR(dev, "Pointer to BIT loadval table invalid\n"); -+ NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n"); - return -EINVAL; - } - -@@ -5883,9 +5918,15 @@ - } - - e->line = (e->entry & 0x0000001f) >> 0; -- e->state_default = (e->entry & 0x01000000) >> 24; -- e->state[0] = (e->entry & 0x18000000) >> 27; -- e->state[1] = (e->entry & 0x60000000) >> 29; -+ if (gpio[0] == 0x40) { -+ e->state_default = (e->entry & 0x01000000) >> 24; -+ e->state[0] = (e->entry & 0x18000000) >> 27; -+ e->state[1] = (e->entry & 0x60000000) >> 29; -+ } else { -+ e->state_default = (e->entry & 0x00000080) >> 7; -+ e->state[0] = (entry[4] >> 4) & 3; -+ e->state[1] = (entry[4] >> 6) & 3; -+ } - } - } - -@@ -5965,6 +6006,12 @@ - if (cte->type == DCB_CONNECTOR_HDMI_1) - cte->type = DCB_CONNECTOR_DVI_I; - } -+ -+ /* Gigabyte GV-NX86T512H */ -+ if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { -+ if (cte->type == DCB_CONNECTOR_HDMI_1) -+ cte->type = DCB_CONNECTOR_DVI_I; -+ } - } - - static const u8 hpd_gpio[16] = { -@@ -6377,6 +6424,37 @@ - } - } - -+ /* Some other twisted XFX board (rhbz#694914) -+ * -+ * The DVI/VGA encoder combo that's supposed to represent the -+ * DVI-I connector actually point at two different ones, and -+ * the HDMI connector ends up paired with the VGA instead. -+ * -+ * Connector table is missing anything for VGA at all, pointing it -+ * an invalid conntab entry 2 so we figure it out ourself. -+ */ -+ if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) { -+ if (idx == 0) { -+ *conn = 0x02002300; /* VGA, connector 2 */ -+ *conf = 0x00000028; -+ } else -+ if (idx == 1) { -+ *conn = 0x01010312; /* DVI, connector 0 */ -+ *conf = 0x00020030; -+ } else -+ if (idx == 2) { -+ *conn = 0x04020310; /* VGA, connector 0 */ -+ *conf = 0x00000028; -+ } else -+ if (idx == 3) { -+ *conn = 0x02021322; /* HDMI, connector 1 */ -+ *conf = 0x00020010; -+ } else { -+ *conn = 0x0000000e; /* EOL */ -+ *conf = 0x00000000; -+ } -+ } -+ - return true; - } - -@@ -6731,7 +6809,7 @@ - - void - nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, -- struct dcb_entry *dcbent) -+ struct dcb_entry *dcbent, int crtc) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; -@@ -6739,6 +6817,7 @@ - - spin_lock_bh(&bios->lock); - bios->display.output = dcbent; -+ bios->display.crtc = crtc; - parse_init_table(bios, table, &iexec); - bios->display.output = NULL; - spin_unlock_bh(&bios->lock); -@@ -6825,9 +6904,8 @@ - - if (dev_priv->card_type >= NV_50) { - for (i = 0; i < bios->dcb.entries; i++) { -- nouveau_bios_run_display_table(dev, -- &bios->dcb.entry[i], -- 0, 0); -+ nouveau_bios_run_display_table(dev, 0, 0, -+ &bios->dcb.entry[i], -1); - } - } - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_bios.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bios.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bios.h 2011-07-26 07:03:44.408050788 +0200 -@@ -289,6 +289,7 @@ - - struct { - struct dcb_entry *output; -+ int crtc; - uint16_t script_table_ptr; - uint16_t dp_table_ptr; - } display; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_bo.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bo.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_bo.c 2011-07-26 07:03:44.409050800 +0200 -@@ -49,16 +49,12 @@ - DRM_ERROR("bo %p still attached to GEM object\n", bo); - - nv10_mem_put_tile_region(dev, nvbo->tile, NULL); -- if (nvbo->vma.node) { -- nouveau_vm_unmap(&nvbo->vma); -- nouveau_vm_put(&nvbo->vma); -- } - kfree(nvbo); - } - - static void - nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, -- int *align, int *size, int *page_shift) -+ int *align, int *size) - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - -@@ -82,67 +78,51 @@ - } - } - } else { -- if (likely(dev_priv->chan_vm)) { -- if (!(flags & TTM_PL_FLAG_TT) && *size > 256 * 1024) -- *page_shift = dev_priv->chan_vm->lpg_shift; -- else -- *page_shift = dev_priv->chan_vm->spg_shift; -- } else { -- *page_shift = 12; -- } -- -- *size = roundup(*size, (1 << *page_shift)); -- *align = max((1 << *page_shift), *align); -+ *size = roundup(*size, (1 << nvbo->page_shift)); -+ *align = max((1 << nvbo->page_shift), *align); - } - - *size = roundup(*size, PAGE_SIZE); - } - - int --nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, -- int size, int align, uint32_t flags, uint32_t tile_mode, -- uint32_t tile_flags, struct nouveau_bo **pnvbo) -+nouveau_bo_new(struct drm_device *dev, int size, int align, -+ uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, -+ struct nouveau_bo **pnvbo) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *nvbo; -- int ret = 0, page_shift = 0; -+ int ret; - - nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); - if (!nvbo) - return -ENOMEM; - INIT_LIST_HEAD(&nvbo->head); - INIT_LIST_HEAD(&nvbo->entry); -+ INIT_LIST_HEAD(&nvbo->vma_list); - nvbo->tile_mode = tile_mode; - nvbo->tile_flags = tile_flags; - nvbo->bo.bdev = &dev_priv->ttm.bdev; - -- nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift); -- align >>= PAGE_SHIFT; -- -- if (dev_priv->chan_vm) { -- ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, -- NV_MEM_ACCESS_RW, &nvbo->vma); -- if (ret) { -- kfree(nvbo); -- return ret; -- } -+ nvbo->page_shift = 12; -+ if (dev_priv->bar1_vm) { -+ if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) -+ nvbo->page_shift = dev_priv->bar1_vm->lpg_shift; - } - -+ nouveau_bo_fixup_align(nvbo, flags, &align, &size); - nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; - nouveau_bo_placement_set(nvbo, flags, 0); - -- nvbo->channel = chan; - ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, -- ttm_bo_type_device, &nvbo->placement, align, 0, -- false, NULL, size, nouveau_bo_del_ttm); -+ ttm_bo_type_device, &nvbo->placement, -+ align >> PAGE_SHIFT, 0, false, NULL, size, -+ nouveau_bo_del_ttm); - if (ret) { - /* ttm will call nouveau_bo_del_ttm if it fails.. */ - return ret; - } -- nvbo->channel = NULL; - -- if (nvbo->vma.node) -- nvbo->bo.offset = nvbo->vma.offset; - *pnvbo = nvbo; - return 0; - } -@@ -312,8 +292,6 @@ - if (ret) - return ret; - -- if (nvbo->vma.node) -- nvbo->bo.offset = nvbo->vma.offset; - return 0; - } - -@@ -440,7 +418,6 @@ - TTM_MEMTYPE_FLAG_CMA; - man->available_caching = TTM_PL_MASK_CACHING; - man->default_caching = TTM_PL_FLAG_CACHED; -- man->gpu_offset = dev_priv->gart_info.aper_base; - break; - default: - NV_ERROR(dev, "Unknown GART type: %d\n", -@@ -501,19 +478,12 @@ - nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -- struct nouveau_mem *old_node = old_mem->mm_node; -- struct nouveau_mem *new_node = new_mem->mm_node; -- struct nouveau_bo *nvbo = nouveau_bo(bo); -+ struct nouveau_mem *node = old_mem->mm_node; -+ u64 src_offset = node->vma[0].offset; -+ u64 dst_offset = node->vma[1].offset; - u32 page_count = new_mem->num_pages; -- u64 src_offset, dst_offset; - int ret; - -- src_offset = old_node->tmp_vma.offset; -- if (new_node->tmp_vma.node) -- dst_offset = new_node->tmp_vma.offset; -- else -- dst_offset = nvbo->vma.offset; -- - page_count = new_mem->num_pages; - while (page_count) { - int line_count = (page_count > 2047) ? 2047 : page_count; -@@ -547,19 +517,13 @@ - nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) - { -- struct nouveau_mem *old_node = old_mem->mm_node; -- struct nouveau_mem *new_node = new_mem->mm_node; -+ struct nouveau_mem *node = old_mem->mm_node; - struct nouveau_bo *nvbo = nouveau_bo(bo); - u64 length = (new_mem->num_pages << PAGE_SHIFT); -- u64 src_offset, dst_offset; -+ u64 src_offset = node->vma[0].offset; -+ u64 dst_offset = node->vma[1].offset; - int ret; - -- src_offset = old_node->tmp_vma.offset; -- if (new_node->tmp_vma.node) -- dst_offset = new_node->tmp_vma.offset; -- else -- dst_offset = nvbo->vma.offset; -- - while (length) { - u32 amount, stride, height; - -@@ -695,6 +659,27 @@ - } - - static int -+nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, -+ struct ttm_mem_reg *mem, struct nouveau_vma *vma) -+{ -+ struct nouveau_mem *node = mem->mm_node; -+ int ret; -+ -+ ret = nouveau_vm_get(chan->vm, mem->num_pages << PAGE_SHIFT, -+ node->page_shift, NV_MEM_ACCESS_RO, vma); -+ if (ret) -+ return ret; -+ -+ if (mem->mem_type == TTM_PL_VRAM) -+ nouveau_vm_map(vma, node); -+ else -+ nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, -+ node, node->pages); -+ -+ return 0; -+} -+ -+static int - nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, - bool no_wait_reserve, bool no_wait_gpu, - struct ttm_mem_reg *new_mem) -@@ -711,31 +696,20 @@ - mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); - } - -- /* create temporary vma for old memory, this will get cleaned -- * up after ttm destroys the ttm_mem_reg -+ /* create temporary vmas for the transfer and attach them to the -+ * old nouveau_mem node, these will get cleaned up after ttm has -+ * destroyed the ttm_mem_reg - */ - if (dev_priv->card_type >= NV_50) { - struct nouveau_mem *node = old_mem->mm_node; -- if (!node->tmp_vma.node) { -- u32 page_shift = nvbo->vma.node->type; -- if (old_mem->mem_type == TTM_PL_TT) -- page_shift = nvbo->vma.vm->spg_shift; -- -- ret = nouveau_vm_get(chan->vm, -- old_mem->num_pages << PAGE_SHIFT, -- page_shift, NV_MEM_ACCESS_RO, -- &node->tmp_vma); -- if (ret) -- goto out; -- } - -- if (old_mem->mem_type == TTM_PL_VRAM) -- nouveau_vm_map(&node->tmp_vma, node); -- else { -- nouveau_vm_map_sg(&node->tmp_vma, 0, -- old_mem->num_pages << PAGE_SHIFT, -- node, node->pages); -- } -+ ret = nouveau_vma_getmap(chan, nvbo, old_mem, &node->vma[0]); -+ if (ret) -+ goto out; -+ -+ ret = nouveau_vma_getmap(chan, nvbo, new_mem, &node->vma[1]); -+ if (ret) -+ goto out; - } - - if (dev_priv->card_type < NV_50) -@@ -762,7 +736,6 @@ - bool no_wait_reserve, bool no_wait_gpu, - struct ttm_mem_reg *new_mem) - { -- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; - struct ttm_placement placement; - struct ttm_mem_reg tmp_mem; -@@ -782,23 +755,7 @@ - if (ret) - goto out; - -- if (dev_priv->card_type >= NV_50) { -- struct nouveau_bo *nvbo = nouveau_bo(bo); -- struct nouveau_mem *node = tmp_mem.mm_node; -- struct nouveau_vma *vma = &nvbo->vma; -- if (vma->node->type != vma->vm->spg_shift) -- vma = &node->tmp_vma; -- nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT, -- node, node->pages); -- } -- - ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem); -- -- if (dev_priv->card_type >= NV_50) { -- struct nouveau_bo *nvbo = nouveau_bo(bo); -- nouveau_vm_unmap(&nvbo->vma); -- } -- - if (ret) - goto out; - -@@ -844,30 +801,22 @@ - static void - nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) - { -- struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_mem *node = new_mem->mm_node; - struct nouveau_bo *nvbo = nouveau_bo(bo); -- struct nouveau_vma *vma = &nvbo->vma; -- struct nouveau_vm *vm = vma->vm; -+ struct nouveau_vma *vma; - -- if (dev_priv->card_type < NV_50) -- return; -- -- switch (new_mem->mem_type) { -- case TTM_PL_VRAM: -- nouveau_vm_map(vma, node); -- break; -- case TTM_PL_TT: -- if (vma->node->type != vm->spg_shift) { -+ list_for_each_entry(vma, &nvbo->vma_list, head) { -+ if (new_mem->mem_type == TTM_PL_VRAM) { -+ nouveau_vm_map(vma, new_mem->mm_node); -+ } else -+ if (new_mem->mem_type == TTM_PL_TT && -+ nvbo->page_shift == vma->vm->spg_shift) { -+ nouveau_vm_map_sg(vma, 0, new_mem-> -+ num_pages << PAGE_SHIFT, -+ node, node->pages); -+ } else { - nouveau_vm_unmap(vma); -- vma = &node->tmp_vma; - } -- nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT, -- node, node->pages); -- break; -- default: -- nouveau_vm_unmap(&nvbo->vma); -- break; - } - } - -@@ -1007,7 +956,7 @@ - break; - } - -- if (dev_priv->card_type == NV_C0) -+ if (dev_priv->card_type >= NV_C0) - page_shift = node->page_shift; - else - page_shift = 12; -@@ -1113,3 +1062,54 @@ - .io_mem_free = &nouveau_ttm_io_mem_free, - }; - -+struct nouveau_vma * -+nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nouveau_vm *vm) -+{ -+ struct nouveau_vma *vma; -+ list_for_each_entry(vma, &nvbo->vma_list, head) { -+ if (vma->vm == vm) -+ return vma; -+ } -+ -+ return NULL; -+} -+ -+int -+nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, -+ struct nouveau_vma *vma) -+{ -+ const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT; -+ struct nouveau_mem *node = nvbo->bo.mem.mm_node; -+ int ret; -+ -+ ret = nouveau_vm_get(vm, size, nvbo->page_shift, -+ NV_MEM_ACCESS_RW, vma); -+ if (ret) -+ return ret; -+ -+ if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) -+ nouveau_vm_map(vma, nvbo->bo.mem.mm_node); -+ else -+ if (nvbo->bo.mem.mem_type == TTM_PL_TT) -+ nouveau_vm_map_sg(vma, 0, size, node, node->pages); -+ -+ list_add_tail(&vma->head, &nvbo->vma_list); -+ vma->refcount = 1; -+ return 0; -+} -+ -+void -+nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nouveau_vma *vma) -+{ -+ if (vma->node) { -+ if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) { -+ spin_lock(&nvbo->bo.bdev->fence_lock); -+ ttm_bo_wait(&nvbo->bo, false, false, false); -+ spin_unlock(&nvbo->bo.bdev->fence_lock); -+ nouveau_vm_unmap(vma); -+ } -+ -+ nouveau_vm_put(vma); -+ list_del(&vma->head); -+ } -+} -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_channel.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_channel.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_channel.c 2011-07-26 07:03:44.410050812 +0200 -@@ -27,40 +27,63 @@ - #include "nouveau_drv.h" - #include "nouveau_drm.h" - #include "nouveau_dma.h" -+#include "nouveau_ramht.h" - - static int --nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan) -+nouveau_channel_pushbuf_init(struct nouveau_channel *chan) - { -+ u32 mem = nouveau_vram_pushbuf ? TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_bo *pb = chan->pushbuf_bo; -- struct nouveau_gpuobj *pushbuf = NULL; -- int ret = 0; -+ int ret; -+ -+ /* allocate buffer object */ -+ ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo); -+ if (ret) -+ goto out; -+ -+ ret = nouveau_bo_pin(chan->pushbuf_bo, mem); -+ if (ret) -+ goto out; -+ -+ ret = nouveau_bo_map(chan->pushbuf_bo); -+ if (ret) -+ goto out; - -+ /* create DMA object covering the entire memtype where the push -+ * buffer resides, userspace can submit its own push buffers from -+ * anywhere within the same memtype. -+ */ -+ chan->pushbuf_base = chan->pushbuf_bo->bo.offset; - if (dev_priv->card_type >= NV_50) { -+ ret = nouveau_bo_vma_add(chan->pushbuf_bo, chan->vm, -+ &chan->pushbuf_vma); -+ if (ret) -+ goto out; -+ - if (dev_priv->card_type < NV_C0) { - ret = nouveau_gpuobj_dma_new(chan, - NV_CLASS_DMA_IN_MEMORY, 0, - (1ULL << 40), - NV_MEM_ACCESS_RO, - NV_MEM_TARGET_VM, -- &pushbuf); -+ &chan->pushbuf); - } -- chan->pushbuf_base = pb->bo.offset; -+ chan->pushbuf_base = chan->pushbuf_vma.offset; - } else -- if (pb->bo.mem.mem_type == TTM_PL_TT) { -+ if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_TT) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->gart_info.aper_size, - NV_MEM_ACCESS_RO, -- NV_MEM_TARGET_GART, &pushbuf); -- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; -+ NV_MEM_TARGET_GART, -+ &chan->pushbuf); - } else - if (dev_priv->card_type != NV_04) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->fb_available_size, - NV_MEM_ACCESS_RO, -- NV_MEM_TARGET_VRAM, &pushbuf); -- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; -+ NV_MEM_TARGET_VRAM, -+ &chan->pushbuf); - } else { - /* NV04 cmdbuf hack, from original ddx.. not sure of it's - * exact reason for existing :) PCI access to cmdbuf in -@@ -70,47 +93,22 @@ - pci_resource_start(dev->pdev, 1), - dev_priv->fb_available_size, - NV_MEM_ACCESS_RO, -- NV_MEM_TARGET_PCI, &pushbuf); -- chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; -+ NV_MEM_TARGET_PCI, -+ &chan->pushbuf); - } - -- nouveau_gpuobj_ref(pushbuf, &chan->pushbuf); -- nouveau_gpuobj_ref(NULL, &pushbuf); -- return ret; --} -- --static struct nouveau_bo * --nouveau_channel_user_pushbuf_alloc(struct drm_device *dev) --{ -- struct nouveau_bo *pushbuf = NULL; -- int location, ret; -- -- if (nouveau_vram_pushbuf) -- location = TTM_PL_FLAG_VRAM; -- else -- location = TTM_PL_FLAG_TT; -- -- ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf); -- if (ret) { -- NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret); -- return NULL; -- } -- -- ret = nouveau_bo_pin(pushbuf, location); -- if (ret) { -- NV_ERROR(dev, "error pinning DMA push buffer: %d\n", ret); -- nouveau_bo_ref(NULL, &pushbuf); -- return NULL; -- } -- -- ret = nouveau_bo_map(pushbuf); -+out: - if (ret) { -- nouveau_bo_unpin(pushbuf); -- nouveau_bo_ref(NULL, &pushbuf); -- return NULL; -+ NV_ERROR(dev, "error initialising pushbuf: %d\n", ret); -+ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); -+ nouveau_gpuobj_ref(NULL, &chan->pushbuf); -+ if (chan->pushbuf_bo) { -+ nouveau_bo_unmap(chan->pushbuf_bo); -+ nouveau_bo_ref(NULL, &chan->pushbuf_bo); -+ } - } - -- return pushbuf; -+ return 0; - } - - /* allocates and initializes a fifo for user space consumption */ -@@ -121,6 +119,7 @@ - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - struct nouveau_channel *chan; - unsigned long flags; - int ret; -@@ -160,19 +159,14 @@ - INIT_LIST_HEAD(&chan->nvsw.flip); - INIT_LIST_HEAD(&chan->fence.pending); - -- /* Allocate DMA push buffer */ -- chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev); -- if (!chan->pushbuf_bo) { -- ret = -ENOMEM; -- NV_ERROR(dev, "pushbuf %d\n", ret); -+ /* setup channel's memory and vm */ -+ ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); -+ if (ret) { -+ NV_ERROR(dev, "gpuobj %d\n", ret); - nouveau_channel_put(&chan); - return ret; - } - -- nouveau_dma_pre_init(chan); -- chan->user_put = 0x40; -- chan->user_get = 0x44; -- - /* Allocate space for per-channel fixed notifier memory */ - ret = nouveau_notifier_init_channel(chan); - if (ret) { -@@ -181,21 +175,17 @@ - return ret; - } - -- /* Setup channel's default objects */ -- ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); -+ /* Allocate DMA push buffer */ -+ ret = nouveau_channel_pushbuf_init(chan); - if (ret) { -- NV_ERROR(dev, "gpuobj %d\n", ret); -+ NV_ERROR(dev, "pushbuf %d\n", ret); - nouveau_channel_put(&chan); - return ret; - } - -- /* Create a dma object for the push buffer */ -- ret = nouveau_channel_pushbuf_ctxdma_init(chan); -- if (ret) { -- NV_ERROR(dev, "pbctxdma %d\n", ret); -- nouveau_channel_put(&chan); -- return ret; -- } -+ nouveau_dma_pre_init(chan); -+ chan->user_put = 0x40; -+ chan->user_get = 0x44; - - /* disable the fifo caches */ - pfifo->reassign(dev, false); -@@ -220,6 +210,11 @@ - nouveau_debugfs_channel_init(chan); - - NV_DEBUG(dev, "channel %d initialised\n", chan->id); -+ if (fpriv) { -+ spin_lock(&fpriv->lock); -+ list_add(&chan->list, &fpriv->channels); -+ spin_unlock(&fpriv->lock); -+ } - *chan_ret = chan; - return 0; - } -@@ -236,29 +231,23 @@ - } - - struct nouveau_channel * --nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) -+nouveau_channel_get(struct drm_file *file_priv, int id) - { -- struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - struct nouveau_channel *chan; -- unsigned long flags; -- -- if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR)) -- return ERR_PTR(-EINVAL); -- -- spin_lock_irqsave(&dev_priv->channels.lock, flags); -- chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); -- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -- -- if (unlikely(!chan)) -- return ERR_PTR(-EINVAL); - -- if (unlikely(file_priv && chan->file_priv != file_priv)) { -- nouveau_channel_put_unlocked(&chan); -- return ERR_PTR(-EINVAL); -+ spin_lock(&fpriv->lock); -+ list_for_each_entry(chan, &fpriv->channels, list) { -+ if (chan->id == id) { -+ chan = nouveau_channel_get_unlocked(chan); -+ spin_unlock(&fpriv->lock); -+ mutex_lock(&chan->mutex); -+ return chan; -+ } - } -+ spin_unlock(&fpriv->lock); - -- mutex_lock(&chan->mutex); -- return chan; -+ return ERR_PTR(-EINVAL); - } - - void -@@ -312,12 +301,14 @@ - /* destroy any resources the channel owned */ - nouveau_gpuobj_ref(NULL, &chan->pushbuf); - if (chan->pushbuf_bo) { -+ nouveau_bo_vma_del(chan->pushbuf_bo, &chan->pushbuf_vma); - nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_unpin(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - } -- nouveau_gpuobj_channel_takedown(chan); -+ nouveau_ramht_ref(NULL, &chan->ramht, chan); - nouveau_notifier_takedown_channel(chan); -+ nouveau_gpuobj_channel_takedown(chan); - - nouveau_channel_ref(NULL, pchan); - } -@@ -383,10 +374,11 @@ - - NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); - for (i = 0; i < engine->fifo.channels; i++) { -- chan = nouveau_channel_get(dev, file_priv, i); -+ chan = nouveau_channel_get(file_priv, i); - if (IS_ERR(chan)) - continue; - -+ list_del(&chan->list); - atomic_dec(&chan->users); - nouveau_channel_put(&chan); - } -@@ -459,10 +451,11 @@ - struct drm_nouveau_channel_free *req = data; - struct nouveau_channel *chan; - -- chan = nouveau_channel_get(dev, file_priv, req->channel); -+ chan = nouveau_channel_get(file_priv, req->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - -+ list_del(&chan->list); - atomic_dec(&chan->users); - nouveau_channel_put(&chan); - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_connector.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_connector.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_connector.c 2011-07-26 07:03:44.411050824 +0200 -@@ -40,7 +40,7 @@ - static void nouveau_connector_hotplug(void *, int); - - static struct nouveau_encoder * --find_encoder_by_type(struct drm_connector *connector, int type) -+find_encoder(struct drm_connector *connector, int type) - { - struct drm_device *dev = connector->dev; - struct nouveau_encoder *nv_encoder; -@@ -170,8 +170,8 @@ - struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); - - if (!dn || -- !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || -- (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) -+ !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) || -+ (nv_encoder = find_encoder(connector, OUTPUT_ANALOG)))) - return NULL; - - for_each_child_of_node(dn, cn) { -@@ -233,6 +233,7 @@ - struct drm_device *dev = connector->dev; - struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct nouveau_encoder *nv_encoder = NULL; -+ struct nouveau_encoder *nv_partner; - struct nouveau_i2c_chan *i2c; - int type; - -@@ -266,19 +267,22 @@ - * same i2c channel so the value returned from ddc_detect - * isn't necessarily correct. - */ -- if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { -+ nv_partner = NULL; -+ if (nv_encoder->dcb->type == OUTPUT_TMDS) -+ nv_partner = find_encoder(connector, OUTPUT_ANALOG); -+ if (nv_encoder->dcb->type == OUTPUT_ANALOG) -+ nv_partner = find_encoder(connector, OUTPUT_TMDS); -+ -+ if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG && -+ nv_partner->dcb->type == OUTPUT_TMDS) || -+ (nv_encoder->dcb->type == OUTPUT_TMDS && -+ nv_partner->dcb->type == OUTPUT_ANALOG))) { - if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) - type = OUTPUT_TMDS; - else - type = OUTPUT_ANALOG; - -- nv_encoder = find_encoder_by_type(connector, type); -- if (!nv_encoder) { -- NV_ERROR(dev, "Detected %d encoder on %s, " -- "but no object!\n", type, -- drm_get_connector_name(connector)); -- return connector_status_disconnected; -- } -+ nv_encoder = find_encoder(connector, type); - } - - nouveau_connector_set_encoder(connector, nv_encoder); -@@ -292,9 +296,9 @@ - } - - detect_analog: -- nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); -+ nv_encoder = find_encoder(connector, OUTPUT_ANALOG); - if (!nv_encoder && !nouveau_tv_disable) -- nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); -+ nv_encoder = find_encoder(connector, OUTPUT_TV); - if (nv_encoder && force) { - struct drm_encoder *encoder = to_drm_encoder(nv_encoder); - struct drm_encoder_helper_funcs *helper = -@@ -327,7 +331,7 @@ - nv_connector->edid = NULL; - } - -- nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); -+ nv_encoder = find_encoder(connector, OUTPUT_LVDS); - if (!nv_encoder) - return connector_status_disconnected; - -@@ -405,7 +409,7 @@ - } else - type = OUTPUT_ANY; - -- nv_encoder = find_encoder_by_type(connector, type); -+ nv_encoder = find_encoder(connector, type); - if (!nv_encoder) { - NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", - drm_get_connector_name(connector)); -@@ -867,7 +871,6 @@ - dev->mode_config.scaling_mode_property, - nv_connector->scaling_mode); - } -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; - /* fall-through */ - case DCB_CONNECTOR_TV_0: - case DCB_CONNECTOR_TV_1: -@@ -884,19 +887,16 @@ - dev->mode_config.dithering_mode_property, - nv_connector->use_dithering ? - DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); -- -- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) { -- if (dev_priv->card_type >= NV_50) -- connector->polled = DRM_CONNECTOR_POLL_HPD; -- else -- connector->polled = DRM_CONNECTOR_POLL_CONNECT; -- } - break; - } - -- if (pgpio->irq_register) { -+ if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { - pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, - nouveau_connector_hotplug, connector); -+ -+ connector->polled = DRM_CONNECTOR_POLL_HPD; -+ } else { -+ connector->polled = DRM_CONNECTOR_POLL_CONNECT; - } - - drm_sysfs_connector_add(connector); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_crtc.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_crtc.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_crtc.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_crtc.h 2011-07-26 07:03:44.411050824 +0200 -@@ -82,14 +82,13 @@ - } - - int nv50_crtc_create(struct drm_device *dev, int index); --int nv50_cursor_init(struct nouveau_crtc *); --void nv50_cursor_fini(struct nouveau_crtc *); - int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, struct drm_file *file_priv, - uint32_t buffer_handle, uint32_t width, - uint32_t height); - int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y); - - int nv04_cursor_init(struct nouveau_crtc *); -+int nv50_cursor_init(struct nouveau_crtc *); - - struct nouveau_connector * - nouveau_crtc_connector_get(struct nouveau_crtc *crtc); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_display.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_display.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_display.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_display.c 2011-07-26 07:03:44.412050836 +0200 -@@ -105,9 +105,12 @@ - if (dev_priv->chipset == 0x50) - nv_fb->r_format |= (tile_flags << 8); - -- if (!tile_flags) -- nv_fb->r_pitch = 0x00100000 | fb->pitch; -- else { -+ if (!tile_flags) { -+ if (dev_priv->card_type < NV_D0) -+ nv_fb->r_pitch = 0x00100000 | fb->pitch; -+ else -+ nv_fb->r_pitch = 0x01000000 | fb->pitch; -+ } else { - u32 mode = nvbo->tile_mode; - if (dev_priv->card_type >= NV_C0) - mode >>= 4; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_dma.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_dma.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_dma.c 2011-07-26 07:03:44.412050836 +0200 -@@ -167,8 +167,13 @@ - int delta, int length) - { - struct nouveau_bo *pb = chan->pushbuf_bo; -- uint64_t offset = bo->bo.offset + delta; -+ struct nouveau_vma *vma; - int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; -+ u64 offset; -+ -+ vma = nouveau_bo_vma_find(bo, chan->vm); -+ BUG_ON(!vma); -+ offset = vma->offset + delta; - - BUG_ON(chan->dma.ib_free < 1); - nouveau_bo_wr32(pb, ip++, lower_32_bits(offset)); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_dp.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_dp.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_dp.c 2011-07-26 07:03:44.413050848 +0200 -@@ -300,7 +300,7 @@ - if (dpe->script0) { - NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); - nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), -- nv_encoder->dcb); -+ nv_encoder->dcb, -1); - } - - train: -@@ -433,7 +433,7 @@ - if (dpe->script1) { - NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); - nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), -- nv_encoder->dcb); -+ nv_encoder->dcb, -1); - } - - /* re-enable hotplug detect */ -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_drv.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_drv.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_drv.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_drv.c 2011-07-26 07:03:44.413050848 +0200 -@@ -41,7 +41,7 @@ - module_param_named(agpmode, nouveau_agpmode, int, 0400); - - MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); --static int nouveau_modeset = -1; /* kms */ -+int nouveau_modeset = -1; - module_param_named(modeset, nouveau_modeset, int, 0400); - - MODULE_PARM_DESC(vbios, "Override default VBIOS location"); -@@ -73,7 +73,7 @@ - module_param_named(ignorelid, nouveau_ignorelid, int, 0400); - - MODULE_PARM_DESC(noaccel, "Disable all acceleration"); --int nouveau_noaccel = 0; -+int nouveau_noaccel = -1; - module_param_named(noaccel, nouveau_noaccel, int, 0400); - - MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); -@@ -119,6 +119,10 @@ - int nouveau_msi; - module_param_named(msi, nouveau_msi, int, 0400); - -+MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); -+int nouveau_ctxfw; -+module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -+ - int nouveau_fbpercrtc; - #if 0 - module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); -@@ -210,10 +214,13 @@ - pfifo->unload_context(dev); - - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { -- if (dev_priv->eng[e]) { -- ret = dev_priv->eng[e]->fini(dev, e); -- if (ret) -- goto out_abort; -+ if (!dev_priv->eng[e]) -+ continue; -+ -+ ret = dev_priv->eng[e]->fini(dev, e, true); -+ if (ret) { -+ NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); -+ goto out_abort; - } - } - -@@ -354,7 +361,7 @@ - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -- u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT; -+ u32 offset = nv_crtc->cursor.nvbo->bo.offset; - - nv_crtc->cursor.set_offset(nv_crtc, offset); - nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, -@@ -389,7 +396,9 @@ - .firstopen = nouveau_firstopen, - .lastclose = nouveau_lastclose, - .unload = nouveau_unload, -+ .open = nouveau_open, - .preclose = nouveau_preclose, -+ .postclose = nouveau_postclose, - #if defined(CONFIG_DRM_NOUVEAU_DEBUG) - .debugfs_init = nouveau_debugfs_init, - .debugfs_cleanup = nouveau_debugfs_takedown, -@@ -420,6 +429,8 @@ - - .gem_init_object = nouveau_gem_object_new, - .gem_free_object = nouveau_gem_object_del, -+ .gem_open_object = nouveau_gem_object_open, -+ .gem_close_object = nouveau_gem_object_close, - - .name = DRIVER_NAME, - .desc = DRIVER_DESC, -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_drv.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_drv.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_drv.h 2011-07-26 07:03:44.415050872 +0200 -@@ -46,9 +46,17 @@ - #include "ttm/ttm_module.h" - - struct nouveau_fpriv { -- struct ttm_object_file *tfile; -+ spinlock_t lock; -+ struct list_head channels; -+ struct nouveau_vm *vm; - }; - -+static inline struct nouveau_fpriv * -+nouveau_fpriv(struct drm_file *file_priv) -+{ -+ return file_priv ? file_priv->driver_priv : NULL; -+} -+ - #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - - #include "nouveau_drm.h" -@@ -69,7 +77,7 @@ - struct drm_device *dev; - - struct nouveau_vma bar_vma; -- struct nouveau_vma tmp_vma; -+ struct nouveau_vma vma[2]; - u8 page_shift; - - struct drm_mm_node *tag; -@@ -107,7 +115,8 @@ - - struct nouveau_channel *channel; - -- struct nouveau_vma vma; -+ struct list_head vma_list; -+ unsigned page_shift; - - uint32_t tile_mode; - uint32_t tile_flags; -@@ -176,9 +185,10 @@ - uint32_t flags; - - u32 size; -- u32 pinst; -- u32 cinst; -- u64 vinst; -+ u32 pinst; /* PRAMIN BAR offset */ -+ u32 cinst; /* Channel offset */ -+ u64 vinst; /* VRAM address */ -+ u64 linst; /* VM address */ - - uint32_t engine; - uint32_t class; -@@ -201,6 +211,7 @@ - - struct nouveau_channel { - struct drm_device *dev; -+ struct list_head list; - int id; - - /* references to the channel data structure */ -@@ -228,15 +239,18 @@ - uint32_t sequence; - uint32_t sequence_ack; - atomic_t last_sequence_irq; -+ struct nouveau_vma vma; - } fence; - - /* DMA push buffer */ - struct nouveau_gpuobj *pushbuf; - struct nouveau_bo *pushbuf_bo; -+ struct nouveau_vma pushbuf_vma; - uint32_t pushbuf_base; - - /* Notifier memory */ - struct nouveau_bo *notifier_bo; -+ struct nouveau_vma notifier_vma; - struct drm_mm notifier_heap; - - /* PFIFO context */ -@@ -278,6 +292,7 @@ - - uint32_t sw_subchannel[8]; - -+ struct nouveau_vma dispc_vma[2]; - struct { - struct nouveau_gpuobj *vblsem; - uint32_t vblsem_head; -@@ -297,7 +312,7 @@ - struct nouveau_exec_engine { - void (*destroy)(struct drm_device *, int engine); - int (*init)(struct drm_device *, int engine); -- int (*fini)(struct drm_device *, int engine); -+ int (*fini)(struct drm_device *, int engine, bool suspend); - int (*context_new)(struct nouveau_channel *, int engine); - void (*context_del)(struct nouveau_channel *, int engine); - int (*object_new)(struct nouveau_channel *, int engine, -@@ -314,7 +329,8 @@ - int (*suspend)(struct drm_device *dev); - void (*resume)(struct drm_device *dev); - -- int (*get)(struct nouveau_gpuobj *, u32 size, u32 align); -+ int (*get)(struct nouveau_gpuobj *, struct nouveau_channel *, -+ u32 size, u32 align); - void (*put)(struct nouveau_gpuobj *); - int (*map)(struct nouveau_gpuobj *); - void (*unmap)(struct nouveau_gpuobj *); -@@ -398,12 +414,13 @@ - }; - - struct nouveau_pm_voltage_level { -- u8 voltage; -- u8 vid; -+ u32 voltage; /* microvolts */ -+ u8 vid; - }; - - struct nouveau_pm_voltage { - bool supported; -+ u8 version; - u8 vid_mask; - - struct nouveau_pm_voltage_level *level; -@@ -412,17 +429,48 @@ - - struct nouveau_pm_memtiming { - int id; -- u32 reg_100220; -- u32 reg_100224; -- u32 reg_100228; -- u32 reg_10022c; -- u32 reg_100230; -- u32 reg_100234; -- u32 reg_100238; -- u32 reg_10023c; -- u32 reg_100240; -+ u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */ -+ u32 reg_1; -+ u32 reg_2; -+ u32 reg_3; -+ u32 reg_4; -+ u32 reg_5; -+ u32 reg_6; -+ u32 reg_7; -+ u32 reg_8; -+ /* To be written to 0x1002c0 */ -+ u8 CL; -+ u8 WR; -+}; -+ -+struct nouveau_pm_tbl_header{ -+ u8 version; -+ u8 header_len; -+ u8 entry_cnt; -+ u8 entry_len; -+}; -+ -+struct nouveau_pm_tbl_entry{ -+ u8 tWR; -+ u8 tUNK_1; -+ u8 tCL; -+ u8 tRP; /* Byte 3 */ -+ u8 empty_4; -+ u8 tRAS; /* Byte 5 */ -+ u8 empty_6; -+ u8 tRFC; /* Byte 7 */ -+ u8 empty_8; -+ u8 tRC; /* Byte 9 */ -+ u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; -+ u8 empty_15,empty_16,empty_17; -+ u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; - }; - -+/* nouveau_mem.c */ -+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing); -+ - #define NOUVEAU_PM_MAX_LEVEL 8 - struct nouveau_pm_level { - struct device_attribute dev_attr; -@@ -432,11 +480,19 @@ - u32 core; - u32 memory; - u32 shader; -- u32 unk05; -- u32 unk0a; -- -- u8 voltage; -- u8 fanspeed; -+ u32 rop; -+ u32 copy; -+ u32 daemon; -+ u32 vdec; -+ u32 unk05; /* nv50:nva3, roughly.. */ -+ u32 unka0; /* nva3:nvc0 */ -+ u32 hub01; /* nvc0- */ -+ u32 hub06; /* nvc0- */ -+ u32 hub07; /* nvc0- */ -+ -+ u32 volt_min; /* microvolts */ -+ u32 volt_max; -+ u8 fanspeed; - - u16 memscript; - struct nouveau_pm_memtiming *timing; -@@ -445,9 +501,9 @@ - struct nouveau_pm_temp_sensor_constants { - u16 offset_constant; - s16 offset_mult; -- u16 offset_div; -- u16 slope_mult; -- u16 slope_div; -+ s16 offset_div; -+ s16 slope_mult; -+ s16 slope_div; - }; - - struct nouveau_pm_threshold_temp { -@@ -480,6 +536,11 @@ - void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, - u32 id, int khz); - void (*clock_set)(struct drm_device *, void *); -+ -+ int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); -+ void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); -+ void (*clocks_set)(struct drm_device *, void *); -+ - int (*voltage_get)(struct drm_device *); - int (*voltage_set)(struct drm_device *, int voltage); - int (*fanspeed_get)(struct drm_device *); -@@ -488,7 +549,10 @@ - }; - - struct nouveau_vram_engine { -+ struct nouveau_mm mm; -+ - int (*init)(struct drm_device *); -+ void (*takedown)(struct drm_device *dev); - int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, - u32 type, struct nouveau_mem **); - void (*put)(struct drm_device *, struct nouveau_mem **); -@@ -604,17 +668,19 @@ - NV_40 = 0x40, - NV_50 = 0x50, - NV_C0 = 0xc0, -+ NV_D0 = 0xd0 - }; - - struct drm_nouveau_private { - struct drm_device *dev; -+ bool noaccel; - - /* the card type, takes NV_* as values */ - enum nouveau_card_type card_type; - /* exact chipset, derived from NV_PMC_BOOT_0 */ - int chipset; -- int stepping; - int flags; -+ u32 crystal; - - void __iomem *mmio; - -@@ -700,9 +766,7 @@ - /* VRAM/fb configuration */ - uint64_t vram_size; - uint64_t vram_sys_base; -- u32 vram_rblock_size; - -- uint64_t fb_phys; - uint64_t fb_available_size; - uint64_t fb_mappable_pages; - uint64_t fb_aper_free; -@@ -765,6 +829,7 @@ - } - - /* nouveau_drv.c */ -+extern int nouveau_modeset; - extern int nouveau_agpmode; - extern int nouveau_duallink; - extern int nouveau_uscript_lvds; -@@ -784,12 +849,15 @@ - extern char *nouveau_perflvl; - extern int nouveau_perflvl_wr; - extern int nouveau_msi; -+extern int nouveau_ctxfw; - - extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); - extern int nouveau_pci_resume(struct pci_dev *pdev); - - /* nouveau_state.c */ -+extern int nouveau_open(struct drm_device *, struct drm_file *); - extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); -+extern void nouveau_postclose(struct drm_device *, struct drm_file *); - extern int nouveau_load(struct drm_device *, unsigned long flags); - extern int nouveau_firstopen(struct drm_device *); - extern void nouveau_lastclose(struct drm_device *); -@@ -802,6 +870,8 @@ - uint32_t reg, uint32_t mask, uint32_t val); - extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); -+extern bool nouveau_wait_cb(struct drm_device *, u64 timeout, -+ bool (*cond)(void *), void *); - extern bool nouveau_wait_for_idle(struct drm_device *); - extern int nouveau_card_init(struct drm_device *); - -@@ -847,7 +917,7 @@ - extern struct nouveau_channel * - nouveau_channel_get_unlocked(struct nouveau_channel *); - extern struct nouveau_channel * --nouveau_channel_get(struct drm_device *, struct drm_file *, int id); -+nouveau_channel_get(struct drm_file *, int id); - extern void nouveau_channel_put_unlocked(struct nouveau_channel **); - extern void nouveau_channel_put(struct nouveau_channel **); - extern void nouveau_channel_ref(struct nouveau_channel *chan, -@@ -1000,7 +1070,7 @@ - extern void nouveau_bios_takedown(struct drm_device *dev); - extern int nouveau_run_vbios_init(struct drm_device *); - extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, -- struct dcb_entry *); -+ struct dcb_entry *, int crtc); - extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, - enum dcb_gpio_tag); - extern struct dcb_connector_table_entry * -@@ -1008,9 +1078,8 @@ - extern u32 get_pll_register(struct drm_device *, enum pll_types); - extern int get_pll_limits(struct drm_device *, uint32_t limit_match, - struct pll_lims *); --extern int nouveau_bios_run_display_table(struct drm_device *, -- struct dcb_entry *, -- uint32_t script, int pxclk); -+extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, -+ struct dcb_entry *, int crtc); - extern void *nouveau_bios_dp_table(struct drm_device *, struct dcb_entry *, - int *length); - extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); -@@ -1120,7 +1189,6 @@ - - /* nv04_graph.c */ - extern int nv04_graph_create(struct drm_device *); --extern void nv04_graph_fifo_access(struct drm_device *, bool); - extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); - extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data); -@@ -1158,8 +1226,8 @@ - /* nvc0_copy.c */ - extern int nvc0_copy_create(struct drm_device *dev, int engine); - --/* nv40_mpeg.c */ --extern int nv40_mpeg_create(struct drm_device *dev); -+/* nv31_mpeg.c */ -+extern int nv31_mpeg_create(struct drm_device *dev); - - /* nv50_mpeg.c */ - extern int nv50_mpeg_create(struct drm_device *dev); -@@ -1169,7 +1237,8 @@ - extern void nv04_instmem_takedown(struct drm_device *); - extern int nv04_instmem_suspend(struct drm_device *); - extern void nv04_instmem_resume(struct drm_device *); --extern int nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); -+extern int nv04_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, -+ u32 size, u32 align); - extern void nv04_instmem_put(struct nouveau_gpuobj *); - extern int nv04_instmem_map(struct nouveau_gpuobj *); - extern void nv04_instmem_unmap(struct nouveau_gpuobj *); -@@ -1180,7 +1249,8 @@ - extern void nv50_instmem_takedown(struct drm_device *); - extern int nv50_instmem_suspend(struct drm_device *); - extern void nv50_instmem_resume(struct drm_device *); --extern int nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); -+extern int nv50_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *, -+ u32 size, u32 align); - extern void nv50_instmem_put(struct nouveau_gpuobj *); - extern int nv50_instmem_map(struct nouveau_gpuobj *); - extern void nv50_instmem_unmap(struct nouveau_gpuobj *); -@@ -1242,15 +1312,19 @@ - extern int nv04_display_init(struct drm_device *); - extern void nv04_display_destroy(struct drm_device *); - -+/* nvd0_display.c */ -+extern int nvd0_display_create(struct drm_device *); -+extern int nvd0_display_init(struct drm_device *); -+extern void nvd0_display_destroy(struct drm_device *); -+ - /* nv04_crtc.c */ - extern int nv04_crtc_create(struct drm_device *, int index); - - /* nouveau_bo.c */ - extern struct ttm_bo_driver nouveau_bo_driver; --extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *, -- int size, int align, uint32_t flags, -- uint32_t tile_mode, uint32_t tile_flags, -- struct nouveau_bo **); -+extern int nouveau_bo_new(struct drm_device *, int size, int align, -+ uint32_t flags, uint32_t tile_mode, -+ uint32_t tile_flags, struct nouveau_bo **); - extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); - extern int nouveau_bo_unpin(struct nouveau_bo *); - extern int nouveau_bo_map(struct nouveau_bo *); -@@ -1265,6 +1339,12 @@ - extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, - bool no_wait_reserve, bool no_wait_gpu); - -+extern struct nouveau_vma * -+nouveau_bo_vma_find(struct nouveau_bo *, struct nouveau_vm *); -+extern int nouveau_bo_vma_add(struct nouveau_bo *, struct nouveau_vm *, -+ struct nouveau_vma *); -+extern void nouveau_bo_vma_del(struct nouveau_bo *, struct nouveau_vma *); -+ - /* nouveau_fence.c */ - struct nouveau_fence; - extern int nouveau_fence_init(struct drm_device *); -@@ -1310,12 +1390,14 @@ - } - - /* nouveau_gem.c */ --extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -- int size, int align, uint32_t domain, -- uint32_t tile_mode, uint32_t tile_flags, -- struct nouveau_bo **); -+extern int nouveau_gem_new(struct drm_device *, int size, int align, -+ uint32_t domain, uint32_t tile_mode, -+ uint32_t tile_flags, struct nouveau_bo **); - extern int nouveau_gem_object_new(struct drm_gem_object *); - extern void nouveau_gem_object_del(struct drm_gem_object *); -+extern int nouveau_gem_object_open(struct drm_gem_object *, struct drm_file *); -+extern void nouveau_gem_object_close(struct drm_gem_object *, -+ struct drm_file *); - extern int nouveau_gem_ioctl_new(struct drm_device *, void *, - struct drm_file *); - extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *, -@@ -1344,6 +1426,8 @@ - void nv50_gpio_fini(struct drm_device *dev); - int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); - int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); -+int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); -+int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); - int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, - void (*)(void *, int), void *); - void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, -@@ -1418,6 +1502,8 @@ - nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) - #define nv_wait_ne(dev, reg, mask, val) \ - nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) -+#define nv_wait_cb(dev, func, data) \ -+ nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) - - /* PRAMIN access */ - static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fbcon.c 2011-07-26 07:03:44.416050884 +0200 -@@ -279,6 +279,7 @@ - struct fb_info *info; - struct drm_framebuffer *fb; - struct nouveau_framebuffer *nouveau_fb; -+ struct nouveau_channel *chan; - struct nouveau_bo *nvbo; - struct drm_mode_fb_cmd mode_cmd; - struct pci_dev *pdev = dev->pdev; -@@ -296,8 +297,8 @@ - size = mode_cmd.pitch * mode_cmd.height; - size = roundup(size, PAGE_SIZE); - -- ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, -- NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo); -+ ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM, -+ 0, 0x0000, &nvbo); - if (ret) { - NV_ERROR(dev, "failed to allocate framebuffer\n"); - goto out; -@@ -318,6 +319,15 @@ - goto out; - } - -+ chan = nouveau_nofbaccel ? NULL : dev_priv->channel; -+ if (chan && dev_priv->card_type >= NV_50) { -+ ret = nouveau_bo_vma_add(nvbo, chan->vm, &nfbdev->nouveau_fb.vma); -+ if (ret) { -+ NV_ERROR(dev, "failed to map fb into chan: %d\n", ret); -+ chan = NULL; -+ } -+ } -+ - mutex_lock(&dev->struct_mutex); - - info = framebuffer_alloc(0, device); -@@ -448,6 +458,7 @@ - - if (nouveau_fb->nvbo) { - nouveau_bo_unmap(nouveau_fb->nvbo); -+ nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma); - drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); - nouveau_fb->nvbo = NULL; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_fb.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fb.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fb.h 2011-07-26 07:03:44.416050884 +0200 -@@ -30,6 +30,7 @@ - struct nouveau_framebuffer { - struct drm_framebuffer base; - struct nouveau_bo *nvbo; -+ struct nouveau_vma vma; - u32 r_dma; - u32 r_format; - u32 r_pitch; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_fence.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fence.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_fence.c 2011-07-26 07:03:44.417050896 +0200 -@@ -336,6 +336,7 @@ - { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_fence *fence = NULL; -+ u64 offset = chan->fence.vma.offset + sema->mem->start; - int ret; - - if (dev_priv->chipset < 0x84) { -@@ -345,13 +346,10 @@ - - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); - OUT_RING (chan, NvSema); -- OUT_RING (chan, sema->mem->start); -+ OUT_RING (chan, offset); - OUT_RING (chan, 1); - } else - if (dev_priv->chipset < 0xc0) { -- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -- u64 offset = vma->offset + sema->mem->start; -- - ret = RING_SPACE(chan, 7); - if (ret) - return ret; -@@ -364,9 +362,6 @@ - OUT_RING (chan, 1); - OUT_RING (chan, 1); /* ACQUIRE_EQ */ - } else { -- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -- u64 offset = vma->offset + sema->mem->start; -- - ret = RING_SPACE(chan, 5); - if (ret) - return ret; -@@ -394,6 +389,7 @@ - { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_fence *fence = NULL; -+ u64 offset = chan->fence.vma.offset + sema->mem->start; - int ret; - - if (dev_priv->chipset < 0x84) { -@@ -403,14 +399,11 @@ - - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); - OUT_RING (chan, NvSema); -- OUT_RING (chan, sema->mem->start); -+ OUT_RING (chan, offset); - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); - OUT_RING (chan, 1); - } else - if (dev_priv->chipset < 0xc0) { -- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -- u64 offset = vma->offset + sema->mem->start; -- - ret = RING_SPACE(chan, 7); - if (ret) - return ret; -@@ -423,9 +416,6 @@ - OUT_RING (chan, 1); - OUT_RING (chan, 2); /* RELEASE */ - } else { -- struct nouveau_vma *vma = &dev_priv->fence.bo->vma; -- u64 offset = vma->offset + sema->mem->start; -- - ret = RING_SPACE(chan, 5); - if (ret) - return ret; -@@ -529,7 +519,7 @@ - if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { - struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; - -- ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, -+ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_FROM_MEMORY, - mem->start << PAGE_SHIFT, - mem->size, NV_MEM_ACCESS_RW, - NV_MEM_TARGET_VRAM, &obj); -@@ -540,6 +530,12 @@ - nouveau_gpuobj_ref(NULL, &obj); - if (ret) - return ret; -+ } else { -+ /* map fence bo into channel's vm */ -+ ret = nouveau_bo_vma_add(dev_priv->fence.bo, chan->vm, -+ &chan->fence.vma); -+ if (ret) -+ return ret; - } - - INIT_LIST_HEAD(&chan->fence.pending); -@@ -551,10 +547,10 @@ - void - nouveau_fence_channel_fini(struct nouveau_channel *chan) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_fence *tmp, *fence; - - spin_lock(&chan->fence.lock); -- - list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { - fence->signalled = true; - list_del(&fence->entry); -@@ -564,8 +560,9 @@ - - kref_put(&fence->refcount, nouveau_fence_del); - } -- - spin_unlock(&chan->fence.lock); -+ -+ nouveau_bo_vma_del(dev_priv->fence.bo, &chan->fence.vma); - } - - int -@@ -577,7 +574,7 @@ - - /* Create a shared VRAM heap for cross-channel sync. */ - if (USE_SEMA(dev)) { -- ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM, - 0, 0, &dev_priv->fence.bo); - if (ret) - return ret; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_gem.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_gem.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_gem.c 2011-07-26 07:03:44.418050908 +0200 -@@ -60,9 +60,71 @@ - } - - int --nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, -- int size, int align, uint32_t domain, uint32_t tile_mode, -- uint32_t tile_flags, struct nouveau_bo **pnvbo) -+nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) -+{ -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); -+ struct nouveau_bo *nvbo = nouveau_gem_object(gem); -+ struct nouveau_vma *vma; -+ int ret; -+ -+ if (!fpriv->vm) -+ return 0; -+ -+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); -+ if (ret) -+ return ret; -+ -+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); -+ if (!vma) { -+ vma = kzalloc(sizeof(*vma), GFP_KERNEL); -+ if (!vma) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = nouveau_bo_vma_add(nvbo, fpriv->vm, vma); -+ if (ret) { -+ kfree(vma); -+ goto out; -+ } -+ } else { -+ vma->refcount++; -+ } -+ -+out: -+ ttm_bo_unreserve(&nvbo->bo); -+ return ret; -+} -+ -+void -+nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) -+{ -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); -+ struct nouveau_bo *nvbo = nouveau_gem_object(gem); -+ struct nouveau_vma *vma; -+ int ret; -+ -+ if (!fpriv->vm) -+ return; -+ -+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0); -+ if (ret) -+ return; -+ -+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); -+ if (vma) { -+ if (--vma->refcount == 0) { -+ nouveau_bo_vma_del(nvbo, vma); -+ kfree(vma); -+ } -+ } -+ ttm_bo_unreserve(&nvbo->bo); -+} -+ -+int -+nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain, -+ uint32_t tile_mode, uint32_t tile_flags, -+ struct nouveau_bo **pnvbo) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *nvbo; -@@ -76,7 +138,7 @@ - if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) - flags |= TTM_PL_FLAG_SYSTEM; - -- ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode, -+ ret = nouveau_bo_new(dev, size, align, flags, tile_mode, - tile_flags, pnvbo); - if (ret) - return ret; -@@ -103,17 +165,28 @@ - } - - static int --nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) -+nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, -+ struct drm_nouveau_gem_info *rep) - { -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); - struct nouveau_bo *nvbo = nouveau_gem_object(gem); -+ struct nouveau_vma *vma; - - if (nvbo->bo.mem.mem_type == TTM_PL_TT) - rep->domain = NOUVEAU_GEM_DOMAIN_GART; - else - rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; - -- rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - rep->offset = nvbo->bo.offset; -+ if (fpriv->vm) { -+ vma = nouveau_bo_vma_find(nvbo, fpriv->vm); -+ if (!vma) -+ return -EINVAL; -+ -+ rep->offset = vma->offset; -+ } -+ -+ rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - rep->map_handle = nvbo->bo.addr_space_offset; - rep->tile_mode = nvbo->tile_mode; - rep->tile_flags = nvbo->tile_flags; -@@ -127,7 +200,6 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct drm_nouveau_gem_new *req = data; - struct nouveau_bo *nvbo = NULL; -- struct nouveau_channel *chan = NULL; - int ret = 0; - - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) -@@ -138,28 +210,21 @@ - return -EINVAL; - } - -- if (req->channel_hint) { -- chan = nouveau_channel_get(dev, file_priv, req->channel_hint); -- if (IS_ERR(chan)) -- return PTR_ERR(chan); -- } -- -- ret = nouveau_gem_new(dev, chan, req->info.size, req->align, -+ ret = nouveau_gem_new(dev, req->info.size, req->align, - req->info.domain, req->info.tile_mode, - req->info.tile_flags, &nvbo); -- if (chan) -- nouveau_channel_put(&chan); - if (ret) - return ret; - -- ret = nouveau_gem_info(nvbo->gem, &req->info); -- if (ret) -- goto out; -- - ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); -+ if (ret == 0) { -+ ret = nouveau_gem_info(file_priv, nvbo->gem, &req->info); -+ if (ret) -+ drm_gem_handle_delete(file_priv, req->info.handle); -+ } -+ - /* drop reference from allocate - handle holds it now */ - drm_gem_object_unreference_unlocked(nvbo->gem); --out: - return ret; - } - -@@ -318,6 +383,7 @@ - validate_list(struct nouveau_channel *chan, struct list_head *list, - struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_nouveau_gem_pushbuf_bo __user *upbbo = - (void __force __user *)(uintptr_t)user_pbbo_ptr; - struct drm_device *dev = chan->dev; -@@ -356,24 +422,26 @@ - return ret; - } - -- if (nvbo->bo.offset == b->presumed.offset && -- ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && -- b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || -- (nvbo->bo.mem.mem_type == TTM_PL_TT && -- b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART))) -- continue; -+ if (dev_priv->card_type < NV_50) { -+ if (nvbo->bo.offset == b->presumed.offset && -+ ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && -+ b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || -+ (nvbo->bo.mem.mem_type == TTM_PL_TT && -+ b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART))) -+ continue; - -- if (nvbo->bo.mem.mem_type == TTM_PL_TT) -- b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART; -- else -- b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM; -- b->presumed.offset = nvbo->bo.offset; -- b->presumed.valid = 0; -- relocs++; -- -- if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, -- &b->presumed, sizeof(b->presumed))) -- return -EFAULT; -+ if (nvbo->bo.mem.mem_type == TTM_PL_TT) -+ b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART; -+ else -+ b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM; -+ b->presumed.offset = nvbo->bo.offset; -+ b->presumed.valid = 0; -+ relocs++; -+ -+ if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed, -+ &b->presumed, sizeof(b->presumed))) -+ return -EFAULT; -+ } - } - - return relocs; -@@ -548,7 +616,7 @@ - struct nouveau_fence *fence = NULL; - int i, j, ret = 0, do_reloc = 0; - -- chan = nouveau_channel_get(dev, file_priv, req->channel); -+ chan = nouveau_channel_get(file_priv, req->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - -@@ -782,7 +850,7 @@ - if (!gem) - return -ENOENT; - -- ret = nouveau_gem_info(gem, req); -+ ret = nouveau_gem_info(file_priv, gem, req); - drm_gem_object_unreference_unlocked(gem); - return ret; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_i2c.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_i2c.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_i2c.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_i2c.c 2011-07-26 07:03:44.444051220 +0200 -@@ -107,6 +107,13 @@ - return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); - } - -+static const uint32_t nv50_i2c_port[] = { -+ 0x00e138, 0x00e150, 0x00e168, 0x00e180, -+ 0x00e254, 0x00e274, 0x00e764, 0x00e780, -+ 0x00e79c, 0x00e7b8 -+}; -+#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) -+ - static int - nv50_i2c_getscl(void *data) - { -@@ -130,28 +137,32 @@ - nv50_i2c_setscl(void *data, int state) - { - struct nouveau_i2c_chan *i2c = data; -- struct drm_device *dev = i2c->dev; - -- nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); -+ nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); - } - - static void - nv50_i2c_setsda(void *data, int state) - { - struct nouveau_i2c_chan *i2c = data; -- struct drm_device *dev = i2c->dev; - -- nv_wr32(dev, i2c->wr, -- (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); -+ nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); - i2c->data = state; - } - --static const uint32_t nv50_i2c_port[] = { -- 0x00e138, 0x00e150, 0x00e168, 0x00e180, -- 0x00e254, 0x00e274, 0x00e764, 0x00e780, -- 0x00e79c, 0x00e7b8 --}; --#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) -+static int -+nvd0_i2c_getscl(void *data) -+{ -+ struct nouveau_i2c_chan *i2c = data; -+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); -+} -+ -+static int -+nvd0_i2c_getsda(void *data) -+{ -+ struct nouveau_i2c_chan *i2c = data; -+ return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); -+} - - int - nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) -@@ -163,7 +174,8 @@ - if (entry->chan) - return -EEXIST; - -- if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { -+ if (dev_priv->card_type >= NV_50 && -+ dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { - NV_ERROR(dev, "unknown i2c port %d\n", entry->read); - return -EINVAL; - } -@@ -192,10 +204,17 @@ - case 5: - i2c->bit.setsda = nv50_i2c_setsda; - i2c->bit.setscl = nv50_i2c_setscl; -- i2c->bit.getsda = nv50_i2c_getsda; -- i2c->bit.getscl = nv50_i2c_getscl; -- i2c->rd = nv50_i2c_port[entry->read]; -- i2c->wr = i2c->rd; -+ if (dev_priv->card_type < NV_D0) { -+ i2c->bit.getsda = nv50_i2c_getsda; -+ i2c->bit.getscl = nv50_i2c_getscl; -+ i2c->rd = nv50_i2c_port[entry->read]; -+ i2c->wr = i2c->rd; -+ } else { -+ i2c->bit.getsda = nvd0_i2c_getsda; -+ i2c->bit.getscl = nvd0_i2c_getscl; -+ i2c->rd = 0x00d014 + (entry->read * 0x20); -+ i2c->wr = i2c->rd; -+ } - break; - case 6: - i2c->rd = entry->read; -@@ -267,7 +286,10 @@ - val = 0xe001; - } - -- nv_wr32(dev, reg, (nv_rd32(dev, reg) & ~0xf003) | val); -+ /* nfi, but neither auxch or i2c work if it's 1 */ -+ nv_mask(dev, reg + 0x0c, 0x00000001, 0x00000000); -+ /* nfi, but switches auxch vs normal i2c */ -+ nv_mask(dev, reg + 0x00, 0x0000f003, val); - } - - if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_irq.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_irq.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_irq.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_irq.c 2011-07-26 07:03:44.445051232 +0200 -@@ -79,7 +79,7 @@ - int i; - - stat = nv_rd32(dev, NV03_PMC_INTR_0); -- if (!stat) -+ if (stat == 0 || stat == ~0) - return IRQ_NONE; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_mem.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mem.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mem.c 2011-07-26 07:03:44.446051244 +0200 -@@ -408,8 +408,6 @@ - if (ret) - return ret; - -- dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); -- - ret = nouveau_ttm_global_init(dev_priv); - if (ret) - return ret; -@@ -423,38 +421,6 @@ - return ret; - } - -- /* reserve space at end of VRAM for PRAMIN */ -- if (dev_priv->card_type >= NV_50) { -- dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; -- } else -- if (dev_priv->card_type >= NV_40) { -- u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); -- u32 rsvd; -- -- /* estimate grctx size, the magics come from nv40_grctx.c */ -- if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; -- else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; -- else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; -- else rsvd = 0x4a40 * vs; -- rsvd += 16 * 1024; -- rsvd *= dev_priv->engine.fifo.channels; -- -- /* pciegart table */ -- if (drm_pci_device_is_pcie(dev)) -- rsvd += 512 * 1024; -- -- /* object storage */ -- rsvd += 512 * 1024; -- -- dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); -- } else { -- dev_priv->ramin_rsvd_vram = 512 * 1024; -- } -- -- ret = dev_priv->engine.vram.init(dev); -- if (ret) -- return ret; -- - NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); - if (dev_priv->vram_sys_base) { - NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", -@@ -479,7 +445,7 @@ - } - - if (dev_priv->card_type < NV_50) { -- ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM, - 0, 0, &dev_priv->vga_ram); - if (ret == 0) - ret = nouveau_bo_pin(dev_priv->vga_ram, -@@ -536,35 +502,146 @@ - return 0; - } - -+/* XXX: For now a dummy. More samples required, possibly even a card -+ * Called from nouveau_perf.c */ -+void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing) { -+ -+ NV_DEBUG(dev,"Timing entry format unknown, please contact nouveau developers"); -+} -+ -+void nv40_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number, -+ struct nouveau_pm_memtiming *timing) { -+ -+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); -+ -+ /* XXX: I don't trust the -1's and +1's... they must come -+ * from somewhere! */ -+ timing->reg_1 = (e->tWR + 2 + magic_number) << 24 | -+ 1 << 16 | -+ (e->tUNK_1 + 2 + magic_number) << 8 | -+ (e->tCL + 2 - magic_number); -+ timing->reg_2 = (magic_number << 24 | e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); -+ timing->reg_2 |= 0x20200000; -+ -+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1,timing->reg_2); -+} -+ -+void nv50_mem_timing_entry(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, uint8_t magic_number,struct nouveau_pm_memtiming *timing) { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ uint8_t unk18 = 1, -+ unk19 = 1, -+ unk20 = 0, -+ unk21 = 0; -+ -+ switch (min(hdr->entry_len, (u8) 22)) { -+ case 22: -+ unk21 = e->tUNK_21; -+ case 21: -+ unk20 = e->tUNK_20; -+ case 20: -+ unk19 = e->tUNK_19; -+ case 19: -+ unk18 = e->tUNK_18; -+ break; -+ } -+ -+ timing->reg_0 = (e->tRC << 24 | e->tRFC << 16 | e->tRAS << 8 | e->tRP); -+ -+ /* XXX: I don't trust the -1's and +1's... they must come -+ * from somewhere! */ -+ timing->reg_1 = (e->tWR + unk19 + 1 + magic_number) << 24 | -+ max(unk18, (u8) 1) << 16 | -+ (e->tUNK_1 + unk19 + 1 + magic_number) << 8; -+ if (dev_priv->chipset == 0xa8) { -+ timing->reg_1 |= (e->tCL - 1); -+ } else { -+ timing->reg_1 |= (e->tCL + 2 - magic_number); -+ } -+ timing->reg_2 = (e->tUNK_12 << 16 | e->tUNK_11 << 8 | e->tUNK_10); -+ -+ timing->reg_5 = (e->tRAS << 24 | e->tRC); -+ timing->reg_5 += max(e->tUNK_10, e->tUNK_11) << 16; -+ -+ if (P->version == 1) { -+ timing->reg_2 |= magic_number << 24; -+ timing->reg_3 = (0x14 + e->tCL) << 24 | -+ 0x16 << 16 | -+ (e->tCL - 1) << 8 | -+ (e->tCL - 1); -+ timing->reg_4 = (nv_rd32(dev,0x10022c) & 0xffff0000) | e->tUNK_13 << 8 | e->tUNK_13; -+ timing->reg_5 |= (e->tCL + 2) << 8; -+ timing->reg_7 = 0x4000202 | (e->tCL - 1) << 16; -+ } else { -+ timing->reg_2 |= (unk19 - 1) << 24; -+ /* XXX: reg_10022c for recentish cards pretty much unknown*/ -+ timing->reg_3 = e->tCL - 1; -+ timing->reg_4 = (unk20 << 24 | unk21 << 16 | -+ e->tUNK_13 << 8 | e->tUNK_13); -+ /* XXX: +6? */ -+ timing->reg_5 |= (unk19 + 6) << 8; -+ -+ /* XXX: reg_10023c currently unknown -+ * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ -+ timing->reg_7 = 0x202; -+ } -+ -+ NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1, -+ timing->reg_2, timing->reg_3); -+ NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", -+ timing->reg_4, timing->reg_5, -+ timing->reg_6, timing->reg_7); -+ NV_DEBUG(dev, " 240: %08x\n", timing->reg_8); -+} -+ -+void nvc0_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, -+ struct nouveau_pm_tbl_entry *e, struct nouveau_pm_memtiming *timing) { -+ timing->reg_0 = (e->tRC << 24 | (e->tRFC & 0x7f) << 17 | e->tRAS << 8 | e->tRP); -+ timing->reg_1 = (nv_rd32(dev,0x10f294) & 0xff000000) | (e->tUNK_11&0x0f) << 20 | (e->tUNK_19 << 7) | (e->tCL & 0x0f); -+ timing->reg_2 = (nv_rd32(dev,0x10f298) & 0xff0000ff) | e->tWR << 16 | e->tUNK_1 << 8; -+ timing->reg_3 = e->tUNK_20 << 9 | e->tUNK_13; -+ timing->reg_4 = (nv_rd32(dev,0x10f2a0) & 0xfff000ff) | e->tUNK_12 << 15; -+ NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", timing->id, -+ timing->reg_0, timing->reg_1, -+ timing->reg_2, timing->reg_3); -+ NV_DEBUG(dev, " 2a0: %08x %08x %08x %08x\n", -+ timing->reg_4, timing->reg_5, -+ timing->reg_6, timing->reg_7); -+} -+ -+/** -+ * Processes the Memory Timing BIOS table, stores generated -+ * register values -+ * @pre init scripts were run, memtiming regs are initialized -+ */ - void - nouveau_mem_timing_init(struct drm_device *dev) - { -- /* cards < NVC0 only */ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nouveau_pm_memtimings *memtimings = &pm->memtimings; - struct nvbios *bios = &dev_priv->vbios; - struct bit_entry P; -- u8 tUNK_0, tUNK_1, tUNK_2; -- u8 tRP; /* Byte 3 */ -- u8 tRAS; /* Byte 5 */ -- u8 tRFC; /* Byte 7 */ -- u8 tRC; /* Byte 9 */ -- u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; -- u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; -- u8 magic_number = 0; /* Yeah... sorry*/ -- u8 *mem = NULL, *entry; -- int i, recordlen, entries; -+ struct nouveau_pm_tbl_header *hdr = NULL; -+ uint8_t magic_number; -+ u8 *entry; -+ int i; - - if (bios->type == NVBIOS_BIT) { - if (bit_table(dev, 'P', &P)) - return; - - if (P.version == 1) -- mem = ROMPTR(bios, P.data[4]); -+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); - else - if (P.version == 2) -- mem = ROMPTR(bios, P.data[8]); -+ hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); - else { - NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); - } -@@ -573,150 +650,56 @@ - return; - } - -- if (!mem) { -+ if (!hdr) { - NV_DEBUG(dev, "memory timing table pointer invalid\n"); - return; - } - -- if (mem[0] != 0x10) { -- NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]); -+ if (hdr->version != 0x10) { -+ NV_WARN(dev, "memory timing table 0x%02x unknown\n", hdr->version); - return; - } - - /* validate record length */ -- entries = mem[2]; -- recordlen = mem[3]; -- if (recordlen < 15) { -- NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]); -+ if (hdr->entry_len < 15) { -+ NV_ERROR(dev, "mem timing table length unknown: %d\n", hdr->entry_len); - return; - } - - /* parse vbios entries into common format */ - memtimings->timing = -- kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); -+ kcalloc(hdr->entry_cnt, sizeof(*memtimings->timing), GFP_KERNEL); - if (!memtimings->timing) - return; - - /* Get "some number" from the timing reg for NV_40 and NV_50 -- * Used in calculations later */ -- if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) { -+ * Used in calculations later... source unknown */ -+ magic_number = 0; -+ if (P.version == 1) { - magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24; - } - -- entry = mem + mem[1]; -- for (i = 0; i < entries; i++, entry += recordlen) { -+ entry = (u8*) hdr + hdr->header_len; -+ for (i = 0; i < hdr->entry_cnt; i++, entry += hdr->entry_len) { - struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i]; - if (entry[0] == 0) - continue; - -- tUNK_18 = 1; -- tUNK_19 = 1; -- tUNK_20 = 0; -- tUNK_21 = 0; -- switch (min(recordlen, 22)) { -- case 22: -- tUNK_21 = entry[21]; -- case 21: -- tUNK_20 = entry[20]; -- case 20: -- tUNK_19 = entry[19]; -- case 19: -- tUNK_18 = entry[18]; -- default: -- tUNK_0 = entry[0]; -- tUNK_1 = entry[1]; -- tUNK_2 = entry[2]; -- tRP = entry[3]; -- tRAS = entry[5]; -- tRFC = entry[7]; -- tRC = entry[9]; -- tUNK_10 = entry[10]; -- tUNK_11 = entry[11]; -- tUNK_12 = entry[12]; -- tUNK_13 = entry[13]; -- tUNK_14 = entry[14]; -- break; -- } -- -- timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP); -- -- /* XXX: I don't trust the -1's and +1's... they must come -- * from somewhere! */ -- timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | -- max(tUNK_18, (u8) 1) << 16 | -- (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; -- if (dev_priv->chipset == 0xa8) { -- timing->reg_100224 |= (tUNK_2 - 1); -- } else { -- timing->reg_100224 |= (tUNK_2 + 2 - magic_number); -- } -- -- timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); -- if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) -- timing->reg_100228 |= (tUNK_19 - 1) << 24; -- else -- timing->reg_100228 |= magic_number << 24; -- -- if (dev_priv->card_type == NV_40) { -- /* NV40: don't know what the rest of the regs are.. -- * And don't need to know either */ -- timing->reg_100228 |= 0x20200000; -- } else if (dev_priv->card_type >= NV_50) { -- if (dev_priv->chipset < 0x98 || -- (dev_priv->chipset == 0x98 && -- dev_priv->stepping <= 0xa1)) { -- timing->reg_10022c = (0x14 + tUNK_2) << 24 | -- 0x16 << 16 | -- (tUNK_2 - 1) << 8 | -- (tUNK_2 - 1); -- } else { -- /* XXX: reg_10022c for recentish cards */ -- timing->reg_10022c = tUNK_2 - 1; -- } -- -- timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | -- tUNK_13 << 8 | tUNK_13); -- -- timing->reg_100234 = (tRAS << 24 | tRC); -- timing->reg_100234 += max(tUNK_10, tUNK_11) << 16; -- -- if (dev_priv->chipset < 0x98 || -- (dev_priv->chipset == 0x98 && -- dev_priv->stepping <= 0xa1)) { -- timing->reg_100234 |= (tUNK_2 + 2) << 8; -- } else { -- /* XXX: +6? */ -- timing->reg_100234 |= (tUNK_19 + 6) << 8; -- } -- -- /* XXX; reg_100238 -- * reg_100238: 0x00?????? */ -- timing->reg_10023c = 0x202; -- if (dev_priv->chipset < 0x98 || -- (dev_priv->chipset == 0x98 && -- dev_priv->stepping <= 0xa1)) { -- timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; -- } else { -- /* XXX: reg_10023c -- * currently unknown -- * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ -- } -- -- /* XXX: reg_100240? */ -- } - timing->id = i; -+ timing->WR = entry[0]; -+ timing->CL = entry[2]; - -- NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, -- timing->reg_100220, timing->reg_100224, -- timing->reg_100228, timing->reg_10022c); -- NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", -- timing->reg_100230, timing->reg_100234, -- timing->reg_100238, timing->reg_10023c); -- NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240); -+ if(dev_priv->card_type <= NV_40) { -+ nv40_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); -+ } else if(dev_priv->card_type == NV_50){ -+ nv50_mem_timing_entry(dev,&P,hdr,(struct nouveau_pm_tbl_entry*) entry,magic_number,&pm->memtimings.timing[i]); -+ } else if(dev_priv->card_type == NV_C0) { -+ nvc0_mem_timing_entry(dev,hdr,(struct nouveau_pm_tbl_entry*) entry,&pm->memtimings.timing[i]); -+ } - } - -- memtimings->nr_timing = entries; -- memtimings->supported = (dev_priv->chipset <= 0x98); -+ memtimings->nr_timing = hdr->entry_cnt; -+ memtimings->supported = P.version == 1; - } - - void -@@ -725,41 +708,38 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings; - -- kfree(mem->timing); -+ if(mem->timing) { -+ kfree(mem->timing); -+ mem->timing = NULL; -+ } - } - - static int --nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) -+nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) - { -- struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); -- struct nouveau_mm *mm; -- u64 size, block, rsvd; -- int ret; -- -- rsvd = (256 * 1024); /* vga memory */ -- size = (p_size << PAGE_SHIFT) - rsvd; -- block = dev_priv->vram_rblock_size; -- -- ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12); -- if (ret) -- return ret; -- -- man->priv = mm; -+ /* nothing to do */ - return 0; - } - - static int - nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) - { -- struct nouveau_mm *mm = man->priv; -- int ret; -+ /* nothing to do */ -+ return 0; -+} - -- ret = nouveau_mm_fini(&mm); -- if (ret) -- return ret; -+static inline void -+nouveau_mem_node_cleanup(struct nouveau_mem *node) -+{ -+ if (node->vma[0].node) { -+ nouveau_vm_unmap(&node->vma[0]); -+ nouveau_vm_put(&node->vma[0]); -+ } - -- man->priv = NULL; -- return 0; -+ if (node->vma[1].node) { -+ nouveau_vm_unmap(&node->vma[1]); -+ nouveau_vm_put(&node->vma[1]); -+ } - } - - static void -@@ -768,14 +748,9 @@ - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); - struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -- struct nouveau_mem *node = mem->mm_node; - struct drm_device *dev = dev_priv->dev; - -- if (node->tmp_vma.node) { -- nouveau_vm_unmap(&node->tmp_vma); -- nouveau_vm_put(&node->tmp_vma); -- } -- -+ nouveau_mem_node_cleanup(mem->mm_node); - vram->put(dev, (struct nouveau_mem **)&mem->mm_node); - } - -@@ -794,7 +769,7 @@ - int ret; - - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) -- size_nc = 1 << nvbo->vma.node->type; -+ size_nc = 1 << nvbo->page_shift; - - ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, - mem->page_alignment << PAGE_SHIFT, size_nc, -@@ -804,9 +779,7 @@ - return (ret == -ENOSPC) ? 0 : ret; - } - -- node->page_shift = 12; -- if (nvbo->vma.node) -- node->page_shift = nvbo->vma.node->type; -+ node->page_shift = nvbo->page_shift; - - mem->mm_node = node; - mem->start = node->offset >> PAGE_SHIFT; -@@ -862,15 +835,9 @@ - nouveau_gart_manager_del(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *mem) - { -- struct nouveau_mem *node = mem->mm_node; -- -- if (node->tmp_vma.node) { -- nouveau_vm_unmap(&node->tmp_vma); -- nouveau_vm_put(&node->tmp_vma); -- } -- -+ nouveau_mem_node_cleanup(mem->mm_node); -+ kfree(mem->mm_node); - mem->mm_node = NULL; -- kfree(node); - } - - static int -@@ -880,11 +847,7 @@ - struct ttm_mem_reg *mem) - { - struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); -- struct nouveau_bo *nvbo = nouveau_bo(bo); -- struct nouveau_vma *vma = &nvbo->vma; -- struct nouveau_vm *vm = vma->vm; - struct nouveau_mem *node; -- int ret; - - if (unlikely((mem->num_pages << PAGE_SHIFT) >= - dev_priv->gart_info.aper_size)) -@@ -893,24 +856,8 @@ - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; -+ node->page_shift = 12; - -- /* This node must be for evicting large-paged VRAM -- * to system memory. Due to a nv50 limitation of -- * not being able to mix large/small pages within -- * the same PDE, we need to create a temporary -- * small-paged VMA for the eviction. -- */ -- if (vma->node->type != vm->spg_shift) { -- ret = nouveau_vm_get(vm, (u64)vma->node->length << 12, -- vm->spg_shift, NV_MEM_ACCESS_RW, -- &node->tmp_vma); -- if (ret) { -- kfree(node); -- return ret; -- } -- } -- -- node->page_shift = nvbo->vma.node->type; - mem->mm_node = node; - mem->start = 0; - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_mm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_mm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mm.c 2011-07-26 07:03:44.447051256 +0200 -@@ -27,7 +27,7 @@ - #include "nouveau_mm.h" - - static inline void --region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) -+region_put(struct nouveau_mm *mm, struct nouveau_mm_node *a) - { - list_del(&a->nl_entry); - list_del(&a->fl_entry); -@@ -35,7 +35,7 @@ - } - - static struct nouveau_mm_node * --region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) -+region_split(struct nouveau_mm *mm, struct nouveau_mm_node *a, u32 size) - { - struct nouveau_mm_node *b; - -@@ -57,33 +57,33 @@ - return b; - } - --#define node(root, dir) ((root)->nl_entry.dir == &rmm->nodes) ? NULL : \ -+#define node(root, dir) ((root)->nl_entry.dir == &mm->nodes) ? NULL : \ - list_entry((root)->nl_entry.dir, struct nouveau_mm_node, nl_entry) - - void --nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) -+nouveau_mm_put(struct nouveau_mm *mm, struct nouveau_mm_node *this) - { - struct nouveau_mm_node *prev = node(this, prev); - struct nouveau_mm_node *next = node(this, next); - -- list_add(&this->fl_entry, &rmm->free); -+ list_add(&this->fl_entry, &mm->free); - this->type = 0; - - if (prev && prev->type == 0) { - prev->length += this->length; -- region_put(rmm, this); -+ region_put(mm, this); - this = prev; - } - - if (next && next->type == 0) { - next->offset = this->offset; - next->length += this->length; -- region_put(rmm, this); -+ region_put(mm, this); - } - } - - int --nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, -+nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **pnode) - { - struct nouveau_mm_node *prev, *this, *next; -@@ -92,17 +92,17 @@ - u32 splitoff; - u32 s, e; - -- list_for_each_entry(this, &rmm->free, fl_entry) { -+ list_for_each_entry(this, &mm->free, fl_entry) { - e = this->offset + this->length; - s = this->offset; - - prev = node(this, prev); - if (prev && prev->type != type) -- s = roundup(s, rmm->block_size); -+ s = roundup(s, mm->block_size); - - next = node(this, next); - if (next && next->type != type) -- e = rounddown(e, rmm->block_size); -+ e = rounddown(e, mm->block_size); - - s = (s + align_mask) & ~align_mask; - e &= ~align_mask; -@@ -110,10 +110,10 @@ - continue; - - splitoff = s - this->offset; -- if (splitoff && !region_split(rmm, this, splitoff)) -+ if (splitoff && !region_split(mm, this, splitoff)) - return -ENOMEM; - -- this = region_split(rmm, this, min(size, e - s)); -+ this = region_split(mm, this, min(size, e - s)); - if (!this) - return -ENOMEM; - -@@ -127,45 +127,49 @@ - } - - int --nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) -+nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) - { -- struct nouveau_mm *rmm; -- struct nouveau_mm_node *heap; -+ struct nouveau_mm_node *node; - -- heap = kzalloc(sizeof(*heap), GFP_KERNEL); -- if (!heap) -- return -ENOMEM; -- heap->offset = roundup(offset, block); -- heap->length = rounddown(offset + length, block) - heap->offset; -+ if (block) { -+ mutex_init(&mm->mutex); -+ INIT_LIST_HEAD(&mm->nodes); -+ INIT_LIST_HEAD(&mm->free); -+ mm->block_size = block; -+ mm->heap_nodes = 0; -+ } - -- rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); -- if (!rmm) { -- kfree(heap); -+ node = kzalloc(sizeof(*node), GFP_KERNEL); -+ if (!node) - return -ENOMEM; -- } -- rmm->block_size = block; -- mutex_init(&rmm->mutex); -- INIT_LIST_HEAD(&rmm->nodes); -- INIT_LIST_HEAD(&rmm->free); -- list_add(&heap->nl_entry, &rmm->nodes); -- list_add(&heap->fl_entry, &rmm->free); -+ node->offset = roundup(offset, mm->block_size); -+ node->length = rounddown(offset + length, mm->block_size) - node->offset; - -- *prmm = rmm; -+ list_add_tail(&node->nl_entry, &mm->nodes); -+ list_add_tail(&node->fl_entry, &mm->free); -+ mm->heap_nodes++; - return 0; - } - - int --nouveau_mm_fini(struct nouveau_mm **prmm) -+nouveau_mm_fini(struct nouveau_mm *mm) - { -- struct nouveau_mm *rmm = *prmm; -- struct nouveau_mm_node *heap = -- list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); -- -- if (!list_is_singular(&rmm->nodes)) -- return -EBUSY; -+ struct nouveau_mm_node *node, *heap = -+ list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry); -+ int nodes = 0; -+ -+ list_for_each_entry(node, &mm->nodes, nl_entry) { -+ if (nodes++ == mm->heap_nodes) { -+ printk(KERN_ERR "nouveau_mm in use at destroy time!\n"); -+ list_for_each_entry(node, &mm->nodes, nl_entry) { -+ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n", -+ node->type, node->offset, node->length); -+ } -+ WARN_ON(1); -+ return -EBUSY; -+ } -+ } - - kfree(heap); -- kfree(rmm); -- *prmm = NULL; - return 0; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_mm.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mm.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_mm.h 2011-07-26 07:03:44.447051256 +0200 -@@ -42,16 +42,18 @@ - struct mutex mutex; - - u32 block_size; -+ int heap_nodes; - }; - --int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); --int nouveau_mm_fini(struct nouveau_mm **); -+int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); -+int nouveau_mm_fini(struct nouveau_mm *); - int nouveau_mm_pre(struct nouveau_mm *); - int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, - u32 align, struct nouveau_mm_node **); - void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); - - int nv50_vram_init(struct drm_device *); -+void nv50_vram_fini(struct drm_device *); - int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, - u32 memtype, struct nouveau_mem **); - void nv50_vram_del(struct drm_device *, struct nouveau_mem **); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_notifier.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_notifier.c 2011-07-26 07:03:44.448051268 +0200 -@@ -34,6 +34,7 @@ - nouveau_notifier_init_channel(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_bo *ntfy = NULL; - uint32_t flags, ttmpl; - int ret; -@@ -46,7 +47,7 @@ - ttmpl = TTM_PL_FLAG_TT; - } - -- ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy); -+ ret = nouveau_gem_new(dev, PAGE_SIZE, 0, flags, 0, 0, &ntfy); - if (ret) - return ret; - -@@ -58,14 +59,22 @@ - if (ret) - goto out_err; - -+ if (dev_priv->card_type >= NV_50) { -+ ret = nouveau_bo_vma_add(ntfy, chan->vm, &chan->notifier_vma); -+ if (ret) -+ goto out_err; -+ } -+ - ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size); - if (ret) - goto out_err; - - chan->notifier_bo = ntfy; - out_err: -- if (ret) -+ if (ret) { -+ nouveau_bo_vma_del(ntfy, &chan->notifier_vma); - drm_gem_object_unreference_unlocked(ntfy->gem); -+ } - - return ret; - } -@@ -78,6 +87,7 @@ - if (!chan->notifier_bo) - return; - -+ nouveau_bo_vma_del(chan->notifier_bo, &chan->notifier_vma); - nouveau_bo_unmap(chan->notifier_bo); - mutex_lock(&dev->struct_mutex); - nouveau_bo_unpin(chan->notifier_bo); -@@ -122,10 +132,10 @@ - target = NV_MEM_TARGET_VRAM; - else - target = NV_MEM_TARGET_GART; -- offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; -+ offset = chan->notifier_bo->bo.offset; - } else { - target = NV_MEM_TARGET_VM; -- offset = chan->notifier_bo->vma.offset; -+ offset = chan->notifier_vma.offset; - } - offset += mem->start; - -@@ -183,7 +193,7 @@ - if (unlikely(dev_priv->card_type >= NV_C0)) - return -EINVAL; - -- chan = nouveau_channel_get(dev, file_priv, na->channel); -+ chan = nouveau_channel_get(file_priv, na->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_object.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_object.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_object.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_object.c 2011-07-26 07:03:44.449051280 +0200 -@@ -125,7 +125,7 @@ - int ret = -EINVAL; - - spin_lock_irqsave(&dev_priv->channels.lock, flags); -- if (chid > 0 && chid < dev_priv->engine.fifo.channels) -+ if (chid >= 0 && chid < dev_priv->engine.fifo.channels) - chan = dev_priv->channels.ptr[chid]; - if (chan) - ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data); -@@ -191,7 +191,7 @@ - list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); - spin_unlock(&dev_priv->ramin_lock); - -- if (chan) { -+ if (!(flags & NVOBJ_FLAG_VM) && chan) { - ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); - if (ramin) - ramin = drm_mm_get_block(ramin, size, align); -@@ -208,7 +208,7 @@ - gpuobj->vinst = ramin->start + chan->ramin->vinst; - gpuobj->node = ramin; - } else { -- ret = instmem->get(gpuobj, size, align); -+ ret = instmem->get(gpuobj, chan, size, align); - if (ret) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; -@@ -690,36 +690,69 @@ - return 0; - } - --int --nouveau_gpuobj_channel_init(struct nouveau_channel *chan, -- uint32_t vram_h, uint32_t tt_h) -+static int -+nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) - { -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *vram = NULL, *tt = NULL; -+ struct nouveau_gpuobj *pgd = NULL; -+ struct nouveau_vm_pgd *vpgd; - int ret, i; - -- NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); -- -- if (dev_priv->card_type == NV_C0) { -- struct nouveau_vm *vm = dev_priv->chan_vm; -- struct nouveau_vm_pgd *vpgd; -+ ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, &chan->ramin); -+ if (ret) -+ return ret; - -- ret = nouveau_gpuobj_new(dev, NULL, 4096, 0x1000, 0, -- &chan->ramin); -+ /* create page directory for this vm if none currently exists, -+ * will be destroyed automagically when last reference to the -+ * vm is removed -+ */ -+ if (list_empty(&vm->pgd_list)) { -+ ret = nouveau_gpuobj_new(dev, NULL, 65536, 0x1000, 0, &pgd); - if (ret) - return ret; -+ } -+ nouveau_vm_ref(vm, &chan->vm, pgd); -+ nouveau_gpuobj_ref(NULL, &pgd); - -- nouveau_vm_ref(vm, &chan->vm, NULL); -+ /* point channel at vm's page directory */ -+ vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); -+ nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); -+ nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); -+ nv_wo32(chan->ramin, 0x0208, 0xffffffff); -+ nv_wo32(chan->ramin, 0x020c, 0x000000ff); - -- vpgd = list_first_entry(&vm->pgd_list, struct nouveau_vm_pgd, head); -- nv_wo32(chan->ramin, 0x0200, lower_32_bits(vpgd->obj->vinst)); -- nv_wo32(chan->ramin, 0x0204, upper_32_bits(vpgd->obj->vinst)); -- nv_wo32(chan->ramin, 0x0208, 0xffffffff); -- nv_wo32(chan->ramin, 0x020c, 0x000000ff); -+ /* map display semaphore buffers into channel's vm */ -+ if (dev_priv->card_type >= NV_D0) - return 0; -+ -+ for (i = 0; i < 2; i++) { -+ struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; -+ -+ ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm, -+ &chan->dispc_vma[i]); -+ if (ret) -+ return ret; - } - -+ return 0; -+} -+ -+int -+nouveau_gpuobj_channel_init(struct nouveau_channel *chan, -+ uint32_t vram_h, uint32_t tt_h) -+{ -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(chan->file_priv); -+ struct nouveau_vm *vm = fpriv ? fpriv->vm : dev_priv->chan_vm; -+ struct nouveau_gpuobj *vram = NULL, *tt = NULL; -+ int ret, i; -+ -+ NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); -+ if (dev_priv->card_type >= NV_C0) -+ return nvc0_gpuobj_channel_init(chan, vm); -+ - /* Allocate a chunk of memory for per-channel object storage */ - ret = nouveau_gpuobj_channel_init_pramin(chan); - if (ret) { -@@ -731,7 +764,7 @@ - * - Allocate per-channel page-directory - * - Link with shared channel VM - */ -- if (dev_priv->chan_vm) { -+ if (vm) { - u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; - u64 vm_vinst = chan->ramin->vinst + pgd_offs; - u32 vm_pinst = chan->ramin->pinst; -@@ -744,7 +777,7 @@ - if (ret) - return ret; - -- nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd); -+ nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); - } - - /* RAMHT */ -@@ -764,11 +797,11 @@ - return ret; - - /* dma objects for display sync channel semaphore blocks */ -- for (i = 0; i < 2; i++) { -+ for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_gpuobj *sem = NULL; - struct nv50_display_crtc *dispc = - &nv50_display(dev)->crtc[i]; -- u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; -+ u64 offset = dispc->sem.bo->bo.offset; - - ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff, - NV_MEM_ACCESS_RW, -@@ -841,10 +874,19 @@ - nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) - { - struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int i; - - NV_DEBUG(dev, "ch%d\n", chan->id); - -- nouveau_ramht_ref(NULL, &chan->ramht, chan); -+ if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { -+ struct nv50_display *disp = nv50_display(dev); -+ -+ for (i = 0; i < dev->mode_config.num_crtc; i++) { -+ struct nv50_display_crtc *dispc = &disp->crtc[i]; -+ nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); -+ } -+ } - - nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_pd); -@@ -909,7 +951,7 @@ - if (init->handle == ~0) - return -EINVAL; - -- chan = nouveau_channel_get(dev, file_priv, init->channel); -+ chan = nouveau_channel_get(file_priv, init->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - -@@ -936,7 +978,7 @@ - struct nouveau_channel *chan; - int ret; - -- chan = nouveau_channel_get(dev, file_priv, objfree->channel); -+ chan = nouveau_channel_get(file_priv, objfree->channel); - if (IS_ERR(chan)) - return PTR_ERR(chan); - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_perf.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_perf.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_perf.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_perf.c 2011-07-26 07:03:44.449051280 +0200 -@@ -127,13 +127,57 @@ - - entry += ramcfg * recordlen; - if (entry[1] >= pm->memtimings.nr_timing) { -- NV_WARN(dev, "timingset %d does not exist\n", entry[1]); -+ if (entry[1] != 0xff) -+ NV_WARN(dev, "timingset %d does not exist\n", entry[1]); - return NULL; - } - - return &pm->memtimings.timing[entry[1]]; - } - -+static void -+nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, -+ struct nouveau_pm_level *perflvl) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvbios *bios = &dev_priv->vbios; -+ u8 *vmap; -+ int id; -+ -+ id = perflvl->volt_min; -+ perflvl->volt_min = 0; -+ -+ /* boards using voltage table version <0x40 store the voltage -+ * level directly in the perflvl entry as a multiple of 10mV -+ */ -+ if (dev_priv->engine.pm.voltage.version < 0x40) { -+ perflvl->volt_min = id * 10000; -+ perflvl->volt_max = perflvl->volt_min; -+ return; -+ } -+ -+ /* on newer ones, the perflvl stores an index into yet another -+ * vbios table containing a min/max voltage value for the perflvl -+ */ -+ if (P->version != 2 || P->length < 34) { -+ NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", -+ P->version, P->length); -+ return; -+ } -+ -+ vmap = ROMPTR(bios, P->data[32]); -+ if (!vmap) { -+ NV_DEBUG(dev, "volt map table pointer invalid\n"); -+ return; -+ } -+ -+ if (id < vmap[3]) { -+ vmap += vmap[1] + (vmap[2] * id); -+ perflvl->volt_min = ROM32(vmap[0]); -+ perflvl->volt_max = ROM32(vmap[4]); -+ } -+} -+ - void - nouveau_perf_init(struct drm_device *dev) - { -@@ -141,6 +185,8 @@ - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nvbios *bios = &dev_priv->vbios; - struct bit_entry P; -+ struct nouveau_pm_memtimings *memtimings = &pm->memtimings; -+ struct nouveau_pm_tbl_header mt_hdr; - u8 version, headerlen, recordlen, entries; - u8 *perf, *entry; - int vid, i; -@@ -188,6 +234,22 @@ - } - - entry = perf + headerlen; -+ -+ /* For version 0x15, initialize memtiming table */ -+ if(version == 0x15) { -+ memtimings->timing = -+ kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); -+ if(!memtimings) { -+ NV_WARN(dev,"Could not allocate memtiming table\n"); -+ return; -+ } -+ -+ mt_hdr.entry_cnt = entries; -+ mt_hdr.entry_len = 14; -+ mt_hdr.version = version; -+ mt_hdr.header_len = 4; -+ } -+ - for (i = 0; i < entries; i++) { - struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; - -@@ -203,7 +265,8 @@ - case 0x13: - case 0x15: - perflvl->fanspeed = entry[55]; -- perflvl->voltage = (recordlen > 56) ? entry[56] : 0; -+ if (recordlen > 56) -+ perflvl->volt_min = entry[56]; - perflvl->core = ROM32(entry[1]) * 10; - perflvl->memory = ROM32(entry[5]) * 20; - break; -@@ -211,7 +274,7 @@ - case 0x23: - case 0x24: - perflvl->fanspeed = entry[4]; -- perflvl->voltage = entry[5]; -+ perflvl->volt_min = entry[5]; - perflvl->core = ROM16(entry[6]) * 1000; - - if (dev_priv->chipset == 0x49 || -@@ -223,7 +286,7 @@ - break; - case 0x25: - perflvl->fanspeed = entry[4]; -- perflvl->voltage = entry[5]; -+ perflvl->volt_min = entry[5]; - perflvl->core = ROM16(entry[6]) * 1000; - perflvl->shader = ROM16(entry[10]) * 1000; - perflvl->memory = ROM16(entry[12]) * 1000; -@@ -232,7 +295,7 @@ - perflvl->memscript = ROM16(entry[2]); - case 0x35: - perflvl->fanspeed = entry[6]; -- perflvl->voltage = entry[7]; -+ perflvl->volt_min = entry[7]; - perflvl->core = ROM16(entry[8]) * 1000; - perflvl->shader = ROM16(entry[10]) * 1000; - perflvl->memory = ROM16(entry[12]) * 1000; -@@ -240,30 +303,34 @@ - perflvl->unk05 = ROM16(entry[16]) * 1000; - break; - case 0x40: --#define subent(n) entry[perf[2] + ((n) * perf[3])] -+#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 - perflvl->fanspeed = 0; /*XXX*/ -- perflvl->voltage = entry[2]; -+ perflvl->volt_min = entry[2]; - if (dev_priv->card_type == NV_50) { -- perflvl->core = ROM16(subent(0)) & 0xfff; -- perflvl->shader = ROM16(subent(1)) & 0xfff; -- perflvl->memory = ROM16(subent(2)) & 0xfff; -+ perflvl->core = subent(0); -+ perflvl->shader = subent(1); -+ perflvl->memory = subent(2); -+ perflvl->vdec = subent(3); -+ perflvl->unka0 = subent(4); - } else { -- perflvl->shader = ROM16(subent(3)) & 0xfff; -+ perflvl->hub06 = subent(0); -+ perflvl->hub01 = subent(1); -+ perflvl->copy = subent(2); -+ perflvl->shader = subent(3); -+ perflvl->rop = subent(4); -+ perflvl->memory = subent(5); -+ perflvl->vdec = subent(6); -+ perflvl->daemon = subent(10); -+ perflvl->hub07 = subent(11); - perflvl->core = perflvl->shader / 2; -- perflvl->unk0a = ROM16(subent(4)) & 0xfff; -- perflvl->memory = ROM16(subent(5)) & 0xfff; - } -- -- perflvl->core *= 1000; -- perflvl->shader *= 1000; -- perflvl->memory *= 1000; -- perflvl->unk0a *= 1000; - break; - } - - /* make sure vid is valid */ -- if (pm->voltage.supported && perflvl->voltage) { -- vid = nouveau_volt_vid_lookup(dev, perflvl->voltage); -+ nouveau_perf_voltage(dev, &P, perflvl); -+ if (pm->voltage.supported && perflvl->volt_min) { -+ vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); - if (vid < 0) { - NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); - entry += recordlen; -@@ -272,7 +339,11 @@ - } - - /* get the corresponding memory timings */ -- if (version > 0x15) { -+ if (version == 0x15) { -+ memtimings->timing[i].id = i; -+ nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); -+ perflvl->timing = &memtimings->timing[i]; -+ } else if (version > 0x15) { - /* last 3 args are for < 0x40, ignored for >= 0x40 */ - perflvl->timing = - nouveau_perf_timing(dev, &P, -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_pm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_pm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_pm.c 2011-07-26 07:03:44.450051292 +0200 -@@ -64,18 +64,26 @@ - if (perflvl == pm->cur) - return 0; - -- if (pm->voltage.supported && pm->voltage_set && perflvl->voltage) { -- ret = pm->voltage_set(dev, perflvl->voltage); -+ if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { -+ ret = pm->voltage_set(dev, perflvl->volt_min); - if (ret) { - NV_ERROR(dev, "voltage_set %d failed: %d\n", -- perflvl->voltage, ret); -+ perflvl->volt_min, ret); - } - } - -- nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); -- nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); -- nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); -- nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); -+ if (pm->clocks_pre) { -+ void *state = pm->clocks_pre(dev, perflvl); -+ if (IS_ERR(state)) -+ return PTR_ERR(state); -+ pm->clocks_set(dev, state); -+ } else -+ if (pm->clock_set) { -+ nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); -+ nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); -+ nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); -+ nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); -+ } - - pm->cur = perflvl; - return 0; -@@ -92,9 +100,6 @@ - if (nouveau_perflvl_wr != 7777) - return -EPERM; - -- if (!pm->clock_set) -- return -EINVAL; -- - if (!strncmp(profile, "boot", 4)) - perflvl = &pm->boot; - else { -@@ -123,31 +128,37 @@ - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - int ret; - -- if (!pm->clock_get) -- return -EINVAL; -- - memset(perflvl, 0, sizeof(*perflvl)); - -- ret = pm->clock_get(dev, PLL_CORE); -- if (ret > 0) -- perflvl->core = ret; -- -- ret = pm->clock_get(dev, PLL_MEMORY); -- if (ret > 0) -- perflvl->memory = ret; -- -- ret = pm->clock_get(dev, PLL_SHADER); -- if (ret > 0) -- perflvl->shader = ret; -- -- ret = pm->clock_get(dev, PLL_UNK05); -- if (ret > 0) -- perflvl->unk05 = ret; -+ if (pm->clocks_get) { -+ ret = pm->clocks_get(dev, perflvl); -+ if (ret) -+ return ret; -+ } else -+ if (pm->clock_get) { -+ ret = pm->clock_get(dev, PLL_CORE); -+ if (ret > 0) -+ perflvl->core = ret; -+ -+ ret = pm->clock_get(dev, PLL_MEMORY); -+ if (ret > 0) -+ perflvl->memory = ret; -+ -+ ret = pm->clock_get(dev, PLL_SHADER); -+ if (ret > 0) -+ perflvl->shader = ret; -+ -+ ret = pm->clock_get(dev, PLL_UNK05); -+ if (ret > 0) -+ perflvl->unk05 = ret; -+ } - - if (pm->voltage.supported && pm->voltage_get) { - ret = pm->voltage_get(dev); -- if (ret > 0) -- perflvl->voltage = ret; -+ if (ret > 0) { -+ perflvl->volt_min = ret; -+ perflvl->volt_max = ret; -+ } - } - - return 0; -@@ -156,7 +167,7 @@ - static void - nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) - { -- char c[16], s[16], v[16], f[16], t[16]; -+ char c[16], s[16], v[32], f[16], t[16], m[16]; - - c[0] = '\0'; - if (perflvl->core) -@@ -166,9 +177,19 @@ - if (perflvl->shader) - snprintf(s, sizeof(s), " shader %dMHz", perflvl->shader / 1000); - -+ m[0] = '\0'; -+ if (perflvl->memory) -+ snprintf(m, sizeof(m), " memory %dMHz", perflvl->memory / 1000); -+ - v[0] = '\0'; -- if (perflvl->voltage) -- snprintf(v, sizeof(v), " voltage %dmV", perflvl->voltage * 10); -+ if (perflvl->volt_min && perflvl->volt_min != perflvl->volt_max) { -+ snprintf(v, sizeof(v), " voltage %dmV-%dmV", -+ perflvl->volt_min / 1000, perflvl->volt_max / 1000); -+ } else -+ if (perflvl->volt_min) { -+ snprintf(v, sizeof(v), " voltage %dmV", -+ perflvl->volt_min / 1000); -+ } - - f[0] = '\0'; - if (perflvl->fanspeed) -@@ -178,8 +199,7 @@ - if (perflvl->timing) - snprintf(t, sizeof(t), " timing %d", perflvl->timing->id); - -- snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000, -- c, s, v, f, t); -+ snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f); - } - - static ssize_t -@@ -190,7 +210,7 @@ - char *ptr = buf; - int len = PAGE_SIZE; - -- snprintf(ptr, len, "%d: ", perflvl->id); -+ snprintf(ptr, len, "%d:", perflvl->id); - ptr += strlen(buf); - len -= strlen(buf); - -@@ -211,9 +231,9 @@ - if (!pm->cur) - snprintf(ptr, len, "setting: boot\n"); - else if (pm->cur == &pm->boot) -- snprintf(ptr, len, "setting: boot\nc: "); -+ snprintf(ptr, len, "setting: boot\nc:"); - else -- snprintf(ptr, len, "setting: static %d\nc: ", pm->cur->id); -+ snprintf(ptr, len, "setting: static %d\nc:", pm->cur->id); - ptr += strlen(buf); - len -= strlen(buf); - -@@ -292,7 +312,7 @@ - } - } - --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - static ssize_t - nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) - { -@@ -409,7 +429,7 @@ - static int - nouveau_hwmon_init(struct drm_device *dev) - { --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct device *hwmon_dev; -@@ -442,7 +462,7 @@ - static void - nouveau_hwmon_fini(struct drm_device *dev) - { --#ifdef CONFIG_HWMON -+#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - -@@ -488,7 +508,7 @@ - NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); - for (i = 0; i < pm->nr_perflvl; i++) { - nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); -- NV_INFO(dev, "%d: %s", pm->perflvl[i].id, info); -+ NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); - } - - /* determine current ("boot") performance level */ -@@ -498,7 +518,7 @@ - pm->cur = &pm->boot; - - nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); -- NV_INFO(dev, "c: %s", info); -+ NV_INFO(dev, "c:%s", info); - } - - /* switch performance levels now if requested */ -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_pm.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_pm.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_pm.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_pm.h 2011-07-26 07:03:44.451051304 +0200 -@@ -59,10 +59,12 @@ - void nv50_pm_clock_set(struct drm_device *, void *); - - /* nva3_pm.c */ --int nva3_pm_clock_get(struct drm_device *, u32 id); --void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, -- u32 id, int khz); --void nva3_pm_clock_set(struct drm_device *, void *); -+int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -+void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -+void nva3_pm_clocks_set(struct drm_device *, void *); -+ -+/* nvc0_pm.c */ -+int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); - - /* nouveau_temp.c */ - void nouveau_temp_init(struct drm_device *dev); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_state.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_state.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_state.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_state.c 2011-07-26 07:03:44.453051328 +0200 -@@ -91,6 +91,7 @@ - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; - engine->vram.init = nouveau_mem_detect; -+ engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x10: -@@ -139,6 +140,7 @@ - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; - engine->vram.init = nouveau_mem_detect; -+ engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x20: -@@ -187,6 +189,7 @@ - engine->pm.clock_pre = nv04_pm_clock_pre; - engine->pm.clock_set = nv04_pm_clock_set; - engine->vram.init = nouveau_mem_detect; -+ engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x30: -@@ -237,6 +240,7 @@ - engine->pm.voltage_get = nouveau_voltage_gpio_get; - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->vram.init = nouveau_mem_detect; -+ engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x40: -@@ -289,12 +293,13 @@ - engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.temp_get = nv40_temp_get; - engine->vram.init = nouveau_mem_detect; -+ engine->vram.takedown = nouveau_stub_takedown; - engine->vram.flags_valid = nouveau_mem_flags_valid; - break; - case 0x50: - case 0x80: /* gotta love NVIDIA's consistency.. */ - case 0x90: -- case 0xA0: -+ case 0xa0: - engine->instmem.init = nv50_instmem_init; - engine->instmem.takedown = nv50_instmem_takedown; - engine->instmem.suspend = nv50_instmem_suspend; -@@ -354,9 +359,9 @@ - engine->pm.clock_set = nv50_pm_clock_set; - break; - default: -- engine->pm.clock_get = nva3_pm_clock_get; -- engine->pm.clock_pre = nva3_pm_clock_pre; -- engine->pm.clock_set = nva3_pm_clock_set; -+ engine->pm.clocks_get = nva3_pm_clocks_get; -+ engine->pm.clocks_pre = nva3_pm_clocks_pre; -+ engine->pm.clocks_set = nva3_pm_clocks_set; - break; - } - engine->pm.voltage_get = nouveau_voltage_gpio_get; -@@ -366,11 +371,12 @@ - else - engine->pm.temp_get = nv40_temp_get; - engine->vram.init = nv50_vram_init; -+ engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nv50_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nv50_vram_flags_valid; - break; -- case 0xC0: -+ case 0xc0: - engine->instmem.init = nvc0_instmem_init; - engine->instmem.takedown = nvc0_instmem_takedown; - engine->instmem.suspend = nvc0_instmem_suspend; -@@ -411,15 +417,78 @@ - engine->gpio.irq_unregister = nv50_gpio_irq_unregister; - engine->gpio.irq_enable = nv50_gpio_irq_enable; - engine->vram.init = nvc0_vram_init; -+ engine->vram.takedown = nv50_vram_fini; - engine->vram.get = nvc0_vram_new; - engine->vram.put = nv50_vram_del; - engine->vram.flags_valid = nvc0_vram_flags_valid; -+ engine->pm.temp_get = nv84_temp_get; -+ engine->pm.clocks_get = nvc0_pm_clocks_get; -+ engine->pm.voltage_get = nouveau_voltage_gpio_get; -+ engine->pm.voltage_set = nouveau_voltage_gpio_set; -+ break; -+ case 0xd0: -+ engine->instmem.init = nvc0_instmem_init; -+ engine->instmem.takedown = nvc0_instmem_takedown; -+ engine->instmem.suspend = nvc0_instmem_suspend; -+ engine->instmem.resume = nvc0_instmem_resume; -+ engine->instmem.get = nv50_instmem_get; -+ engine->instmem.put = nv50_instmem_put; -+ engine->instmem.map = nv50_instmem_map; -+ engine->instmem.unmap = nv50_instmem_unmap; -+ engine->instmem.flush = nv84_instmem_flush; -+ engine->mc.init = nv50_mc_init; -+ engine->mc.takedown = nv50_mc_takedown; -+ engine->timer.init = nv04_timer_init; -+ engine->timer.read = nv04_timer_read; -+ engine->timer.takedown = nv04_timer_takedown; -+ engine->fb.init = nvc0_fb_init; -+ engine->fb.takedown = nvc0_fb_takedown; -+ engine->fifo.channels = 128; -+ engine->fifo.init = nvc0_fifo_init; -+ engine->fifo.takedown = nvc0_fifo_takedown; -+ engine->fifo.disable = nvc0_fifo_disable; -+ engine->fifo.enable = nvc0_fifo_enable; -+ engine->fifo.reassign = nvc0_fifo_reassign; -+ engine->fifo.channel_id = nvc0_fifo_channel_id; -+ engine->fifo.create_context = nvc0_fifo_create_context; -+ engine->fifo.destroy_context = nvc0_fifo_destroy_context; -+ engine->fifo.load_context = nvc0_fifo_load_context; -+ engine->fifo.unload_context = nvc0_fifo_unload_context; -+ engine->display.early_init = nouveau_stub_init; -+ engine->display.late_takedown = nouveau_stub_takedown; -+ engine->display.create = nvd0_display_create; -+ engine->display.init = nvd0_display_init; -+ engine->display.destroy = nvd0_display_destroy; -+ engine->gpio.init = nv50_gpio_init; -+ engine->gpio.takedown = nouveau_stub_takedown; -+ engine->gpio.get = nvd0_gpio_get; -+ engine->gpio.set = nvd0_gpio_set; -+ engine->gpio.irq_register = nv50_gpio_irq_register; -+ engine->gpio.irq_unregister = nv50_gpio_irq_unregister; -+ engine->gpio.irq_enable = nv50_gpio_irq_enable; -+ engine->vram.init = nvc0_vram_init; -+ engine->vram.takedown = nv50_vram_fini; -+ engine->vram.get = nvc0_vram_new; -+ engine->vram.put = nv50_vram_del; -+ engine->vram.flags_valid = nvc0_vram_flags_valid; -+ engine->pm.clocks_get = nvc0_pm_clocks_get; -+ engine->pm.voltage_get = nouveau_voltage_gpio_get; -+ engine->pm.voltage_set = nouveau_voltage_gpio_set; - break; - default: - NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); - return 1; - } - -+ /* headless mode */ -+ if (nouveau_modeset == 2) { -+ engine->display.early_init = nouveau_stub_init; -+ engine->display.late_takedown = nouveau_stub_takedown; -+ engine->display.create = nouveau_stub_init; -+ engine->display.init = nouveau_stub_init; -+ engine->display.destroy = nouveau_stub_takedown; -+ } -+ - return 0; - } - -@@ -441,21 +510,6 @@ - return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; - } - --static int --nouveau_card_init_channel(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- int ret; -- -- ret = nouveau_channel_alloc(dev, &dev_priv->channel, -- (struct drm_file *)-2, NvDmaFB, NvDmaTT); -- if (ret) -- return ret; -- -- mutex_unlock(&dev_priv->channel->mutex); -- return 0; --} -- - static void nouveau_switcheroo_set_state(struct pci_dev *pdev, - enum vga_switcheroo_state state) - { -@@ -527,7 +581,7 @@ - - nouveau_pm_init(dev); - -- ret = nouveau_mem_vram_init(dev); -+ ret = engine->vram.init(dev); - if (ret) - goto out_bios; - -@@ -539,10 +593,14 @@ - if (ret) - goto out_gpuobj; - -- ret = nouveau_mem_gart_init(dev); -+ ret = nouveau_mem_vram_init(dev); - if (ret) - goto out_instmem; - -+ ret = nouveau_mem_gart_init(dev); -+ if (ret) -+ goto out_ttmvram; -+ - /* PMC */ - ret = engine->mc.init(dev); - if (ret) -@@ -563,7 +621,7 @@ - if (ret) - goto out_timer; - -- if (!nouveau_noaccel) { -+ if (!dev_priv->noaccel) { - switch (dev_priv->card_type) { - case NV_04: - nv04_graph_create(dev); -@@ -618,8 +676,11 @@ - break; - } - -- if (dev_priv->card_type == NV_40) -- nv40_mpeg_create(dev); -+ if (dev_priv->card_type == NV_40 || -+ dev_priv->chipset == 0x31 || -+ dev_priv->chipset == 0x34 || -+ dev_priv->chipset == 0x36) -+ nv31_mpeg_create(dev); - else - if (dev_priv->card_type == NV_50 && - (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) -@@ -639,50 +700,75 @@ - goto out_engine; - } - -- ret = engine->display.create(dev); -+ ret = nouveau_irq_init(dev); - if (ret) - goto out_fifo; - -- ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); -- if (ret) -- goto out_vblank; -+ /* initialise general modesetting */ -+ drm_mode_config_init(dev); -+ drm_mode_create_scaling_mode_property(dev); -+ drm_mode_create_dithering_property(dev); -+ dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -+ dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); -+ dev->mode_config.min_width = 0; -+ dev->mode_config.min_height = 0; -+ if (dev_priv->card_type < NV_10) { -+ dev->mode_config.max_width = 2048; -+ dev->mode_config.max_height = 2048; -+ } else -+ if (dev_priv->card_type < NV_50) { -+ dev->mode_config.max_width = 4096; -+ dev->mode_config.max_height = 4096; -+ } else { -+ dev->mode_config.max_width = 8192; -+ dev->mode_config.max_height = 8192; -+ } - -- ret = nouveau_irq_init(dev); -+ ret = engine->display.create(dev); - if (ret) -- goto out_vblank; -- -- /* what about PVIDEO/PCRTC/PRAMDAC etc? */ -+ goto out_irq; - - if (dev_priv->eng[NVOBJ_ENGINE_GR]) { - ret = nouveau_fence_init(dev); - if (ret) -- goto out_irq; -+ goto out_disp; - -- ret = nouveau_card_init_channel(dev); -+ ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, -+ NvDmaFB, NvDmaTT); - if (ret) - goto out_fence; -+ -+ mutex_unlock(&dev_priv->channel->mutex); -+ } -+ -+ if (dev->mode_config.num_crtc) { -+ ret = drm_vblank_init(dev, dev->mode_config.num_crtc); -+ if (ret) -+ goto out_chan; -+ -+ nouveau_fbcon_init(dev); -+ drm_kms_helper_poll_init(dev); - } - -- nouveau_fbcon_init(dev); -- drm_kms_helper_poll_init(dev); - return 0; - -+out_chan: -+ nouveau_channel_put_unlocked(&dev_priv->channel); - out_fence: - nouveau_fence_fini(dev); -+out_disp: -+ engine->display.destroy(dev); - out_irq: - nouveau_irq_fini(dev); --out_vblank: -- drm_vblank_cleanup(dev); -- engine->display.destroy(dev); - out_fifo: -- if (!nouveau_noaccel) -+ if (!dev_priv->noaccel) - engine->fifo.takedown(dev); - out_engine: -- if (!nouveau_noaccel) { -+ if (!dev_priv->noaccel) { - for (e = e - 1; e >= 0; e--) { - if (!dev_priv->eng[e]) - continue; -- dev_priv->eng[e]->fini(dev, e); -+ dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } -@@ -696,12 +782,14 @@ - engine->mc.takedown(dev); - out_gart: - nouveau_mem_gart_fini(dev); -+out_ttmvram: -+ nouveau_mem_vram_fini(dev); - out_instmem: - engine->instmem.takedown(dev); - out_gpuobj: - nouveau_gpuobj_takedown(dev); - out_vram: -- nouveau_mem_vram_fini(dev); -+ engine->vram.takedown(dev); - out_bios: - nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); -@@ -718,16 +806,25 @@ - struct nouveau_engine *engine = &dev_priv->engine; - int e; - -+ if (dev->mode_config.num_crtc) { -+ drm_kms_helper_poll_fini(dev); -+ nouveau_fbcon_fini(dev); -+ drm_vblank_cleanup(dev); -+ } -+ - if (dev_priv->channel) { -- nouveau_fence_fini(dev); - nouveau_channel_put_unlocked(&dev_priv->channel); -+ nouveau_fence_fini(dev); - } - -- if (!nouveau_noaccel) { -+ engine->display.destroy(dev); -+ drm_mode_config_cleanup(dev); -+ -+ if (!dev_priv->noaccel) { - engine->fifo.takedown(dev); - for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { - if (dev_priv->eng[e]) { -- dev_priv->eng[e]->fini(dev, e); -+ dev_priv->eng[e]->fini(dev, e, false); - dev_priv->eng[e]->destroy(dev,e ); - } - } -@@ -748,13 +845,13 @@ - ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); - mutex_unlock(&dev->struct_mutex); - nouveau_mem_gart_fini(dev); -+ nouveau_mem_vram_fini(dev); - - engine->instmem.takedown(dev); - nouveau_gpuobj_takedown(dev); -- nouveau_mem_vram_fini(dev); -+ engine->vram.takedown(dev); - - nouveau_irq_fini(dev); -- drm_vblank_cleanup(dev); - - nouveau_pm_fini(dev); - nouveau_bios_takedown(dev); -@@ -762,6 +859,41 @@ - vga_client_register(dev->pdev, NULL, NULL, NULL); - } - -+int -+nouveau_open(struct drm_device *dev, struct drm_file *file_priv) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fpriv *fpriv; -+ int ret; -+ -+ fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); -+ if (unlikely(!fpriv)) -+ return -ENOMEM; -+ -+ spin_lock_init(&fpriv->lock); -+ INIT_LIST_HEAD(&fpriv->channels); -+ -+ if (dev_priv->card_type == NV_50) { -+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, -+ &fpriv->vm); -+ if (ret) { -+ kfree(fpriv); -+ return ret; -+ } -+ } else -+ if (dev_priv->card_type >= NV_C0) { -+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, -+ &fpriv->vm); -+ if (ret) { -+ kfree(fpriv); -+ return ret; -+ } -+ } -+ -+ file_priv->driver_priv = fpriv; -+ return 0; -+} -+ - /* here a client dies, release the stuff that was allocated for its - * file_priv */ - void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) -@@ -769,6 +901,14 @@ - nouveau_channel_cleanup(dev, file_priv); - } - -+void -+nouveau_postclose(struct drm_device *dev, struct drm_file *file_priv) -+{ -+ struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv); -+ nouveau_vm_ref(NULL, &fpriv->vm, NULL); -+ kfree(fpriv); -+} -+ - /* first module load, setup the mmio/fb mapping */ - /* KMS: we need mmio at load time, not when the first drm client opens. */ - int nouveau_firstopen(struct drm_device *dev) -@@ -844,7 +984,7 @@ - int nouveau_load(struct drm_device *dev, unsigned long flags) - { - struct drm_nouveau_private *dev_priv; -- uint32_t reg0; -+ uint32_t reg0, strap; - resource_size_t mmio_start_offs; - int ret; - -@@ -888,13 +1028,11 @@ - - /* Time to determine the card architecture */ - reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); -- dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */ - - /* We're dealing with >=NV10 */ - if ((reg0 & 0x0f000000) > 0) { - /* Bit 27-20 contain the architecture in hex */ - dev_priv->chipset = (reg0 & 0xff00000) >> 20; -- dev_priv->stepping = (reg0 & 0xff); - /* NV04 or NV05 */ - } else if ((reg0 & 0xff00fff0) == 0x20004000) { - if (reg0 & 0x00f00000) -@@ -924,6 +1062,9 @@ - case 0xc0: - dev_priv->card_type = NV_C0; - break; -+ case 0xd0: -+ dev_priv->card_type = NV_D0; -+ break; - default: - NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); - ret = -EINVAL; -@@ -933,6 +1074,42 @@ - NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", - dev_priv->card_type, reg0); - -+ /* determine frequency of timing crystal */ -+ strap = nv_rd32(dev, 0x101000); -+ if ( dev_priv->chipset < 0x17 || -+ (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) -+ strap &= 0x00000040; -+ else -+ strap &= 0x00400040; -+ -+ switch (strap) { -+ case 0x00000000: dev_priv->crystal = 13500; break; -+ case 0x00000040: dev_priv->crystal = 14318; break; -+ case 0x00400000: dev_priv->crystal = 27000; break; -+ case 0x00400040: dev_priv->crystal = 25000; break; -+ } -+ -+ NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); -+ -+ /* Determine whether we'll attempt acceleration or not, some -+ * cards are disabled by default here due to them being known -+ * non-functional, or never been tested due to lack of hw. -+ */ -+ dev_priv->noaccel = !!nouveau_noaccel; -+ if (nouveau_noaccel == -1) { -+ switch (dev_priv->chipset) { -+ case 0xc1: /* known broken */ -+ case 0xc8: /* never tested */ -+ NV_INFO(dev, "acceleration disabled by default, pass " -+ "noaccel=0 to force enable\n"); -+ dev_priv->noaccel = true; -+ break; -+ default: -+ dev_priv->noaccel = false; -+ break; -+ } -+ } -+ - ret = nouveau_remove_conflicting_drivers(dev); - if (ret) - goto err_mmio; -@@ -997,11 +1174,7 @@ - int nouveau_unload(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_engine *engine = &dev_priv->engine; - -- drm_kms_helper_poll_fini(dev); -- nouveau_fbcon_fini(dev); -- engine->display.destroy(dev); - nouveau_card_takedown(dev); - - iounmap(dev_priv->mmio); -@@ -1052,7 +1225,7 @@ - getparam->value = 1; - break; - case NOUVEAU_GETPARAM_HAS_PAGEFLIP: -- getparam->value = 1; -+ getparam->value = dev_priv->card_type < NV_D0; - break; - case NOUVEAU_GETPARAM_GRAPH_UNITS: - /* NV40 and NV50 versions are quite different, but register -@@ -1120,6 +1293,23 @@ - return false; - } - -+/* Wait until cond(data) == true, up until timeout has hit */ -+bool -+nouveau_wait_cb(struct drm_device *dev, u64 timeout, -+ bool (*cond)(void *), void *data) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; -+ u64 start = ptimer->read(dev); -+ -+ do { -+ if (cond(data) == true) -+ return true; -+ } while (ptimer->read(dev) - start < timeout); -+ -+ return false; -+} -+ - /* Waits for PGRAPH to go completely idle */ - bool nouveau_wait_for_idle(struct drm_device *dev) - { -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_temp.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_temp.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_temp.c 2011-07-26 07:03:44.454051340 +0200 -@@ -43,7 +43,7 @@ - - /* Set the default sensor's contants */ - sensor->offset_constant = 0; -- sensor->offset_mult = 1; -+ sensor->offset_mult = 0; - sensor->offset_div = 1; - sensor->slope_mult = 1; - sensor->slope_div = 1; -@@ -99,6 +99,13 @@ - sensor->slope_mult = 431; - sensor->slope_div = 10000; - break; -+ -+ case 0x67: -+ sensor->offset_mult = -26149; -+ sensor->offset_div = 100; -+ sensor->slope_mult = 484; -+ sensor->slope_div = 10000; -+ break; - } - } - -@@ -109,7 +116,7 @@ - - /* Read the entries from the table */ - for (i = 0; i < entries; i++) { -- u16 value = ROM16(temp[1]); -+ s16 value = ROM16(temp[1]); - - switch (temp[0]) { - case 0x01: -@@ -160,8 +167,8 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; -- u32 offset = sensor->offset_mult / sensor->offset_div; -- u32 sensor_calibration; -+ s32 offset = sensor->offset_mult / sensor->offset_div; -+ s32 sensor_calibration; - - /* set up the sensors */ - sensor_calibration = 120 - offset - sensor->offset_constant; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_vm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_vm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_vm.c 2011-07-26 07:03:44.454051340 +0200 -@@ -172,9 +172,9 @@ - vm->map_pgt(vpgd->obj, pde, vpgt->obj); - } - -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - nouveau_gpuobj_ref(NULL, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - } - } - -@@ -191,18 +191,18 @@ - pgt_size = (1 << (vm->pgt_bits + 12)) >> type; - pgt_size *= 8; - -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - if (unlikely(ret)) - return ret; - - /* someone beat us to filling the PDE while we didn't have the lock */ - if (unlikely(vpgt->refcount[big]++)) { -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - nouveau_gpuobj_ref(NULL, &pgt); -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - return 0; - } - -@@ -223,10 +223,10 @@ - u32 fpde, lpde, pde; - int ret; - -- mutex_lock(&vm->mm->mutex); -- ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); -+ mutex_lock(&vm->mm.mutex); -+ ret = nouveau_mm_get(&vm->mm, page_shift, msize, 0, align, &vma->node); - if (unlikely(ret != 0)) { -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - return ret; - } - -@@ -245,13 +245,13 @@ - if (ret) { - if (pde != fpde) - nouveau_vm_unmap_pgt(vm, big, fpde, pde - 1); -- nouveau_mm_put(vm->mm, vma->node); -- mutex_unlock(&vm->mm->mutex); -+ nouveau_mm_put(&vm->mm, vma->node); -+ mutex_unlock(&vm->mm.mutex); - vma->node = NULL; - return ret; - } - } -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - - vma->vm = vm; - vma->offset = (u64)vma->node->offset << 12; -@@ -270,11 +270,11 @@ - fpde = (vma->node->offset >> vm->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - nouveau_vm_unmap_pgt(vm, vma->node->type != vm->spg_shift, fpde, lpde); -- nouveau_mm_put(vm->mm, vma->node); -+ nouveau_mm_put(&vm->mm, vma->node); - vma->node = NULL; -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - } - - int -@@ -306,7 +306,7 @@ - block = length; - - } else -- if (dev_priv->card_type == NV_C0) { -+ if (dev_priv->card_type >= NV_C0) { - vm->map_pgt = nvc0_vm_map_pgt; - vm->map = nvc0_vm_map; - vm->map_sg = nvc0_vm_map_sg; -@@ -360,32 +360,35 @@ - - nouveau_gpuobj_ref(pgd, &vpgd->obj); - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - for (i = vm->fpde; i <= vm->lpde; i++) - vm->map_pgt(pgd, i, vm->pgt[i - vm->fpde].obj); - list_add(&vpgd->head, &vm->pgd_list); -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); - return 0; - } - - static void --nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) -+nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd) - { - struct nouveau_vm_pgd *vpgd, *tmp; -+ struct nouveau_gpuobj *pgd = NULL; - -- if (!pgd) -+ if (!mpgd) - return; - -- mutex_lock(&vm->mm->mutex); -+ mutex_lock(&vm->mm.mutex); - list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { -- if (vpgd->obj != pgd) -- continue; -- -- list_del(&vpgd->head); -- nouveau_gpuobj_ref(NULL, &vpgd->obj); -- kfree(vpgd); -+ if (vpgd->obj == mpgd) { -+ pgd = vpgd->obj; -+ list_del(&vpgd->head); -+ kfree(vpgd); -+ break; -+ } - } -- mutex_unlock(&vm->mm->mutex); -+ mutex_unlock(&vm->mm.mutex); -+ -+ nouveau_gpuobj_ref(NULL, &pgd); - } - - static void -@@ -396,8 +399,8 @@ - list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { - nouveau_vm_unlink(vm, vpgd->obj); - } -- WARN_ON(nouveau_mm_fini(&vm->mm) != 0); - -+ nouveau_mm_fini(&vm->mm); - kfree(vm->pgt); - kfree(vm); - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_vm.h linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_vm.h ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_vm.h 2011-07-26 07:03:44.455051352 +0200 -@@ -41,6 +41,8 @@ - }; - - struct nouveau_vma { -+ struct list_head head; -+ int refcount; - struct nouveau_vm *vm; - struct nouveau_mm_node *node; - u64 offset; -@@ -49,7 +51,7 @@ - - struct nouveau_vm { - struct drm_device *dev; -- struct nouveau_mm *mm; -+ struct nouveau_mm mm; - int refcount; - - struct list_head pgd_list; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nouveau_volt.c linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_volt.c ---- linux-3.0/drivers/gpu/drm/nouveau/nouveau_volt.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nouveau_volt.c 2011-07-26 07:03:44.456051364 +0200 -@@ -27,7 +27,7 @@ - #include "nouveau_drv.h" - #include "nouveau_pm.h" - --static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a }; -+static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; - static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); - - int -@@ -170,6 +170,13 @@ - */ - vidshift = 2; - break; -+ case 0x40: -+ headerlen = volt[1]; -+ recordlen = volt[2]; -+ entries = volt[3]; /* not a clue what the entries are for.. */ -+ vidmask = volt[11]; /* guess.. */ -+ vidshift = 0; -+ break; - default: - NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); - return; -@@ -197,16 +204,37 @@ - } - - /* parse vbios entries into common format */ -- voltage->level = kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -- if (!voltage->level) -- return; -+ voltage->version = volt[0]; -+ if (voltage->version < 0x40) { -+ voltage->nr_level = entries; -+ voltage->level = -+ kcalloc(entries, sizeof(*voltage->level), GFP_KERNEL); -+ if (!voltage->level) -+ return; - -- entry = volt + headerlen; -- for (i = 0; i < entries; i++, entry += recordlen) { -- voltage->level[i].voltage = entry[0]; -- voltage->level[i].vid = entry[1] >> vidshift; -+ entry = volt + headerlen; -+ for (i = 0; i < entries; i++, entry += recordlen) { -+ voltage->level[i].voltage = entry[0] * 10000; -+ voltage->level[i].vid = entry[1] >> vidshift; -+ } -+ } else { -+ u32 volt_uv = ROM32(volt[4]); -+ s16 step_uv = ROM16(volt[8]); -+ u8 vid; -+ -+ voltage->nr_level = voltage->vid_mask + 1; -+ voltage->level = kcalloc(voltage->nr_level, -+ sizeof(*voltage->level), GFP_KERNEL); -+ if (!voltage->level) -+ return; -+ -+ for (vid = 0; vid <= voltage->vid_mask; vid++) { -+ voltage->level[vid].voltage = volt_uv; -+ voltage->level[vid].vid = vid; -+ volt_uv += step_uv; -+ } - } -- voltage->nr_level = entries; -+ - voltage->supported = true; - } - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_crtc.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_crtc.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_crtc.c 2011-07-26 07:03:44.457051376 +0200 -@@ -1035,7 +1035,7 @@ - drm_crtc_helper_add(&nv_crtc->base, &nv04_crtc_helper_funcs); - drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); - -- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, &nv_crtc->cursor.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_display.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_display.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_display.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_display.c 2011-07-26 07:03:44.457051376 +0200 -@@ -126,27 +126,6 @@ - - nouveau_hw_save_vga_fonts(dev, 1); - -- drm_mode_config_init(dev); -- drm_mode_create_scaling_mode_property(dev); -- drm_mode_create_dithering_property(dev); -- -- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -- -- dev->mode_config.min_width = 0; -- dev->mode_config.min_height = 0; -- switch (dev_priv->card_type) { -- case NV_04: -- dev->mode_config.max_width = 2048; -- dev->mode_config.max_height = 2048; -- break; -- default: -- dev->mode_config.max_width = 4096; -- dev->mode_config.max_height = 4096; -- break; -- } -- -- dev->mode_config.fb_base = dev_priv->fb_phys; -- - nv04_crtc_create(dev, 0); - if (nv_two_heads(dev)) - nv04_crtc_create(dev, 1); -@@ -235,8 +214,6 @@ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - crtc->funcs->restore(crtc); - -- drm_mode_config_cleanup(dev); -- - nouveau_hw_save_vga_fonts(dev, 0); - } - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_graph.c 2011-07-26 07:03:44.458051388 +0200 -@@ -450,13 +450,13 @@ - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv04_graph_channel(dev) == chan) - nv04_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -538,24 +538,18 @@ - } - - static int --nv04_graph_fini(struct drm_device *dev, int engine) -+nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv04_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; - } - --void --nv04_graph_fifo_access(struct drm_device *dev, bool enabled) --{ -- if (enabled) -- nv_wr32(dev, NV04_PGRAPH_FIFO, -- nv_rd32(dev, NV04_PGRAPH_FIFO) | 1); -- else -- nv_wr32(dev, NV04_PGRAPH_FIFO, -- nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1); --} -- - static int - nv04_graph_mthd_set_ref(struct nouveau_channel *chan, - u32 class, u32 mthd, u32 data) -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_instmem.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_instmem.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_instmem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_instmem.c 2011-07-26 07:03:44.459051400 +0200 -@@ -28,6 +28,31 @@ - /* RAMIN always available */ - dev_priv->ramin_available = true; - -+ /* Reserve space at end of VRAM for PRAMIN */ -+ if (dev_priv->card_type >= NV_40) { -+ u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); -+ u32 rsvd; -+ -+ /* estimate grctx size, the magics come from nv40_grctx.c */ -+ if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; -+ else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; -+ else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; -+ else rsvd = 0x4a40 * vs; -+ rsvd += 16 * 1024; -+ rsvd *= dev_priv->engine.fifo.channels; -+ -+ /* pciegart table */ -+ if (drm_pci_device_is_pcie(dev)) -+ rsvd += 512 * 1024; -+ -+ /* object storage */ -+ rsvd += 512 * 1024; -+ -+ dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); -+ } else { -+ dev_priv->ramin_rsvd_vram = 512 * 1024; -+ } -+ - /* Setup shared RAMHT */ - ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, - NVOBJ_FLAG_ZERO_ALLOC, &ramht); -@@ -112,7 +137,8 @@ - } - - int --nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) -+nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, -+ u32 size, u32 align) - { - struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; - struct drm_mm_node *ramin = NULL; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_pm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_pm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_pm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_pm.c 2011-07-26 07:03:44.459051400 +0200 -@@ -68,6 +68,7 @@ - nv04_pm_clock_set(struct drm_device *dev, void *pre_state) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nv04_pm_state *state = pre_state; - u32 reg = state->pll.reg; - -@@ -85,6 +86,9 @@ - nv_mask(dev, 0x1002c0, 0, 1 << 8); - } - -+ if (reg == NV_PRAMDAC_NVPLL_COEFF) -+ ptimer->init(dev); -+ - kfree(state); - } - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv04_timer.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_timer.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv04_timer.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv04_timer.c 2011-07-26 07:03:44.460051412 +0200 -@@ -6,43 +6,75 @@ - int - nv04_timer_init(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 m, n, d; -+ - nv_wr32(dev, NV04_PTIMER_INTR_EN_0, 0x00000000); - nv_wr32(dev, NV04_PTIMER_INTR_0, 0xFFFFFFFF); - -- /* Just use the pre-existing values when possible for now; these regs -- * are not written in nv (driver writer missed a /4 on the address), and -- * writing 8 and 3 to the correct regs breaks the timings on the LVDS -- * hardware sequencing microcode. -- * A correct solution (involving calculations with the GPU PLL) can -- * be done when kernel modesetting lands -- */ -- if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || -- !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { -- nv_wr32(dev, NV04_PTIMER_NUMERATOR, 0x00000008); -- nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 0x00000003); -+ /* aim for 31.25MHz, which gives us nanosecond timestamps */ -+ d = 1000000 / 32; -+ -+ /* determine base clock for timer source */ -+ if (dev_priv->chipset < 0x40) { -+ n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); -+ } else -+ if (dev_priv->chipset == 0x40) { -+ /*XXX: figure this out */ -+ n = 0; -+ } else { -+ n = dev_priv->crystal; -+ m = 1; -+ while (n < (d * 2)) { -+ n += (n / m); -+ m++; -+ } -+ -+ nv_wr32(dev, 0x009220, m - 1); -+ } -+ -+ if (!n) { -+ NV_WARN(dev, "PTIMER: unknown input clock freq\n"); -+ if (!nv_rd32(dev, NV04_PTIMER_NUMERATOR) || -+ !nv_rd32(dev, NV04_PTIMER_DENOMINATOR)) { -+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, 1); -+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, 1); -+ } -+ return 0; -+ } -+ -+ /* reduce ratio to acceptable values */ -+ while (((n % 5) == 0) && ((d % 5) == 0)) { -+ n /= 5; -+ d /= 5; - } - -+ while (((n % 2) == 0) && ((d % 2) == 0)) { -+ n /= 2; -+ d /= 2; -+ } -+ -+ while (n > 0xffff || d > 0xffff) { -+ n >>= 1; -+ d >>= 1; -+ } -+ -+ nv_wr32(dev, NV04_PTIMER_NUMERATOR, n); -+ nv_wr32(dev, NV04_PTIMER_DENOMINATOR, d); - return 0; - } - --uint64_t -+u64 - nv04_timer_read(struct drm_device *dev) - { -- uint32_t low; -- /* From kmmio dumps on nv28 this looks like how the blob does this. -- * It reads the high dword twice, before and after. -- * The only explanation seems to be that the 64-bit timer counter -- * advances between high and low dword reads and may corrupt the -- * result. Not confirmed. -- */ -- uint32_t high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); -- uint32_t high1; -+ u32 hi, lo; -+ - do { -- high1 = high2; -- low = nv_rd32(dev, NV04_PTIMER_TIME_0); -- high2 = nv_rd32(dev, NV04_PTIMER_TIME_1); -- } while (high1 != high2); -- return (((uint64_t)high2) << 32) | (uint64_t)low; -+ hi = nv_rd32(dev, NV04_PTIMER_TIME_1); -+ lo = nv_rd32(dev, NV04_PTIMER_TIME_0); -+ } while (hi != nv_rd32(dev, NV04_PTIMER_TIME_1)); -+ -+ return ((u64)hi << 32 | lo); - } - - void -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv10_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv10_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv10_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv10_graph.c 2011-07-26 07:03:44.461051424 +0200 -@@ -708,8 +708,8 @@ - 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); - nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); - nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); -- nv04_graph_fifo_access(dev, true); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Restore the FIFO state */ - for (i = 0; i < ARRAY_SIZE(fifo); i++) -@@ -879,13 +879,13 @@ - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv10_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -957,8 +957,13 @@ - } - - static int --nv10_graph_fini(struct drm_device *dev, int engine) -+nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv10_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv20_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv20_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv20_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv20_graph.c 2011-07-26 07:03:44.461051424 +0200 -@@ -454,13 +454,13 @@ - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); - - /* Unload the context if it's the currently active one */ - if (nv10_graph_channel(dev) == chan) - nv20_graph_unload_context(dev); - -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -654,8 +654,13 @@ - } - - int --nv20_graph_fini(struct drm_device *dev, int engine) -+nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { -+ nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); -+ return -EBUSY; -+ } - nv20_graph_unload_context(dev); - nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); - return 0; -@@ -753,6 +758,7 @@ - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); -+ kfree(pgraph); - return 0; - } - } else { -@@ -774,6 +780,7 @@ - break; - default: - NV_ERROR(dev, "PGRAPH: unknown chipset\n"); -+ kfree(pgraph); - return 0; - } - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv31_mpeg.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv31_mpeg.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv31_mpeg.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv31_mpeg.c 2011-07-26 07:03:44.462051436 +0200 -@@ -0,0 +1,344 @@ -+/* -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_ramht.h" -+ -+struct nv31_mpeg_engine { -+ struct nouveau_exec_engine base; -+ atomic_t refcount; -+}; -+ -+ -+static int -+nv31_mpeg_context_new(struct nouveau_channel *chan, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); -+ -+ if (!atomic_add_unless(&pmpeg->refcount, 1, 1)) -+ return -EBUSY; -+ -+ chan->engctx[engine] = (void *)0xdeadcafe; -+ return 0; -+} -+ -+static void -+nv31_mpeg_context_del(struct nouveau_channel *chan, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(chan->dev, engine); -+ atomic_dec(&pmpeg->refcount); -+ chan->engctx[engine] = NULL; -+} -+ -+static int -+nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) -+{ -+ struct drm_device *dev = chan->dev; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ctx = NULL; -+ unsigned long flags; -+ int ret; -+ -+ NV_DEBUG(dev, "ch%d\n", chan->id); -+ -+ ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &ctx); -+ if (ret) -+ return ret; -+ -+ nv_wo32(ctx, 0x78, 0x02001ec1); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -+ if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) -+ nv_wr32(dev, 0x00330c, ctx->pinst >> 4); -+ nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); -+ nv_mask(dev, 0x002500, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ chan->engctx[engine] = ctx; -+ return 0; -+} -+ -+static void -+nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) -+{ -+ struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -+ struct nouveau_gpuobj *ctx = chan->engctx[engine]; -+ struct drm_device *dev = chan->dev; -+ unsigned long flags; -+ u32 inst = 0x80000000 | (ctx->pinst >> 4); -+ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -+ if (nv_rd32(dev, 0x00b318) == inst) -+ nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ -+ nouveau_gpuobj_ref(NULL, &ctx); -+ chan->engctx[engine] = NULL; -+} -+ -+static int -+nv31_mpeg_object_new(struct nouveau_channel *chan, int engine, -+ u32 handle, u16 class) -+{ -+ struct drm_device *dev = chan->dev; -+ struct nouveau_gpuobj *obj = NULL; -+ int ret; -+ -+ ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | -+ NVOBJ_FLAG_ZERO_FREE, &obj); -+ if (ret) -+ return ret; -+ obj->engine = 2; -+ obj->class = class; -+ -+ nv_wo32(obj, 0x00, class); -+ -+ ret = nouveau_ramht_insert(chan, handle, obj); -+ nouveau_gpuobj_ref(NULL, &obj); -+ return ret; -+} -+ -+static int -+nv31_mpeg_init(struct drm_device *dev, int engine) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); -+ int i; -+ -+ /* VPE init */ -+ nv_mask(dev, 0x000200, 0x00000002, 0x00000000); -+ nv_mask(dev, 0x000200, 0x00000002, 0x00000002); -+ nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -+ nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -+ -+ for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) -+ pmpeg->base.set_tile_region(dev, i); -+ -+ /* PMPEG init */ -+ nv_wr32(dev, 0x00b32c, 0x00000000); -+ nv_wr32(dev, 0x00b314, 0x00000100); -+ nv_wr32(dev, 0x00b220, nv44_graph_class(dev) ? 0x00000044 : 0x00000031); -+ nv_wr32(dev, 0x00b300, 0x02001ec1); -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -+ -+ nv_wr32(dev, 0x00b100, 0xffffffff); -+ nv_wr32(dev, 0x00b140, 0xffffffff); -+ -+ if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { -+ NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+ -+static int -+nv31_mpeg_fini(struct drm_device *dev, int engine, bool suspend) -+{ -+ /*XXX: context save? */ -+ nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -+ nv_wr32(dev, 0x00b140, 0x00000000); -+ return 0; -+} -+ -+static int -+nv31_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) -+{ -+ struct drm_device *dev = chan->dev; -+ u32 inst = data << 4; -+ u32 dma0 = nv_ri32(dev, inst + 0); -+ u32 dma1 = nv_ri32(dev, inst + 4); -+ u32 dma2 = nv_ri32(dev, inst + 8); -+ u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); -+ u32 size = dma1 + 1; -+ -+ /* only allow linear DMA objects */ -+ if (!(dma0 & 0x00002000)) -+ return -EINVAL; -+ -+ if (mthd == 0x0190) { -+ /* DMA_CMD */ -+ nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); -+ nv_wr32(dev, 0x00b334, base); -+ nv_wr32(dev, 0x00b324, size); -+ } else -+ if (mthd == 0x01a0) { -+ /* DMA_DATA */ -+ nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); -+ nv_wr32(dev, 0x00b360, base); -+ nv_wr32(dev, 0x00b364, size); -+ } else { -+ /* DMA_IMAGE, VRAM only */ -+ if (dma0 & 0x000c0000) -+ return -EINVAL; -+ -+ nv_wr32(dev, 0x00b370, base); -+ nv_wr32(dev, 0x00b374, size); -+ } -+ -+ return 0; -+} -+ -+static int -+nv31_mpeg_isr_chid(struct drm_device *dev, u32 inst) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_gpuobj *ctx; -+ unsigned long flags; -+ int i; -+ -+ /* hardcode drm channel id on nv3x, so swmthd lookup works */ -+ if (dev_priv->card_type < NV_40) -+ return 0; -+ -+ spin_lock_irqsave(&dev_priv->channels.lock, flags); -+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -+ if (!dev_priv->channels.ptr[i]) -+ continue; -+ -+ ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; -+ if (ctx && ctx->pinst == inst) -+ break; -+ } -+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -+ return i; -+} -+ -+static void -+nv31_vpe_set_tile_region(struct drm_device *dev, int i) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -+ -+ nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); -+ nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); -+ nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); -+} -+ -+static void -+nv31_mpeg_isr(struct drm_device *dev) -+{ -+ u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; -+ u32 chid = nv31_mpeg_isr_chid(dev, inst); -+ u32 stat = nv_rd32(dev, 0x00b100); -+ u32 type = nv_rd32(dev, 0x00b230); -+ u32 mthd = nv_rd32(dev, 0x00b234); -+ u32 data = nv_rd32(dev, 0x00b238); -+ u32 show = stat; -+ -+ if (stat & 0x01000000) { -+ /* happens on initial binding of the object */ -+ if (type == 0x00000020 && mthd == 0x0000) { -+ nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); -+ show &= ~0x01000000; -+ } -+ -+ if (type == 0x00000010) { -+ if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) -+ show &= ~0x01000000; -+ } -+ } -+ -+ nv_wr32(dev, 0x00b100, stat); -+ nv_wr32(dev, 0x00b230, 0x00000001); -+ -+ if (show && nouveau_ratelimit()) { -+ NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ chid, inst, stat, type, mthd, data); -+ } -+} -+ -+static void -+nv31_vpe_isr(struct drm_device *dev) -+{ -+ if (nv_rd32(dev, 0x00b100)) -+ nv31_mpeg_isr(dev); -+ -+ if (nv_rd32(dev, 0x00b800)) { -+ u32 stat = nv_rd32(dev, 0x00b800); -+ NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); -+ nv_wr32(dev, 0xb800, stat); -+ } -+} -+ -+static void -+nv31_mpeg_destroy(struct drm_device *dev, int engine) -+{ -+ struct nv31_mpeg_engine *pmpeg = nv_engine(dev, engine); -+ -+ nouveau_irq_unregister(dev, 0); -+ -+ NVOBJ_ENGINE_DEL(dev, MPEG); -+ kfree(pmpeg); -+} -+ -+int -+nv31_mpeg_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nv31_mpeg_engine *pmpeg; -+ -+ pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); -+ if (!pmpeg) -+ return -ENOMEM; -+ atomic_set(&pmpeg->refcount, 0); -+ -+ pmpeg->base.destroy = nv31_mpeg_destroy; -+ pmpeg->base.init = nv31_mpeg_init; -+ pmpeg->base.fini = nv31_mpeg_fini; -+ if (dev_priv->card_type < NV_40) { -+ pmpeg->base.context_new = nv31_mpeg_context_new; -+ pmpeg->base.context_del = nv31_mpeg_context_del; -+ } else { -+ pmpeg->base.context_new = nv40_mpeg_context_new; -+ pmpeg->base.context_del = nv40_mpeg_context_del; -+ } -+ pmpeg->base.object_new = nv31_mpeg_object_new; -+ -+ /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between -+ * all VPE engines, for this driver's purposes the PMPEG engine -+ * will be treated as the "master" and handle the global VPE -+ * bits too -+ */ -+ pmpeg->base.set_tile_region = nv31_vpe_set_tile_region; -+ nouveau_irq_register(dev, 0, nv31_vpe_isr); -+ -+ NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); -+ NVOBJ_CLASS(dev, 0x3174, MPEG); -+ NVOBJ_MTHD (dev, 0x3174, 0x0190, nv31_mpeg_mthd_dma); -+ NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv31_mpeg_mthd_dma); -+ NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv31_mpeg_mthd_dma); -+ -+#if 0 -+ NVOBJ_ENGINE_ADD(dev, ME, &pme->base); -+ NVOBJ_CLASS(dev, 0x4075, ME); -+#endif -+ return 0; -+ -+} -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv40_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv40_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv40_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv40_graph.c 2011-07-26 07:03:44.463051448 +0200 -@@ -35,89 +35,6 @@ - u32 grctx_size; - }; - --static struct nouveau_channel * --nv40_graph_channel(struct drm_device *dev) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *grctx; -- uint32_t inst; -- int i; -- -- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -- return NULL; -- inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; -- -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (!dev_priv->channels.ptr[i]) -- continue; -- -- grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; -- if (grctx && grctx->pinst == inst) -- return dev_priv->channels.ptr[i]; -- } -- -- return NULL; --} -- --static int --nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) --{ -- uint32_t old_cp, tv = 1000, tmp; -- int i; -- -- old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); -- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); -- -- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); -- tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : -- NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); -- -- tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); -- tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); -- -- nouveau_wait_for_idle(dev); -- -- for (i = 0; i < tv; i++) { -- if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) -- break; -- } -- -- nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); -- -- if (i == tv) { -- uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); -- NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); -- NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", -- ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, -- ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); -- NV_ERROR(dev, "0x40030C = 0x%08x\n", -- nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); -- return -EBUSY; -- } -- -- return 0; --} -- --static int --nv40_graph_unload_context(struct drm_device *dev) --{ -- uint32_t inst; -- int ret; -- -- inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -- if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -- return 0; -- inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; -- -- ret = nv40_graph_transfer_context(dev, inst, 1); -- -- nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); -- return ret; --} -- - static int - nv40_graph_context_new(struct nouveau_channel *chan, int engine) - { -@@ -163,16 +80,16 @@ - struct nouveau_gpuobj *grctx = chan->engctx[engine]; - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 inst = 0x01000000 | (grctx->pinst >> 4); - unsigned long flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv04_graph_fifo_access(dev, false); -- -- /* Unload the context if it's the currently active one */ -- if (nv40_graph_channel(dev) == chan) -- nv40_graph_unload_context(dev); -- -- nv04_graph_fifo_access(dev, true); -+ nv_mask(dev, 0x400720, 0x00000000, 0x00000001); -+ if (nv_rd32(dev, 0x40032c) == inst) -+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); -+ if (nv_rd32(dev, 0x400330) == inst) -+ nv_mask(dev, 0x400330, 0x01000000, 0x00000000); -+ nv_mask(dev, 0x400720, 0x00000001, 0x00000001); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - /* Free the context resources */ -@@ -429,9 +346,20 @@ - } - - static int --nv40_graph_fini(struct drm_device *dev, int engine) -+nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -- nv40_graph_unload_context(dev); -+ u32 inst = nv_rd32(dev, 0x40032c); -+ if (inst & 0x01000000) { -+ nv_wr32(dev, 0x400720, 0x00000000); -+ nv_wr32(dev, 0x400784, inst); -+ nv_mask(dev, 0x400310, 0x00000020, 0x00000020); -+ nv_mask(dev, 0x400304, 0x00000001, 0x00000001); -+ if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { -+ u32 insn = nv_rd32(dev, 0x400308); -+ NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); -+ } -+ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); -+ } - return 0; - } - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv40_mpeg.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv40_mpeg.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv40_mpeg.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv40_mpeg.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,311 +0,0 @@ --/* -- * Copyright 2011 Red Hat Inc. -- * -- * Permission is hereby granted, free of charge, to any person obtaining a -- * copy of this software and associated documentation files (the "Software"), -- * to deal in the Software without restriction, including without limitation -- * the rights to use, copy, modify, merge, publish, distribute, sublicense, -- * and/or sell copies of the Software, and to permit persons to whom the -- * Software is furnished to do so, subject to the following conditions: -- * -- * The above copyright notice and this permission notice shall be included in -- * all copies or substantial portions of the Software. -- * -- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -- * OTHER DEALINGS IN THE SOFTWARE. -- * -- * Authors: Ben Skeggs -- */ -- --#include "drmP.h" --#include "nouveau_drv.h" --#include "nouveau_ramht.h" -- --struct nv40_mpeg_engine { -- struct nouveau_exec_engine base; --}; -- --static int --nv40_mpeg_context_new(struct nouveau_channel *chan, int engine) --{ -- struct drm_device *dev = chan->dev; -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ctx = NULL; -- unsigned long flags; -- int ret; -- -- NV_DEBUG(dev, "ch%d\n", chan->id); -- -- ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &ctx); -- if (ret) -- return ret; -- -- nv_wo32(ctx, 0x78, 0x02001ec1); -- -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv_mask(dev, 0x002500, 0x00000001, 0x00000000); -- if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id) -- nv_wr32(dev, 0x00330c, ctx->pinst >> 4); -- nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4); -- nv_mask(dev, 0x002500, 0x00000001, 0x00000001); -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- -- chan->engctx[engine] = ctx; -- return 0; --} -- --static void --nv40_mpeg_context_del(struct nouveau_channel *chan, int engine) --{ -- struct drm_nouveau_private *dev_priv = chan->dev->dev_private; -- struct nouveau_gpuobj *ctx = chan->engctx[engine]; -- struct drm_device *dev = chan->dev; -- unsigned long flags; -- u32 inst = 0x80000000 | (ctx->pinst >> 4); -- -- spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -- if (nv_rd32(dev, 0x00b318) == inst) -- nv_mask(dev, 0x00b318, 0x80000000, 0x00000000); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -- spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -- -- nouveau_gpuobj_ref(NULL, &ctx); -- chan->engctx[engine] = NULL; --} -- --static int --nv40_mpeg_object_new(struct nouveau_channel *chan, int engine, -- u32 handle, u16 class) --{ -- struct drm_device *dev = chan->dev; -- struct nouveau_gpuobj *obj = NULL; -- int ret; -- -- ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC | -- NVOBJ_FLAG_ZERO_FREE, &obj); -- if (ret) -- return ret; -- obj->engine = 2; -- obj->class = class; -- -- nv_wo32(obj, 0x00, class); -- -- ret = nouveau_ramht_insert(chan, handle, obj); -- nouveau_gpuobj_ref(NULL, &obj); -- return ret; --} -- --static int --nv40_mpeg_init(struct drm_device *dev, int engine) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); -- int i; -- -- /* VPE init */ -- nv_mask(dev, 0x000200, 0x00000002, 0x00000000); -- nv_mask(dev, 0x000200, 0x00000002, 0x00000002); -- nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -- nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */ -- -- for (i = 0; i < dev_priv->engine.fb.num_tiles; i++) -- pmpeg->base.set_tile_region(dev, i); -- -- /* PMPEG init */ -- nv_wr32(dev, 0x00b32c, 0x00000000); -- nv_wr32(dev, 0x00b314, 0x00000100); -- nv_wr32(dev, 0x00b220, 0x00000044); -- nv_wr32(dev, 0x00b300, 0x02001ec1); -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001); -- -- nv_wr32(dev, 0x00b100, 0xffffffff); -- nv_wr32(dev, 0x00b140, 0xffffffff); -- -- if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) { -- NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200)); -- return -EBUSY; -- } -- -- return 0; --} -- --static int --nv40_mpeg_fini(struct drm_device *dev, int engine) --{ -- /*XXX: context save? */ -- nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -- nv_wr32(dev, 0x00b140, 0x00000000); -- return 0; --} -- --static int --nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data) --{ -- struct drm_device *dev = chan->dev; -- u32 inst = data << 4; -- u32 dma0 = nv_ri32(dev, inst + 0); -- u32 dma1 = nv_ri32(dev, inst + 4); -- u32 dma2 = nv_ri32(dev, inst + 8); -- u32 base = (dma2 & 0xfffff000) | (dma0 >> 20); -- u32 size = dma1 + 1; -- -- /* only allow linear DMA objects */ -- if (!(dma0 & 0x00002000)) -- return -EINVAL; -- -- if (mthd == 0x0190) { -- /* DMA_CMD */ -- nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000)); -- nv_wr32(dev, 0x00b334, base); -- nv_wr32(dev, 0x00b324, size); -- } else -- if (mthd == 0x01a0) { -- /* DMA_DATA */ -- nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2); -- nv_wr32(dev, 0x00b360, base); -- nv_wr32(dev, 0x00b364, size); -- } else { -- /* DMA_IMAGE, VRAM only */ -- if (dma0 & 0x000c0000) -- return -EINVAL; -- -- nv_wr32(dev, 0x00b370, base); -- nv_wr32(dev, 0x00b374, size); -- } -- -- return 0; --} -- --static int --nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_gpuobj *ctx; -- unsigned long flags; -- int i; -- -- spin_lock_irqsave(&dev_priv->channels.lock, flags); -- for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -- if (!dev_priv->channels.ptr[i]) -- continue; -- -- ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG]; -- if (ctx && ctx->pinst == inst) -- break; -- } -- spin_unlock_irqrestore(&dev_priv->channels.lock, flags); -- return i; --} -- --static void --nv40_vpe_set_tile_region(struct drm_device *dev, int i) --{ -- struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; -- -- nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch); -- nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit); -- nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr); --} -- --static void --nv40_mpeg_isr(struct drm_device *dev) --{ -- u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4; -- u32 chid = nv40_mpeg_isr_chid(dev, inst); -- u32 stat = nv_rd32(dev, 0x00b100); -- u32 type = nv_rd32(dev, 0x00b230); -- u32 mthd = nv_rd32(dev, 0x00b234); -- u32 data = nv_rd32(dev, 0x00b238); -- u32 show = stat; -- -- if (stat & 0x01000000) { -- /* happens on initial binding of the object */ -- if (type == 0x00000020 && mthd == 0x0000) { -- nv_mask(dev, 0x00b308, 0x00000000, 0x00000000); -- show &= ~0x01000000; -- } -- -- if (type == 0x00000010) { -- if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data)) -- show &= ~0x01000000; -- } -- } -- -- nv_wr32(dev, 0x00b100, stat); -- nv_wr32(dev, 0x00b230, 0x00000001); -- -- if (show && nouveau_ratelimit()) { -- NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", -- chid, inst, stat, type, mthd, data); -- } --} -- --static void --nv40_vpe_isr(struct drm_device *dev) --{ -- if (nv_rd32(dev, 0x00b100)) -- nv40_mpeg_isr(dev); -- -- if (nv_rd32(dev, 0x00b800)) { -- u32 stat = nv_rd32(dev, 0x00b800); -- NV_INFO(dev, "PMSRCH: 0x%08x\n", stat); -- nv_wr32(dev, 0xb800, stat); -- } --} -- --static void --nv40_mpeg_destroy(struct drm_device *dev, int engine) --{ -- struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine); -- -- nouveau_irq_unregister(dev, 0); -- -- NVOBJ_ENGINE_DEL(dev, MPEG); -- kfree(pmpeg); --} -- --int --nv40_mpeg_create(struct drm_device *dev) --{ -- struct nv40_mpeg_engine *pmpeg; -- -- pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL); -- if (!pmpeg) -- return -ENOMEM; -- -- pmpeg->base.destroy = nv40_mpeg_destroy; -- pmpeg->base.init = nv40_mpeg_init; -- pmpeg->base.fini = nv40_mpeg_fini; -- pmpeg->base.context_new = nv40_mpeg_context_new; -- pmpeg->base.context_del = nv40_mpeg_context_del; -- pmpeg->base.object_new = nv40_mpeg_object_new; -- -- /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between -- * all VPE engines, for this driver's purposes the PMPEG engine -- * will be treated as the "master" and handle the global VPE -- * bits too -- */ -- pmpeg->base.set_tile_region = nv40_vpe_set_tile_region; -- nouveau_irq_register(dev, 0, nv40_vpe_isr); -- -- NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base); -- NVOBJ_CLASS(dev, 0x3174, MPEG); -- NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma); -- NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma); -- NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma); -- --#if 0 -- NVOBJ_ENGINE_ADD(dev, ME, &pme->base); -- NVOBJ_CLASS(dev, 0x4075, ME); --#endif -- return 0; -- --} -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_crtc.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_crtc.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_crtc.c 2011-07-26 07:03:44.488051747 +0200 -@@ -104,7 +104,7 @@ - OUT_RING(evo, nv_crtc->lut.depth == 8 ? - NV50_EVO_CRTC_CLUT_MODE_OFF : - NV50_EVO_CRTC_CLUT_MODE_ON); -- OUT_RING(evo, (nv_crtc->lut.nvbo->bo.mem.start << PAGE_SHIFT) >> 8); -+ OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); - if (dev_priv->chipset != 0x50) { - BEGIN_RING(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); - OUT_RING(evo, NvEvoVRAM); -@@ -329,8 +329,6 @@ - - drm_crtc_cleanup(&nv_crtc->base); - -- nv50_cursor_fini(nv_crtc); -- - nouveau_bo_unmap(nv_crtc->lut.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); - nouveau_bo_unmap(nv_crtc->cursor.nvbo); -@@ -372,7 +370,7 @@ - - nouveau_bo_unmap(cursor); - -- nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT); -+ nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset); - nv_crtc->cursor.show(nv_crtc, true); - - out: -@@ -546,7 +544,7 @@ - } - } - -- nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; -+ nv_crtc->fb.offset = fb->nvbo->bo.offset; - nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); - nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; - if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { -@@ -747,7 +745,7 @@ - } - nv_crtc->lut.depth = 0; - -- ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, &nv_crtc->lut.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); -@@ -773,7 +771,7 @@ - drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); - drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); - -- ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, &nv_crtc->cursor.nvbo); - if (!ret) { - ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_cursor.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_cursor.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_cursor.c 2011-07-26 07:03:44.489051759 +0200 -@@ -137,21 +137,3 @@ - nv_crtc->cursor.show = nv50_cursor_show; - return 0; - } -- --void --nv50_cursor_fini(struct nouveau_crtc *nv_crtc) --{ -- struct drm_device *dev = nv_crtc->base.dev; -- int idx = nv_crtc->index; -- -- NV_DEBUG_KMS(dev, "\n"); -- -- nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); -- if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), -- NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { -- NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); -- NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -- nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx))); -- } --} -- -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_display.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_display.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_display.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_display.c 2011-07-26 07:03:44.490051771 +0200 -@@ -247,6 +247,16 @@ - } - } - -+ for (i = 0; i < 2; i++) { -+ nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); -+ if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), -+ NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { -+ NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); -+ NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", -+ nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); -+ } -+ } -+ - nv50_evo_fini(dev); - - for (i = 0; i < 3; i++) { -@@ -286,23 +296,6 @@ - return -ENOMEM; - dev_priv->engine.display.priv = priv; - -- /* init basic kernel modesetting */ -- drm_mode_config_init(dev); -- -- /* Initialise some optional connector properties. */ -- drm_mode_create_scaling_mode_property(dev); -- drm_mode_create_dithering_property(dev); -- -- dev->mode_config.min_width = 0; -- dev->mode_config.min_height = 0; -- -- dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; -- -- dev->mode_config.max_width = 8192; -- dev->mode_config.max_height = 8192; -- -- dev->mode_config.fb_base = dev_priv->fb_phys; -- - /* Create CRTC objects */ - for (i = 0; i < 2; i++) - nv50_crtc_create(dev, i); -@@ -364,8 +357,6 @@ - - NV_DEBUG_KMS(dev, "\n"); - -- drm_mode_config_cleanup(dev); -- - nv50_display_disable(dev); - nouveau_irq_unregister(dev, 26); - kfree(disp); -@@ -415,8 +406,6 @@ - - /* synchronise with the rendering channel, if necessary */ - if (likely(chan)) { -- u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset; -- - ret = RING_SPACE(chan, 10); - if (ret) { - WIND_RING(evo); -@@ -438,6 +427,8 @@ - else - OUT_RING (chan, chan->vram_handle); - } else { -+ u64 offset = chan->dispc_vma[nv_crtc->index].offset; -+ offset += dispc->sem.offset; - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset)); -@@ -484,7 +475,7 @@ - OUT_RING (evo, 0x00000000); - OUT_RING (evo, 0x00000000); - BEGIN_RING(evo, 0, 0x0800, 5); -- OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8); -+ OUT_RING (evo, nv_fb->nvbo->bo.offset >> 8); - OUT_RING (evo, 0); - OUT_RING (evo, (fb->height << 16) | fb->width); - OUT_RING (evo, nv_fb->r_pitch); -@@ -698,7 +689,7 @@ - struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; - - if (dcb->type == type && (dcb->or & (1 << or))) { -- nouveau_bios_run_display_table(dev, dcb, 0, -1); -+ nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); - disp->irq.dcb = dcb; - goto ack; - } -@@ -753,7 +744,7 @@ - NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); - dcb = disp->irq.dcb; - if (dcb) { -- nouveau_bios_run_display_table(dev, dcb, 0, -2); -+ nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); - disp->irq.dcb = NULL; - } - -@@ -837,7 +828,7 @@ - } - - script = nv50_display_script_select(dev, dcb, mc, pclk); -- nouveau_bios_run_display_table(dev, dcb, script, pclk); -+ nouveau_bios_run_display_table(dev, script, pclk, dcb, -1); - - nv50_display_unk20_dp_hack(dev, dcb); - -@@ -904,7 +895,7 @@ - if (!dcb) - goto ack; - -- nouveau_bios_run_display_table(dev, dcb, script, -pclk); -+ nouveau_bios_run_display_table(dev, script, -pclk, dcb, -1); - nv50_display_unk40_dp_set_tmds(dev, dcb); - - ack: -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_evo.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_evo.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_evo.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_evo.c 2011-07-26 07:03:44.490051771 +0200 -@@ -38,6 +38,7 @@ - return; - *pevo = NULL; - -+ nouveau_ramht_ref(NULL, &evo->ramht, evo); - nouveau_gpuobj_channel_takedown(evo); - nouveau_bo_unmap(evo->pushbuf_bo); - nouveau_bo_ref(NULL, &evo->pushbuf_bo); -@@ -116,7 +117,7 @@ - evo->user_get = 4; - evo->user_put = 0; - -- ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, -+ ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, - &evo->pushbuf_bo); - if (ret == 0) - ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); -@@ -153,7 +154,7 @@ - { - struct drm_device *dev = evo->dev; - int id = evo->id, ret, i; -- u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT; -+ u64 pushbuf = evo->pushbuf_bo->bo.offset; - u32 tmp; - - tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); -@@ -331,16 +332,15 @@ - if (ret) - goto err; - -- ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM, -+ ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, &dispc->sem.bo); - if (!ret) { -- offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT; -- - ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(dispc->sem.bo); - if (ret) - nouveau_bo_ref(NULL, &dispc->sem.bo); -+ offset = dispc->sem.bo->bo.offset; - } - - if (ret) -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_fbcon.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_fbcon.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_fbcon.c 2011-07-26 07:03:44.492051795 +0200 -@@ -159,7 +159,7 @@ - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; -+ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; - int ret, format; - - switch (info->var.bits_per_pixel) { -@@ -247,8 +247,8 @@ - OUT_RING(chan, info->fix.line_length); - OUT_RING(chan, info->var.xres_virtual); - OUT_RING(chan, info->var.yres_virtual); -- OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); -- OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); -+ OUT_RING(chan, upper_32_bits(fb->vma.offset)); -+ OUT_RING(chan, lower_32_bits(fb->vma.offset)); - BEGIN_RING(chan, NvSub2D, 0x0230, 2); - OUT_RING(chan, format); - OUT_RING(chan, 1); -@@ -256,8 +256,8 @@ - OUT_RING(chan, info->fix.line_length); - OUT_RING(chan, info->var.xres_virtual); - OUT_RING(chan, info->var.yres_virtual); -- OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); -- OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); -+ OUT_RING(chan, upper_32_bits(fb->vma.offset)); -+ OUT_RING(chan, lower_32_bits(fb->vma.offset)); - - return 0; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_gpio.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_gpio.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_gpio.c 2011-07-26 07:03:44.492051795 +0200 -@@ -98,6 +98,37 @@ - } - - int -+nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) -+{ -+ struct dcb_gpio_entry *gpio; -+ u32 v; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return -ENOENT; -+ -+ v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); -+ v &= 0x00004000; -+ return (!!v == (gpio->state[1] & 1)); -+} -+ -+int -+nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) -+{ -+ struct dcb_gpio_entry *gpio; -+ u32 v; -+ -+ gpio = nouveau_bios_gpio_entry(dev, tag); -+ if (!gpio) -+ return -ENOENT; -+ -+ v = gpio->state[state] ^ 2; -+ -+ nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); -+ return 0; -+} -+ -+int - nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, - void (*handler)(void *, int), void *data) - { -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_graph.c 2011-07-26 07:03:44.493051807 +0200 -@@ -125,7 +125,6 @@ - nv50_graph_init_reset(struct drm_device *dev) - { - uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); -- - NV_DEBUG(dev, "\n"); - - nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); -@@ -255,9 +254,13 @@ - } - - static int --nv50_graph_fini(struct drm_device *dev, int engine) -+nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) - { -- NV_DEBUG(dev, "\n"); -+ nv_mask(dev, 0x400500, 0x00010001, 0x00000000); -+ if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) { -+ nv_mask(dev, 0x400500, 0x00010001, 0x00010001); -+ return -EBUSY; -+ } - nv50_graph_unload_context(dev); - nv_wr32(dev, 0x40013c, 0x00000000); - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_grctx.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_grctx.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_grctx.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_grctx.c 2011-07-26 07:03:44.495051831 +0200 -@@ -40,6 +40,9 @@ - #define CP_FLAG_UNK0B ((0 * 32) + 0xb) - #define CP_FLAG_UNK0B_CLEAR 0 - #define CP_FLAG_UNK0B_SET 1 -+#define CP_FLAG_STATE ((0 * 32) + 0x1c) -+#define CP_FLAG_STATE_STOPPED 0 -+#define CP_FLAG_STATE_RUNNING 1 - #define CP_FLAG_UNK1D ((0 * 32) + 0x1d) - #define CP_FLAG_UNK1D_CLEAR 0 - #define CP_FLAG_UNK1D_SET 1 -@@ -194,6 +197,8 @@ - "the devs.\n"); - return -ENOSYS; - } -+ -+ cp_set (ctx, STATE, RUNNING); - /* decide whether we're loading/unloading the context */ - cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); - cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); -@@ -260,6 +265,7 @@ - cp_name(ctx, cp_exit); - cp_set (ctx, USER_SAVE, NOT_PENDING); - cp_set (ctx, USER_LOAD, NOT_PENDING); -+ cp_set (ctx, STATE, STOPPED); - cp_out (ctx, CP_END); - ctx->ctxvals_pos += 0x400; /* padding... no idea why you need it */ - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_instmem.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_instmem.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_instmem.c 2011-07-26 07:03:44.496051843 +0200 -@@ -305,9 +305,9 @@ - u32 align; - }; - -- - int --nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) -+nv50_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, -+ u32 size, u32 align) - { - struct drm_device *dev = gpuobj->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -336,7 +336,7 @@ - if (!(gpuobj->flags & NVOBJ_FLAG_VM_USER)) - flags |= NV_MEM_ACCESS_SYS; - -- ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, flags, -+ ret = nouveau_vm_get(chan->vm, size, 12, flags, - &node->chan_vma); - if (ret) { - vram->put(dev, &node->vram); -@@ -345,7 +345,7 @@ - } - - nouveau_vm_map(&node->chan_vma, node->vram); -- gpuobj->vinst = node->chan_vma.offset; -+ gpuobj->linst = node->chan_vma.offset; - } - - gpuobj->size = size; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_mpeg.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_mpeg.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_mpeg.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_mpeg.c 2011-07-26 07:03:44.497051855 +0200 -@@ -160,7 +160,7 @@ - } - - static int --nv50_mpeg_fini(struct drm_device *dev, int engine) -+nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) - { - /*XXX: context save for s/r */ - nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_pm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_pm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_pm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_pm.c 2011-07-26 07:03:44.497051855 +0200 -@@ -115,15 +115,15 @@ - BIT_M.version == 1 && BIT_M.length >= 0x0b) { - script = ROM16(BIT_M.data[0x05]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - script = ROM16(BIT_M.data[0x07]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - script = ROM16(BIT_M.data[0x09]); - if (script) -- nouveau_bios_run_init_table(dev, script, NULL); -+ nouveau_bios_run_init_table(dev, script, NULL, -1); - -- nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); -+ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); - } - - if (state->type == PLL_MEMORY) { -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_sor.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_sor.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_sor.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_sor.c 2011-07-26 07:03:44.499051879 +0200 -@@ -318,6 +318,8 @@ - uint32_t tmp; - - tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); -+ if (!tmp) -+ tmp = nv_rd32(dev, 0x610798 + (or * 8)); - - switch ((tmp & 0x00000f00) >> 8) { - case 8: -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_vm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_vm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_vm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_vm.c 2011-07-26 07:03:44.500051891 +0200 -@@ -156,7 +156,7 @@ - pinstmem->flush(vm->dev); - - /* BAR */ -- if (vm != dev_priv->chan_vm) { -+ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) { - nv50_vm_flush_engine(vm->dev, 6); - return; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv50_vram.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_vram.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv50_vram.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv50_vram.c 2011-07-26 07:03:44.500051891 +0200 -@@ -51,9 +51,7 @@ - nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; -- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; -- struct nouveau_mm *mm = man->priv; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *this; - struct nouveau_mem *mem; - -@@ -84,9 +82,7 @@ - u32 memtype, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; -- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; -- struct nouveau_mm *mm = man->priv; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int comp = (memtype & 0x300) >> 8; -@@ -190,22 +186,35 @@ - nv50_vram_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ -+ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ -+ u32 rblock, length; - - dev_priv->vram_size = nv_rd32(dev, 0x10020c); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ULL; - -- switch (dev_priv->chipset) { -- case 0xaa: -- case 0xac: -- case 0xaf: -+ /* IGPs, no funky reordering happens here, they don't have VRAM */ -+ if (dev_priv->chipset == 0xaa || -+ dev_priv->chipset == 0xac || -+ dev_priv->chipset == 0xaf) { - dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; -- dev_priv->vram_rblock_size = 4096; -- break; -- default: -- dev_priv->vram_rblock_size = nv50_vram_rblock(dev); -- break; -+ rblock = 4096 >> 12; -+ } else { -+ rblock = nv50_vram_rblock(dev) >> 12; - } - -- return 0; -+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; -+ -+ return nouveau_mm_init(&vram->mm, rsvd_head, length, rblock); -+} -+ -+void -+nv50_vram_fini(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ -+ nouveau_mm_fini(&vram->mm); - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nv84_crypt.c linux-3.0.patch/drivers/gpu/drm/nouveau/nv84_crypt.c ---- linux-3.0/drivers/gpu/drm/nouveau/nv84_crypt.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nv84_crypt.c 2011-07-26 07:03:44.501051903 +0200 -@@ -138,7 +138,7 @@ - } - - static int --nv84_crypt_fini(struct drm_device *dev, int engine) -+nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) - { - nv_wr32(dev, 0x102140, 0x00000000); - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nva3_copy.c linux-3.0.patch/drivers/gpu/drm/nouveau/nva3_copy.c ---- linux-3.0/drivers/gpu/drm/nouveau/nva3_copy.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nva3_copy.c 2011-07-26 07:03:44.501051903 +0200 -@@ -140,7 +140,7 @@ - } - - static int --nva3_copy_fini(struct drm_device *dev, int engine) -+nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) - { - nv_mask(dev, 0x104048, 0x00000003, 0x00000000); - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nva3_pm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nva3_pm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nva3_pm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nva3_pm.c 2011-07-26 07:03:44.502051915 +0200 -@@ -27,178 +27,316 @@ - #include "nouveau_bios.h" - #include "nouveau_pm.h" - --/* This is actually a lot more complex than it appears here, but hopefully -- * this should be able to deal with what the VBIOS leaves for us.. -- * -- * If not, well, I'll jump off that bridge when I come to it. -- */ -+static u32 read_clk(struct drm_device *, int, bool); -+static u32 read_pll(struct drm_device *, int, u32); - --struct nva3_pm_state { -- enum pll_types type; -- u32 src0; -- u32 src1; -- u32 ctrl; -- u32 coef; -- u32 old_pnm; -- u32 new_pnm; -- u32 new_div; --}; -+static u32 -+read_vco(struct drm_device *dev, int clk) -+{ -+ u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); -+ if ((sctl & 0x00000030) != 0x00000030) -+ return read_pll(dev, 0x41, 0x00e820); -+ return read_pll(dev, 0x42, 0x00e8a0); -+} - --static int --nva3_pm_pll_offset(u32 id) -+static u32 -+read_clk(struct drm_device *dev, int clk, bool ignore_en) - { -- static const u32 pll_map[] = { -- 0x00, PLL_CORE, -- 0x01, PLL_SHADER, -- 0x02, PLL_MEMORY, -- 0x00, 0x00 -- }; -- const u32 *map = pll_map; -- -- while (map[1]) { -- if (id == map[1]) -- return map[0]; -- map += 2; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ u32 sctl, sdiv, sclk; -+ -+ /* refclk for the 0xe8xx plls is a fixed frequency */ -+ if (clk >= 0x40) { -+ if (dev_priv->chipset == 0xaf) { -+ /* no joke.. seriously.. sigh.. */ -+ return nv_rd32(dev, 0x00471c) * 1000; -+ } -+ -+ return dev_priv->crystal; - } - -- return -ENOENT; -+ sctl = nv_rd32(dev, 0x4120 + (clk * 4)); -+ if (!ignore_en && !(sctl & 0x00000100)) -+ return 0; -+ -+ switch (sctl & 0x00003000) { -+ case 0x00000000: -+ return dev_priv->crystal; -+ case 0x00002000: -+ if (sctl & 0x00000040) -+ return 108000; -+ return 100000; -+ case 0x00003000: -+ sclk = read_vco(dev, clk); -+ sdiv = ((sctl & 0x003f0000) >> 16) + 2; -+ return (sclk * 2) / sdiv; -+ default: -+ return 0; -+ } - } - --int --nva3_pm_clock_get(struct drm_device *dev, u32 id) -+static u32 -+read_pll(struct drm_device *dev, int clk, u32 pll) -+{ -+ u32 ctrl = nv_rd32(dev, pll + 0); -+ u32 sclk = 0, P = 1, N = 1, M = 1; -+ -+ if (!(ctrl & 0x00000008)) { -+ if (ctrl & 0x00000001) { -+ u32 coef = nv_rd32(dev, pll + 4); -+ M = (coef & 0x000000ff) >> 0; -+ N = (coef & 0x0000ff00) >> 8; -+ P = (coef & 0x003f0000) >> 16; -+ -+ /* no post-divider on these.. */ -+ if ((pll & 0x00ff00) == 0x00e800) -+ P = 1; -+ -+ sclk = read_clk(dev, 0x00 + clk, false); -+ } -+ } else { -+ sclk = read_clk(dev, 0x10 + clk, false); -+ } -+ -+ return sclk * N / (M * P); -+} -+ -+struct creg { -+ u32 clk; -+ u32 pll; -+}; -+ -+static int -+calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) - { -- u32 src0, src1, ctrl, coef; -- struct pll_lims pll; -- int ret, off; -- int P, N, M; -+ struct pll_lims limits; -+ u32 oclk, sclk, sdiv; -+ int P, N, M, diff; -+ int ret; -+ -+ reg->pll = 0; -+ reg->clk = 0; -+ if (!khz) { -+ NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); -+ return 0; -+ } - -- ret = get_pll_limits(dev, id, &pll); -+ switch (khz) { -+ case 27000: -+ reg->clk = 0x00000100; -+ return khz; -+ case 100000: -+ reg->clk = 0x00002100; -+ return khz; -+ case 108000: -+ reg->clk = 0x00002140; -+ return khz; -+ default: -+ sclk = read_vco(dev, clk); -+ sdiv = min((sclk * 2) / (khz - 2999), (u32)65); -+ /* if the clock has a PLL attached, and we can get a within -+ * [-2, 3) MHz of a divider, we'll disable the PLL and use -+ * the divider instead. -+ * -+ * divider can go as low as 2, limited here because NVIDIA -+ * and the VBIOS on my NVA8 seem to prefer using the PLL -+ * for 810MHz - is there a good reason? -+ */ -+ if (sdiv > 4) { -+ oclk = (sclk * 2) / sdiv; -+ diff = khz - oclk; -+ if (!pll || (diff >= -2000 && diff < 3000)) { -+ reg->clk = (((sdiv - 2) << 16) | 0x00003100); -+ return oclk; -+ } -+ } -+ -+ if (!pll) { -+ NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); -+ return -ERANGE; -+ } -+ -+ break; -+ } -+ -+ ret = get_pll_limits(dev, pll, &limits); - if (ret) - return ret; - -- off = nva3_pm_pll_offset(id); -- if (off < 0) -- return off; -- -- src0 = nv_rd32(dev, 0x4120 + (off * 4)); -- src1 = nv_rd32(dev, 0x4160 + (off * 4)); -- ctrl = nv_rd32(dev, pll.reg + 0); -- coef = nv_rd32(dev, pll.reg + 4); -- NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", -- id, src0, src1, ctrl, coef); -- -- if (ctrl & 0x00000008) { -- u32 div = ((src1 & 0x003c0000) >> 18) + 1; -- return (pll.refclk * 2) / div; -- } -- -- P = (coef & 0x003f0000) >> 16; -- N = (coef & 0x0000ff00) >> 8; -- M = (coef & 0x000000ff); -- return pll.refclk * N / M / P; -+ limits.refclk = read_clk(dev, clk - 0x10, true); -+ if (!limits.refclk) -+ return -EINVAL; -+ -+ ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -+ if (ret >= 0) { -+ reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); -+ reg->pll = (P << 16) | (N << 8) | M; -+ } -+ return ret; - } - -+static void -+prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) -+{ -+ const u32 src0 = 0x004120 + (clk * 4); -+ const u32 src1 = 0x004160 + (clk * 4); -+ const u32 ctrl = pll + 0; -+ const u32 coef = pll + 4; -+ u32 cntl; -+ -+ if (!reg->clk && !reg->pll) { -+ NV_DEBUG(dev, "no clock for %02x\n", clk); -+ return; -+ } -+ -+ cntl = nv_rd32(dev, ctrl) & 0xfffffff2; -+ if (reg->pll) { -+ nv_mask(dev, src0, 0x00000101, 0x00000101); -+ nv_wr32(dev, coef, reg->pll); -+ nv_wr32(dev, ctrl, cntl | 0x00000015); -+ nv_mask(dev, src1, 0x00000100, 0x00000000); -+ nv_mask(dev, src1, 0x00000001, 0x00000000); -+ } else { -+ nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); -+ nv_wr32(dev, ctrl, cntl | 0x0000001d); -+ nv_mask(dev, ctrl, 0x00000001, 0x00000000); -+ nv_mask(dev, src0, 0x00000100, 0x00000000); -+ nv_mask(dev, src0, 0x00000001, 0x00000000); -+ } -+} -+ -+static void -+prog_clk(struct drm_device *dev, int clk, struct creg *reg) -+{ -+ if (!reg->clk) { -+ NV_DEBUG(dev, "no clock for %02x\n", clk); -+ return; -+ } -+ -+ nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); -+} -+ -+int -+nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ perflvl->core = read_pll(dev, 0x00, 0x4200); -+ perflvl->shader = read_pll(dev, 0x01, 0x4220); -+ perflvl->memory = read_pll(dev, 0x02, 0x4000); -+ perflvl->unka0 = read_clk(dev, 0x20, false); -+ perflvl->vdec = read_clk(dev, 0x21, false); -+ perflvl->daemon = read_clk(dev, 0x25, false); -+ perflvl->copy = perflvl->core; -+ return 0; -+} -+ -+struct nva3_pm_state { -+ struct creg nclk; -+ struct creg sclk; -+ struct creg mclk; -+ struct creg vdec; -+ struct creg unka0; -+}; -+ - void * --nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, -- u32 id, int khz) -+nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) - { -- struct nva3_pm_state *pll; -- struct pll_lims limits; -- int N, M, P, diff; -- int ret, off; -+ struct nva3_pm_state *info; -+ int ret; -+ -+ info = kzalloc(sizeof(*info), GFP_KERNEL); -+ if (!info) -+ return ERR_PTR(-ENOMEM); - -- ret = get_pll_limits(dev, id, &limits); -+ ret = calc_clk(dev, 0x10, 0x4200, perflvl->core, &info->nclk); - if (ret < 0) -- return (ret == -ENOENT) ? NULL : ERR_PTR(ret); -+ goto out; - -- off = nva3_pm_pll_offset(id); -- if (id < 0) -- return ERR_PTR(-EINVAL); -+ ret = calc_clk(dev, 0x11, 0x4220, perflvl->shader, &info->sclk); -+ if (ret < 0) -+ goto out; - -+ ret = calc_clk(dev, 0x12, 0x4000, perflvl->memory, &info->mclk); -+ if (ret < 0) -+ goto out; - -- pll = kzalloc(sizeof(*pll), GFP_KERNEL); -- if (!pll) -- return ERR_PTR(-ENOMEM); -- pll->type = id; -- pll->src0 = 0x004120 + (off * 4); -- pll->src1 = 0x004160 + (off * 4); -- pll->ctrl = limits.reg + 0; -- pll->coef = limits.reg + 4; -- -- /* If target clock is within [-2, 3) MHz of a divisor, we'll -- * use that instead of calculating MNP values -- */ -- pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16); -- if (pll->new_div) { -- diff = khz - ((limits.refclk * 2) / pll->new_div); -- if (diff < -2000 || diff >= 3000) -- pll->new_div = 0; -- } -- -- if (!pll->new_div) { -- ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); -- if (ret < 0) -- return ERR_PTR(ret); -+ ret = calc_clk(dev, 0x20, 0x0000, perflvl->unka0, &info->unka0); -+ if (ret < 0) -+ goto out; - -- pll->new_pnm = (P << 16) | (N << 8) | M; -- pll->new_div = 2 - 1; -- } else { -- pll->new_pnm = 0; -- pll->new_div--; -+ ret = calc_clk(dev, 0x21, 0x0000, perflvl->vdec, &info->vdec); -+ if (ret < 0) -+ goto out; -+ -+out: -+ if (ret < 0) { -+ kfree(info); -+ info = ERR_PTR(ret); - } -+ return info; -+} -+ -+static bool -+nva3_pm_grcp_idle(void *data) -+{ -+ struct drm_device *dev = data; - -- if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101) -- pll->old_pnm = nv_rd32(dev, pll->coef); -- return pll; -+ if (!(nv_rd32(dev, 0x400304) & 0x00000001)) -+ return true; -+ if (nv_rd32(dev, 0x400308) == 0x0050001c) -+ return true; -+ return false; - } - - void --nva3_pm_clock_set(struct drm_device *dev, void *pre_state) -+nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) - { -- struct nva3_pm_state *pll = pre_state; -- u32 ctrl = 0; -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nva3_pm_state *info = pre_state; -+ unsigned long flags; -+ -+ /* prevent any new grctx switches from starting */ -+ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -+ nv_wr32(dev, 0x400324, 0x00000000); -+ nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ -+ /* wait for any pending grctx switches to complete */ -+ if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { -+ NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); -+ goto cleanup; -+ } -+ /* freeze PFIFO */ -+ nv_mask(dev, 0x002504, 0x00000001, 0x00000001); -+ if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { -+ NV_ERROR(dev, "pm: fifo didn't go idle\n"); -+ goto cleanup; -+ } -+ -+ prog_pll(dev, 0x00, 0x004200, &info->nclk); -+ prog_pll(dev, 0x01, 0x004220, &info->sclk); -+ prog_clk(dev, 0x20, &info->unka0); -+ prog_clk(dev, 0x21, &info->vdec); - -- /* For the memory clock, NVIDIA will build a "script" describing -- * the reclocking process and ask PDAEMON to execute it. -- */ -- if (pll->type == PLL_MEMORY) { -+ if (info->mclk.clk || info->mclk.pll) { - nv_wr32(dev, 0x100210, 0); - nv_wr32(dev, 0x1002dc, 1); - nv_wr32(dev, 0x004018, 0x00001000); -- ctrl = 0x18000100; -- } -- -- if (pll->old_pnm || !pll->new_pnm) { -- nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 | -- (pll->new_div << 18)); -- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); -- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); -- } -- -- if (pll->new_pnm) { -- nv_mask(dev, pll->src0, 0x00000101, 0x00000101); -- nv_wr32(dev, pll->coef, pll->new_pnm); -- nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl); -- nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000); -- nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010); -- nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl); -- nv_mask(dev, pll->src1, 0x00000100, 0x00000000); -- nv_mask(dev, pll->src1, 0x00000001, 0x00000000); -- if (pll->type == PLL_MEMORY) -- nv_wr32(dev, 0x4018, 0x10005000); -- } else { -- nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000); -- nv_mask(dev, pll->src0, 0x00000100, 0x00000000); -- nv_mask(dev, pll->src0, 0x00000001, 0x00000000); -- if (pll->type == PLL_MEMORY) -- nv_wr32(dev, 0x4018, 0x1000d000); -- } -- -- if (pll->type == PLL_MEMORY) { -+ prog_pll(dev, 0x02, 0x004000, &info->mclk); -+ if (nv_rd32(dev, 0x4000) & 0x00000008) -+ nv_wr32(dev, 0x004018, 0x1000d000); -+ else -+ nv_wr32(dev, 0x004018, 0x10005000); - nv_wr32(dev, 0x1002dc, 0); - nv_wr32(dev, 0x100210, 0x80000000); - } - -- kfree(pll); -+cleanup: -+ /* unfreeze PFIFO */ -+ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); -+ /* restore ctxprog to normal */ -+ nv_wr32(dev, 0x400324, 0x00000000); -+ nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ -+ /* unblock it if necessary */ -+ if (nv_rd32(dev, 0x400308) == 0x0050001c) -+ nv_mask(dev, 0x400824, 0x10000000, 0x10000000); -+ spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); -+ kfree(info); - } -- -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_copy.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_copy.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_copy.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_copy.c 2011-07-26 07:03:44.503051927 +0200 -@@ -48,14 +48,14 @@ - struct nouveau_gpuobj *ctx = NULL; - int ret; - -- ret = nouveau_gpuobj_new(dev, NULL, 256, 256, -+ ret = nouveau_gpuobj_new(dev, chan, 256, 256, - NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER | - NVOBJ_FLAG_ZERO_ALLOC, &ctx); - if (ret) - return ret; - -- nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst)); -- nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst)); -+ nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->linst)); -+ nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->linst)); - dev_priv->engine.instmem.flush(dev); - - chan->engctx[engine] = ctx; -@@ -127,7 +127,7 @@ - } - - static int --nvc0_copy_fini(struct drm_device *dev, int engine) -+nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) - { - struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_fb.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fb.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_fb.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fb.c 2011-07-26 07:03:44.503051927 +0200 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2010 Red Hat Inc. -+ * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), -@@ -23,16 +23,80 @@ - */ - - #include "drmP.h" -- -+#include "drm.h" - #include "nouveau_drv.h" -+#include "nouveau_drm.h" -+ -+struct nvc0_fb_priv { -+ struct page *r100c10_page; -+ dma_addr_t r100c10; -+}; -+ -+static void -+nvc0_fb_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nvc0_fb_priv *priv = pfb->priv; -+ -+ if (priv->r100c10_page) { -+ pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, -+ PCI_DMA_BIDIRECTIONAL); -+ __free_page(priv->r100c10_page); -+ } -+ -+ kfree(priv); -+ pfb->priv = NULL; -+} -+ -+static int -+nvc0_fb_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; -+ struct nvc0_fb_priv *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ pfb->priv = priv; -+ -+ priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); -+ if (!priv->r100c10_page) { -+ nvc0_fb_destroy(dev); -+ return -ENOMEM; -+ } -+ -+ priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, -+ PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); -+ if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { -+ nvc0_fb_destroy(dev); -+ return -EFAULT; -+ } -+ -+ return 0; -+} - - int - nvc0_fb_init(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvc0_fb_priv *priv; -+ int ret; -+ -+ if (!dev_priv->engine.fb.priv) { -+ ret = nvc0_fb_create(dev); -+ if (ret) -+ return ret; -+ } -+ priv = dev_priv->engine.fb.priv; -+ -+ nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); - return 0; - } - - void - nvc0_fb_takedown(struct drm_device *dev) - { -+ nvc0_fb_destroy(dev); - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fbcon.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_fbcon.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fbcon.c 2011-07-26 07:03:44.504051939 +0200 -@@ -159,7 +159,7 @@ - struct drm_device *dev = nfbdev->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->channel; -- struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; -+ struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; - int ret, format; - - ret = nouveau_gpuobj_gr_new(chan, 0x902d, 0x902d); -@@ -203,8 +203,8 @@ - BEGIN_NVC0(chan, 2, NvSub2D, 0x0000, 1); - OUT_RING (chan, 0x0000902d); - BEGIN_NVC0(chan, 2, NvSub2D, 0x0104, 2); -- OUT_RING (chan, upper_32_bits(chan->notifier_bo->bo.offset)); -- OUT_RING (chan, lower_32_bits(chan->notifier_bo->bo.offset)); -+ OUT_RING (chan, upper_32_bits(chan->notifier_vma.offset)); -+ OUT_RING (chan, lower_32_bits(chan->notifier_vma.offset)); - BEGIN_NVC0(chan, 2, NvSub2D, 0x0290, 1); - OUT_RING (chan, 0); - BEGIN_NVC0(chan, 2, NvSub2D, 0x0888, 1); -@@ -249,8 +249,8 @@ - OUT_RING (chan, info->fix.line_length); - OUT_RING (chan, info->var.xres_virtual); - OUT_RING (chan, info->var.yres_virtual); -- OUT_RING (chan, upper_32_bits(nvbo->vma.offset)); -- OUT_RING (chan, lower_32_bits(nvbo->vma.offset)); -+ OUT_RING (chan, upper_32_bits(fb->vma.offset)); -+ OUT_RING (chan, lower_32_bits(fb->vma.offset)); - BEGIN_NVC0(chan, 2, NvSub2D, 0x0230, 10); - OUT_RING (chan, format); - OUT_RING (chan, 1); -@@ -260,8 +260,8 @@ - OUT_RING (chan, info->fix.line_length); - OUT_RING (chan, info->var.xres_virtual); - OUT_RING (chan, info->var.yres_virtual); -- OUT_RING (chan, upper_32_bits(nvbo->vma.offset)); -- OUT_RING (chan, lower_32_bits(nvbo->vma.offset)); -+ OUT_RING (chan, upper_32_bits(fb->vma.offset)); -+ OUT_RING (chan, lower_32_bits(fb->vma.offset)); - FIRE_RING (chan); - - return 0; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fifo.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_fifo.c 2011-07-26 07:03:44.504051939 +0200 -@@ -210,10 +210,10 @@ - int i; - - for (i = 0; i < 128; i++) { -- if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1)) -+ if (!(nv_rd32(dev, 0x003004 + (i * 8)) & 1)) - continue; - -- nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000); -+ nv_mask(dev, 0x003004 + (i * 8), 0x00000001, 0x00000000); - nv_wr32(dev, 0x002634, i); - if (!nv_wait(dev, 0x002634, 0xffffffff, i)) { - NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n", -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.c 2011-07-26 07:03:44.505051951 +0200 -@@ -28,7 +28,34 @@ - - #include "nouveau_drv.h" - #include "nouveau_mm.h" -+ - #include "nvc0_graph.h" -+#include "nvc0_grhub.fuc.h" -+#include "nvc0_grgpc.fuc.h" -+ -+static void -+nvc0_graph_ctxctl_debug_unit(struct drm_device *dev, u32 base) -+{ -+ NV_INFO(dev, "PGRAPH: %06x - done 0x%08x\n", base, -+ nv_rd32(dev, base + 0x400)); -+ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, -+ nv_rd32(dev, base + 0x800), nv_rd32(dev, base + 0x804), -+ nv_rd32(dev, base + 0x808), nv_rd32(dev, base + 0x80c)); -+ NV_INFO(dev, "PGRAPH: %06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base, -+ nv_rd32(dev, base + 0x810), nv_rd32(dev, base + 0x814), -+ nv_rd32(dev, base + 0x818), nv_rd32(dev, base + 0x81c)); -+} -+ -+static void -+nvc0_graph_ctxctl_debug(struct drm_device *dev) -+{ -+ u32 gpcnr = nv_rd32(dev, 0x409604) & 0xffff; -+ u32 gpc; -+ -+ nvc0_graph_ctxctl_debug_unit(dev, 0x409000); -+ for (gpc = 0; gpc < gpcnr; gpc++) -+ nvc0_graph_ctxctl_debug_unit(dev, 0x502000 + (gpc * 0x8000)); -+} - - static int - nvc0_graph_load_context(struct nouveau_channel *chan) -@@ -72,24 +99,44 @@ - if (!ctx) - return -ENOMEM; - -- nvc0_graph_load_context(chan); -+ if (!nouveau_ctxfw) { -+ nv_wr32(dev, 0x409840, 0x80000000); -+ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); -+ nv_wr32(dev, 0x409504, 0x00000001); -+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { -+ NV_ERROR(dev, "PGRAPH: HUB_SET_CHAN timeout\n"); -+ nvc0_graph_ctxctl_debug(dev); -+ ret = -EBUSY; -+ goto err; -+ } -+ } else { -+ nvc0_graph_load_context(chan); - -- nv_wo32(grch->grctx, 0x1c, 1); -- nv_wo32(grch->grctx, 0x20, 0); -- nv_wo32(grch->grctx, 0x28, 0); -- nv_wo32(grch->grctx, 0x2c, 0); -- dev_priv->engine.instmem.flush(dev); -+ nv_wo32(grch->grctx, 0x1c, 1); -+ nv_wo32(grch->grctx, 0x20, 0); -+ nv_wo32(grch->grctx, 0x28, 0); -+ nv_wo32(grch->grctx, 0x2c, 0); -+ dev_priv->engine.instmem.flush(dev); -+ } - - ret = nvc0_grctx_generate(chan); -- if (ret) { -- kfree(ctx); -- return ret; -- } -+ if (ret) -+ goto err; - -- ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); -- if (ret) { -- kfree(ctx); -- return ret; -+ if (!nouveau_ctxfw) { -+ nv_wr32(dev, 0x409840, 0x80000000); -+ nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); -+ nv_wr32(dev, 0x409504, 0x00000002); -+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { -+ NV_ERROR(dev, "PGRAPH: HUB_CTX_SAVE timeout\n"); -+ nvc0_graph_ctxctl_debug(dev); -+ ret = -EBUSY; -+ goto err; -+ } -+ } else { -+ ret = nvc0_graph_unload_context_to(dev, chan->ramin->vinst); -+ if (ret) -+ goto err; - } - - for (i = 0; i < priv->grctx_size; i += 4) -@@ -97,6 +144,10 @@ - - priv->grctx_vals = ctx; - return 0; -+ -+err: -+ kfree(ctx); -+ return ret; - } - - static int -@@ -108,50 +159,50 @@ - int i = 0, gpc, tp, ret; - u32 magic; - -- ret = nouveau_gpuobj_new(dev, NULL, 0x2000, 256, NVOBJ_FLAG_VM, -+ ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM, - &grch->unk408004); - if (ret) - return ret; - -- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 256, NVOBJ_FLAG_VM, -+ ret = nouveau_gpuobj_new(dev, chan, 0x8000, 256, NVOBJ_FLAG_VM, - &grch->unk40800c); - if (ret) - return ret; - -- ret = nouveau_gpuobj_new(dev, NULL, 384 * 1024, 4096, -+ ret = nouveau_gpuobj_new(dev, chan, 384 * 1024, 4096, - NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER, - &grch->unk418810); - if (ret) - return ret; - -- ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0, NVOBJ_FLAG_VM, -+ ret = nouveau_gpuobj_new(dev, chan, 0x1000, 0, NVOBJ_FLAG_VM, - &grch->mmio); - if (ret) - return ret; - - - nv_wo32(grch->mmio, i++ * 4, 0x00408004); -- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8); -+ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00408008); - nv_wo32(grch->mmio, i++ * 4, 0x80000018); - - nv_wo32(grch->mmio, i++ * 4, 0x0040800c); -- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8); -+ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00408010); - nv_wo32(grch->mmio, i++ * 4, 0x80000000); - - nv_wo32(grch->mmio, i++ * 4, 0x00418810); -- nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->vinst >> 12); -+ nv_wo32(grch->mmio, i++ * 4, 0x80000000 | grch->unk418810->linst >> 12); - nv_wo32(grch->mmio, i++ * 4, 0x00419848); -- nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->vinst >> 12); -+ nv_wo32(grch->mmio, i++ * 4, 0x10000000 | grch->unk418810->linst >> 12); - - nv_wo32(grch->mmio, i++ * 4, 0x00419004); -- nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->vinst >> 8); -+ nv_wo32(grch->mmio, i++ * 4, grch->unk40800c->linst >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x00419008); - nv_wo32(grch->mmio, i++ * 4, 0x00000000); - - nv_wo32(grch->mmio, i++ * 4, 0x00418808); -- nv_wo32(grch->mmio, i++ * 4, grch->unk408004->vinst >> 8); -+ nv_wo32(grch->mmio, i++ * 4, grch->unk408004->linst >> 8); - nv_wo32(grch->mmio, i++ * 4, 0x0041880c); - nv_wo32(grch->mmio, i++ * 4, 0x80000018); - -@@ -159,7 +210,7 @@ - nv_wo32(grch->mmio, i++ * 4, 0x00405830); - nv_wo32(grch->mmio, i++ * 4, magic); - for (gpc = 0; gpc < priv->gpc_nr; gpc++) { -- for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x02fc) { -+ for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) { - u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800); - nv_wo32(grch->mmio, i++ * 4, reg); - nv_wo32(grch->mmio, i++ * 4, magic); -@@ -186,7 +237,7 @@ - return -ENOMEM; - chan->engctx[NVOBJ_ENGINE_GR] = grch; - -- ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, -+ ret = nouveau_gpuobj_new(dev, chan, priv->grctx_size, 256, - NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, - &grch->grctx); - if (ret) -@@ -197,8 +248,8 @@ - if (ret) - goto error; - -- nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->vinst) | 4); -- nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->vinst)); -+ nv_wo32(chan->ramin, 0x0210, lower_32_bits(grctx->linst) | 4); -+ nv_wo32(chan->ramin, 0x0214, upper_32_bits(grctx->linst)); - pinstmem->flush(dev); - - if (!priv->grctx_vals) { -@@ -210,15 +261,20 @@ - for (i = 0; i < priv->grctx_size; i += 4) - nv_wo32(grctx, i, priv->grctx_vals[i / 4]); - -- nv_wo32(grctx, 0xf4, 0); -- nv_wo32(grctx, 0xf8, 0); -- nv_wo32(grctx, 0x10, grch->mmio_nr); -- nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); -- nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); -- nv_wo32(grctx, 0x1c, 1); -- nv_wo32(grctx, 0x20, 0); -- nv_wo32(grctx, 0x28, 0); -- nv_wo32(grctx, 0x2c, 0); -+ if (!nouveau_ctxfw) { -+ nv_wo32(grctx, 0x00, grch->mmio_nr); -+ nv_wo32(grctx, 0x04, grch->mmio->linst >> 8); -+ } else { -+ nv_wo32(grctx, 0xf4, 0); -+ nv_wo32(grctx, 0xf8, 0); -+ nv_wo32(grctx, 0x10, grch->mmio_nr); -+ nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->linst)); -+ nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->linst)); -+ nv_wo32(grctx, 0x1c, 1); -+ nv_wo32(grctx, 0x20, 0); -+ nv_wo32(grctx, 0x28, 0); -+ nv_wo32(grctx, 0x2c, 0); -+ } - pinstmem->flush(dev); - return 0; - -@@ -248,7 +304,7 @@ - } - - static int --nvc0_graph_fini(struct drm_device *dev, int engine) -+nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) - { - return 0; - } -@@ -296,6 +352,7 @@ - nvc0_graph_init_gpc_0(struct drm_device *dev) - { - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); -+ const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tp_total); - u32 data[TP_MAX / 8]; - u8 tpnr[GPC_MAX]; - int i, gpc, tpc; -@@ -307,13 +364,6 @@ - * 465: 3/4/4/0 4 7 - * 470: 3/3/4/4 5 5 - * 480: 3/4/4/4 6 6 -- * -- * magicgpc918 -- * 450: 00200000 00000000001000000000000000000000 -- * 460: 00124925 00000000000100100100100100100101 -- * 465: 000ba2e9 00000000000010111010001011101001 -- * 470: 00092493 00000000000010010010010010010011 -- * 480: 00088889 00000000000010001000100010001001 - */ - - memset(data, 0x00, sizeof(data)); -@@ -336,11 +386,11 @@ - nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | - priv->tp_nr[gpc]); - nv_wr32(dev, GPC_UNIT(gpc, 0x0910), 0x00040000 | priv->tp_total); -- nv_wr32(dev, GPC_UNIT(gpc, 0x0918), priv->magicgpc918); -+ nv_wr32(dev, GPC_UNIT(gpc, 0x0918), magicgpc918); - } - -- nv_wr32(dev, GPC_BCAST(0x1bd4), priv->magicgpc918); -- nv_wr32(dev, GPC_BCAST(0x08ac), priv->rop_nr); -+ nv_wr32(dev, GPC_BCAST(0x1bd4), magicgpc918); -+ nv_wr32(dev, GPC_BCAST(0x08ac), nv_rd32(dev, 0x100800)); - } - - static void -@@ -419,8 +469,51 @@ - static int - nvc0_graph_init_ctxctl(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); - u32 r000260; -+ int i; -+ -+ if (!nouveau_ctxfw) { -+ /* load HUB microcode */ -+ r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); -+ nv_wr32(dev, 0x4091c0, 0x01000000); -+ for (i = 0; i < sizeof(nvc0_grhub_data) / 4; i++) -+ nv_wr32(dev, 0x4091c4, nvc0_grhub_data[i]); -+ -+ nv_wr32(dev, 0x409180, 0x01000000); -+ for (i = 0; i < sizeof(nvc0_grhub_code) / 4; i++) { -+ if ((i & 0x3f) == 0) -+ nv_wr32(dev, 0x409188, i >> 6); -+ nv_wr32(dev, 0x409184, nvc0_grhub_code[i]); -+ } -+ -+ /* load GPC microcode */ -+ nv_wr32(dev, 0x41a1c0, 0x01000000); -+ for (i = 0; i < sizeof(nvc0_grgpc_data) / 4; i++) -+ nv_wr32(dev, 0x41a1c4, nvc0_grgpc_data[i]); -+ -+ nv_wr32(dev, 0x41a180, 0x01000000); -+ for (i = 0; i < sizeof(nvc0_grgpc_code) / 4; i++) { -+ if ((i & 0x3f) == 0) -+ nv_wr32(dev, 0x41a188, i >> 6); -+ nv_wr32(dev, 0x41a184, nvc0_grgpc_code[i]); -+ } -+ nv_wr32(dev, 0x000260, r000260); -+ -+ /* start HUB ucode running, it'll init the GPCs */ -+ nv_wr32(dev, 0x409800, dev_priv->chipset); -+ nv_wr32(dev, 0x40910c, 0x00000000); -+ nv_wr32(dev, 0x409100, 0x00000002); -+ if (!nv_wait(dev, 0x409800, 0x80000000, 0x80000000)) { -+ NV_ERROR(dev, "PGRAPH: HUB_INIT timed out\n"); -+ nvc0_graph_ctxctl_debug(dev); -+ return -EBUSY; -+ } -+ -+ priv->grctx_size = nv_rd32(dev, 0x409804); -+ return 0; -+ } - - /* load fuc microcode */ - r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); -@@ -528,6 +621,22 @@ - } - - static void -+nvc0_graph_ctxctl_isr(struct drm_device *dev) -+{ -+ u32 ustat = nv_rd32(dev, 0x409c18); -+ -+ if (ustat & 0x00000001) -+ NV_INFO(dev, "PGRAPH: CTXCTRL ucode error\n"); -+ if (ustat & 0x00080000) -+ NV_INFO(dev, "PGRAPH: CTXCTRL watchdog timeout\n"); -+ if (ustat & ~0x00080001) -+ NV_INFO(dev, "PGRAPH: CTXCTRL 0x%08x\n", ustat); -+ -+ nvc0_graph_ctxctl_debug(dev); -+ nv_wr32(dev, 0x409c20, ustat); -+} -+ -+static void - nvc0_graph_isr(struct drm_device *dev) - { - u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; -@@ -578,11 +687,7 @@ - } - - if (stat & 0x00080000) { -- u32 ustat = nv_rd32(dev, 0x409c18); -- -- NV_INFO(dev, "PGRAPH: CTXCTRL ustat 0x%08x\n", ustat); -- -- nv_wr32(dev, 0x409c20, ustat); -+ nvc0_graph_ctxctl_isr(dev); - nv_wr32(dev, 0x400100, 0x00080000); - stat &= ~0x00080000; - } -@@ -606,7 +711,7 @@ - u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); - u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); - -- NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); -+ NV_DEBUG(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); - units &= ~(1 << unit); - } - } -@@ -651,10 +756,12 @@ - { - struct nvc0_graph_priv *priv = nv_engine(dev, engine); - -- nvc0_graph_destroy_fw(&priv->fuc409c); -- nvc0_graph_destroy_fw(&priv->fuc409d); -- nvc0_graph_destroy_fw(&priv->fuc41ac); -- nvc0_graph_destroy_fw(&priv->fuc41ad); -+ if (nouveau_ctxfw) { -+ nvc0_graph_destroy_fw(&priv->fuc409c); -+ nvc0_graph_destroy_fw(&priv->fuc409d); -+ nvc0_graph_destroy_fw(&priv->fuc41ac); -+ nvc0_graph_destroy_fw(&priv->fuc41ad); -+ } - - nouveau_irq_unregister(dev, 12); - nouveau_irq_unregister(dev, 25); -@@ -675,13 +782,10 @@ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_graph_priv *priv; - int ret, gpc, i; -+ u32 fermi; - -- switch (dev_priv->chipset) { -- case 0xc0: -- case 0xc3: -- case 0xc4: -- break; -- default: -+ fermi = nvc0_graph_class(dev); -+ if (!fermi) { - NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n"); - return 0; - } -@@ -701,15 +805,17 @@ - nouveau_irq_register(dev, 12, nvc0_graph_isr); - nouveau_irq_register(dev, 25, nvc0_runk140_isr); - -- if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || -- nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || -- nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || -- nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { -- ret = 0; -- goto error; -+ if (nouveau_ctxfw) { -+ NV_INFO(dev, "PGRAPH: using external firmware\n"); -+ if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) || -+ nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) || -+ nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) || -+ nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) { -+ ret = 0; -+ goto error; -+ } - } - -- - ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); - if (ret) - goto error; -@@ -735,25 +841,31 @@ - case 0xc0: - if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ - priv->magic_not_rop_nr = 0x07; -- /* filled values up to tp_total, the rest 0 */ -- priv->magicgpc918 = 0x000ba2e9; - } else - if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ - priv->magic_not_rop_nr = 0x05; -- priv->magicgpc918 = 0x00092493; - } else - if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ - priv->magic_not_rop_nr = 0x06; -- priv->magicgpc918 = 0x00088889; - } - break; - case 0xc3: /* 450, 4/0/0/0, 2 */ - priv->magic_not_rop_nr = 0x03; -- priv->magicgpc918 = 0x00200000; - break; - case 0xc4: /* 460, 3/4/0/0, 4 */ - priv->magic_not_rop_nr = 0x01; -- priv->magicgpc918 = 0x00124925; -+ break; -+ case 0xc1: /* 2/0/0/0, 1 */ -+ priv->magic_not_rop_nr = 0x01; -+ break; -+ case 0xc8: /* 4/4/3/4, 5 */ -+ priv->magic_not_rop_nr = 0x06; -+ break; -+ case 0xce: /* 4/4/0/0, 4 */ -+ priv->magic_not_rop_nr = 0x03; -+ break; -+ case 0xcf: /* 4/0/0/0, 3 */ -+ priv->magic_not_rop_nr = 0x03; - break; - } - -@@ -763,13 +875,16 @@ - priv->tp_nr[3], priv->rop_nr); - /* use 0xc3's values... */ - priv->magic_not_rop_nr = 0x03; -- priv->magicgpc918 = 0x00200000; - } - - NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ - NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ - NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); - NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ -+ if (fermi >= 0x9197) -+ NVOBJ_CLASS(dev, 0x9197, GR); /* 3D (NVC1-) */ -+ if (fermi >= 0x9297) -+ NVOBJ_CLASS(dev, 0x9297, GR); /* 3D (NVC8-) */ - NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ - return 0; - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.fuc linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.fuc ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.fuc 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.fuc 2011-07-26 07:03:44.506051963 +0200 -@@ -0,0 +1,400 @@ -+/* fuc microcode util functions for nvc0 PGRAPH -+ * -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+define(`mmctx_data', `.b32 eval((($2 - 1) << 26) | $1)') -+define(`queue_init', `.skip eval((2 * 4) + ((8 * 4) * 2))') -+ -+ifdef(`include_code', ` -+// Error codes -+define(`E_BAD_COMMAND', 0x01) -+define(`E_CMD_OVERFLOW', 0x02) -+ -+// Util macros to help with debugging ucode hangs etc -+define(`T_WAIT', 0) -+define(`T_MMCTX', 1) -+define(`T_STRWAIT', 2) -+define(`T_STRINIT', 3) -+define(`T_AUTO', 4) -+define(`T_CHAN', 5) -+define(`T_LOAD', 6) -+define(`T_SAVE', 7) -+define(`T_LCHAN', 8) -+define(`T_LCTXH', 9) -+ -+define(`trace_set', ` -+ mov $r8 0x83c -+ shl b32 $r8 6 -+ clear b32 $r9 -+ bset $r9 $1 -+ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] -+') -+ -+define(`trace_clr', ` -+ mov $r8 0x85c -+ shl b32 $r8 6 -+ clear b32 $r9 -+ bset $r9 $1 -+ iowr I[$r8 + 0x000] $r9 // CC_SCRATCH[7] -+') -+ -+// queue_put - add request to queue -+// -+// In : $r13 queue pointer -+// $r14 command -+// $r15 data -+// -+queue_put: -+ // make sure we have space.. -+ ld b32 $r8 D[$r13 + 0x0] // GET -+ ld b32 $r9 D[$r13 + 0x4] // PUT -+ xor $r8 8 -+ cmpu b32 $r8 $r9 -+ bra ne queue_put_next -+ mov $r15 E_CMD_OVERFLOW -+ call error -+ ret -+ -+ // store cmd/data on queue -+ queue_put_next: -+ and $r8 $r9 7 -+ shl b32 $r8 3 -+ add b32 $r8 $r13 -+ add b32 $r8 8 -+ st b32 D[$r8 + 0x0] $r14 -+ st b32 D[$r8 + 0x4] $r15 -+ -+ // update PUT -+ add b32 $r9 1 -+ and $r9 0xf -+ st b32 D[$r13 + 0x4] $r9 -+ ret -+ -+// queue_get - fetch request from queue -+// -+// In : $r13 queue pointer -+// -+// Out: $p1 clear on success (data available) -+// $r14 command -+// $r15 data -+// -+queue_get: -+ bset $flags $p1 -+ ld b32 $r8 D[$r13 + 0x0] // GET -+ ld b32 $r9 D[$r13 + 0x4] // PUT -+ cmpu b32 $r8 $r9 -+ bra e queue_get_done -+ // fetch first cmd/data pair -+ and $r9 $r8 7 -+ shl b32 $r9 3 -+ add b32 $r9 $r13 -+ add b32 $r9 8 -+ ld b32 $r14 D[$r9 + 0x0] -+ ld b32 $r15 D[$r9 + 0x4] -+ -+ // update GET -+ add b32 $r8 1 -+ and $r8 0xf -+ st b32 D[$r13 + 0x0] $r8 -+ bclr $flags $p1 -+queue_get_done: -+ ret -+ -+// nv_rd32 - read 32-bit value from nv register -+// -+// In : $r14 register -+// Out: $r15 value -+// -+nv_rd32: -+ mov $r11 0x728 -+ shl b32 $r11 6 -+ mov b32 $r12 $r14 -+ bset $r12 31 // MMIO_CTRL_PENDING -+ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL -+ nv_rd32_wait: -+ iord $r12 I[$r11 + 0x000] -+ xbit $r12 $r12 31 -+ bra ne nv_rd32_wait -+ mov $r10 6 // DONE_MMIO_RD -+ call wait_doneo -+ iord $r15 I[$r11 + 0x100] // MMIO_RDVAL -+ ret -+ -+// nv_wr32 - write 32-bit value to nv register -+// -+// In : $r14 register -+// $r15 value -+// -+nv_wr32: -+ mov $r11 0x728 -+ shl b32 $r11 6 -+ iowr I[$r11 + 0x200] $r15 // MMIO_WRVAL -+ mov b32 $r12 $r14 -+ bset $r12 31 // MMIO_CTRL_PENDING -+ bset $r12 30 // MMIO_CTRL_WRITE -+ iowr I[$r11 + 0x000] $r12 // MMIO_CTRL -+ nv_wr32_wait: -+ iord $r12 I[$r11 + 0x000] -+ xbit $r12 $r12 31 -+ bra ne nv_wr32_wait -+ ret -+ -+// (re)set watchdog timer -+// -+// In : $r15 timeout -+// -+watchdog_reset: -+ mov $r8 0x430 -+ shl b32 $r8 6 -+ bset $r15 31 -+ iowr I[$r8 + 0x000] $r15 -+ ret -+ -+// clear watchdog timer -+watchdog_clear: -+ mov $r8 0x430 -+ shl b32 $r8 6 -+ iowr I[$r8 + 0x000] $r0 -+ ret -+ -+// wait_done{z,o} - wait on FUC_DONE bit to become clear/set -+// -+// In : $r10 bit to wait on -+// -+define(`wait_done', ` -+$1: -+ trace_set(T_WAIT); -+ mov $r8 0x818 -+ shl b32 $r8 6 -+ iowr I[$r8 + 0x000] $r10 // CC_SCRATCH[6] = wait bit -+ wait_done_$1: -+ mov $r8 0x400 -+ shl b32 $r8 6 -+ iord $r8 I[$r8 + 0x000] // DONE -+ xbit $r8 $r8 $r10 -+ bra $2 wait_done_$1 -+ trace_clr(T_WAIT) -+ ret -+') -+wait_done(wait_donez, ne) -+wait_done(wait_doneo, e) -+ -+// mmctx_size - determine size of a mmio list transfer -+// -+// In : $r14 mmio list head -+// $r15 mmio list tail -+// Out: $r15 transfer size (in bytes) -+// -+mmctx_size: -+ clear b32 $r9 -+ nv_mmctx_size_loop: -+ ld b32 $r8 D[$r14] -+ shr b32 $r8 26 -+ add b32 $r8 1 -+ shl b32 $r8 2 -+ add b32 $r9 $r8 -+ add b32 $r14 4 -+ cmpu b32 $r14 $r15 -+ bra ne nv_mmctx_size_loop -+ mov b32 $r15 $r9 -+ ret -+ -+// mmctx_xfer - execute a list of mmio transfers -+// -+// In : $r10 flags -+// bit 0: direction (0 = save, 1 = load) -+// bit 1: set if first transfer -+// bit 2: set if last transfer -+// $r11 base -+// $r12 mmio list head -+// $r13 mmio list tail -+// $r14 multi_stride -+// $r15 multi_mask -+// -+mmctx_xfer: -+ trace_set(T_MMCTX) -+ mov $r8 0x710 -+ shl b32 $r8 6 -+ clear b32 $r9 -+ or $r11 $r11 -+ bra e mmctx_base_disabled -+ iowr I[$r8 + 0x000] $r11 // MMCTX_BASE -+ bset $r9 0 // BASE_EN -+ mmctx_base_disabled: -+ or $r14 $r14 -+ bra e mmctx_multi_disabled -+ iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE -+ iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK -+ bset $r9 1 // MULTI_EN -+ mmctx_multi_disabled: -+ add b32 $r8 0x100 -+ -+ xbit $r11 $r10 0 -+ shl b32 $r11 16 // DIR -+ bset $r11 12 // QLIMIT = 0x10 -+ xbit $r14 $r10 1 -+ shl b32 $r14 17 -+ or $r11 $r14 // START_TRIGGER -+ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL -+ -+ // loop over the mmio list, and send requests to the hw -+ mmctx_exec_loop: -+ // wait for space in mmctx queue -+ mmctx_wait_free: -+ iord $r14 I[$r8 + 0x000] // MMCTX_CTRL -+ and $r14 0x1f -+ bra e mmctx_wait_free -+ -+ // queue up an entry -+ ld b32 $r14 D[$r12] -+ or $r14 $r9 -+ iowr I[$r8 + 0x300] $r14 -+ add b32 $r12 4 -+ cmpu b32 $r12 $r13 -+ bra ne mmctx_exec_loop -+ -+ xbit $r11 $r10 2 -+ bra ne mmctx_stop -+ // wait for queue to empty -+ mmctx_fini_wait: -+ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL -+ and $r11 0x1f -+ cmpu b32 $r11 0x10 -+ bra ne mmctx_fini_wait -+ mov $r10 2 // DONE_MMCTX -+ call wait_donez -+ bra mmctx_done -+ mmctx_stop: -+ xbit $r11 $r10 0 -+ shl b32 $r11 16 // DIR -+ bset $r11 12 // QLIMIT = 0x10 -+ bset $r11 18 // STOP_TRIGGER -+ iowr I[$r8 + 0x000] $r11 // MMCTX_CTRL -+ mmctx_stop_wait: -+ // wait for STOP_TRIGGER to clear -+ iord $r11 I[$r8 + 0x000] // MMCTX_CTRL -+ xbit $r11 $r11 18 -+ bra ne mmctx_stop_wait -+ mmctx_done: -+ trace_clr(T_MMCTX) -+ ret -+ -+// Wait for DONE_STRAND -+// -+strand_wait: -+ push $r10 -+ mov $r10 2 -+ call wait_donez -+ pop $r10 -+ ret -+ -+// unknown - call before issuing strand commands -+// -+strand_pre: -+ mov $r8 0x4afc -+ sethi $r8 0x20000 -+ mov $r9 0xc -+ iowr I[$r8] $r9 -+ call strand_wait -+ ret -+ -+// unknown - call after issuing strand commands -+// -+strand_post: -+ mov $r8 0x4afc -+ sethi $r8 0x20000 -+ mov $r9 0xd -+ iowr I[$r8] $r9 -+ call strand_wait -+ ret -+ -+// Selects strand set?! -+// -+// In: $r14 id -+// -+strand_set: -+ mov $r10 0x4ffc -+ sethi $r10 0x20000 -+ sub b32 $r11 $r10 0x500 -+ mov $r12 0xf -+ iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf -+ mov $r12 0xb -+ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb -+ call strand_wait -+ iowr I[$r10 + 0x000] $r14 // 0x93c = -+ mov $r12 0xa -+ iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa -+ call strand_wait -+ ret -+ -+// Initialise strand context data -+// -+// In : $r15 context base -+// Out: $r15 context size (in bytes) -+// -+// Strandset(?) 3 hardcoded currently -+// -+strand_ctx_init: -+ trace_set(T_STRINIT) -+ call strand_pre -+ mov $r14 3 -+ call strand_set -+ mov $r10 0x46fc -+ sethi $r10 0x20000 -+ add b32 $r11 $r10 0x400 -+ iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 -+ mov $r12 1 -+ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE -+ call strand_wait -+ sub b32 $r12 $r0 1 -+ iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff -+ mov $r12 2 -+ iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT -+ call strand_wait -+ call strand_post -+ -+ // read the size of each strand, poke the context offset of -+ // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry -+ // about it later then. -+ mov $r8 0x880 -+ shl b32 $r8 6 -+ iord $r9 I[$r8 + 0x000] // STRANDS -+ add b32 $r8 0x2200 -+ shr b32 $r14 $r15 8 -+ ctx_init_strand_loop: -+ iowr I[$r8 + 0x000] $r14 // STRAND_SAVE_SWBASE -+ iowr I[$r8 + 0x100] $r14 // STRAND_LOAD_SWBASE -+ iord $r10 I[$r8 + 0x200] // STRAND_SIZE -+ shr b32 $r10 6 -+ add b32 $r10 1 -+ add b32 $r14 $r10 -+ add b32 $r8 4 -+ sub b32 $r9 1 -+ bra ne ctx_init_strand_loop -+ -+ shl b32 $r14 8 -+ sub b32 $r15 $r14 $r15 -+ trace_clr(T_STRINIT) -+ ret -+') -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.h linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.h ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_graph.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_graph.h 2011-07-26 07:03:44.507051975 +0200 -@@ -57,8 +57,7 @@ - struct nouveau_gpuobj *unk4188b4; - struct nouveau_gpuobj *unk4188b8; - -- u8 magic_not_rop_nr; -- u32 magicgpc918; -+ u8 magic_not_rop_nr; - }; - - struct nvc0_graph_chan { -@@ -72,4 +71,26 @@ - - int nvc0_grctx_generate(struct nouveau_channel *); - -+/* nvc0_graph.c uses this also to determine supported chipsets */ -+static inline u32 -+nvc0_graph_class(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ switch (dev_priv->chipset) { -+ case 0xc0: -+ case 0xc3: -+ case 0xc4: -+ case 0xce: /* guess, mmio trace shows only 0x9097 state */ -+ case 0xcf: /* guess, mmio trace shows only 0x9097 state */ -+ return 0x9097; -+ case 0xc1: -+ return 0x9197; -+ case 0xc8: -+ return 0x9297; -+ default: -+ return 0; -+ } -+} -+ - #endif -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_grctx.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grctx.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_grctx.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grctx.c 2011-07-26 07:03:44.509051999 +0200 -@@ -45,6 +45,9 @@ - static void - nvc0_grctx_generate_9097(struct drm_device *dev) - { -+ u32 fermi = nvc0_graph_class(dev); -+ u32 mthd; -+ - nv_mthd(dev, 0x9097, 0x0800, 0x00000000); - nv_mthd(dev, 0x9097, 0x0840, 0x00000000); - nv_mthd(dev, 0x9097, 0x0880, 0x00000000); -@@ -824,134 +827,10 @@ - nv_mthd(dev, 0x9097, 0x1eb8, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ed8, 0x00000001); - nv_mthd(dev, 0x9097, 0x1ef8, 0x00000001); -- nv_mthd(dev, 0x9097, 0x3400, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3404, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3408, 0x00000000); -- nv_mthd(dev, 0x9097, 0x340c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3410, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3414, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3418, 0x00000000); -- nv_mthd(dev, 0x9097, 0x341c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3420, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3424, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3428, 0x00000000); -- nv_mthd(dev, 0x9097, 0x342c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3430, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3434, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3438, 0x00000000); -- nv_mthd(dev, 0x9097, 0x343c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3440, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3444, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3448, 0x00000000); -- nv_mthd(dev, 0x9097, 0x344c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3450, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3454, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3458, 0x00000000); -- nv_mthd(dev, 0x9097, 0x345c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3460, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3464, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3468, 0x00000000); -- nv_mthd(dev, 0x9097, 0x346c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3470, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3474, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3478, 0x00000000); -- nv_mthd(dev, 0x9097, 0x347c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3480, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3484, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3488, 0x00000000); -- nv_mthd(dev, 0x9097, 0x348c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3490, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3494, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3498, 0x00000000); -- nv_mthd(dev, 0x9097, 0x349c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34a0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34a4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34a8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34ac, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34b0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34b4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34b8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34bc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34c0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34c4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34c8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34cc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34d0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34d4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34d8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34dc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34e0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34e4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34e8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34ec, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34f0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34f4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34f8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x34fc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3500, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3504, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3508, 0x00000000); -- nv_mthd(dev, 0x9097, 0x350c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3510, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3514, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3518, 0x00000000); -- nv_mthd(dev, 0x9097, 0x351c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3520, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3524, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3528, 0x00000000); -- nv_mthd(dev, 0x9097, 0x352c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3530, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3534, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3538, 0x00000000); -- nv_mthd(dev, 0x9097, 0x353c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3540, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3544, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3548, 0x00000000); -- nv_mthd(dev, 0x9097, 0x354c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3550, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3554, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3558, 0x00000000); -- nv_mthd(dev, 0x9097, 0x355c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3560, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3564, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3568, 0x00000000); -- nv_mthd(dev, 0x9097, 0x356c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3570, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3574, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3578, 0x00000000); -- nv_mthd(dev, 0x9097, 0x357c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3580, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3584, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3588, 0x00000000); -- nv_mthd(dev, 0x9097, 0x358c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3590, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3594, 0x00000000); -- nv_mthd(dev, 0x9097, 0x3598, 0x00000000); -- nv_mthd(dev, 0x9097, 0x359c, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35a0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35a4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35a8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35ac, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35b0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35b4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35b8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35bc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35c0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35c4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35c8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35cc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35d0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35d4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35d8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35dc, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35e0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35e4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35e8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35ec, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35f0, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35f4, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35f8, 0x00000000); -- nv_mthd(dev, 0x9097, 0x35fc, 0x00000000); -+ if (fermi == 0x9097) { -+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) -+ nv_mthd(dev, 0x9097, mthd, 0x00000000); -+ } - nv_mthd(dev, 0x9097, 0x030c, 0x00000001); - nv_mthd(dev, 0x9097, 0x1944, 0x00000000); - nv_mthd(dev, 0x9097, 0x1514, 0x00000000); -@@ -1321,6 +1200,37 @@ - } - - static void -+nvc0_grctx_generate_9197(struct drm_device *dev) -+{ -+ u32 fermi = nvc0_graph_class(dev); -+ u32 mthd; -+ -+ if (fermi == 0x9197) { -+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) -+ nv_mthd(dev, 0x9197, mthd, 0x00000000); -+ } -+ nv_mthd(dev, 0x9197, 0x02e4, 0x0000b001); -+} -+ -+static void -+nvc0_grctx_generate_9297(struct drm_device *dev) -+{ -+ u32 fermi = nvc0_graph_class(dev); -+ u32 mthd; -+ -+ if (fermi == 0x9297) { -+ for (mthd = 0x3400; mthd <= 0x35fc; mthd += 4) -+ nv_mthd(dev, 0x9297, mthd, 0x00000000); -+ } -+ nv_mthd(dev, 0x9297, 0x036c, 0x00000000); -+ nv_mthd(dev, 0x9297, 0x0370, 0x00000000); -+ nv_mthd(dev, 0x9297, 0x07a4, 0x00000000); -+ nv_mthd(dev, 0x9297, 0x07a8, 0x00000000); -+ nv_mthd(dev, 0x9297, 0x0374, 0x00000000); -+ nv_mthd(dev, 0x9297, 0x0378, 0x00000020); -+} -+ -+static void - nvc0_grctx_generate_902d(struct drm_device *dev) - { - nv_mthd(dev, 0x902d, 0x0200, 0x000000cf); -@@ -1559,8 +1469,15 @@ - static void - nvc0_grctx_generate_shaders(struct drm_device *dev) - { -- nv_wr32(dev, 0x405800, 0x078000bf); -- nv_wr32(dev, 0x405830, 0x02180000); -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ -+ if (dev_priv->chipset != 0xc1) { -+ nv_wr32(dev, 0x405800, 0x078000bf); -+ nv_wr32(dev, 0x405830, 0x02180000); -+ } else { -+ nv_wr32(dev, 0x405800, 0x0f8000bf); -+ nv_wr32(dev, 0x405830, 0x02180218); -+ } - nv_wr32(dev, 0x405834, 0x00000000); - nv_wr32(dev, 0x405838, 0x00000000); - nv_wr32(dev, 0x405854, 0x00000000); -@@ -1586,10 +1503,16 @@ - static void - nvc0_grctx_generate_unk64xx(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ - nv_wr32(dev, 0x4064a8, 0x00000000); - nv_wr32(dev, 0x4064ac, 0x00003fff); - nv_wr32(dev, 0x4064b4, 0x00000000); - nv_wr32(dev, 0x4064b8, 0x00000000); -+ if (dev_priv->chipset == 0xc1) { -+ nv_wr32(dev, 0x4064c0, 0x80140078); -+ nv_wr32(dev, 0x4064c4, 0x0086ffff); -+ } - } - - static void -@@ -1622,21 +1545,14 @@ - nvc0_grctx_generate_rop(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int chipset = dev_priv->chipset; - - /* ROPC_BROADCAST */ - nv_wr32(dev, 0x408800, 0x02802a3c); - nv_wr32(dev, 0x408804, 0x00000040); -- nv_wr32(dev, 0x408808, 0x0003e00d); -- switch (dev_priv->chipset) { -- case 0xc0: -- nv_wr32(dev, 0x408900, 0x0080b801); -- break; -- case 0xc3: -- case 0xc4: -- nv_wr32(dev, 0x408900, 0x3080b801); -- break; -- } -- nv_wr32(dev, 0x408904, 0x02000001); -+ nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005); -+ nv_wr32(dev, 0x408900, 0x3080b801); -+ nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001); - nv_wr32(dev, 0x408908, 0x00c80929); - nv_wr32(dev, 0x40890c, 0x00000000); - nv_wr32(dev, 0x408980, 0x0000011d); -@@ -1645,6 +1561,8 @@ - static void - nvc0_grctx_generate_gpc(struct drm_device *dev) - { -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int chipset = dev_priv->chipset; - int i; - - /* GPC_BROADCAST */ -@@ -1676,7 +1594,7 @@ - nv_wr32(dev, 0x41880c, 0x00000000); - nv_wr32(dev, 0x418810, 0x00000000); - nv_wr32(dev, 0x418828, 0x00008442); -- nv_wr32(dev, 0x418830, 0x00000001); -+ nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001); - nv_wr32(dev, 0x4188d8, 0x00000008); - nv_wr32(dev, 0x4188e0, 0x01000000); - nv_wr32(dev, 0x4188e8, 0x00000000); -@@ -1684,7 +1602,7 @@ - nv_wr32(dev, 0x4188f0, 0x00000000); - nv_wr32(dev, 0x4188f4, 0x00000000); - nv_wr32(dev, 0x4188f8, 0x00000000); -- nv_wr32(dev, 0x4188fc, 0x00100000); -+ nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018); - nv_wr32(dev, 0x41891c, 0x00ff00ff); - nv_wr32(dev, 0x418924, 0x00000000); - nv_wr32(dev, 0x418928, 0x00ffff00); -@@ -1715,6 +1633,8 @@ - nv_wr32(dev, 0x418c24, 0x00000000); - nv_wr32(dev, 0x418c28, 0x00000000); - nv_wr32(dev, 0x418c2c, 0x00000000); -+ if (chipset == 0xc1) -+ nv_wr32(dev, 0x418c6c, 0x00000001); - nv_wr32(dev, 0x418c80, 0x20200004); - nv_wr32(dev, 0x418c8c, 0x00000001); - nv_wr32(dev, 0x419000, 0x00000780); -@@ -1727,10 +1647,13 @@ - nvc0_grctx_generate_tp(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int chipset = dev_priv->chipset; - - /* GPC_BROADCAST.TP_BROADCAST */ -+ nv_wr32(dev, 0x419818, 0x00000000); -+ nv_wr32(dev, 0x41983c, 0x00038bc7); - nv_wr32(dev, 0x419848, 0x00000000); -- nv_wr32(dev, 0x419864, 0x0000012a); -+ nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129); - nv_wr32(dev, 0x419888, 0x00000000); - nv_wr32(dev, 0x419a00, 0x000001f0); - nv_wr32(dev, 0x419a04, 0x00000001); -@@ -1740,8 +1663,8 @@ - nv_wr32(dev, 0x419a14, 0x00000200); - nv_wr32(dev, 0x419a1c, 0x00000000); - nv_wr32(dev, 0x419a20, 0x00000800); -- if (dev_priv->chipset != 0xc0) -- nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */ -+ if (chipset != 0xc0 && chipset != 0xc8) -+ nv_wr32(dev, 0x00419ac4, 0x0007f440); - nv_wr32(dev, 0x419b00, 0x0a418820); - nv_wr32(dev, 0x419b04, 0x062080e6); - nv_wr32(dev, 0x419b08, 0x020398a4); -@@ -1749,17 +1672,22 @@ - nv_wr32(dev, 0x419b10, 0x0a418820); - nv_wr32(dev, 0x419b14, 0x000000e6); - nv_wr32(dev, 0x419bd0, 0x00900103); -- nv_wr32(dev, 0x419be0, 0x00000001); -+ nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001); - nv_wr32(dev, 0x419be4, 0x00000000); - nv_wr32(dev, 0x419c00, 0x00000002); - nv_wr32(dev, 0x419c04, 0x00000006); - nv_wr32(dev, 0x419c08, 0x00000002); - nv_wr32(dev, 0x419c20, 0x00000000); -- nv_wr32(dev, 0x419cbc, 0x28137606); -+ if (chipset == 0xce || chipset == 0xcf) -+ nv_wr32(dev, 0x419cb0, 0x00020048); -+ else -+ nv_wr32(dev, 0x419cb0, 0x00060048); - nv_wr32(dev, 0x419ce8, 0x00000000); - nv_wr32(dev, 0x419cf4, 0x00000183); -- nv_wr32(dev, 0x419d20, 0x02180000); -+ nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); - nv_wr32(dev, 0x419d24, 0x00001fff); -+ if (chipset == 0xc1) -+ nv_wr32(dev, 0x419d44, 0x02180218); - nv_wr32(dev, 0x419e04, 0x00000000); - nv_wr32(dev, 0x419e08, 0x00000000); - nv_wr32(dev, 0x419e0c, 0x00000000); -@@ -1785,11 +1713,11 @@ - nv_wr32(dev, 0x419e8c, 0x00000000); - nv_wr32(dev, 0x419e90, 0x00000000); - nv_wr32(dev, 0x419e98, 0x00000000); -- if (dev_priv->chipset != 0xc0) -+ if (chipset != 0xc0 && chipset != 0xc8) - nv_wr32(dev, 0x419ee0, 0x00011110); - nv_wr32(dev, 0x419f50, 0x00000000); - nv_wr32(dev, 0x419f54, 0x00000000); -- if (dev_priv->chipset != 0xc0) -+ if (chipset != 0xc0 && chipset != 0xc8) - nv_wr32(dev, 0x419f58, 0x00000000); - } - -@@ -1801,6 +1729,7 @@ - struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; - struct drm_device *dev = chan->dev; - int i, gpc, tp, id; -+ u32 fermi = nvc0_graph_class(dev); - u32 r000260, tmp; - - r000260 = nv_rd32(dev, 0x000260); -@@ -1857,10 +1786,7 @@ - nv_wr32(dev, 0x40587c, 0x00000000); - - if (1) { -- const u8 chipset_tp_max[] = { 16, 0, 0, 4, 8 }; -- u8 max = chipset_tp_max[dev_priv->chipset & 0x0f]; -- u8 tpnr[GPC_MAX]; -- u8 data[32]; -+ u8 tpnr[GPC_MAX], data[TP_MAX]; - - memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr)); - memset(data, 0x1f, sizeof(data)); -@@ -1874,7 +1800,7 @@ - data[tp] = gpc; - } - -- for (i = 0; i < max / 4; i++) -+ for (i = 0; i < 4; i++) - nv_wr32(dev, 0x4060a8 + (i * 4), ((u32 *)data)[i]); - } - -@@ -2633,6 +2559,8 @@ - nv_icmd(dev, 0x0000053f, 0xffff0000); - nv_icmd(dev, 0x00000585, 0x0000003f); - nv_icmd(dev, 0x00000576, 0x00000003); -+ if (dev_priv->chipset == 0xc1) -+ nv_icmd(dev, 0x0000057b, 0x00000059); - nv_icmd(dev, 0x00000586, 0x00000040); - nv_icmd(dev, 0x00000582, 0x00000080); - nv_icmd(dev, 0x00000583, 0x00000080); -@@ -2865,6 +2793,10 @@ - nv_wr32(dev, 0x404154, 0x00000400); - - nvc0_grctx_generate_9097(dev); -+ if (fermi >= 0x9197) -+ nvc0_grctx_generate_9197(dev); -+ if (fermi >= 0x9297) -+ nvc0_grctx_generate_9297(dev); - nvc0_grctx_generate_902d(dev); - nvc0_grctx_generate_9039(dev); - nvc0_grctx_generate_90c0(dev); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc 2011-07-26 07:03:44.511052023 +0200 -@@ -0,0 +1,480 @@ -+/* fuc microcode for nvc0 PGRAPH/GPC -+ * -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+/* To build: -+ * m4 nvc0_grgpc.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grgpc.fuc.h -+ */ -+ -+/* TODO -+ * - bracket certain functions with scratch writes, useful for debugging -+ * - watchdog timer around ctx operations -+ */ -+ -+.section nvc0_grgpc_data -+include(`nvc0_graph.fuc') -+gpc_id: .b32 0 -+gpc_mmio_list_head: .b32 0 -+gpc_mmio_list_tail: .b32 0 -+ -+tpc_count: .b32 0 -+tpc_mask: .b32 0 -+tpc_mmio_list_head: .b32 0 -+tpc_mmio_list_tail: .b32 0 -+ -+cmd_queue: queue_init -+ -+// chipset descriptions -+chipsets: -+.b8 0xc0 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc0_tpc_mmio_tail -+.b8 0xc1 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc1_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc1_tpc_mmio_tail -+.b8 0xc3 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc3_tpc_mmio_tail -+.b8 0xc4 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc3_tpc_mmio_tail -+.b8 0xc8 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc0_tpc_mmio_tail -+.b8 0xce 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvc3_tpc_mmio_tail -+.b8 0xcf 0 0 0 -+.b16 nvc0_gpc_mmio_head -+.b16 nvc0_gpc_mmio_tail -+.b16 nvc0_tpc_mmio_head -+.b16 nvcf_tpc_mmio_tail -+.b8 0 0 0 0 -+ -+// GPC mmio lists -+nvc0_gpc_mmio_head: -+mmctx_data(0x000380, 1) -+mmctx_data(0x000400, 6) -+mmctx_data(0x000450, 9) -+mmctx_data(0x000600, 1) -+mmctx_data(0x000684, 1) -+mmctx_data(0x000700, 5) -+mmctx_data(0x000800, 1) -+mmctx_data(0x000808, 3) -+mmctx_data(0x000828, 1) -+mmctx_data(0x000830, 1) -+mmctx_data(0x0008d8, 1) -+mmctx_data(0x0008e0, 1) -+mmctx_data(0x0008e8, 6) -+mmctx_data(0x00091c, 1) -+mmctx_data(0x000924, 3) -+mmctx_data(0x000b00, 1) -+mmctx_data(0x000b08, 6) -+mmctx_data(0x000bb8, 1) -+mmctx_data(0x000c08, 1) -+mmctx_data(0x000c10, 8) -+mmctx_data(0x000c80, 1) -+mmctx_data(0x000c8c, 1) -+mmctx_data(0x001000, 3) -+mmctx_data(0x001014, 1) -+nvc0_gpc_mmio_tail: -+mmctx_data(0x000c6c, 1); -+nvc1_gpc_mmio_tail: -+ -+// TPC mmio lists -+nvc0_tpc_mmio_head: -+mmctx_data(0x000018, 1) -+mmctx_data(0x00003c, 1) -+mmctx_data(0x000048, 1) -+mmctx_data(0x000064, 1) -+mmctx_data(0x000088, 1) -+mmctx_data(0x000200, 6) -+mmctx_data(0x00021c, 2) -+mmctx_data(0x000300, 6) -+mmctx_data(0x0003d0, 1) -+mmctx_data(0x0003e0, 2) -+mmctx_data(0x000400, 3) -+mmctx_data(0x000420, 1) -+mmctx_data(0x0004b0, 1) -+mmctx_data(0x0004e8, 1) -+mmctx_data(0x0004f4, 1) -+mmctx_data(0x000520, 2) -+mmctx_data(0x000604, 4) -+mmctx_data(0x000644, 20) -+mmctx_data(0x000698, 1) -+mmctx_data(0x000750, 2) -+nvc0_tpc_mmio_tail: -+mmctx_data(0x000758, 1) -+mmctx_data(0x0002c4, 1) -+mmctx_data(0x0006e0, 1) -+nvcf_tpc_mmio_tail: -+mmctx_data(0x0004bc, 1) -+nvc3_tpc_mmio_tail: -+mmctx_data(0x000544, 1) -+nvc1_tpc_mmio_tail: -+ -+ -+.section nvc0_grgpc_code -+bra init -+define(`include_code') -+include(`nvc0_graph.fuc') -+ -+// reports an exception to the host -+// -+// In: $r15 error code (see nvc0_graph.fuc) -+// -+error: -+ push $r14 -+ mov $r14 -0x67ec // 0x9814 -+ sethi $r14 0x400000 -+ call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code -+ add b32 $r14 0x41c -+ mov $r15 1 -+ call nv_wr32 // HUB_CTXCTL_INTR_UP_SET -+ pop $r14 -+ ret -+ -+// GPC fuc initialisation, executed by triggering ucode start, will -+// fall through to main loop after completion. -+// -+// Input: -+// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) -+// CC_SCRATCH[1]: context base -+// -+// Output: -+// CC_SCRATCH[0]: -+// 31:31: set to signal completion -+// CC_SCRATCH[1]: -+// 31:0: GPC context size -+// -+init: -+ clear b32 $r0 -+ mov $sp $r0 -+ -+ // enable fifo access -+ mov $r1 0x1200 -+ mov $r2 2 -+ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE -+ -+ // setup i0 handler, and route all interrupts to it -+ mov $r1 ih -+ mov $iv0 $r1 -+ mov $r1 0x400 -+ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH -+ -+ // enable fifo interrupt -+ mov $r2 4 -+ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET -+ -+ // enable interrupts -+ bset $flags ie0 -+ -+ // figure out which GPC we are, and how many TPCs we have -+ mov $r1 0x608 -+ shl b32 $r1 6 -+ iord $r2 I[$r1 + 0x000] // UNITS -+ mov $r3 1 -+ and $r2 0x1f -+ shl b32 $r3 $r2 -+ sub b32 $r3 1 -+ st b32 D[$r0 + tpc_count] $r2 -+ st b32 D[$r0 + tpc_mask] $r3 -+ add b32 $r1 0x400 -+ iord $r2 I[$r1 + 0x000] // MYINDEX -+ st b32 D[$r0 + gpc_id] $r2 -+ -+ // find context data for this chipset -+ mov $r2 0x800 -+ shl b32 $r2 6 -+ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] -+ mov $r1 chipsets - 12 -+ init_find_chipset: -+ add b32 $r1 12 -+ ld b32 $r3 D[$r1 + 0x00] -+ cmpu b32 $r3 $r2 -+ bra e init_context -+ cmpu b32 $r3 0 -+ bra ne init_find_chipset -+ // unknown chipset -+ ret -+ -+ // initialise context base, and size tracking -+ init_context: -+ mov $r2 0x800 -+ shl b32 $r2 6 -+ iord $r2 I[$r2 + 0x100] // CC_SCRATCH[1], initial base -+ clear b32 $r3 // track GPC context size here -+ -+ // set mmctx base addresses now so we don't have to do it later, -+ // they don't currently ever change -+ mov $r4 0x700 -+ shl b32 $r4 6 -+ shr b32 $r5 $r2 8 -+ iowr I[$r4 + 0x000] $r5 // MMCTX_SAVE_SWBASE -+ iowr I[$r4 + 0x100] $r5 // MMCTX_LOAD_SWBASE -+ -+ // calculate GPC mmio context size, store the chipset-specific -+ // mmio list pointers somewhere we can get at them later without -+ // re-parsing the chipset list -+ clear b32 $r14 -+ clear b32 $r15 -+ ld b16 $r14 D[$r1 + 4] -+ ld b16 $r15 D[$r1 + 6] -+ st b16 D[$r0 + gpc_mmio_list_head] $r14 -+ st b16 D[$r0 + gpc_mmio_list_tail] $r15 -+ call mmctx_size -+ add b32 $r2 $r15 -+ add b32 $r3 $r15 -+ -+ // calculate per-TPC mmio context size, store the list pointers -+ ld b16 $r14 D[$r1 + 8] -+ ld b16 $r15 D[$r1 + 10] -+ st b16 D[$r0 + tpc_mmio_list_head] $r14 -+ st b16 D[$r0 + tpc_mmio_list_tail] $r15 -+ call mmctx_size -+ ld b32 $r14 D[$r0 + tpc_count] -+ mulu $r14 $r15 -+ add b32 $r2 $r14 -+ add b32 $r3 $r14 -+ -+ // round up base/size to 256 byte boundary (for strand SWBASE) -+ add b32 $r4 0x1300 -+ shr b32 $r3 2 -+ iowr I[$r4 + 0x000] $r3 // MMCTX_LOAD_COUNT, wtf for?!? -+ shr b32 $r2 8 -+ shr b32 $r3 6 -+ add b32 $r2 1 -+ add b32 $r3 1 -+ shl b32 $r2 8 -+ shl b32 $r3 8 -+ -+ // calculate size of strand context data -+ mov b32 $r15 $r2 -+ call strand_ctx_init -+ add b32 $r3 $r15 -+ -+ // save context size, and tell HUB we're done -+ mov $r1 0x800 -+ shl b32 $r1 6 -+ iowr I[$r1 + 0x100] $r3 // CC_SCRATCH[1] = context size -+ add b32 $r1 0x800 -+ clear b32 $r2 -+ bset $r2 31 -+ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 -+ -+// Main program loop, very simple, sleeps until woken up by the interrupt -+// handler, pulls a command from the queue and executes its handler -+// -+main: -+ bset $flags $p0 -+ sleep $p0 -+ mov $r13 cmd_queue -+ call queue_get -+ bra $p1 main -+ -+ // 0x0000-0x0003 are all context transfers -+ cmpu b32 $r14 0x04 -+ bra nc main_not_ctx_xfer -+ // fetch $flags and mask off $p1/$p2 -+ mov $r1 $flags -+ mov $r2 0x0006 -+ not b32 $r2 -+ and $r1 $r2 -+ // set $p1/$p2 according to transfer type -+ shl b32 $r14 1 -+ or $r1 $r14 -+ mov $flags $r1 -+ // transfer context data -+ call ctx_xfer -+ bra main -+ -+ main_not_ctx_xfer: -+ shl b32 $r15 $r14 16 -+ or $r15 E_BAD_COMMAND -+ call error -+ bra main -+ -+// interrupt handler -+ih: -+ push $r8 -+ mov $r8 $flags -+ push $r8 -+ push $r9 -+ push $r10 -+ push $r11 -+ push $r13 -+ push $r14 -+ push $r15 -+ -+ // incoming fifo command? -+ iord $r10 I[$r0 + 0x200] // INTR -+ and $r11 $r10 0x00000004 -+ bra e ih_no_fifo -+ // queue incoming fifo command for later processing -+ mov $r11 0x1900 -+ mov $r13 cmd_queue -+ iord $r14 I[$r11 + 0x100] // FIFO_CMD -+ iord $r15 I[$r11 + 0x000] // FIFO_DATA -+ call queue_put -+ add b32 $r11 0x400 -+ mov $r14 1 -+ iowr I[$r11 + 0x000] $r14 // FIFO_ACK -+ -+ // ack, and wake up main() -+ ih_no_fifo: -+ iowr I[$r0 + 0x100] $r10 // INTR_ACK -+ -+ pop $r15 -+ pop $r14 -+ pop $r13 -+ pop $r11 -+ pop $r10 -+ pop $r9 -+ pop $r8 -+ mov $flags $r8 -+ pop $r8 -+ bclr $flags $p0 -+ iret -+ -+// Set this GPC's bit in HUB_BAR, used to signal completion of various -+// activities to the HUB fuc -+// -+hub_barrier_done: -+ mov $r15 1 -+ ld b32 $r14 D[$r0 + gpc_id] -+ shl b32 $r15 $r14 -+ mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET -+ sethi $r14 0x400000 -+ call nv_wr32 -+ ret -+ -+// Disables various things, waits a bit, and re-enables them.. -+// -+// Not sure how exactly this helps, perhaps "ENABLE" is not such a -+// good description for the bits we turn off? Anyways, without this, -+// funny things happen. -+// -+ctx_redswitch: -+ mov $r14 0x614 -+ shl b32 $r14 6 -+ mov $r15 0x020 -+ iowr I[$r14] $r15 // GPC_RED_SWITCH = POWER -+ mov $r15 8 -+ ctx_redswitch_delay: -+ sub b32 $r15 1 -+ bra ne ctx_redswitch_delay -+ mov $r15 0xa20 -+ iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER -+ ret -+ -+// Transfer GPC context data between GPU and storage area -+// -+// In: $r15 context base address -+// $p1 clear on save, set on load -+// $p2 set if opposite direction done/will be done, so: -+// on save it means: "a load will follow this save" -+// on load it means: "a save preceeded this load" -+// -+ctx_xfer: -+ // set context base address -+ mov $r1 0xa04 -+ shl b32 $r1 6 -+ iowr I[$r1 + 0x000] $r15// MEM_BASE -+ bra not $p1 ctx_xfer_not_load -+ call ctx_redswitch -+ ctx_xfer_not_load: -+ -+ // strands -+ mov $r1 0x4afc -+ sethi $r1 0x20000 -+ mov $r2 0xc -+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c -+ call strand_wait -+ mov $r2 0x47fc -+ sethi $r2 0x20000 -+ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 -+ xbit $r2 $flags $p1 -+ add b32 $r2 3 -+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) -+ -+ // mmio context -+ xbit $r10 $flags $p1 // direction -+ or $r10 2 // first -+ mov $r11 0x0000 -+ sethi $r11 0x500000 -+ ld b32 $r12 D[$r0 + gpc_id] -+ shl b32 $r12 15 -+ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn -+ ld b32 $r12 D[$r0 + gpc_mmio_list_head] -+ ld b32 $r13 D[$r0 + gpc_mmio_list_tail] -+ mov $r14 0 // not multi -+ call mmctx_xfer -+ -+ // per-TPC mmio context -+ xbit $r10 $flags $p1 // direction -+ or $r10 4 // last -+ mov $r11 0x4000 -+ sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 -+ ld b32 $r12 D[$r0 + gpc_id] -+ shl b32 $r12 15 -+ add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 -+ ld b32 $r12 D[$r0 + tpc_mmio_list_head] -+ ld b32 $r13 D[$r0 + tpc_mmio_list_tail] -+ ld b32 $r15 D[$r0 + tpc_mask] -+ mov $r14 0x800 // stride = 0x800 -+ call mmctx_xfer -+ -+ // wait for strands to finish -+ call strand_wait -+ -+ // if load, or a save without a load following, do some -+ // unknown stuff that's done after finishing a block of -+ // strand commands -+ bra $p1 ctx_xfer_post -+ bra not $p2 ctx_xfer_done -+ ctx_xfer_post: -+ mov $r1 0x4afc -+ sethi $r1 0x20000 -+ mov $r2 0xd -+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d -+ call strand_wait -+ -+ // mark completion in HUB's barrier -+ ctx_xfer_done: -+ call hub_barrier_done -+ ret -+ -+.align 256 -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h 2011-07-26 07:03:44.511052023 +0200 -@@ -0,0 +1,486 @@ -+uint32_t nvc0_grgpc_data[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x000000c0, -+ 0x011c00bc, -+ 0x01700120, -+ 0x000000c1, -+ 0x012000bc, -+ 0x01840120, -+ 0x000000c3, -+ 0x011c00bc, -+ 0x01800120, -+ 0x000000c4, -+ 0x011c00bc, -+ 0x01800120, -+ 0x000000c8, -+ 0x011c00bc, -+ 0x01700120, -+ 0x000000ce, -+ 0x011c00bc, -+ 0x01800120, -+ 0x000000cf, -+ 0x011c00bc, -+ 0x017c0120, -+ 0x00000000, -+ 0x00000380, -+ 0x14000400, -+ 0x20000450, -+ 0x00000600, -+ 0x00000684, -+ 0x10000700, -+ 0x00000800, -+ 0x08000808, -+ 0x00000828, -+ 0x00000830, -+ 0x000008d8, -+ 0x000008e0, -+ 0x140008e8, -+ 0x0000091c, -+ 0x08000924, -+ 0x00000b00, -+ 0x14000b08, -+ 0x00000bb8, -+ 0x00000c08, -+ 0x1c000c10, -+ 0x00000c80, -+ 0x00000c8c, -+ 0x08001000, -+ 0x00001014, -+ 0x00000c6c, -+ 0x00000018, -+ 0x0000003c, -+ 0x00000048, -+ 0x00000064, -+ 0x00000088, -+ 0x14000200, -+ 0x0400021c, -+ 0x14000300, -+ 0x000003d0, -+ 0x040003e0, -+ 0x08000400, -+ 0x00000420, -+ 0x000004b0, -+ 0x000004e8, -+ 0x000004f4, -+ 0x04000520, -+ 0x0c000604, -+ 0x4c000644, -+ 0x00000698, -+ 0x04000750, -+ 0x00000758, -+ 0x000002c4, -+ 0x000006e0, -+ 0x000004bc, -+ 0x00000544, -+}; -+ -+uint32_t nvc0_grgpc_code[] = { -+ 0x03060ef5, -+ 0x9800d898, -+ 0x86f001d9, -+ 0x0489b808, -+ 0xf00c1bf4, -+ 0x21f502f7, -+ 0x00f802ec, -+ 0xb60798c4, -+ 0x8dbb0384, -+ 0x0880b600, -+ 0x80008e80, -+ 0x90b6018f, -+ 0x0f94f001, -+ 0xf801d980, -+ 0x0131f400, -+ 0x9800d898, -+ 0x89b801d9, -+ 0x210bf404, -+ 0xb60789c4, -+ 0x9dbb0394, -+ 0x0890b600, -+ 0x98009e98, -+ 0x80b6019f, -+ 0x0f84f001, -+ 0xf400d880, -+ 0x00f80132, -+ 0x0728b7f1, -+ 0xb906b4b6, -+ 0xc9f002ec, -+ 0x00bcd01f, -+ 0xc800bccf, -+ 0x1bf41fcc, -+ 0x06a7f0fa, -+ 0x010321f5, -+ 0xf840bfcf, -+ 0x28b7f100, -+ 0x06b4b607, -+ 0xb980bfd0, -+ 0xc9f002ec, -+ 0x1ec9f01f, -+ 0xcf00bcd0, -+ 0xccc800bc, -+ 0xfa1bf41f, -+ 0x87f100f8, -+ 0x84b60430, -+ 0x1ff9f006, -+ 0xf8008fd0, -+ 0x3087f100, -+ 0x0684b604, -+ 0xf80080d0, -+ 0x3c87f100, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d000, -+ 0x081887f1, -+ 0xd00684b6, -+ 0x87f1008a, -+ 0x84b60400, -+ 0x0088cf06, -+ 0xf4888aff, -+ 0x87f1f31b, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00099, -+ 0xf100f800, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00099f0, -+ 0x87f10089, -+ 0x84b60818, -+ 0x008ad006, -+ 0x040087f1, -+ 0xcf0684b6, -+ 0x8aff0088, -+ 0xf30bf488, -+ 0x085c87f1, -+ 0xbd0684b6, -+ 0x0099f094, -+ 0xf80089d0, -+ 0x9894bd00, -+ 0x85b600e8, -+ 0x0180b61a, -+ 0xbb0284b6, -+ 0xe0b60098, -+ 0x04efb804, -+ 0xb9eb1bf4, -+ 0x00f8029f, -+ 0x083c87f1, -+ 0xbd0684b6, -+ 0x0199f094, -+ 0xf10089d0, -+ 0xb6071087, -+ 0x94bd0684, -+ 0xf405bbfd, -+ 0x8bd0090b, -+ 0x0099f000, -+ 0xf405eefd, -+ 0x8ed00c0b, -+ 0xc08fd080, -+ 0xb70199f0, -+ 0xc8010080, -+ 0xb4b600ab, -+ 0x0cb9f010, -+ 0xb601aec8, -+ 0xbefd11e4, -+ 0x008bd005, -+ 0xf0008ecf, -+ 0x0bf41fe4, -+ 0x00ce98fa, -+ 0xd005e9fd, -+ 0xc0b6c08e, -+ 0x04cdb804, -+ 0xc8e81bf4, -+ 0x1bf402ab, -+ 0x008bcf18, -+ 0xb01fb4f0, -+ 0x1bf410b4, -+ 0x02a7f0f7, -+ 0xf4c921f4, -+ 0xabc81b0e, -+ 0x10b4b600, -+ 0xf00cb9f0, -+ 0x8bd012b9, -+ 0x008bcf00, -+ 0xf412bbc8, -+ 0x87f1fa1b, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00199, -+ 0xf900f800, -+ 0x02a7f0a0, -+ 0xfcc921f4, -+ 0xf100f8a0, -+ 0xf04afc87, -+ 0x97f00283, -+ 0x0089d00c, -+ 0x020721f5, -+ 0x87f100f8, -+ 0x83f04afc, -+ 0x0d97f002, -+ 0xf50089d0, -+ 0xf8020721, -+ 0xfca7f100, -+ 0x02a3f04f, -+ 0x0500aba2, -+ 0xd00fc7f0, -+ 0xc7f000ac, -+ 0x00bcd00b, -+ 0x020721f5, -+ 0xf000aed0, -+ 0xbcd00ac7, -+ 0x0721f500, -+ 0xf100f802, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00399f0, -+ 0x21f50089, -+ 0xe7f00213, -+ 0x3921f503, -+ 0xfca7f102, -+ 0x02a3f046, -+ 0x0400aba0, -+ 0xf040a0d0, -+ 0xbcd001c7, -+ 0x0721f500, -+ 0x010c9202, -+ 0xf000acd0, -+ 0xbcd002c7, -+ 0x0721f500, -+ 0x2621f502, -+ 0x8087f102, -+ 0x0684b608, -+ 0xb70089cf, -+ 0x95220080, -+ 0x8ed008fe, -+ 0x408ed000, -+ 0xb6808acf, -+ 0xa0b606a5, -+ 0x00eabb01, -+ 0xb60480b6, -+ 0x1bf40192, -+ 0x08e4b6e8, -+ 0xf1f2efbc, -+ 0xb6085c87, -+ 0x94bd0684, -+ 0xd00399f0, -+ 0x00f80089, -+ 0xe7f1e0f9, -+ 0xe3f09814, -+ 0x8d21f440, -+ 0x041ce0b7, -+ 0xf401f7f0, -+ 0xe0fc8d21, -+ 0x04bd00f8, -+ 0xf10004fe, -+ 0xf0120017, -+ 0x12d00227, -+ 0x3e17f100, -+ 0x0010fe04, -+ 0x040017f1, -+ 0xf0c010d0, -+ 0x12d00427, -+ 0x1031f400, -+ 0x060817f1, -+ 0xcf0614b6, -+ 0x37f00012, -+ 0x1f24f001, -+ 0xb60432bb, -+ 0x02800132, -+ 0x04038003, -+ 0x040010b7, -+ 0x800012cf, -+ 0x27f10002, -+ 0x24b60800, -+ 0x0022cf06, -+ 0xb65817f0, -+ 0x13980c10, -+ 0x0432b800, -+ 0xb00b0bf4, -+ 0x1bf40034, -+ 0xf100f8f1, -+ 0xb6080027, -+ 0x22cf0624, -+ 0xf134bd40, -+ 0xb6070047, -+ 0x25950644, -+ 0x0045d008, -+ 0xbd4045d0, -+ 0x58f4bde4, -+ 0x1f58021e, -+ 0x020e4003, -+ 0xf5040f40, -+ 0xbb013d21, -+ 0x3fbb002f, -+ 0x041e5800, -+ 0x40051f58, -+ 0x0f400a0e, -+ 0x3d21f50c, -+ 0x030e9801, -+ 0xbb00effd, -+ 0x3ebb002e, -+ 0x0040b700, -+ 0x0235b613, -+ 0xb60043d0, -+ 0x35b60825, -+ 0x0120b606, -+ 0xb60130b6, -+ 0x34b60824, -+ 0x022fb908, -+ 0x026321f5, -+ 0xf1003fbb, -+ 0xb6080017, -+ 0x13d00614, -+ 0x0010b740, -+ 0xf024bd08, -+ 0x12d01f29, -+ 0x0031f400, -+ 0xf00028f4, -+ 0x21f41cd7, -+ 0xf401f439, -+ 0xf404e4b0, -+ 0x81fe1e18, -+ 0x0627f001, -+ 0x12fd20bd, -+ 0x01e4b604, -+ 0xfe051efd, -+ 0x21f50018, -+ 0x0ef404c3, -+ 0x10ef94d3, -+ 0xf501f5f0, -+ 0xf402ec21, -+ 0x80f9c60e, -+ 0xf90188fe, -+ 0xf990f980, -+ 0xf9b0f9a0, -+ 0xf9e0f9d0, -+ 0x800acff0, -+ 0xf404abc4, -+ 0xb7f11d0b, -+ 0xd7f01900, -+ 0x40becf1c, -+ 0xf400bfcf, -+ 0xb0b70421, -+ 0xe7f00400, -+ 0x00bed001, -+ 0xfc400ad0, -+ 0xfce0fcf0, -+ 0xfcb0fcd0, -+ 0xfc90fca0, -+ 0x0088fe80, -+ 0x32f480fc, -+ 0xf001f800, -+ 0x0e9801f7, -+ 0x04febb00, -+ 0x9418e7f1, -+ 0xf440e3f0, -+ 0x00f88d21, -+ 0x0614e7f1, -+ 0xf006e4b6, -+ 0xefd020f7, -+ 0x08f7f000, -+ 0xf401f2b6, -+ 0xf7f1fd1b, -+ 0xefd00a20, -+ 0xf100f800, -+ 0xb60a0417, -+ 0x1fd00614, -+ 0x0711f400, -+ 0x04a421f5, -+ 0x4afc17f1, -+ 0xf00213f0, -+ 0x12d00c27, -+ 0x0721f500, -+ 0xfc27f102, -+ 0x0223f047, -+ 0xf00020d0, -+ 0x20b6012c, -+ 0x0012d003, -+ 0xf001acf0, -+ 0xb7f002a5, -+ 0x50b3f000, -+ 0xb6000c98, -+ 0xbcbb0fc4, -+ 0x010c9800, -+ 0xf0020d98, -+ 0x21f500e7, -+ 0xacf0015c, -+ 0x04a5f001, -+ 0x4000b7f1, -+ 0x9850b3f0, -+ 0xc4b6000c, -+ 0x00bcbb0f, -+ 0x98050c98, -+ 0x0f98060d, -+ 0x00e7f104, -+ 0x5c21f508, -+ 0x0721f501, -+ 0x0601f402, -+ 0xf11412f4, -+ 0xf04afc17, -+ 0x27f00213, -+ 0x0012d00d, -+ 0x020721f5, -+ 0x048f21f5, -+ 0x000000f8, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_grhub.fuc linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grhub.fuc ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_grhub.fuc 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grhub.fuc 2011-07-26 07:03:44.512052035 +0200 -@@ -0,0 +1,811 @@ -+/* fuc microcode for nvc0 PGRAPH/HUB -+ * -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+/* To build: -+ * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h -+ */ -+ -+.section nvc0_grhub_data -+include(`nvc0_graph.fuc') -+gpc_count: .b32 0 -+rop_count: .b32 0 -+cmd_queue: queue_init -+hub_mmio_list_head: .b32 0 -+hub_mmio_list_tail: .b32 0 -+ -+ctx_current: .b32 0 -+ -+chipsets: -+.b8 0xc0 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0xc1 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc1_hub_mmio_tail -+.b8 0xc3 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0xc4 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0xc8 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0xce 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0xcf 0 0 0 -+.b16 nvc0_hub_mmio_head -+.b16 nvc0_hub_mmio_tail -+.b8 0 0 0 0 -+ -+nvc0_hub_mmio_head: -+mmctx_data(0x17e91c, 2) -+mmctx_data(0x400204, 2) -+mmctx_data(0x404004, 11) -+mmctx_data(0x404044, 1) -+mmctx_data(0x404094, 14) -+mmctx_data(0x4040d0, 7) -+mmctx_data(0x4040f8, 1) -+mmctx_data(0x404130, 3) -+mmctx_data(0x404150, 3) -+mmctx_data(0x404164, 2) -+mmctx_data(0x404174, 3) -+mmctx_data(0x404200, 8) -+mmctx_data(0x404404, 14) -+mmctx_data(0x404460, 4) -+mmctx_data(0x404480, 1) -+mmctx_data(0x404498, 1) -+mmctx_data(0x404604, 4) -+mmctx_data(0x404618, 32) -+mmctx_data(0x404698, 21) -+mmctx_data(0x4046f0, 2) -+mmctx_data(0x404700, 22) -+mmctx_data(0x405800, 1) -+mmctx_data(0x405830, 3) -+mmctx_data(0x405854, 1) -+mmctx_data(0x405870, 4) -+mmctx_data(0x405a00, 2) -+mmctx_data(0x405a18, 1) -+mmctx_data(0x406020, 1) -+mmctx_data(0x406028, 4) -+mmctx_data(0x4064a8, 2) -+mmctx_data(0x4064b4, 2) -+mmctx_data(0x407804, 1) -+mmctx_data(0x40780c, 6) -+mmctx_data(0x4078bc, 1) -+mmctx_data(0x408000, 7) -+mmctx_data(0x408064, 1) -+mmctx_data(0x408800, 3) -+mmctx_data(0x408900, 4) -+mmctx_data(0x408980, 1) -+nvc0_hub_mmio_tail: -+mmctx_data(0x4064c0, 2) -+nvc1_hub_mmio_tail: -+ -+.align 256 -+chan_data: -+chan_mmio_count: .b32 0 -+chan_mmio_address: .b32 0 -+ -+.align 256 -+xfer_data: .b32 0 -+ -+.section nvc0_grhub_code -+bra init -+define(`include_code') -+include(`nvc0_graph.fuc') -+ -+// reports an exception to the host -+// -+// In: $r15 error code (see nvc0_graph.fuc) -+// -+error: -+ push $r14 -+ mov $r14 0x814 -+ shl b32 $r14 6 -+ iowr I[$r14 + 0x000] $r15 // CC_SCRATCH[5] = error code -+ mov $r14 0xc1c -+ shl b32 $r14 6 -+ mov $r15 1 -+ iowr I[$r14 + 0x000] $r15 // INTR_UP_SET -+ pop $r14 -+ ret -+ -+// HUB fuc initialisation, executed by triggering ucode start, will -+// fall through to main loop after completion. -+// -+// Input: -+// CC_SCRATCH[0]: chipset (PMC_BOOT_0 read returns 0x0bad0bad... sigh) -+// -+// Output: -+// CC_SCRATCH[0]: -+// 31:31: set to signal completion -+// CC_SCRATCH[1]: -+// 31:0: total PGRAPH context size -+// -+init: -+ clear b32 $r0 -+ mov $sp $r0 -+ mov $xdbase $r0 -+ -+ // enable fifo access -+ mov $r1 0x1200 -+ mov $r2 2 -+ iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE -+ -+ // setup i0 handler, and route all interrupts to it -+ mov $r1 ih -+ mov $iv0 $r1 -+ mov $r1 0x400 -+ iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH -+ -+ // route HUB_CHANNEL_SWITCH to fuc interrupt 8 -+ mov $r3 0x404 -+ shl b32 $r3 6 -+ mov $r2 0x2003 // { HUB_CHANNEL_SWITCH, ZERO } -> intr 8 -+ iowr I[$r3 + 0x000] $r2 -+ -+ // not sure what these are, route them because NVIDIA does, and -+ // the IRQ handler will signal the host if we ever get one.. we -+ // may find out if/why we need to handle these if so.. -+ // -+ mov $r2 0x2004 -+ iowr I[$r3 + 0x004] $r2 // { 0x04, ZERO } -> intr 9 -+ mov $r2 0x200b -+ iowr I[$r3 + 0x008] $r2 // { 0x0b, ZERO } -> intr 10 -+ mov $r2 0x200c -+ iowr I[$r3 + 0x01c] $r2 // { 0x0c, ZERO } -> intr 15 -+ -+ // enable all INTR_UP interrupts -+ mov $r2 0xc24 -+ shl b32 $r2 6 -+ not b32 $r3 $r0 -+ iowr I[$r2] $r3 -+ -+ // enable fifo, ctxsw, 9, 10, 15 interrupts -+ mov $r2 -0x78fc // 0x8704 -+ sethi $r2 0 -+ iowr I[$r1 + 0x000] $r2 // INTR_EN_SET -+ -+ // fifo level triggered, rest edge -+ sub b32 $r1 0x100 -+ mov $r2 4 -+ iowr I[$r1] $r2 -+ -+ // enable interrupts -+ bset $flags ie0 -+ -+ // fetch enabled GPC/ROP counts -+ mov $r14 -0x69fc // 0x409604 -+ sethi $r14 0x400000 -+ call nv_rd32 -+ extr $r1 $r15 16:20 -+ st b32 D[$r0 + rop_count] $r1 -+ and $r15 0x1f -+ st b32 D[$r0 + gpc_count] $r15 -+ -+ // set BAR_REQMASK to GPC mask -+ mov $r1 1 -+ shl b32 $r1 $r15 -+ sub b32 $r1 1 -+ mov $r2 0x40c -+ shl b32 $r2 6 -+ iowr I[$r2 + 0x000] $r1 -+ iowr I[$r2 + 0x100] $r1 -+ -+ // find context data for this chipset -+ mov $r2 0x800 -+ shl b32 $r2 6 -+ iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] -+ mov $r15 chipsets - 8 -+ init_find_chipset: -+ add b32 $r15 8 -+ ld b32 $r3 D[$r15 + 0x00] -+ cmpu b32 $r3 $r2 -+ bra e init_context -+ cmpu b32 $r3 0 -+ bra ne init_find_chipset -+ // unknown chipset -+ ret -+ -+ // context size calculation, reserve first 256 bytes for use by fuc -+ init_context: -+ mov $r1 256 -+ -+ // calculate size of mmio context data -+ ld b16 $r14 D[$r15 + 4] -+ ld b16 $r15 D[$r15 + 6] -+ sethi $r14 0 -+ st b32 D[$r0 + hub_mmio_list_head] $r14 -+ st b32 D[$r0 + hub_mmio_list_tail] $r15 -+ call mmctx_size -+ -+ // set mmctx base addresses now so we don't have to do it later, -+ // they don't (currently) ever change -+ mov $r3 0x700 -+ shl b32 $r3 6 -+ shr b32 $r4 $r1 8 -+ iowr I[$r3 + 0x000] $r4 // MMCTX_SAVE_SWBASE -+ iowr I[$r3 + 0x100] $r4 // MMCTX_LOAD_SWBASE -+ add b32 $r3 0x1300 -+ add b32 $r1 $r15 -+ shr b32 $r15 2 -+ iowr I[$r3 + 0x000] $r15 // MMCTX_LOAD_COUNT, wtf for?!? -+ -+ // strands, base offset needs to be aligned to 256 bytes -+ shr b32 $r1 8 -+ add b32 $r1 1 -+ shl b32 $r1 8 -+ mov b32 $r15 $r1 -+ call strand_ctx_init -+ add b32 $r1 $r15 -+ -+ // initialise each GPC in sequence by passing in the offset of its -+ // context data in GPCn_CC_SCRATCH[1], and starting its FUC (which -+ // has previously been uploaded by the host) running. -+ // -+ // the GPC fuc init sequence will set GPCn_CC_SCRATCH[0] bit 31 -+ // when it has completed, and return the size of its context data -+ // in GPCn_CC_SCRATCH[1] -+ // -+ ld b32 $r3 D[$r0 + gpc_count] -+ mov $r4 0x2000 -+ sethi $r4 0x500000 -+ init_gpc: -+ // setup, and start GPC ucode running -+ add b32 $r14 $r4 0x804 -+ mov b32 $r15 $r1 -+ call nv_wr32 // CC_SCRATCH[1] = ctx offset -+ add b32 $r14 $r4 0x800 -+ mov b32 $r15 $r2 -+ call nv_wr32 // CC_SCRATCH[0] = chipset -+ add b32 $r14 $r4 0x10c -+ clear b32 $r15 -+ call nv_wr32 -+ add b32 $r14 $r4 0x104 -+ call nv_wr32 // ENTRY -+ add b32 $r14 $r4 0x100 -+ mov $r15 2 // CTRL_START_TRIGGER -+ call nv_wr32 // CTRL -+ -+ // wait for it to complete, and adjust context size -+ add b32 $r14 $r4 0x800 -+ init_gpc_wait: -+ call nv_rd32 -+ xbit $r15 $r15 31 -+ bra e init_gpc_wait -+ add b32 $r14 $r4 0x804 -+ call nv_rd32 -+ add b32 $r1 $r15 -+ -+ // next! -+ add b32 $r4 0x8000 -+ sub b32 $r3 1 -+ bra ne init_gpc -+ -+ // save context size, and tell host we're ready -+ mov $r2 0x800 -+ shl b32 $r2 6 -+ iowr I[$r2 + 0x100] $r1 // CC_SCRATCH[1] = context size -+ add b32 $r2 0x800 -+ clear b32 $r1 -+ bset $r1 31 -+ iowr I[$r2 + 0x000] $r1 // CC_SCRATCH[0] |= 0x80000000 -+ -+// Main program loop, very simple, sleeps until woken up by the interrupt -+// handler, pulls a command from the queue and executes its handler -+// -+main: -+ // sleep until we have something to do -+ bset $flags $p0 -+ sleep $p0 -+ mov $r13 cmd_queue -+ call queue_get -+ bra $p1 main -+ -+ // context switch, requested by GPU? -+ cmpu b32 $r14 0x4001 -+ bra ne main_not_ctx_switch -+ trace_set(T_AUTO) -+ mov $r1 0xb00 -+ shl b32 $r1 6 -+ iord $r2 I[$r1 + 0x100] // CHAN_NEXT -+ iord $r1 I[$r1 + 0x000] // CHAN_CUR -+ -+ xbit $r3 $r1 31 -+ bra e chsw_no_prev -+ xbit $r3 $r2 31 -+ bra e chsw_prev_no_next -+ push $r2 -+ mov b32 $r2 $r1 -+ trace_set(T_SAVE) -+ bclr $flags $p1 -+ bset $flags $p2 -+ call ctx_xfer -+ trace_clr(T_SAVE); -+ pop $r2 -+ trace_set(T_LOAD); -+ bset $flags $p1 -+ call ctx_xfer -+ trace_clr(T_LOAD); -+ bra chsw_done -+ chsw_prev_no_next: -+ push $r2 -+ mov b32 $r2 $r1 -+ bclr $flags $p1 -+ bclr $flags $p2 -+ call ctx_xfer -+ pop $r2 -+ mov $r1 0xb00 -+ shl b32 $r1 6 -+ iowr I[$r1] $r2 -+ bra chsw_done -+ chsw_no_prev: -+ xbit $r3 $r2 31 -+ bra e chsw_done -+ bset $flags $p1 -+ bclr $flags $p2 -+ call ctx_xfer -+ -+ // ack the context switch request -+ chsw_done: -+ mov $r1 0xb0c -+ shl b32 $r1 6 -+ mov $r2 1 -+ iowr I[$r1 + 0x000] $r2 // 0x409b0c -+ trace_clr(T_AUTO) -+ bra main -+ -+ // request to set current channel? (*not* a context switch) -+ main_not_ctx_switch: -+ cmpu b32 $r14 0x0001 -+ bra ne main_not_ctx_chan -+ mov b32 $r2 $r15 -+ call ctx_chan -+ bra main_done -+ -+ // request to store current channel context? -+ main_not_ctx_chan: -+ cmpu b32 $r14 0x0002 -+ bra ne main_not_ctx_save -+ trace_set(T_SAVE) -+ bclr $flags $p1 -+ bclr $flags $p2 -+ call ctx_xfer -+ trace_clr(T_SAVE) -+ bra main_done -+ -+ main_not_ctx_save: -+ shl b32 $r15 $r14 16 -+ or $r15 E_BAD_COMMAND -+ call error -+ bra main -+ -+ main_done: -+ mov $r1 0x820 -+ shl b32 $r1 6 -+ clear b32 $r2 -+ bset $r2 31 -+ iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 -+ bra main -+ -+// interrupt handler -+ih: -+ push $r8 -+ mov $r8 $flags -+ push $r8 -+ push $r9 -+ push $r10 -+ push $r11 -+ push $r13 -+ push $r14 -+ push $r15 -+ -+ // incoming fifo command? -+ iord $r10 I[$r0 + 0x200] // INTR -+ and $r11 $r10 0x00000004 -+ bra e ih_no_fifo -+ // queue incoming fifo command for later processing -+ mov $r11 0x1900 -+ mov $r13 cmd_queue -+ iord $r14 I[$r11 + 0x100] // FIFO_CMD -+ iord $r15 I[$r11 + 0x000] // FIFO_DATA -+ call queue_put -+ add b32 $r11 0x400 -+ mov $r14 1 -+ iowr I[$r11 + 0x000] $r14 // FIFO_ACK -+ -+ // context switch request? -+ ih_no_fifo: -+ and $r11 $r10 0x00000100 -+ bra e ih_no_ctxsw -+ // enqueue a context switch for later processing -+ mov $r13 cmd_queue -+ mov $r14 0x4001 -+ call queue_put -+ -+ // anything we didn't handle, bring it to the host's attention -+ ih_no_ctxsw: -+ mov $r11 0x104 -+ not b32 $r11 -+ and $r11 $r10 $r11 -+ bra e ih_no_other -+ mov $r10 0xc1c -+ shl b32 $r10 6 -+ iowr I[$r10] $r11 // INTR_UP_SET -+ -+ // ack, and wake up main() -+ ih_no_other: -+ iowr I[$r0 + 0x100] $r10 // INTR_ACK -+ -+ pop $r15 -+ pop $r14 -+ pop $r13 -+ pop $r11 -+ pop $r10 -+ pop $r9 -+ pop $r8 -+ mov $flags $r8 -+ pop $r8 -+ bclr $flags $p0 -+ iret -+ -+// Not real sure, but, MEM_CMD 7 will hang forever if this isn't done -+ctx_4160s: -+ mov $r14 0x4160 -+ sethi $r14 0x400000 -+ mov $r15 1 -+ call nv_wr32 -+ ctx_4160s_wait: -+ call nv_rd32 -+ xbit $r15 $r15 4 -+ bra e ctx_4160s_wait -+ ret -+ -+// Without clearing again at end of xfer, some things cause PGRAPH -+// to hang with STATUS=0x00000007 until it's cleared.. fbcon can -+// still function with it set however... -+ctx_4160c: -+ mov $r14 0x4160 -+ sethi $r14 0x400000 -+ clear b32 $r15 -+ call nv_wr32 -+ ret -+ -+// Again, not real sure -+// -+// In: $r15 value to set 0x404170 to -+// -+ctx_4170s: -+ mov $r14 0x4170 -+ sethi $r14 0x400000 -+ or $r15 0x10 -+ call nv_wr32 -+ ret -+ -+// Waits for a ctx_4170s() call to complete -+// -+ctx_4170w: -+ mov $r14 0x4170 -+ sethi $r14 0x400000 -+ call nv_rd32 -+ and $r15 0x10 -+ bra ne ctx_4170w -+ ret -+ -+// Disables various things, waits a bit, and re-enables them.. -+// -+// Not sure how exactly this helps, perhaps "ENABLE" is not such a -+// good description for the bits we turn off? Anyways, without this, -+// funny things happen. -+// -+ctx_redswitch: -+ mov $r14 0x614 -+ shl b32 $r14 6 -+ mov $r15 0x270 -+ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_GPC, POWER_ALL -+ mov $r15 8 -+ ctx_redswitch_delay: -+ sub b32 $r15 1 -+ bra ne ctx_redswitch_delay -+ mov $r15 0x770 -+ iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL -+ ret -+ -+// Not a clue what this is for, except that unless the value is 0x10, the -+// strand context is saved (and presumably restored) incorrectly.. -+// -+// In: $r15 value to set to (0x00/0x10 are used) -+// -+ctx_86c: -+ mov $r14 0x86c -+ shl b32 $r14 6 -+ iowr I[$r14] $r15 // HUB(0x86c) = val -+ mov $r14 -0x75ec -+ sethi $r14 0x400000 -+ call nv_wr32 // ROP(0xa14) = val -+ mov $r14 -0x5794 -+ sethi $r14 0x410000 -+ call nv_wr32 // GPC(0x86c) = val -+ ret -+ -+// ctx_load - load's a channel's ctxctl data, and selects its vm -+// -+// In: $r2 channel address -+// -+ctx_load: -+ trace_set(T_CHAN) -+ -+ // switch to channel, somewhat magic in parts.. -+ mov $r10 12 // DONE_UNK12 -+ call wait_donez -+ mov $r1 0xa24 -+ shl b32 $r1 6 -+ iowr I[$r1 + 0x000] $r0 // 0x409a24 -+ mov $r3 0xb00 -+ shl b32 $r3 6 -+ iowr I[$r3 + 0x100] $r2 // CHAN_NEXT -+ mov $r1 0xa0c -+ shl b32 $r1 6 -+ mov $r4 7 -+ iowr I[$r1 + 0x000] $r2 // MEM_CHAN -+ iowr I[$r1 + 0x100] $r4 // MEM_CMD -+ ctx_chan_wait_0: -+ iord $r4 I[$r1 + 0x100] -+ and $r4 0x1f -+ bra ne ctx_chan_wait_0 -+ iowr I[$r3 + 0x000] $r2 // CHAN_CUR -+ -+ // load channel header, fetch PGRAPH context pointer -+ mov $xtargets $r0 -+ bclr $r2 31 -+ shl b32 $r2 4 -+ add b32 $r2 2 -+ -+ trace_set(T_LCHAN) -+ mov $r1 0xa04 -+ shl b32 $r1 6 -+ iowr I[$r1 + 0x000] $r2 // MEM_BASE -+ mov $r1 0xa20 -+ shl b32 $r1 6 -+ mov $r2 0x0002 -+ sethi $r2 0x80000000 -+ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram -+ mov $r1 0x10 // chan + 0x0210 -+ mov $r2 xfer_data -+ sethi $r2 0x00020000 // 16 bytes -+ xdld $r1 $r2 -+ xdwait -+ trace_clr(T_LCHAN) -+ -+ // update current context -+ ld b32 $r1 D[$r0 + xfer_data + 4] -+ shl b32 $r1 24 -+ ld b32 $r2 D[$r0 + xfer_data + 0] -+ shr b32 $r2 8 -+ or $r1 $r2 -+ st b32 D[$r0 + ctx_current] $r1 -+ -+ // set transfer base to start of context, and fetch context header -+ trace_set(T_LCTXH) -+ mov $r2 0xa04 -+ shl b32 $r2 6 -+ iowr I[$r2 + 0x000] $r1 // MEM_BASE -+ mov $r2 1 -+ mov $r1 0xa20 -+ shl b32 $r1 6 -+ iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm -+ mov $r1 chan_data -+ sethi $r1 0x00060000 // 256 bytes -+ xdld $r0 $r1 -+ xdwait -+ trace_clr(T_LCTXH) -+ -+ trace_clr(T_CHAN) -+ ret -+ -+// ctx_chan - handler for HUB_SET_CHAN command, will set a channel as -+// the active channel for ctxctl, but not actually transfer -+// any context data. intended for use only during initial -+// context construction. -+// -+// In: $r2 channel address -+// -+ctx_chan: -+ call ctx_4160s -+ call ctx_load -+ mov $r10 12 // DONE_UNK12 -+ call wait_donez -+ mov $r1 0xa10 -+ shl b32 $r1 6 -+ mov $r2 5 -+ iowr I[$r1 + 0x000] $r2 // MEM_CMD = 5 (???) -+ ctx_chan_wait: -+ iord $r2 I[$r1 + 0x000] -+ or $r2 $r2 -+ bra ne ctx_chan_wait -+ call ctx_4160c -+ ret -+ -+// Execute per-context state overrides list -+// -+// Only executed on the first load of a channel. Might want to look into -+// removing this and having the host directly modify the channel's context -+// to change this state... The nouveau DRM already builds this list as -+// it's definitely needed for NVIDIA's, so we may as well use it for now -+// -+// Input: $r1 mmio list length -+// -+ctx_mmio_exec: -+ // set transfer base to be the mmio list -+ ld b32 $r3 D[$r0 + chan_mmio_address] -+ mov $r2 0xa04 -+ shl b32 $r2 6 -+ iowr I[$r2 + 0x000] $r3 // MEM_BASE -+ -+ clear b32 $r3 -+ ctx_mmio_loop: -+ // fetch next 256 bytes of mmio list if necessary -+ and $r4 $r3 0xff -+ bra ne ctx_mmio_pull -+ mov $r5 xfer_data -+ sethi $r5 0x00060000 // 256 bytes -+ xdld $r3 $r5 -+ xdwait -+ -+ // execute a single list entry -+ ctx_mmio_pull: -+ ld b32 $r14 D[$r4 + xfer_data + 0x00] -+ ld b32 $r15 D[$r4 + xfer_data + 0x04] -+ call nv_wr32 -+ -+ // next! -+ add b32 $r3 8 -+ sub b32 $r1 1 -+ bra ne ctx_mmio_loop -+ -+ // set transfer base back to the current context -+ ctx_mmio_done: -+ ld b32 $r3 D[$r0 + ctx_current] -+ iowr I[$r2 + 0x000] $r3 // MEM_BASE -+ -+ // disable the mmio list now, we don't need/want to execute it again -+ st b32 D[$r0 + chan_mmio_count] $r0 -+ mov $r1 chan_data -+ sethi $r1 0x00060000 // 256 bytes -+ xdst $r0 $r1 -+ xdwait -+ ret -+ -+// Transfer HUB context data between GPU and storage area -+// -+// In: $r2 channel address -+// $p1 clear on save, set on load -+// $p2 set if opposite direction done/will be done, so: -+// on save it means: "a load will follow this save" -+// on load it means: "a save preceeded this load" -+// -+ctx_xfer: -+ bra not $p1 ctx_xfer_pre -+ bra $p2 ctx_xfer_pre_load -+ ctx_xfer_pre: -+ mov $r15 0x10 -+ call ctx_86c -+ call ctx_4160s -+ bra not $p1 ctx_xfer_exec -+ -+ ctx_xfer_pre_load: -+ mov $r15 2 -+ call ctx_4170s -+ call ctx_4170w -+ call ctx_redswitch -+ clear b32 $r15 -+ call ctx_4170s -+ call ctx_load -+ -+ // fetch context pointer, and initiate xfer on all GPCs -+ ctx_xfer_exec: -+ ld b32 $r1 D[$r0 + ctx_current] -+ mov $r2 0x414 -+ shl b32 $r2 6 -+ iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset -+ mov $r14 -0x5b00 -+ sethi $r14 0x410000 -+ mov b32 $r15 $r1 -+ call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer -+ add b32 $r14 4 -+ xbit $r15 $flags $p1 -+ xbit $r2 $flags $p2 -+ shl b32 $r2 1 -+ or $r15 $r2 -+ call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) -+ -+ // strands -+ mov $r1 0x4afc -+ sethi $r1 0x20000 -+ mov $r2 0xc -+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c -+ call strand_wait -+ mov $r2 0x47fc -+ sethi $r2 0x20000 -+ iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 -+ xbit $r2 $flags $p1 -+ add b32 $r2 3 -+ iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x03/0x04 (SAVE/LOAD) -+ -+ // mmio context -+ xbit $r10 $flags $p1 // direction -+ or $r10 6 // first, last -+ mov $r11 0 // base = 0 -+ ld b32 $r12 D[$r0 + hub_mmio_list_head] -+ ld b32 $r13 D[$r0 + hub_mmio_list_tail] -+ mov $r14 0 // not multi -+ call mmctx_xfer -+ -+ // wait for GPCs to all complete -+ mov $r10 8 // DONE_BAR -+ call wait_doneo -+ -+ // wait for strand xfer to complete -+ call strand_wait -+ -+ // post-op -+ bra $p1 ctx_xfer_post -+ mov $r10 12 // DONE_UNK12 -+ call wait_donez -+ mov $r1 0xa10 -+ shl b32 $r1 6 -+ mov $r2 5 -+ iowr I[$r1] $r2 // MEM_CMD -+ ctx_xfer_post_save_wait: -+ iord $r2 I[$r1] -+ or $r2 $r2 -+ bra ne ctx_xfer_post_save_wait -+ -+ bra $p2 ctx_xfer_done -+ ctx_xfer_post: -+ mov $r15 2 -+ call ctx_4170s -+ clear b32 $r15 -+ call ctx_86c -+ call strand_post -+ call ctx_4170w -+ clear b32 $r15 -+ call ctx_4170s -+ -+ bra not $p1 ctx_xfer_no_post_mmio -+ ld b32 $r1 D[$r0 + chan_mmio_count] -+ or $r1 $r1 -+ bra e ctx_xfer_no_post_mmio -+ call ctx_mmio_exec -+ -+ ctx_xfer_no_post_mmio: -+ call ctx_4160c -+ -+ ctx_xfer_done: -+ ret -+ -+.align 256 -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h 2011-07-26 07:03:44.513052047 +0200 -@@ -0,0 +1,838 @@ -+uint32_t nvc0_grhub_data[] = { -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x000000c0, -+ 0x01340098, -+ 0x000000c1, -+ 0x01380098, -+ 0x000000c3, -+ 0x01340098, -+ 0x000000c4, -+ 0x01340098, -+ 0x000000c8, -+ 0x01340098, -+ 0x000000ce, -+ 0x01340098, -+ 0x000000cf, -+ 0x01340098, -+ 0x00000000, -+ 0x0417e91c, -+ 0x04400204, -+ 0x28404004, -+ 0x00404044, -+ 0x34404094, -+ 0x184040d0, -+ 0x004040f8, -+ 0x08404130, -+ 0x08404150, -+ 0x04404164, -+ 0x08404174, -+ 0x1c404200, -+ 0x34404404, -+ 0x0c404460, -+ 0x00404480, -+ 0x00404498, -+ 0x0c404604, -+ 0x7c404618, -+ 0x50404698, -+ 0x044046f0, -+ 0x54404700, -+ 0x00405800, -+ 0x08405830, -+ 0x00405854, -+ 0x0c405870, -+ 0x04405a00, -+ 0x00405a18, -+ 0x00406020, -+ 0x0c406028, -+ 0x044064a8, -+ 0x044064b4, -+ 0x00407804, -+ 0x1440780c, -+ 0x004078bc, -+ 0x18408000, -+ 0x00408064, -+ 0x08408800, -+ 0x0c408900, -+ 0x00408980, -+ 0x044064c0, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -+ -+uint32_t nvc0_grhub_code[] = { -+ 0x03090ef5, -+ 0x9800d898, -+ 0x86f001d9, -+ 0x0489b808, -+ 0xf00c1bf4, -+ 0x21f502f7, -+ 0x00f802ec, -+ 0xb60798c4, -+ 0x8dbb0384, -+ 0x0880b600, -+ 0x80008e80, -+ 0x90b6018f, -+ 0x0f94f001, -+ 0xf801d980, -+ 0x0131f400, -+ 0x9800d898, -+ 0x89b801d9, -+ 0x210bf404, -+ 0xb60789c4, -+ 0x9dbb0394, -+ 0x0890b600, -+ 0x98009e98, -+ 0x80b6019f, -+ 0x0f84f001, -+ 0xf400d880, -+ 0x00f80132, -+ 0x0728b7f1, -+ 0xb906b4b6, -+ 0xc9f002ec, -+ 0x00bcd01f, -+ 0xc800bccf, -+ 0x1bf41fcc, -+ 0x06a7f0fa, -+ 0x010321f5, -+ 0xf840bfcf, -+ 0x28b7f100, -+ 0x06b4b607, -+ 0xb980bfd0, -+ 0xc9f002ec, -+ 0x1ec9f01f, -+ 0xcf00bcd0, -+ 0xccc800bc, -+ 0xfa1bf41f, -+ 0x87f100f8, -+ 0x84b60430, -+ 0x1ff9f006, -+ 0xf8008fd0, -+ 0x3087f100, -+ 0x0684b604, -+ 0xf80080d0, -+ 0x3c87f100, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d000, -+ 0x081887f1, -+ 0xd00684b6, -+ 0x87f1008a, -+ 0x84b60400, -+ 0x0088cf06, -+ 0xf4888aff, -+ 0x87f1f31b, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00099, -+ 0xf100f800, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00099f0, -+ 0x87f10089, -+ 0x84b60818, -+ 0x008ad006, -+ 0x040087f1, -+ 0xcf0684b6, -+ 0x8aff0088, -+ 0xf30bf488, -+ 0x085c87f1, -+ 0xbd0684b6, -+ 0x0099f094, -+ 0xf80089d0, -+ 0x9894bd00, -+ 0x85b600e8, -+ 0x0180b61a, -+ 0xbb0284b6, -+ 0xe0b60098, -+ 0x04efb804, -+ 0xb9eb1bf4, -+ 0x00f8029f, -+ 0x083c87f1, -+ 0xbd0684b6, -+ 0x0199f094, -+ 0xf10089d0, -+ 0xb6071087, -+ 0x94bd0684, -+ 0xf405bbfd, -+ 0x8bd0090b, -+ 0x0099f000, -+ 0xf405eefd, -+ 0x8ed00c0b, -+ 0xc08fd080, -+ 0xb70199f0, -+ 0xc8010080, -+ 0xb4b600ab, -+ 0x0cb9f010, -+ 0xb601aec8, -+ 0xbefd11e4, -+ 0x008bd005, -+ 0xf0008ecf, -+ 0x0bf41fe4, -+ 0x00ce98fa, -+ 0xd005e9fd, -+ 0xc0b6c08e, -+ 0x04cdb804, -+ 0xc8e81bf4, -+ 0x1bf402ab, -+ 0x008bcf18, -+ 0xb01fb4f0, -+ 0x1bf410b4, -+ 0x02a7f0f7, -+ 0xf4c921f4, -+ 0xabc81b0e, -+ 0x10b4b600, -+ 0xf00cb9f0, -+ 0x8bd012b9, -+ 0x008bcf00, -+ 0xf412bbc8, -+ 0x87f1fa1b, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00199, -+ 0xf900f800, -+ 0x02a7f0a0, -+ 0xfcc921f4, -+ 0xf100f8a0, -+ 0xf04afc87, -+ 0x97f00283, -+ 0x0089d00c, -+ 0x020721f5, -+ 0x87f100f8, -+ 0x83f04afc, -+ 0x0d97f002, -+ 0xf50089d0, -+ 0xf8020721, -+ 0xfca7f100, -+ 0x02a3f04f, -+ 0x0500aba2, -+ 0xd00fc7f0, -+ 0xc7f000ac, -+ 0x00bcd00b, -+ 0x020721f5, -+ 0xf000aed0, -+ 0xbcd00ac7, -+ 0x0721f500, -+ 0xf100f802, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00399f0, -+ 0x21f50089, -+ 0xe7f00213, -+ 0x3921f503, -+ 0xfca7f102, -+ 0x02a3f046, -+ 0x0400aba0, -+ 0xf040a0d0, -+ 0xbcd001c7, -+ 0x0721f500, -+ 0x010c9202, -+ 0xf000acd0, -+ 0xbcd002c7, -+ 0x0721f500, -+ 0x2621f502, -+ 0x8087f102, -+ 0x0684b608, -+ 0xb70089cf, -+ 0x95220080, -+ 0x8ed008fe, -+ 0x408ed000, -+ 0xb6808acf, -+ 0xa0b606a5, -+ 0x00eabb01, -+ 0xb60480b6, -+ 0x1bf40192, -+ 0x08e4b6e8, -+ 0xf1f2efbc, -+ 0xb6085c87, -+ 0x94bd0684, -+ 0xd00399f0, -+ 0x00f80089, -+ 0xe7f1e0f9, -+ 0xe4b60814, -+ 0x00efd006, -+ 0x0c1ce7f1, -+ 0xf006e4b6, -+ 0xefd001f7, -+ 0xf8e0fc00, -+ 0xfe04bd00, -+ 0x07fe0004, -+ 0x0017f100, -+ 0x0227f012, -+ 0xf10012d0, -+ 0xfe05b917, -+ 0x17f10010, -+ 0x10d00400, -+ 0x0437f1c0, -+ 0x0634b604, -+ 0x200327f1, -+ 0xf10032d0, -+ 0xd0200427, -+ 0x27f10132, -+ 0x32d0200b, -+ 0x0c27f102, -+ 0x0732d020, -+ 0x0c2427f1, -+ 0xb90624b6, -+ 0x23d00003, -+ 0x0427f100, -+ 0x0023f087, -+ 0xb70012d0, -+ 0xf0010012, -+ 0x12d00427, -+ 0x1031f400, -+ 0x9604e7f1, -+ 0xf440e3f0, -+ 0xf1c76821, -+ 0x01018090, -+ 0x801ff4f0, -+ 0x17f0000f, -+ 0x041fbb01, -+ 0xf10112b6, -+ 0xb6040c27, -+ 0x21d00624, -+ 0x4021d000, -+ 0x080027f1, -+ 0xcf0624b6, -+ 0xf7f00022, -+ 0x08f0b654, -+ 0xb800f398, -+ 0x0bf40432, -+ 0x0034b00b, -+ 0xf8f11bf4, -+ 0x0017f100, -+ 0x02fe5801, -+ 0xf003ff58, -+ 0x0e8000e3, -+ 0x150f8014, -+ 0x013d21f5, -+ 0x070037f1, -+ 0x950634b6, -+ 0x34d00814, -+ 0x4034d000, -+ 0x130030b7, -+ 0xb6001fbb, -+ 0x3fd002f5, -+ 0x0815b600, -+ 0xb60110b6, -+ 0x1fb90814, -+ 0x6321f502, -+ 0x001fbb02, -+ 0xf1000398, -+ 0xf0200047, -+ 0x4ea05043, -+ 0x1fb90804, -+ 0x8d21f402, -+ 0x08004ea0, -+ 0xf4022fb9, -+ 0x4ea08d21, -+ 0xf4bd010c, -+ 0xa08d21f4, -+ 0xf401044e, -+ 0x4ea08d21, -+ 0xf7f00100, -+ 0x8d21f402, -+ 0x08004ea0, -+ 0xc86821f4, -+ 0x0bf41fff, -+ 0x044ea0fa, -+ 0x6821f408, -+ 0xb7001fbb, -+ 0xb6800040, -+ 0x1bf40132, -+ 0x0027f1b4, -+ 0x0624b608, -+ 0xb74021d0, -+ 0xbd080020, -+ 0x1f19f014, -+ 0xf40021d0, -+ 0x28f40031, -+ 0x08d7f000, -+ 0xf43921f4, -+ 0xe4b1f401, -+ 0x1bf54001, -+ 0x87f100d1, -+ 0x84b6083c, -+ 0xf094bd06, -+ 0x89d00499, -+ 0x0017f100, -+ 0x0614b60b, -+ 0xcf4012cf, -+ 0x13c80011, -+ 0x7e0bf41f, -+ 0xf41f23c8, -+ 0x20f95a0b, -+ 0xf10212b9, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00799f0, -+ 0x32f40089, -+ 0x0231f401, -+ 0x082921f5, -+ 0x085c87f1, -+ 0xbd0684b6, -+ 0x0799f094, -+ 0xfc0089d0, -+ 0x3c87f120, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d006, -+ 0xf50131f4, -+ 0xf1082921, -+ 0xb6085c87, -+ 0x94bd0684, -+ 0xd00699f0, -+ 0x0ef40089, -+ 0xb920f931, -+ 0x32f40212, -+ 0x0232f401, -+ 0x082921f5, -+ 0x17f120fc, -+ 0x14b60b00, -+ 0x0012d006, -+ 0xc8130ef4, -+ 0x0bf41f23, -+ 0x0131f40d, -+ 0xf50232f4, -+ 0xf1082921, -+ 0xb60b0c17, -+ 0x27f00614, -+ 0x0012d001, -+ 0x085c87f1, -+ 0xbd0684b6, -+ 0x0499f094, -+ 0xf50089d0, -+ 0xb0ff200e, -+ 0x1bf401e4, -+ 0x02f2b90d, -+ 0x07b521f5, -+ 0xb0420ef4, -+ 0x1bf402e4, -+ 0x3c87f12e, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d007, -+ 0xf40132f4, -+ 0x21f50232, -+ 0x87f10829, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00799, -+ 0x110ef400, -+ 0xf010ef94, -+ 0x21f501f5, -+ 0x0ef502ec, -+ 0x17f1fed1, -+ 0x14b60820, -+ 0xf024bd06, -+ 0x12d01f29, -+ 0xbe0ef500, -+ 0xfe80f9fe, -+ 0x80f90188, -+ 0xa0f990f9, -+ 0xd0f9b0f9, -+ 0xf0f9e0f9, -+ 0xc4800acf, -+ 0x0bf404ab, -+ 0x00b7f11d, -+ 0x08d7f019, -+ 0xcf40becf, -+ 0x21f400bf, -+ 0x00b0b704, -+ 0x01e7f004, -+ 0xe400bed0, -+ 0xf40100ab, -+ 0xd7f00d0b, -+ 0x01e7f108, -+ 0x0421f440, -+ 0x0104b7f1, -+ 0xabffb0bd, -+ 0x0d0bf4b4, -+ 0x0c1ca7f1, -+ 0xd006a4b6, -+ 0x0ad000ab, -+ 0xfcf0fc40, -+ 0xfcd0fce0, -+ 0xfca0fcb0, -+ 0xfe80fc90, -+ 0x80fc0088, -+ 0xf80032f4, -+ 0x60e7f101, -+ 0x40e3f041, -+ 0xf401f7f0, -+ 0x21f48d21, -+ 0x04ffc868, -+ 0xf8fa0bf4, -+ 0x60e7f100, -+ 0x40e3f041, -+ 0x21f4f4bd, -+ 0xf100f88d, -+ 0xf04170e7, -+ 0xf5f040e3, -+ 0x8d21f410, -+ 0xe7f100f8, -+ 0xe3f04170, -+ 0x6821f440, -+ 0xf410f4f0, -+ 0x00f8f31b, -+ 0x0614e7f1, -+ 0xf106e4b6, -+ 0xd00270f7, -+ 0xf7f000ef, -+ 0x01f2b608, -+ 0xf1fd1bf4, -+ 0xd00770f7, -+ 0x00f800ef, -+ 0x086ce7f1, -+ 0xd006e4b6, -+ 0xe7f100ef, -+ 0xe3f08a14, -+ 0x8d21f440, -+ 0xa86ce7f1, -+ 0xf441e3f0, -+ 0x00f88d21, -+ 0x083c87f1, -+ 0xbd0684b6, -+ 0x0599f094, -+ 0xf00089d0, -+ 0x21f40ca7, -+ 0x2417f1c9, -+ 0x0614b60a, -+ 0xf10010d0, -+ 0xb60b0037, -+ 0x32d00634, -+ 0x0c17f140, -+ 0x0614b60a, -+ 0xd00747f0, -+ 0x14d00012, -+ 0x4014cf40, -+ 0xf41f44f0, -+ 0x32d0fa1b, -+ 0x000bfe00, -+ 0xb61f2af0, -+ 0x20b60424, -+ 0x3c87f102, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d008, -+ 0x0a0417f1, -+ 0xd00614b6, -+ 0x17f10012, -+ 0x14b60a20, -+ 0x0227f006, -+ 0x800023f1, -+ 0xf00012d0, -+ 0x27f11017, -+ 0x23f00300, -+ 0x0512fa02, -+ 0x87f103f8, -+ 0x84b6085c, -+ 0xf094bd06, -+ 0x89d00899, -+ 0xc1019800, -+ 0x981814b6, -+ 0x25b6c002, -+ 0x0512fd08, -+ 0xf1160180, -+ 0xb6083c87, -+ 0x94bd0684, -+ 0xd00999f0, -+ 0x27f10089, -+ 0x24b60a04, -+ 0x0021d006, -+ 0xf10127f0, -+ 0xb60a2017, -+ 0x12d00614, -+ 0x0017f100, -+ 0x0613f002, -+ 0xf80501fa, -+ 0x5c87f103, -+ 0x0684b608, -+ 0x99f094bd, -+ 0x0089d009, -+ 0x085c87f1, -+ 0xbd0684b6, -+ 0x0599f094, -+ 0xf80089d0, -+ 0x3121f500, -+ 0xb821f506, -+ 0x0ca7f006, -+ 0xf1c921f4, -+ 0xb60a1017, -+ 0x27f00614, -+ 0x0012d005, -+ 0xfd0012cf, -+ 0x1bf40522, -+ 0x4921f5fa, -+ 0x9800f806, -+ 0x27f18103, -+ 0x24b60a04, -+ 0x0023d006, -+ 0x34c434bd, -+ 0x0f1bf4ff, -+ 0x030057f1, -+ 0xfa0653f0, -+ 0x03f80535, -+ 0x98c04e98, -+ 0x21f4c14f, -+ 0x0830b68d, -+ 0xf40112b6, -+ 0x0398df1b, -+ 0x0023d016, -+ 0xf1800080, -+ 0xf0020017, -+ 0x01fa0613, -+ 0xf803f806, -+ 0x0611f400, -+ 0xf01102f4, -+ 0x21f510f7, -+ 0x21f50698, -+ 0x11f40631, -+ 0x02f7f01c, -+ 0x065721f5, -+ 0x066621f5, -+ 0x067821f5, -+ 0x21f5f4bd, -+ 0x21f50657, -+ 0x019806b8, -+ 0x1427f116, -+ 0x0624b604, -+ 0xf10020d0, -+ 0xf0a500e7, -+ 0x1fb941e3, -+ 0x8d21f402, -+ 0xf004e0b6, -+ 0x2cf001fc, -+ 0x0124b602, -+ 0xf405f2fd, -+ 0x17f18d21, -+ 0x13f04afc, -+ 0x0c27f002, -+ 0xf50012d0, -+ 0xf1020721, -+ 0xf047fc27, -+ 0x20d00223, -+ 0x012cf000, -+ 0xd00320b6, -+ 0xacf00012, -+ 0x06a5f001, -+ 0x9800b7f0, -+ 0x0d98140c, -+ 0x00e7f015, -+ 0x015c21f5, -+ 0xf508a7f0, -+ 0xf5010321, -+ 0xf4020721, -+ 0xa7f02201, -+ 0xc921f40c, -+ 0x0a1017f1, -+ 0xf00614b6, -+ 0x12d00527, -+ 0x0012cf00, -+ 0xf40522fd, -+ 0x02f4fa1b, -+ 0x02f7f032, -+ 0x065721f5, -+ 0x21f5f4bd, -+ 0x21f50698, -+ 0x21f50226, -+ 0xf4bd0666, -+ 0x065721f5, -+ 0x981011f4, -+ 0x11fd8001, -+ 0x070bf405, -+ 0x07df21f5, -+ 0x064921f5, -+ 0x000000f8, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+ 0x00000000, -+}; -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_instmem.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_instmem.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_instmem.c 2011-07-26 07:03:44.514052059 +0200 -@@ -32,7 +32,6 @@ - struct nouveau_channel *bar1; - struct nouveau_gpuobj *bar3_pgd; - struct nouveau_channel *bar3; -- struct nouveau_gpuobj *chan_pgd; - }; - - int -@@ -181,17 +180,11 @@ - goto error; - - /* channel vm */ -- ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, &vm); -+ ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0008000000ULL, -+ &dev_priv->chan_vm); - if (ret) - goto error; - -- ret = nouveau_gpuobj_new(dev, NULL, 0x8000, 4096, 0, &priv->chan_pgd); -- if (ret) -- goto error; -- -- nouveau_vm_ref(vm, &dev_priv->chan_vm, priv->chan_pgd); -- nouveau_vm_ref(NULL, &vm, NULL); -- - nvc0_instmem_resume(dev); - return 0; - error: -@@ -211,8 +204,7 @@ - nv_wr32(dev, 0x1704, 0x00000000); - nv_wr32(dev, 0x1714, 0x00000000); - -- nouveau_vm_ref(NULL, &dev_priv->chan_vm, priv->chan_pgd); -- nouveau_gpuobj_ref(NULL, &priv->chan_pgd); -+ nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); - - nvc0_channel_del(&priv->bar1); - nouveau_vm_ref(NULL, &dev_priv->bar1_vm, priv->bar1_pgd); -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_pm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_pm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_pm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_pm.c 2011-07-26 07:03:44.514052059 +0200 -@@ -0,0 +1,151 @@ -+/* -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include "drmP.h" -+#include "nouveau_drv.h" -+#include "nouveau_bios.h" -+#include "nouveau_pm.h" -+ -+static u32 read_div(struct drm_device *, int, u32, u32); -+static u32 read_pll(struct drm_device *, u32); -+ -+static u32 -+read_vco(struct drm_device *dev, u32 dsrc) -+{ -+ u32 ssrc = nv_rd32(dev, dsrc); -+ if (!(ssrc & 0x00000100)) -+ return read_pll(dev, 0x00e800); -+ return read_pll(dev, 0x00e820); -+} -+ -+static u32 -+read_pll(struct drm_device *dev, u32 pll) -+{ -+ u32 coef = nv_rd32(dev, pll + 4); -+ u32 P = (coef & 0x003f0000) >> 16; -+ u32 N = (coef & 0x0000ff00) >> 8; -+ u32 M = (coef & 0x000000ff) >> 0; -+ u32 sclk, doff; -+ -+ switch (pll & 0xfff000) { -+ case 0x00e000: -+ sclk = 27000; -+ P = 1; -+ break; -+ case 0x137000: -+ doff = (pll - 0x137000) / 0x20; -+ sclk = read_div(dev, doff, 0x137120, 0x137140); -+ break; -+ case 0x132000: -+ switch (pll) { -+ case 0x132000: -+ sclk = read_pll(dev, 0x132020); -+ break; -+ case 0x132020: -+ sclk = read_div(dev, 0, 0x137320, 0x137330); -+ break; -+ default: -+ return 0; -+ } -+ break; -+ default: -+ return 0; -+ } -+ -+ return sclk * N / M / P; -+} -+ -+static u32 -+read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) -+{ -+ u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); -+ u32 sctl = nv_rd32(dev, dctl + (doff * 4)); -+ -+ switch (ssrc & 0x00000003) { -+ case 0: -+ if ((ssrc & 0x00030000) != 0x00030000) -+ return 27000; -+ return 108000; -+ case 2: -+ return 100000; -+ case 3: -+ if (sctl & 0x80000000) { -+ u32 sclk = read_vco(dev, dsrc); -+ u32 sdiv = (sctl & 0x0000003f) + 2; -+ return (sclk * 2) / sdiv; -+ } -+ -+ return read_vco(dev, dsrc); -+ default: -+ return 0; -+ } -+} -+ -+static u32 -+read_mem(struct drm_device *dev) -+{ -+ u32 ssel = nv_rd32(dev, 0x1373f0); -+ if (ssel & 0x00000001) -+ return read_div(dev, 0, 0x137300, 0x137310); -+ return read_pll(dev, 0x132000); -+} -+ -+static u32 -+read_clk(struct drm_device *dev, int clk) -+{ -+ u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); -+ u32 ssel = nv_rd32(dev, 0x137100); -+ u32 sclk, sdiv; -+ -+ if (ssel & (1 << clk)) { -+ if (clk < 7) -+ sclk = read_pll(dev, 0x137000 + (clk * 0x20)); -+ else -+ sclk = read_pll(dev, 0x1370e0); -+ sdiv = ((sctl & 0x00003f00) >> 8) + 2; -+ } else { -+ sclk = read_div(dev, clk, 0x137160, 0x1371d0); -+ sdiv = ((sctl & 0x0000003f) >> 0) + 2; -+ } -+ -+ if (sctl & 0x80000000) -+ return (sclk * 2) / sdiv; -+ return sclk; -+} -+ -+int -+nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -+{ -+ perflvl->shader = read_clk(dev, 0x00); -+ perflvl->core = perflvl->shader / 2; -+ perflvl->memory = read_mem(dev); -+ perflvl->rop = read_clk(dev, 0x01); -+ perflvl->hub07 = read_clk(dev, 0x02); -+ perflvl->hub06 = read_clk(dev, 0x07); -+ perflvl->hub01 = read_clk(dev, 0x08); -+ perflvl->copy = read_clk(dev, 0x09); -+ perflvl->daemon = read_clk(dev, 0x0c); -+ perflvl->vdec = read_clk(dev, 0x0e); -+ return 0; -+} -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_vm.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_vm.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_vm.c 2011-07-26 07:03:44.515052071 +0200 -@@ -105,7 +105,11 @@ - struct drm_device *dev = vm->dev; - struct nouveau_vm_pgd *vpgd; - unsigned long flags; -- u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5; -+ u32 engine; -+ -+ engine = 1; -+ if (vm == dev_priv->bar1_vm || vm == dev_priv->bar3_vm) -+ engine |= 4; - - pinstmem->flush(vm->dev); - -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvc0_vram.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_vram.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvc0_vram.c 2011-07-26 07:03:44.515052071 +0200 -@@ -61,9 +61,7 @@ - u32 type, struct nouveau_mem **pmem) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -- struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; -- struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; -- struct nouveau_mm *mm = man->priv; -+ struct nouveau_mm *mm = &dev_priv->engine.vram.mm; - struct nouveau_mm_node *r; - struct nouveau_mem *mem; - int ret; -@@ -105,9 +103,53 @@ - nvc0_vram_init(struct drm_device *dev) - { - struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_vram_engine *vram = &dev_priv->engine.vram; -+ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ -+ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ -+ u32 parts = nv_rd32(dev, 0x121c74); -+ u32 bsize = nv_rd32(dev, 0x10f20c); -+ u32 offset, length; -+ bool uniform = true; -+ int ret, i; -+ -+ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); -+ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); -+ -+ /* read amount of vram attached to each memory controller */ -+ for (i = 0; i < parts; i++) { -+ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000)); -+ if (psize != bsize) { -+ if (psize < bsize) -+ bsize = psize; -+ uniform = false; -+ } -+ -+ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize); -+ -+ dev_priv->vram_size += (u64)psize << 20; -+ } -+ -+ /* if all controllers have the same amount attached, there's no holes */ -+ if (uniform) { -+ offset = rsvd_head; -+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; -+ return nouveau_mm_init(&vram->mm, offset, length, 1); -+ } -+ -+ /* otherwise, address lowest common amount from 0GiB */ -+ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1); -+ if (ret) -+ return ret; -+ -+ /* and the rest starting from (8GiB + common_size) */ -+ offset = (0x0200000000ULL >> 12) + (bsize << 8); -+ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail; -+ -+ ret = nouveau_mm_init(&vram->mm, offset, length, 0); -+ if (ret) { -+ nouveau_mm_fini(&vram->mm); -+ return ret; -+ } - -- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; -- dev_priv->vram_size *= nv_rd32(dev, 0x121c74); -- dev_priv->vram_rblock_size = 4096; - return 0; - } -diff -Naur linux-3.0/drivers/gpu/drm/nouveau/nvd0_display.c linux-3.0.patch/drivers/gpu/drm/nouveau/nvd0_display.c ---- linux-3.0/drivers/gpu/drm/nouveau/nvd0_display.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.0.patch/drivers/gpu/drm/nouveau/nvd0_display.c 2011-07-26 07:03:44.517052095 +0200 -@@ -0,0 +1,1456 @@ -+/* -+ * Copyright 2011 Red Hat Inc. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: Ben Skeggs -+ */ -+ -+#include -+ -+#include "drmP.h" -+#include "drm_crtc_helper.h" -+ -+#include "nouveau_drv.h" -+#include "nouveau_connector.h" -+#include "nouveau_encoder.h" -+#include "nouveau_crtc.h" -+#include "nouveau_dma.h" -+#include "nouveau_fb.h" -+#include "nv50_display.h" -+ -+struct nvd0_display { -+ struct nouveau_gpuobj *mem; -+ struct { -+ dma_addr_t handle; -+ u32 *ptr; -+ } evo[1]; -+ -+ struct tasklet_struct tasklet; -+ u32 modeset; -+}; -+ -+static struct nvd0_display * -+nvd0_display(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ return dev_priv->engine.display.priv; -+} -+ -+static inline int -+evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) -+{ -+ int ret = 0; -+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); -+ nv_wr32(dev, 0x610704 + (id * 0x10), data); -+ nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); -+ if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) -+ ret = -EBUSY; -+ nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); -+ return ret; -+} -+ -+static u32 * -+evo_wait(struct drm_device *dev, int id, int nr) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; -+ -+ if (put + nr >= (PAGE_SIZE / 4)) { -+ disp->evo[id].ptr[put] = 0x20000000; -+ -+ nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); -+ if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { -+ NV_ERROR(dev, "evo %d dma stalled\n", id); -+ return NULL; -+ } -+ -+ put = 0; -+ } -+ -+ return disp->evo[id].ptr + put; -+} -+ -+static void -+evo_kick(u32 *push, struct drm_device *dev, int id) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); -+} -+ -+#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) -+#define evo_data(p,d) *((p)++) = (d) -+ -+static struct drm_crtc * -+nvd0_display_crtc_get(struct drm_encoder *encoder) -+{ -+ return nouveau_encoder(encoder)->crtc; -+} -+ -+/****************************************************************************** -+ * CRTC -+ *****************************************************************************/ -+static int -+nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) -+{ -+ struct drm_device *dev = nv_crtc->base.dev; -+ u32 *push, mode; -+ -+ mode = 0x00000000; -+ if (on) { -+ /* 0x11: 6bpc dynamic 2x2 -+ * 0x13: 8bpc dynamic 2x2 -+ * 0x19: 6bpc static 2x2 -+ * 0x1b: 8bpc static 2x2 -+ * 0x21: 6bpc temporal -+ * 0x23: 8bpc temporal -+ */ -+ mode = 0x00000011; -+ } -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, mode); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, dev, 0); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) -+{ -+ struct drm_display_mode *mode = &nv_crtc->base.mode; -+ struct drm_device *dev = nv_crtc->base.dev; -+ struct nouveau_connector *nv_connector; -+ u32 *push, outX, outY; -+ -+ outX = mode->hdisplay; -+ outY = mode->vdisplay; -+ -+ nv_connector = nouveau_crtc_connector_get(nv_crtc); -+ if (nv_connector && nv_connector->native_mode) { -+ struct drm_display_mode *native = nv_connector->native_mode; -+ u32 xratio = (native->hdisplay << 19) / mode->hdisplay; -+ u32 yratio = (native->vdisplay << 19) / mode->vdisplay; -+ -+ switch (type) { -+ case DRM_MODE_SCALE_ASPECT: -+ if (xratio > yratio) { -+ outX = (mode->hdisplay * yratio) >> 19; -+ outY = (mode->vdisplay * yratio) >> 19; -+ } else { -+ outX = (mode->hdisplay * xratio) >> 19; -+ outY = (mode->vdisplay * xratio) >> 19; -+ } -+ break; -+ case DRM_MODE_SCALE_FULLSCREEN: -+ outX = native->hdisplay; -+ outY = native->vdisplay; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ push = evo_wait(dev, 0, 16); -+ if (push) { -+ evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); -+ evo_data(push, (outY << 16) | outX); -+ evo_data(push, (outY << 16) | outX); -+ evo_data(push, (outY << 16) | outX); -+ evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, dev, 0); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, -+ int x, int y, bool update) -+{ -+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); -+ u32 *push; -+ -+ push = evo_wait(fb->dev, 0, 16); -+ if (push) { -+ evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, nvfb->nvbo->bo.offset >> 8); -+ evo_mthd(push, 0x0468 + (nv_crtc->index * 0x300), 4); -+ evo_data(push, (fb->height << 16) | fb->width); -+ evo_data(push, nvfb->r_pitch); -+ evo_data(push, nvfb->r_format); -+ evo_data(push, nvfb->r_dma); -+ evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, (y << 16) | x); -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ evo_kick(push, fb->dev, 0); -+ } -+ -+ nv_crtc->fb.tile_flags = nvfb->r_dma; -+ return 0; -+} -+ -+static void -+nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) -+{ -+ struct drm_device *dev = nv_crtc->base.dev; -+ u32 *push = evo_wait(dev, 0, 16); -+ if (push) { -+ if (show) { -+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); -+ evo_data(push, 0x85000000); -+ evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8); -+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, NvEvoVRAM); -+ } else { -+ evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x05000000); -+ evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ } -+ -+ if (update) { -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ } -+ -+ evo_kick(push, dev, 0); -+ } -+} -+ -+static void -+nvd0_crtc_dpms(struct drm_crtc *crtc, int mode) -+{ -+} -+ -+static void -+nvd0_crtc_prepare(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 *push; -+ -+ push = evo_wait(crtc->dev, 0, 2); -+ if (push) { -+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x03000000); -+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nvd0_crtc_cursor_show(nv_crtc, false, false); -+} -+ -+static void -+nvd0_crtc_commit(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 *push; -+ -+ push = evo_wait(crtc->dev, 0, 32); -+ if (push) { -+ evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, nv_crtc->fb.tile_flags); -+ evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4); -+ evo_data(push, 0x83000000); -+ evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8); -+ evo_data(push, 0x00000000); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, NvEvoVRAM); -+ evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0xffffff00); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); -+} -+ -+static bool -+nvd0_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ return true; -+} -+ -+static int -+nvd0_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); -+ int ret; -+ -+ ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); -+ if (ret) -+ return ret; -+ -+ if (old_fb) { -+ nvfb = nouveau_framebuffer(old_fb); -+ nouveau_bo_unpin(nvfb->nvbo); -+ } -+ -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, -+ struct drm_display_mode *mode, int x, int y, -+ struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct nouveau_connector *nv_connector; -+ u32 htotal = mode->htotal; -+ u32 vtotal = mode->vtotal; -+ u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; -+ u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; -+ u32 hfrntp = mode->hsync_start - mode->hdisplay; -+ u32 vfrntp = mode->vsync_start - mode->vdisplay; -+ u32 hbackp = mode->htotal - mode->hsync_end; -+ u32 vbackp = mode->vtotal - mode->vsync_end; -+ u32 hss2be = hsyncw + hbackp; -+ u32 vss2be = vsyncw + vbackp; -+ u32 hss2de = htotal - hfrntp; -+ u32 vss2de = vtotal - vfrntp; -+ u32 syncs, *push; -+ int ret; -+ -+ syncs = 0x00000001; -+ if (mode->flags & DRM_MODE_FLAG_NHSYNC) -+ syncs |= 0x00000008; -+ if (mode->flags & DRM_MODE_FLAG_NVSYNC) -+ syncs |= 0x00000010; -+ -+ ret = nvd0_crtc_swap_fbs(crtc, old_fb); -+ if (ret) -+ return ret; -+ -+ push = evo_wait(crtc->dev, 0, 64); -+ if (push) { -+ evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); -+ evo_data(push, 0x00000000); -+ evo_data(push, (vtotal << 16) | htotal); -+ evo_data(push, (vsyncw << 16) | hsyncw); -+ evo_data(push, (vss2be << 16) | hss2be); -+ evo_data(push, (vss2de << 16) | hss2de); -+ evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); -+ evo_data(push, 0x00000000); /* ??? */ -+ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); -+ evo_data(push, mode->clock * 1000); -+ evo_data(push, 0x00200000); /* ??? */ -+ evo_data(push, mode->clock * 1000); -+ evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); -+ evo_data(push, syncs); -+ evo_kick(push, crtc->dev, 0); -+ } -+ -+ nv_connector = nouveau_crtc_connector_get(nv_crtc); -+ nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); -+ nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); -+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, -+ struct drm_framebuffer *old_fb) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ int ret; -+ -+ ret = nvd0_crtc_swap_fbs(crtc, old_fb); -+ if (ret) -+ return ret; -+ -+ nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); -+ return 0; -+} -+ -+static int -+nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, int x, int y, -+ enum mode_set_atomic state) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ nvd0_crtc_set_image(nv_crtc, fb, x, y, true); -+ return 0; -+} -+ -+static void -+nvd0_crtc_lut_load(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); -+ int i; -+ -+ for (i = 0; i < 256; i++) { -+ writew(0x6000 + (nv_crtc->lut.r[i] >> 2), lut + (i * 0x20) + 0); -+ writew(0x6000 + (nv_crtc->lut.g[i] >> 2), lut + (i * 0x20) + 2); -+ writew(0x6000 + (nv_crtc->lut.b[i] >> 2), lut + (i * 0x20) + 4); -+ } -+} -+ -+static int -+nvd0_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, -+ uint32_t handle, uint32_t width, uint32_t height) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ struct drm_gem_object *gem; -+ struct nouveau_bo *nvbo; -+ bool visible = (handle != 0); -+ int i, ret = 0; -+ -+ if (visible) { -+ if (width != 64 || height != 64) -+ return -EINVAL; -+ -+ gem = drm_gem_object_lookup(dev, file_priv, handle); -+ if (unlikely(!gem)) -+ return -ENOENT; -+ nvbo = nouveau_gem_object(gem); -+ -+ ret = nouveau_bo_map(nvbo); -+ if (ret == 0) { -+ for (i = 0; i < 64 * 64; i++) { -+ u32 v = nouveau_bo_rd32(nvbo, i); -+ nouveau_bo_wr32(nv_crtc->cursor.nvbo, i, v); -+ } -+ nouveau_bo_unmap(nvbo); -+ } -+ -+ drm_gem_object_unreference_unlocked(gem); -+ } -+ -+ if (visible != nv_crtc->cursor.visible) { -+ nvd0_crtc_cursor_show(nv_crtc, visible, true); -+ nv_crtc->cursor.visible = visible; -+ } -+ -+ return ret; -+} -+ -+static int -+nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ const u32 data = (y << 16) | x; -+ -+ nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); -+ nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); -+ return 0; -+} -+ -+static void -+nvd0_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, -+ uint32_t start, uint32_t size) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ u32 end = max(start + size, (u32)256); -+ u32 i; -+ -+ for (i = start; i < end; i++) { -+ nv_crtc->lut.r[i] = r[i]; -+ nv_crtc->lut.g[i] = g[i]; -+ nv_crtc->lut.b[i] = b[i]; -+ } -+ -+ nvd0_crtc_lut_load(crtc); -+} -+ -+static void -+nvd0_crtc_destroy(struct drm_crtc *crtc) -+{ -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); -+ nouveau_bo_unmap(nv_crtc->cursor.nvbo); -+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); -+ nouveau_bo_unmap(nv_crtc->lut.nvbo); -+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); -+ drm_crtc_cleanup(crtc); -+ kfree(crtc); -+} -+ -+static const struct drm_crtc_helper_funcs nvd0_crtc_hfunc = { -+ .dpms = nvd0_crtc_dpms, -+ .prepare = nvd0_crtc_prepare, -+ .commit = nvd0_crtc_commit, -+ .mode_fixup = nvd0_crtc_mode_fixup, -+ .mode_set = nvd0_crtc_mode_set, -+ .mode_set_base = nvd0_crtc_mode_set_base, -+ .mode_set_base_atomic = nvd0_crtc_mode_set_base_atomic, -+ .load_lut = nvd0_crtc_lut_load, -+}; -+ -+static const struct drm_crtc_funcs nvd0_crtc_func = { -+ .cursor_set = nvd0_crtc_cursor_set, -+ .cursor_move = nvd0_crtc_cursor_move, -+ .gamma_set = nvd0_crtc_gamma_set, -+ .set_config = drm_crtc_helper_set_config, -+ .destroy = nvd0_crtc_destroy, -+}; -+ -+static int -+nvd0_crtc_create(struct drm_device *dev, int index) -+{ -+ struct nouveau_crtc *nv_crtc; -+ struct drm_crtc *crtc; -+ int ret, i; -+ -+ nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); -+ if (!nv_crtc) -+ return -ENOMEM; -+ -+ nv_crtc->index = index; -+ nv_crtc->set_dither = nvd0_crtc_set_dither; -+ nv_crtc->set_scale = nvd0_crtc_set_scale; -+ for (i = 0; i < 256; i++) { -+ nv_crtc->lut.r[i] = i << 8; -+ nv_crtc->lut.g[i] = i << 8; -+ nv_crtc->lut.b[i] = i << 8; -+ } -+ -+ crtc = &nv_crtc->base; -+ drm_crtc_init(dev, crtc, &nvd0_crtc_func); -+ drm_crtc_helper_add(crtc, &nvd0_crtc_hfunc); -+ drm_mode_crtc_set_gamma_size(crtc, 256); -+ -+ ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, &nv_crtc->cursor.nvbo); -+ if (!ret) { -+ ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); -+ if (!ret) -+ ret = nouveau_bo_map(nv_crtc->cursor.nvbo); -+ if (ret) -+ nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); -+ } -+ -+ if (ret) -+ goto out; -+ -+ ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, -+ 0, 0x0000, &nv_crtc->lut.nvbo); -+ if (!ret) { -+ ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); -+ if (!ret) -+ ret = nouveau_bo_map(nv_crtc->lut.nvbo); -+ if (ret) -+ nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); -+ } -+ -+ if (ret) -+ goto out; -+ -+ nvd0_crtc_lut_load(crtc); -+ -+out: -+ if (ret) -+ nvd0_crtc_destroy(crtc); -+ return ret; -+} -+ -+/****************************************************************************** -+ * DAC -+ *****************************************************************************/ -+static void -+nvd0_dac_dpms(struct drm_encoder *encoder, int mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ int or = nv_encoder->or; -+ u32 dpms_ctrl; -+ -+ dpms_ctrl = 0x80000000; -+ if (mode == DRM_MODE_DPMS_STANDBY || mode == DRM_MODE_DPMS_OFF) -+ dpms_ctrl |= 0x00000001; -+ if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) -+ dpms_ctrl |= 0x00000004; -+ -+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); -+ nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); -+} -+ -+static bool -+nvd0_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_connector *nv_connector; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ if (nv_connector && nv_connector->native_mode) { -+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -+ int id = adjusted_mode->base.id; -+ *adjusted_mode = *nv_connector->native_mode; -+ adjusted_mode->base.id = id; -+ } -+ } -+ -+ return true; -+} -+ -+static void -+nvd0_dac_prepare(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_dac_commit(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ u32 *push; -+ -+ nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); -+ -+ push = evo_wait(encoder->dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); -+ evo_data(push, 1 << nv_crtc->index); -+ evo_data(push, 0x00ff); -+ evo_kick(push, encoder->dev, 0); -+ } -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static void -+nvd0_dac_disconnect(struct drm_encoder *encoder) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ u32 *push; -+ -+ if (nv_encoder->crtc) { -+ nvd0_crtc_prepare(nv_encoder->crtc); -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ } -+ -+ nv_encoder->crtc = NULL; -+ } -+} -+ -+static enum drm_connector_status -+nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) -+{ -+ enum drm_connector_status status = connector_status_disconnected; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ int or = nv_encoder->or; -+ u32 load; -+ -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); -+ udelay(9500); -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); -+ -+ load = nv_rd32(dev, 0x61a00c + (or * 0x800)); -+ if ((load & 0x38000000) == 0x38000000) -+ status = connector_status_connected; -+ -+ nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); -+ return status; -+} -+ -+static void -+nvd0_dac_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+ kfree(encoder); -+} -+ -+static const struct drm_encoder_helper_funcs nvd0_dac_hfunc = { -+ .dpms = nvd0_dac_dpms, -+ .mode_fixup = nvd0_dac_mode_fixup, -+ .prepare = nvd0_dac_prepare, -+ .commit = nvd0_dac_commit, -+ .mode_set = nvd0_dac_mode_set, -+ .disable = nvd0_dac_disconnect, -+ .get_crtc = nvd0_display_crtc_get, -+ .detect = nvd0_dac_detect -+}; -+ -+static const struct drm_encoder_funcs nvd0_dac_func = { -+ .destroy = nvd0_dac_destroy, -+}; -+ -+static int -+nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) -+{ -+ struct drm_device *dev = connector->dev; -+ struct nouveau_encoder *nv_encoder; -+ struct drm_encoder *encoder; -+ -+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); -+ if (!nv_encoder) -+ return -ENOMEM; -+ nv_encoder->dcb = dcbe; -+ nv_encoder->or = ffs(dcbe->or) - 1; -+ -+ encoder = to_drm_encoder(nv_encoder); -+ encoder->possible_crtcs = dcbe->heads; -+ encoder->possible_clones = 0; -+ drm_encoder_init(dev, encoder, &nvd0_dac_func, DRM_MODE_ENCODER_DAC); -+ drm_encoder_helper_add(encoder, &nvd0_dac_hfunc); -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ return 0; -+} -+ -+/****************************************************************************** -+ * SOR -+ *****************************************************************************/ -+static void -+nvd0_sor_dpms(struct drm_encoder *encoder, int mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ struct drm_encoder *partner; -+ int or = nv_encoder->or; -+ u32 dpms_ctrl; -+ -+ nv_encoder->last_dpms = mode; -+ -+ list_for_each_entry(partner, &dev->mode_config.encoder_list, head) { -+ struct nouveau_encoder *nv_partner = nouveau_encoder(partner); -+ -+ if (partner->encoder_type != DRM_MODE_ENCODER_TMDS) -+ continue; -+ -+ if (nv_partner != nv_encoder && -+ nv_partner->dcb->or == nv_encoder->or) { -+ if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) -+ return; -+ break; -+ } -+ } -+ -+ dpms_ctrl = (mode == DRM_MODE_DPMS_ON); -+ dpms_ctrl |= 0x80000000; -+ -+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); -+ nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); -+ nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); -+} -+ -+static bool -+nvd0_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_connector *nv_connector; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ if (nv_connector && nv_connector->native_mode) { -+ if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { -+ int id = adjusted_mode->base.id; -+ *adjusted_mode = *nv_connector->native_mode; -+ adjusted_mode->base.id = id; -+ } -+ } -+ -+ return true; -+} -+ -+static void -+nvd0_sor_prepare(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_sor_commit(struct drm_encoder *encoder) -+{ -+} -+ -+static void -+nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, -+ struct drm_display_mode *mode) -+{ -+ struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); -+ struct nouveau_connector *nv_connector; -+ struct nvbios *bios = &dev_priv->vbios; -+ u32 mode_ctrl = (1 << nv_crtc->index); -+ u32 *push, or_config; -+ -+ nv_connector = nouveau_encoder_connector_get(nv_encoder); -+ switch (nv_encoder->dcb->type) { -+ case OUTPUT_TMDS: -+ if (nv_encoder->dcb->sorconf.link & 1) { -+ if (mode->clock < 165000) -+ mode_ctrl |= 0x00000100; -+ else -+ mode_ctrl |= 0x00000500; -+ } else { -+ mode_ctrl |= 0x00000200; -+ } -+ -+ or_config = (mode_ctrl & 0x00000f00) >> 8; -+ if (mode->clock >= 165000) -+ or_config |= 0x0100; -+ break; -+ case OUTPUT_LVDS: -+ or_config = (mode_ctrl & 0x00000f00) >> 8; -+ if (bios->fp_no_ddc) { -+ if (bios->fp.dual_link) -+ or_config |= 0x0100; -+ if (bios->fp.if_is_24bit) -+ or_config |= 0x0200; -+ } else { -+ if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { -+ if (((u8 *)nv_connector->edid)[121] == 2) -+ or_config |= 0x0100; -+ } else -+ if (mode->clock >= bios->fp.duallink_transition_clk) { -+ or_config |= 0x0100; -+ } -+ -+ if (or_config & 0x0100) { -+ if (bios->fp.strapless_is_24bit & 2) -+ or_config |= 0x0200; -+ } else { -+ if (bios->fp.strapless_is_24bit & 1) -+ or_config |= 0x0200; -+ } -+ -+ if (nv_connector->base.display_info.bpc == 8) -+ or_config |= 0x0200; -+ -+ } -+ break; -+ default: -+ BUG_ON(1); -+ break; -+ } -+ -+ nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); -+ -+ push = evo_wait(encoder->dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); -+ evo_data(push, mode_ctrl); -+ evo_data(push, or_config); -+ evo_kick(push, encoder->dev, 0); -+ } -+ -+ nv_encoder->crtc = encoder->crtc; -+} -+ -+static void -+nvd0_sor_disconnect(struct drm_encoder *encoder) -+{ -+ struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); -+ struct drm_device *dev = encoder->dev; -+ u32 *push; -+ -+ if (nv_encoder->crtc) { -+ nvd0_crtc_prepare(nv_encoder->crtc); -+ -+ push = evo_wait(dev, 0, 4); -+ if (push) { -+ evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0080, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ } -+ -+ nv_encoder->crtc = NULL; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; -+ } -+} -+ -+static void -+nvd0_sor_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+ kfree(encoder); -+} -+ -+static const struct drm_encoder_helper_funcs nvd0_sor_hfunc = { -+ .dpms = nvd0_sor_dpms, -+ .mode_fixup = nvd0_sor_mode_fixup, -+ .prepare = nvd0_sor_prepare, -+ .commit = nvd0_sor_commit, -+ .mode_set = nvd0_sor_mode_set, -+ .disable = nvd0_sor_disconnect, -+ .get_crtc = nvd0_display_crtc_get, -+}; -+ -+static const struct drm_encoder_funcs nvd0_sor_func = { -+ .destroy = nvd0_sor_destroy, -+}; -+ -+static int -+nvd0_sor_create(struct drm_connector *connector, struct dcb_entry *dcbe) -+{ -+ struct drm_device *dev = connector->dev; -+ struct nouveau_encoder *nv_encoder; -+ struct drm_encoder *encoder; -+ -+ nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); -+ if (!nv_encoder) -+ return -ENOMEM; -+ nv_encoder->dcb = dcbe; -+ nv_encoder->or = ffs(dcbe->or) - 1; -+ nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; -+ -+ encoder = to_drm_encoder(nv_encoder); -+ encoder->possible_crtcs = dcbe->heads; -+ encoder->possible_clones = 0; -+ drm_encoder_init(dev, encoder, &nvd0_sor_func, DRM_MODE_ENCODER_TMDS); -+ drm_encoder_helper_add(encoder, &nvd0_sor_hfunc); -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ return 0; -+} -+ -+/****************************************************************************** -+ * IRQ -+ *****************************************************************************/ -+static struct dcb_entry * -+lookup_dcb(struct drm_device *dev, int id, u32 mc) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ int type, or, i; -+ -+ if (id < 4) { -+ type = OUTPUT_ANALOG; -+ or = id; -+ } else { -+ switch (mc & 0x00000f00) { -+ case 0x00000000: type = OUTPUT_LVDS; break; -+ case 0x00000100: type = OUTPUT_TMDS; break; -+ case 0x00000200: type = OUTPUT_TMDS; break; -+ case 0x00000500: type = OUTPUT_TMDS; break; -+ default: -+ NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); -+ return NULL; -+ } -+ -+ or = id - 4; -+ } -+ -+ for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { -+ struct dcb_entry *dcb = &dev_priv->vbios.dcb.entry[i]; -+ if (dcb->type == type && (dcb->or & (1 << or))) -+ return dcb; -+ } -+ -+ NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); -+ return NULL; -+} -+ -+static void -+nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ int i; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); -+ if (!(mcc & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcc); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ u32 or, tmp, pclk; -+ int i; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); -+ if (!(mcc & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcc); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); -+ } -+ -+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; -+ if (mask & 0x00010000) { -+ nv50_crtc_set_clock(dev, crtc, pclk); -+ } -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); -+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); -+ if (!(mcp & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcp); -+ if (!dcb) -+ continue; -+ or = ffs(dcb->or) - 1; -+ -+ nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); -+ -+ nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); -+ switch (dcb->type) { -+ case OUTPUT_ANALOG: -+ nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); -+ break; -+ case OUTPUT_TMDS: -+ case OUTPUT_LVDS: -+ if (cfg & 0x00000100) -+ tmp = 0x00000101; -+ else -+ tmp = 0x00000000; -+ -+ nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); -+ break; -+ default: -+ break; -+ } -+ -+ break; -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) -+{ -+ struct dcb_entry *dcb; -+ int pclk, i; -+ -+ pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; -+ -+ for (i = 0; mask && i < 8; i++) { -+ u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); -+ u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); -+ if (!(mcp & (1 << crtc))) -+ continue; -+ -+ dcb = lookup_dcb(dev, i, mcp); -+ if (!dcb) -+ continue; -+ -+ nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); -+ } -+ -+ nv_wr32(dev, 0x6101d4, 0x00000000); -+ nv_wr32(dev, 0x6109d4, 0x00000000); -+ nv_wr32(dev, 0x6101d0, 0x80000000); -+} -+ -+static void -+nvd0_display_bh(unsigned long data) -+{ -+ struct drm_device *dev = (struct drm_device *)data; -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 mask, crtc; -+ int i; -+ -+ if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { -+ NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); -+ NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", -+ nv_rd32(dev, 0x6101d0), -+ nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); -+ for (i = 0; i < 8; i++) { -+ NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", -+ i < 4 ? "DAC" : "SOR", i, -+ nv_rd32(dev, 0x640180 + (i * 0x20)), -+ nv_rd32(dev, 0x660180 + (i * 0x20))); -+ } -+ } -+ -+ mask = nv_rd32(dev, 0x6101d4); -+ crtc = 0; -+ if (!mask) { -+ mask = nv_rd32(dev, 0x6109d4); -+ crtc = 1; -+ } -+ -+ if (disp->modeset & 0x00000001) -+ nvd0_display_unk1_handler(dev, crtc, mask); -+ if (disp->modeset & 0x00000002) -+ nvd0_display_unk2_handler(dev, crtc, mask); -+ if (disp->modeset & 0x00000004) -+ nvd0_display_unk4_handler(dev, crtc, mask); -+} -+ -+static void -+nvd0_display_intr(struct drm_device *dev) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 intr = nv_rd32(dev, 0x610088); -+ -+ if (intr & 0x00000002) { -+ u32 stat = nv_rd32(dev, 0x61009c); -+ int chid = ffs(stat) - 1; -+ if (chid >= 0) { -+ u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); -+ u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); -+ u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); -+ -+ NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " -+ "0x%08x 0x%08x\n", -+ chid, (mthd & 0x0000ffc), data, mthd, unkn); -+ nv_wr32(dev, 0x61009c, (1 << chid)); -+ nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); -+ } -+ -+ intr &= ~0x00000002; -+ } -+ -+ if (intr & 0x00100000) { -+ u32 stat = nv_rd32(dev, 0x6100ac); -+ -+ if (stat & 0x00000007) { -+ disp->modeset = stat; -+ tasklet_schedule(&disp->tasklet); -+ -+ nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); -+ stat &= ~0x00000007; -+ } -+ -+ if (stat) { -+ NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); -+ nv_wr32(dev, 0x6100ac, stat); -+ } -+ -+ intr &= ~0x00100000; -+ } -+ -+ if (intr & 0x01000000) { -+ u32 stat = nv_rd32(dev, 0x6100bc); -+ nv_wr32(dev, 0x6100bc, stat); -+ intr &= ~0x01000000; -+ } -+ -+ if (intr & 0x02000000) { -+ u32 stat = nv_rd32(dev, 0x6108bc); -+ nv_wr32(dev, 0x6108bc, stat); -+ intr &= ~0x02000000; -+ } -+ -+ if (intr) -+ NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); -+} -+ -+/****************************************************************************** -+ * Init -+ *****************************************************************************/ -+static void -+nvd0_display_fini(struct drm_device *dev) -+{ -+ int i; -+ -+ /* fini cursors */ -+ for (i = 14; i >= 13; i--) { -+ if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) -+ continue; -+ -+ nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); -+ nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); -+ nv_mask(dev, 0x610090, 1 << i, 0x00000000); -+ nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); -+ } -+ -+ /* fini master */ -+ if (nv_rd32(dev, 0x610490) & 0x00000010) { -+ nv_mask(dev, 0x610490, 0x00000010, 0x00000000); -+ nv_mask(dev, 0x610490, 0x00000003, 0x00000000); -+ nv_wait(dev, 0x610490, 0x80000000, 0x00000000); -+ nv_mask(dev, 0x610090, 0x00000001, 0x00000000); -+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); -+ } -+} -+ -+int -+nvd0_display_init(struct drm_device *dev) -+{ -+ struct nvd0_display *disp = nvd0_display(dev); -+ u32 *push; -+ int i; -+ -+ if (nv_rd32(dev, 0x6100ac) & 0x00000100) { -+ nv_wr32(dev, 0x6100ac, 0x00000100); -+ nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); -+ if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { -+ NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", -+ nv_rd32(dev, 0x6194e8)); -+ return -EBUSY; -+ } -+ } -+ -+ /* nfi what these are exactly, i do know that SOR_MODE_CTRL won't -+ * work at all unless you do the SOR part below. -+ */ -+ for (i = 0; i < 3; i++) { -+ u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); -+ nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); -+ } -+ -+ for (i = 0; i < 4; i++) { -+ u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); -+ nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); -+ } -+ -+ for (i = 0; i < 2; i++) { -+ u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); -+ u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); -+ u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); -+ nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); -+ nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); -+ nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); -+ } -+ -+ /* point at our hash table / objects, enable interrupts */ -+ nv_wr32(dev, 0x610010, (disp->mem->vinst >> 8) | 9); -+ nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); -+ -+ /* init master */ -+ nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); -+ nv_wr32(dev, 0x610498, 0x00010000); -+ nv_wr32(dev, 0x61049c, 0x00000001); -+ nv_mask(dev, 0x610490, 0x00000010, 0x00000010); -+ nv_wr32(dev, 0x640000, 0x00000000); -+ nv_wr32(dev, 0x610490, 0x01000013); -+ if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { -+ NV_ERROR(dev, "PDISP: master 0x%08x\n", -+ nv_rd32(dev, 0x610490)); -+ return -EBUSY; -+ } -+ nv_mask(dev, 0x610090, 0x00000001, 0x00000001); -+ nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); -+ -+ /* init cursors */ -+ for (i = 13; i <= 14; i++) { -+ nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); -+ if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { -+ NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, -+ nv_rd32(dev, 0x610490 + (i * 0x10))); -+ return -EBUSY; -+ } -+ -+ nv_mask(dev, 0x610090, 1 << i, 1 << i); -+ nv_mask(dev, 0x6100a0, 1 << i, 1 << i); -+ } -+ -+ push = evo_wait(dev, 0, 32); -+ if (!push) -+ return -EBUSY; -+ evo_mthd(push, 0x0088, 1); -+ evo_data(push, NvEvoSync); -+ evo_mthd(push, 0x0084, 1); -+ evo_data(push, 0x00000000); -+ evo_mthd(push, 0x0084, 1); -+ evo_data(push, 0x80000000); -+ evo_mthd(push, 0x008c, 1); -+ evo_data(push, 0x00000000); -+ evo_kick(push, dev, 0); -+ -+ return 0; -+} -+ -+void -+nvd0_display_destroy(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nvd0_display *disp = nvd0_display(dev); -+ struct pci_dev *pdev = dev->pdev; -+ -+ nvd0_display_fini(dev); -+ -+ pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); -+ nouveau_gpuobj_ref(NULL, &disp->mem); -+ nouveau_irq_unregister(dev, 26); -+ -+ dev_priv->engine.display.priv = NULL; -+ kfree(disp); -+} -+ -+int -+nvd0_display_create(struct drm_device *dev) -+{ -+ struct drm_nouveau_private *dev_priv = dev->dev_private; -+ struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; -+ struct dcb_table *dcb = &dev_priv->vbios.dcb; -+ struct drm_connector *connector, *tmp; -+ struct pci_dev *pdev = dev->pdev; -+ struct nvd0_display *disp; -+ struct dcb_entry *dcbe; -+ int ret, i; -+ -+ disp = kzalloc(sizeof(*disp), GFP_KERNEL); -+ if (!disp) -+ return -ENOMEM; -+ dev_priv->engine.display.priv = disp; -+ -+ /* create crtc objects to represent the hw heads */ -+ for (i = 0; i < 2; i++) { -+ ret = nvd0_crtc_create(dev, i); -+ if (ret) -+ goto out; -+ } -+ -+ /* create encoder/connector objects based on VBIOS DCB table */ -+ for (i = 0, dcbe = &dcb->entry[0]; i < dcb->entries; i++, dcbe++) { -+ connector = nouveau_connector_create(dev, dcbe->connector); -+ if (IS_ERR(connector)) -+ continue; -+ -+ if (dcbe->location != DCB_LOC_ON_CHIP) { -+ NV_WARN(dev, "skipping off-chip encoder %d/%d\n", -+ dcbe->type, ffs(dcbe->or) - 1); -+ continue; -+ } -+ -+ switch (dcbe->type) { -+ case OUTPUT_TMDS: -+ case OUTPUT_LVDS: -+ nvd0_sor_create(connector, dcbe); -+ break; -+ case OUTPUT_ANALOG: -+ nvd0_dac_create(connector, dcbe); -+ break; -+ default: -+ NV_WARN(dev, "skipping unsupported encoder %d/%d\n", -+ dcbe->type, ffs(dcbe->or) - 1); -+ continue; -+ } -+ } -+ -+ /* cull any connectors we created that don't have an encoder */ -+ list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { -+ if (connector->encoder_ids[0]) -+ continue; -+ -+ NV_WARN(dev, "%s has no encoders, removing\n", -+ drm_get_connector_name(connector)); -+ connector->funcs->destroy(connector); -+ } -+ -+ /* setup interrupt handling */ -+ tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); -+ nouveau_irq_register(dev, 26, nvd0_display_intr); -+ -+ /* hash table and dma objects for the memory areas we care about */ -+ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, -+ NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); -+ if (ret) -+ goto out; -+ -+ nv_wo32(disp->mem, 0x1000, 0x00000049); -+ nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); -+ nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); -+ nv_wo32(disp->mem, 0x100c, 0x00000000); -+ nv_wo32(disp->mem, 0x1010, 0x00000000); -+ nv_wo32(disp->mem, 0x1014, 0x00000000); -+ nv_wo32(disp->mem, 0x0000, NvEvoSync); -+ nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1020, 0x00000049); -+ nv_wo32(disp->mem, 0x1024, 0x00000000); -+ nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x102c, 0x00000000); -+ nv_wo32(disp->mem, 0x1030, 0x00000000); -+ nv_wo32(disp->mem, 0x1034, 0x00000000); -+ nv_wo32(disp->mem, 0x0008, NvEvoVRAM); -+ nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1040, 0x00000009); -+ nv_wo32(disp->mem, 0x1044, 0x00000000); -+ nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x104c, 0x00000000); -+ nv_wo32(disp->mem, 0x1050, 0x00000000); -+ nv_wo32(disp->mem, 0x1054, 0x00000000); -+ nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); -+ nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); -+ -+ nv_wo32(disp->mem, 0x1060, 0x0fe00009); -+ nv_wo32(disp->mem, 0x1064, 0x00000000); -+ nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); -+ nv_wo32(disp->mem, 0x106c, 0x00000000); -+ nv_wo32(disp->mem, 0x1070, 0x00000000); -+ nv_wo32(disp->mem, 0x1074, 0x00000000); -+ nv_wo32(disp->mem, 0x0018, NvEvoFB32); -+ nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); -+ -+ pinstmem->flush(dev); -+ -+ /* push buffers for evo channels */ -+ disp->evo[0].ptr = -+ pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); -+ if (!disp->evo[0].ptr) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ ret = nvd0_display_init(dev); -+ if (ret) -+ goto out; -+ -+out: -+ if (ret) -+ nvd0_display_destroy(dev); -+ return ret; -+} -diff -Naur linux-3.0/include/drm/drmP.h linux-3.0.patch/include/drm/drmP.h ---- linux-3.0/include/drm/drmP.h 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/include/drm/drmP.h 2011-07-26 07:03:44.518052107 +0200 -@@ -886,6 +886,8 @@ - */ - int (*gem_init_object) (struct drm_gem_object *obj); - void (*gem_free_object) (struct drm_gem_object *obj); -+ int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); -+ void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); - - /* vga arb irq handler */ - void (*vgaarb_irq)(struct drm_device *dev, bool state);