diff --git a/drm-nouveau-race-fix.patch b/drm-nouveau-race-fix.patch index 8b6f4df..bf6cc4f 100644 --- a/drm-nouveau-race-fix.patch +++ b/drm-nouveau-race-fix.patch @@ -1,7 +1,7 @@ -From 6b33cff9cd4f6f26df99e1486d53c91698d133b4 Mon Sep 17 00:00:00 2001 +From 4733f633c4bfb0672d5bd88a8d19a03e27a3c1d0 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 23 Jul 2010 09:06:52 +1000 -Subject: [PATCH 5/5] drm-nouveau-race-fix +Subject: [PATCH 2/2] drm-nouveau-race-fix drm/nouveau: fix race condition when under memory pressure @@ -30,7 +30,7 @@ Signed-off-by: Ben Skeggs 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index f1357f1..f552c76 100644 +index 553a01d..5e62d1b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -36,6 +36,21 @@ @@ -56,10 +56,10 @@ index f1357f1..f552c76 100644 nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index c001574..922ef43 100644 +index 2eb622b..70a16f3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h -@@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); +@@ -1167,6 +1167,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); @@ -68,7 +68,7 @@ index c001574..922ef43 100644 /* nouveau_fence.c */ struct nouveau_fence; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c -index 547f2c2..a915dcd 100644 +index 62ac673..613f878 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, @@ -137,5 +137,5 @@ index 547f2c2..a915dcd 100644 ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, req->nr_buffers, &op, &do_reloc); -- -1.7.2 +1.7.2.2 diff --git a/drm-nouveau-updates.patch b/drm-nouveau-updates.patch index 08baed1..82ded47 100644 --- a/drm-nouveau-updates.patch +++ b/drm-nouveau-updates.patch @@ -1,7 +1,7 @@ -From 0983b95112413e5239b09f1f1a4500c0bccfe3b7 Mon Sep 17 00:00:00 2001 +From c156fa3c71b6581b34526a9b2b649c3f4d57dd3e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 1 Jun 2010 15:32:24 +1000 -Subject: [PATCH 4/4] drm-nouveau-updates +Subject: [PATCH 1/2] drm-nouveau-updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -656,73 +656,268 @@ drm/nouveau: Don't try DDC on the dummy I2C channel. Signed-off-by: Francisco Jerez drm/nv50: fix minor thinko from nvc0 changes + +drm/nouveau: check for error when allocating/mapping dummy page + +Signed-off-by: Ben Skeggs + +drm/nouveau: remove warning about unknown tmds table revisions + +This message is apparently confusing people, and is being blamed for some +modesetting issues. Lets remove the message, and instead replace it +with an unconditional printout of the table revision. + +Signed-off-by: Ben Skeggs + +drm/nouveau: punt some more log messages to debug level + +Signed-off-by: Ben Skeggs + +drm/nv50-nvc0: ramht_size is meant to be in bytes, not entries + +Fixes an infinite loop that can happen in RAMHT lookup. + +Signed-off-by: Ben Skeggs + +drm/nouveau: Add TV-out quirk for an MSI nForce2 IGP. + +The blob also thinks there's a TV connected, so hardware bug... + +Signed-off-by: Francisco Jerez + +drm/nouveau: Workaround missing GPIO tables on an Apple iMac G4 NV18. + +This should fix the reported TV-out load detection false positives +(fdo bug 29455). + +Reported-by: Vlado Plaga +Signed-off-by: Francisco Jerez + +drm/nvc0: fix thinko in instmem suspend/resume + +Signed-off-by: Ben Skeggs + +drm/nv50: calculate vram reordering block size + +Will be used at a later point when we plug in an alternative VRAM memory +manager for GeForce 8+ boards. + +Based on pscnv code to do the same. + +Signed-off-by: Ben Skeggs +Signed-off-by: Marcin Koƛcielnicki + +drm/nv50: add dcb type 14 to enum to prevent compiler complaint + +Signed-off-by: Ben Skeggs + +drm/nouveau: Use a helper function to match PCI device/subsystem IDs. + +Signed-off-by: Francisco Jerez + +drm/nv30: Apply modesetting to the correct slave encoder + +Signed-off-by: Patrice Mandin +Reviewed-by: Francisco Jerez + +drm/nouveau: Fix backlight control on PPC machines with an internal TMDS panel. + +This commit fixes fdo bug 29685. + +Reported-by: Vlado Plaga +Signed-off-by: Francisco Jerez + +drm/nouveau: Fix TMDS on some DCB1.5 boards. + +The TMDS output of an nv11 was being detected as LVDS, because it uses +DCB type 2 for TMDS instead of type 4. + +Reported-by: Bertrand VIEILLE +Signed-off-by: Francisco Jerez + +drm/nv20: Don't use pushbuf calls on the original nv20. + +The "return" command is buggy on the original nv20, it jumps back to +the caller address as expected, but it doesn't clear the subroutine +active bit making the subsequent pushbuf calls fail with a "stack" +overflow. + +Signed-off-by: Francisco Jerez + +drm/nouveau: Fix suspend on some nv4x AGP cards. + +On some nv4x cards (specifically, the ones that use an internal +PCIE->AGP bridge) the AGP controller state isn't preserved after a +suspend/resume cycle, and the AGP control registers have moved from +0x18xx to 0x100xx, so the FW check in nouveau_mem_reset_agp() doesn't +quite work. Check "dev->agp->mode" instead. + +Signed-off-by: Francisco Jerez + +drm/nv20: Use the nv30 CRTC bandwidth calculation code. + +nv2x CRTC FIFOs are as large as in nv3x (4kB it seems), and the FIFO +control registers have the same layout: we can make them share the +same implementation. + +Previously we were using the nv1x code, but the calculated FIFO +watermarks are usually too low for nv2x and they cause horrible +scanout artifacts. They've gone unnoticed until now because we've been +leaving one of the bandwidth regs uninitialized (CRE 47, which +contains the most significant bits of FFLWM), so everything seemed to +work fine except in some cases after a cold boot, depending on the +memory bandwidth and pixel clocks used. + +Signed-off-by: Francisco Jerez + +drm/nv50: add new accelerated bo move funtion + +Hopefully this one will be better able to cope with moving tiled buffers +around without getting them all scrambled as a result. + +Signed-off-by: Ben Skeggs + +drm/nouveau: move check for no-op bo move before memcpy fallback + +Signed-off-by: Ben Skeggs + +drm/nouveau: remove second map of notifier bo + +Signed-off-by: Ben Skeggs + +drm/nouveau: require explicit unmap of kmapped bos + +Signed-off-by: Ben Skeggs + +drm/nv17-nv4x: Fix analog load detection false positive on rare occasions. + +On some boards the residual current DAC outputs can draw when they're +disconnected can be high enough to give a false load detection +positive (I've only seen it in the S-video luma output of some cards, +but just to be sure). The output line capacitance is limited and +sampling twice should fix it reliably. + +Signed-off-by: Francisco Jerez + +drm/nv40: Try to set up CRE_LCD even if it has unknown bits set. + +They don't seem to do anything useful, and we really want to program +CRE_LCD if we aren't lucky enough to find the right CRTC binding +already set. + +Signed-off-by: Francisco Jerez + +drm/nouveau: have nv_mask return original register value + +Signed-off-by: Ben Skeggs + +drm/nv50: initialize ramht_refs list for faked 0 channel + +We need it for PFIFO_INTR_CACHE_ERROR interrupt handling, +because nouveau_fifo_swmthd looks for matching gpuobj in +ramht_refs list. +It fixes kernel panic in nouveau_gpuobj_ref_find. + +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs + +drm/nouveau: move ramht code out of nouveau_object.c, nothing to see here + +Reviewed-by: Francisco Jerez +Signed-off-by: Ben Skeggs + +drm/nouveau: modify object accessors, offset in bytes rather than dwords + +Reviewed-by: Francisco Jerez +Signed-off-by: Ben Skeggs + +drm/nv50: demagic grctx, and add NVAF support + +Signed-off-by: Ben Skeggs +Signed-off-by: Marcin Koƛcielnicki + +drm/nv50: move vm trap to nv50_fb.c + +Signed-off-by: Ben Skeggs + +drm/nv50: report BAR access faults + +Signed-off-by: Ben Skeggs --- drivers/gpu/drm/drm_crtc_helper.c | 22 +- drivers/gpu/drm/i2c/ch7006_drv.c | 22 +- drivers/gpu/drm/i2c/ch7006_priv.h | 2 +- drivers/gpu/drm/nouveau/Makefile | 12 +- - drivers/gpu/drm/nouveau/nouveau_acpi.c | 38 ++- - drivers/gpu/drm/nouveau/nouveau_bios.c | 820 ++++++++++++++++++++++----- - drivers/gpu/drm/nouveau/nouveau_bios.h | 5 +- - drivers/gpu/drm/nouveau/nouveau_bo.c | 15 +- - drivers/gpu/drm/nouveau/nouveau_calc.c | 4 +- - drivers/gpu/drm/nouveau/nouveau_channel.c | 5 - - drivers/gpu/drm/nouveau/nouveau_connector.c | 417 ++++++-------- + drivers/gpu/drm/nouveau/nouveau_acpi.c | 38 +- + drivers/gpu/drm/nouveau/nouveau_bios.c | 910 ++++++-- + drivers/gpu/drm/nouveau/nouveau_bios.h | 6 +- + drivers/gpu/drm/nouveau/nouveau_bo.c | 223 ++- + drivers/gpu/drm/nouveau/nouveau_calc.c | 10 +- + drivers/gpu/drm/nouveau/nouveau_channel.c | 6 +- + drivers/gpu/drm/nouveau/nouveau_connector.c | 417 ++-- drivers/gpu/drm/nouveau/nouveau_connector.h | 7 +- - drivers/gpu/drm/nouveau/nouveau_dma.c | 8 +- - drivers/gpu/drm/nouveau/nouveau_dp.c | 128 +++-- + drivers/gpu/drm/nouveau/nouveau_dma.c | 7 - + drivers/gpu/drm/nouveau/nouveau_dp.c | 128 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 39 +- - drivers/gpu/drm/nouveau/nouveau_drv.h | 178 ++++--- + drivers/gpu/drm/nouveau/nouveau_drv.h | 203 +- drivers/gpu/drm/nouveau/nouveau_encoder.h | 16 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 35 +- - drivers/gpu/drm/nouveau/nouveau_gem.c | 11 +- - drivers/gpu/drm/nouveau/nouveau_grctx.c | 160 ------ - drivers/gpu/drm/nouveau/nouveau_hw.c | 11 +- - drivers/gpu/drm/nouveau/nouveau_i2c.c | 83 ++- + drivers/gpu/drm/nouveau/nouveau_gem.c | 15 +- + drivers/gpu/drm/nouveau/nouveau_grctx.c | 160 -- + drivers/gpu/drm/nouveau/nouveau_grctx.h | 2 +- + drivers/gpu/drm/nouveau/nouveau_hw.c | 13 +- + drivers/gpu/drm/nouveau/nouveau_i2c.c | 83 +- drivers/gpu/drm/nouveau/nouveau_i2c.h | 11 +- - drivers/gpu/drm/nouveau/nouveau_irq.c | 6 +- - drivers/gpu/drm/nouveau/nouveau_mem.c | 327 +++--------- + drivers/gpu/drm/nouveau/nouveau_irq.c | 70 +- + drivers/gpu/drm/nouveau/nouveau_mem.c | 404 ++--- drivers/gpu/drm/nouveau/nouveau_notifier.c | 30 +- - drivers/gpu/drm/nouveau/nouveau_object.c | 105 +--- - drivers/gpu/drm/nouveau/nouveau_reg.h | 109 +++-- - drivers/gpu/drm/nouveau/nouveau_sgdma.c | 46 +-- - drivers/gpu/drm/nouveau/nouveau_state.c | 340 +++++++---- - drivers/gpu/drm/nouveau/nv04_crtc.c | 8 + - drivers/gpu/drm/nouveau/nv04_dac.c | 50 ++- - drivers/gpu/drm/nouveau/nv04_dfp.c | 85 +++- - drivers/gpu/drm/nouveau/nv04_display.c | 90 ++-- - drivers/gpu/drm/nouveau/nv04_fifo.c | 20 +- + drivers/gpu/drm/nouveau/nouveau_object.c | 325 +-- + drivers/gpu/drm/nouveau/nouveau_ramht.c | 160 ++ + drivers/gpu/drm/nouveau/nouveau_ramht.h | 31 + + drivers/gpu/drm/nouveau/nouveau_reg.h | 109 +- + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 108 +- + drivers/gpu/drm/nouveau/nouveau_state.c | 340 ++- + drivers/gpu/drm/nouveau/nv04_crtc.c | 11 +- + drivers/gpu/drm/nouveau/nv04_dac.c | 60 +- + drivers/gpu/drm/nouveau/nv04_dfp.c | 145 +- + drivers/gpu/drm/nouveau/nv04_display.c | 90 +- + drivers/gpu/drm/nouveau/nv04_fifo.c | 28 +- drivers/gpu/drm/nouveau/nv04_graph.c | 5 +- drivers/gpu/drm/nouveau/nv04_instmem.c | 21 +- drivers/gpu/drm/nouveau/nv04_mc.c | 4 + - drivers/gpu/drm/nouveau/nv04_tv.c | 133 ++--- + drivers/gpu/drm/nouveau/nv04_tv.c | 133 +- drivers/gpu/drm/nouveau/nv10_fifo.c | 10 - - drivers/gpu/drm/nouveau/nv10_gpio.c | 92 +++ - drivers/gpu/drm/nouveau/nv10_graph.c | 175 ++++-- - drivers/gpu/drm/nouveau/nv17_gpio.c | 92 --- - drivers/gpu/drm/nouveau/nv17_tv.c | 65 ++- - drivers/gpu/drm/nouveau/nv20_graph.c | 96 ++-- - drivers/gpu/drm/nouveau/nv30_fb.c | 95 +++ + drivers/gpu/drm/nouveau/nv10_gpio.c | 92 + + drivers/gpu/drm/nouveau/nv10_graph.c | 175 +- + drivers/gpu/drm/nouveau/nv17_gpio.c | 92 - + drivers/gpu/drm/nouveau/nv17_tv.c | 82 +- + drivers/gpu/drm/nouveau/nv20_graph.c | 564 +++--- + drivers/gpu/drm/nouveau/nv30_fb.c | 95 + drivers/gpu/drm/nouveau/nv40_fifo.c | 8 - - drivers/gpu/drm/nouveau/nv40_graph.c | 58 +-- + drivers/gpu/drm/nouveau/nv40_graph.c | 62 +- + drivers/gpu/drm/nouveau/nv40_grctx.c | 6 +- drivers/gpu/drm/nouveau/nv40_mc.c | 2 +- - drivers/gpu/drm/nouveau/nv50_crtc.c | 65 +-- + drivers/gpu/drm/nouveau/nv50_crtc.c | 67 +- drivers/gpu/drm/nouveau/nv50_dac.c | 43 +- - drivers/gpu/drm/nouveau/nv50_display.c | 424 +++++++++------ + drivers/gpu/drm/nouveau/nv50_display.c | 435 +++-- drivers/gpu/drm/nouveau/nv50_display.h | 6 +- - drivers/gpu/drm/nouveau/nv50_fifo.c | 126 ++--- - drivers/gpu/drm/nouveau/nv50_gpio.c | 35 ++ - drivers/gpu/drm/nouveau/nv50_graph.c | 86 ++-- - drivers/gpu/drm/nouveau/nv50_instmem.c | 67 +-- - drivers/gpu/drm/nouveau/nv50_sor.c | 105 ++-- - drivers/gpu/drm/nouveau/nvc0_fb.c | 38 ++ - drivers/gpu/drm/nouveau/nvc0_fifo.c | 95 +++ - drivers/gpu/drm/nouveau/nvc0_graph.c | 74 +++ - drivers/gpu/drm/nouveau/nvc0_instmem.c | 231 ++++++++ + drivers/gpu/drm/nouveau/nv50_fb.c | 39 + + drivers/gpu/drm/nouveau/nv50_fifo.c | 335 ++-- + drivers/gpu/drm/nouveau/nv50_gpio.c | 35 + + drivers/gpu/drm/nouveau/nv50_graph.c | 104 +- + drivers/gpu/drm/nouveau/nv50_grctx.c | 3305 +++++++++++++++++---------- + drivers/gpu/drm/nouveau/nv50_instmem.c | 81 +- + drivers/gpu/drm/nouveau/nv50_sor.c | 105 +- + drivers/gpu/drm/nouveau/nvc0_fb.c | 38 + + drivers/gpu/drm/nouveau/nvc0_fifo.c | 95 + + drivers/gpu/drm/nouveau/nvc0_graph.c | 74 + + drivers/gpu/drm/nouveau/nvc0_instmem.c | 234 ++ drivers/gpu/drm/nouveau/nvreg.h | 22 - - 64 files changed, 3285 insertions(+), 2257 deletions(-) + 70 files changed, 6456 insertions(+), 4215 deletions(-) delete mode 100644 drivers/gpu/drm/nouveau/nouveau_grctx.c + create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.c + create mode 100644 drivers/gpu/drm/nouveau/nouveau_ramht.h create mode 100644 drivers/gpu/drm/nouveau/nv10_gpio.c delete mode 100644 drivers/gpu/drm/nouveau/nv17_gpio.c create mode 100644 drivers/gpu/drm/nouveau/nv30_fb.c @@ -857,7 +1052,7 @@ index 9487123..17667b7 100644 struct ch7006_state state; diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile -index acd31ed..e9b06e4 100644 +index acd31ed..d6cfbf2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -9,20 +9,20 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ @@ -865,7 +1060,7 @@ index acd31ed..e9b06e4 100644 nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_dp.o nouveau_grctx.o \ -+ nouveau_dp.o \ ++ nouveau_dp.o nouveau_ramht.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ - nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \ @@ -955,7 +1150,7 @@ index d4bcca8..c17a055 100644 + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c -index e492919..eb77710 100644 +index e492919..8fa3396 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -28,6 +28,8 @@ @@ -2043,7 +2238,52 @@ index e492919..eb77710 100644 { NULL , 0 , NULL } }; -@@ -4068,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, +@@ -3376,27 +3869,10 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr + } + #ifdef __powerpc__ + /* Powerbook specific quirks */ +- if ((dev->pci_device & 0xffff) == 0x0179 || +- (dev->pci_device & 0xffff) == 0x0189 || +- (dev->pci_device & 0xffff) == 0x0329) { +- if (script == LVDS_RESET) { +- nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); +- +- } else if (script == LVDS_PANEL_ON) { +- bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, +- bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) +- | (1 << 31)); +- bios_wr32(bios, NV_PCRTC_GPIO_EXT, +- bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); +- +- } else if (script == LVDS_PANEL_OFF) { +- bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, +- bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) +- & ~(1 << 31)); +- bios_wr32(bios, NV_PCRTC_GPIO_EXT, +- bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); +- } +- } ++ if (script == LVDS_RESET && ++ (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || ++ dev->pci_device == 0x0329)) ++ nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); + #endif + + return 0; +@@ -3888,11 +4364,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b + * + * For the moment, a quirk will do :) + */ +- if ((dev->pdev->device == 0x01d7) && +- (dev->pdev->subsystem_vendor == 0x1028) && +- (dev->pdev->subsystem_device == 0x01c2)) { ++ if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2)) + bios->fp.duallink_transition_clk = 80000; +- } + + /* set dual_link flag for EDID case */ + if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) +@@ -4068,7 +4541,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, bios->display.script_table_ptr, table[2], table[3], table[0] >= 0x21); if (!otable) { @@ -2052,7 +2292,34 @@ index e492919..eb77710 100644 return 1; } -@@ -4125,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, +@@ -4094,7 +4567,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + return 1; + } + +- NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); ++ NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); + nouveau_bios_run_init_table(dev, script, dcbent); + } else + if (pxclk == -1) { +@@ -4104,7 +4577,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + return 1; + } + +- NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); ++ NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); + nouveau_bios_run_init_table(dev, script, dcbent); + } else + if (pxclk == -2) { +@@ -4117,7 +4590,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + return 1; + } + +- NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); ++ NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); + nouveau_bios_run_init_table(dev, script, dcbent); + } else + if (pxclk > 0) { +@@ -4125,11 +4598,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, if (script) script = clkcmptable(bios, script, pxclk); if (!script) { @@ -2061,7 +2328,21 @@ index e492919..eb77710 100644 return 1; } -@@ -4484,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims +- NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); ++ NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); + nouveau_bios_run_init_table(dev, script, dcbent); + } else + if (pxclk < 0) { +@@ -4141,7 +4614,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, + return 1; + } + +- NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); ++ NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); + nouveau_bios_run_init_table(dev, script, dcbent); + } + +@@ -4484,7 +4957,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims pll_lim->min_p = record[12]; pll_lim->max_p = record[13]; /* where did this go to?? */ @@ -2070,7 +2351,32 @@ index e492919..eb77710 100644 pll_lim->refclk = 27000; else pll_lim->refclk = 100000; -@@ -5151,10 +5644,14 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi +@@ -4864,19 +5337,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, + } + + tmdstableptr = ROM16(bios->data[bitentry->offset]); +- +- if (tmdstableptr == 0x0) { ++ if (!tmdstableptr) { + NV_ERROR(dev, "Pointer to TMDS table invalid\n"); + return -EINVAL; + } + ++ NV_INFO(dev, "TMDS table version %d.%d\n", ++ bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); ++ + /* nv50+ has v2.0, but we don't parse it atm */ +- if (bios->data[tmdstableptr] != 0x11) { +- NV_WARN(dev, +- "TMDS table revision %d.%d not currently supported\n", +- bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); ++ if (bios->data[tmdstableptr] != 0x11) + return -ENOSYS; +- } + + /* + * These two scripts are odd: they don't seem to get run even when +@@ -5151,10 +5622,14 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; @@ -2089,7 +2395,39 @@ index e492919..eb77710 100644 if (bmplength > 74) { bios->fmaxvco = ROM32(bmp[67]); -@@ -5506,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) +@@ -5312,6 +5787,20 @@ parse_dcb_gpio_table(struct nvbios *bios) + gpio->line = tvdac_gpio[1] >> 4; + gpio->invert = tvdac_gpio[0] & 2; + } ++ } else { ++ /* ++ * No systematic way to store GPIO info on pre-v2.2 ++ * DCBs, try to match the PCI device IDs. ++ */ ++ ++ /* Apple iMac G4 NV18 */ ++ if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { ++ struct dcb_gpio_entry *gpio = new_gpio_entry(bios); ++ ++ gpio->tag = DCB_GPIO_TVDAC0; ++ gpio->line = 4; ++ } ++ + } + + if (!gpio_table_ptr) +@@ -5387,9 +5876,7 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) + struct drm_device *dev = bios->dev; + + /* Gigabyte NX85T */ +- if ((dev->pdev->device == 0x0421) && +- (dev->pdev->subsystem_vendor == 0x1458) && +- (dev->pdev->subsystem_device == 0x344c)) { ++ if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { + if (cte->type == DCB_CONNECTOR_HDMI_1) + cte->type = DCB_CONNECTOR_DVI_I; + } +@@ -5506,7 +5993,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) entry->i2c_index = i2c; entry->heads = heads; entry->location = DCB_LOC_ON_CHIP; @@ -2098,7 +2436,7 @@ index e492919..eb77710 100644 } static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) -@@ -5589,9 +6086,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, +@@ -5589,9 +6076,12 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, if (conf & 0x4 || conf & 0x8) entry->lvdsconf.use_power_scripts = true; } else { @@ -2112,7 +2450,7 @@ index e492919..eb77710 100644 } if (conf & mask) { /* -@@ -5631,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, +@@ -5631,9 +6121,15 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, } break; case OUTPUT_TMDS: @@ -2125,9 +2463,41 @@ index e492919..eb77710 100644 + entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; + break; - case 0xe: +- case 0xe: ++ case OUTPUT_EOL: /* weird g80 mobile type that "nv" treats as a terminator */ -@@ -5706,13 +6212,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, + dcb->entries--; + return false; +@@ -5670,22 +6166,14 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, + entry->type = OUTPUT_TV; + break; + case 2: +- case 3: +- entry->type = OUTPUT_LVDS; +- break; + case 4: +- switch ((conn & 0x000000f0) >> 4) { +- case 0: +- entry->type = OUTPUT_TMDS; +- break; +- case 1: ++ if (conn & 0x10) + entry->type = OUTPUT_LVDS; +- break; +- default: +- NV_ERROR(dev, "Unknown DCB subtype 4/%d\n", +- (conn & 0x000000f0) >> 4); +- return false; +- } ++ else ++ entry->type = OUTPUT_TMDS; ++ break; ++ case 3: ++ entry->type = OUTPUT_LVDS; + break; + default: + NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); +@@ -5706,13 +6194,6 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, case OUTPUT_TV: entry->tvconf.has_component_output = false; break; @@ -2141,7 +2511,7 @@ index e492919..eb77710 100644 case OUTPUT_LVDS: if ((conn & 0x00003f00) != 0x10) entry->lvdsconf.use_straps_for_mode = true; -@@ -5793,6 +6292,31 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) +@@ -5793,6 +6274,29 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) dcb->entries = newentries; } @@ -2160,9 +2530,7 @@ index e492919..eb77710 100644 + * nasty problems until this is sorted (assuming it's not a + * VBIOS bug). + */ -+ if ((dev->pdev->device == 0x040d) && -+ (dev->pdev->subsystem_vendor == 0x1028) && -+ (dev->pdev->subsystem_device == 0x019b)) { ++ if (nv_match_device(dev, 0x040d, 0x1028, 0x019b)) { + if (*conn == 0x02026312 && *conf == 0x00000020) + return false; + } @@ -2173,7 +2541,7 @@ index e492919..eb77710 100644 static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) { -@@ -5903,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) +@@ -5903,6 +6407,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) dcb->i2c_table = &bios->data[i2ctabptr]; if (dcb->version >= 0x30) dcb->i2c_default_indices = dcb->i2c_table[4]; @@ -2193,7 +2561,7 @@ index e492919..eb77710 100644 } if (entries > DCB_MAX_NUM_ENTRIES) -@@ -5926,6 +6463,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) +@@ -5926,6 +6443,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) if ((connection & 0x0000000f) == 0x0000000f) continue; @@ -2203,7 +2571,7 @@ index e492919..eb77710 100644 NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", dcb->entries, connection, config); -@@ -6181,9 +6721,8 @@ nouveau_run_vbios_init(struct drm_device *dev) +@@ -6181,9 +6701,8 @@ nouveau_run_vbios_init(struct drm_device *dev) struct nvbios *bios = &dev_priv->vbios; int i, ret = 0; @@ -2215,7 +2583,7 @@ index e492919..eb77710 100644 if (bios->major_version < 5) /* BMP only */ load_nv17_hw_sequencer_ucode(dev, bios); -@@ -6216,8 +6755,6 @@ nouveau_run_vbios_init(struct drm_device *dev) +@@ -6216,8 +6735,6 @@ nouveau_run_vbios_init(struct drm_device *dev) } } @@ -2224,7 +2592,7 @@ index e492919..eb77710 100644 return ret; } -@@ -6238,7 +6775,6 @@ static bool +@@ -6238,7 +6755,6 @@ static bool nouveau_bios_posted(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -2232,7 +2600,7 @@ index e492919..eb77710 100644 unsigned htotal; if (dev_priv->chipset >= NV_50) { -@@ -6248,13 +6784,12 @@ nouveau_bios_posted(struct drm_device *dev) +@@ -6248,13 +6764,12 @@ nouveau_bios_posted(struct drm_device *dev) return true; } @@ -2247,7 +2615,7 @@ index e492919..eb77710 100644 return (htotal != 0); } -@@ -6263,8 +6798,6 @@ nouveau_bios_init(struct drm_device *dev) +@@ -6263,8 +6778,6 @@ nouveau_bios_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvbios *bios = &dev_priv->vbios; @@ -2256,7 +2624,7 @@ index e492919..eb77710 100644 int ret; if (!NVInitVBIOS(dev)) -@@ -6284,40 +6817,27 @@ nouveau_bios_init(struct drm_device *dev) +@@ -6284,40 +6797,27 @@ nouveau_bios_init(struct drm_device *dev) if (!bios->major_version) /* we don't run version 0 bios */ return 0; @@ -2300,7 +2668,7 @@ index e492919..eb77710 100644 /* allow subsequent scripts to execute */ bios->execute = true; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h -index adf4ec2..fd14dfd 100644 +index adf4ec2..c1de2f3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -81,6 +81,7 @@ struct dcb_connector_table_entry { @@ -2311,7 +2679,15 @@ index adf4ec2..fd14dfd 100644 }; struct dcb_connector_table { -@@ -117,6 +118,7 @@ struct dcb_entry { +@@ -94,6 +95,7 @@ enum dcb_type { + OUTPUT_TMDS = 2, + OUTPUT_LVDS = 3, + OUTPUT_DP = 6, ++ OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */ + OUTPUT_ANY = -1 + }; + +@@ -117,6 +119,7 @@ struct dcb_entry { struct { struct sor_conf sor; bool use_straps_for_mode; @@ -2319,7 +2695,7 @@ index adf4ec2..fd14dfd 100644 bool use_power_scripts; } lvdsconf; struct { -@@ -129,6 +131,7 @@ struct dcb_entry { +@@ -129,6 +132,7 @@ struct dcb_entry { } dpconf; struct { struct sor_conf sor; @@ -2327,7 +2703,7 @@ index adf4ec2..fd14dfd 100644 } tmdsconf; }; bool i2c_upper_default; -@@ -249,8 +252,6 @@ struct nvbios { +@@ -249,8 +253,6 @@ struct nvbios { struct { int crtchead; @@ -2337,10 +2713,18 @@ index adf4ec2..fd14dfd 100644 struct { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c -index 6f3c195..f1357f1 100644 +index 6f3c195..553a01d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c -@@ -51,9 +51,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) +@@ -43,17 +43,12 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); + +- ttm_bo_kunmap(&nvbo->kmap); +- + if (unlikely(nvbo->gem)) + DRM_ERROR("bo %p still attached to GEM object\n", bo); + if (nvbo->tile) nv10_mem_expire_tiling(dev, nvbo->tile, NULL); @@ -2350,7 +2734,7 @@ index 6f3c195..f1357f1 100644 kfree(nvbo); } -@@ -166,9 +163,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, +@@ -166,9 +161,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, } nvbo->channel = NULL; @@ -2360,7 +2744,17 @@ index 6f3c195..f1357f1 100644 *pnvbo = nvbo; return 0; } -@@ -461,9 +455,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, +@@ -296,7 +288,8 @@ nouveau_bo_map(struct nouveau_bo *nvbo) + void + nouveau_bo_unmap(struct nouveau_bo *nvbo) + { +- ttm_bo_kunmap(&nvbo->kmap); ++ if (nvbo) ++ ttm_bo_kunmap(&nvbo->kmap); + } + + u16 +@@ -461,18 +454,20 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, return ret; ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, @@ -2373,92 +2767,384 @@ index 6f3c195..f1357f1 100644 nouveau_fence_unref((void *)&fence); return ret; } -@@ -711,8 +705,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - return ret; - - /* Software copy if the card isn't up and running yet. */ -- if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || -- !dev_priv->channel) { -+ if (!dev_priv->channel) { - ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); - goto out; - } -diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c -index 88f9bc0..ca85da7 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_calc.c -+++ b/drivers/gpu/drm/nouveau/nouveau_calc.c -@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, - struct nv_sim_state sim_data; - int MClk = nouveau_hw_get_clock(dev, MPLL); - int NVClk = nouveau_hw_get_clock(dev, NVPLL); -- uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); -+ uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); - - sim_data.pclk_khz = VClk; - sim_data.mclk_khz = MClk; -@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, - sim_data.mem_latency = 3; - sim_data.mem_page_miss = 10; - } else { -- sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; -+ sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1; - sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; - sim_data.mem_latency = cfg1 & 0xf; - sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); -diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c -index 1fc57ef..e952c3b 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_channel.c -+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c -@@ -257,9 +257,7 @@ nouveau_channel_free(struct nouveau_channel *chan) - nouveau_debugfs_channel_fini(chan); - /* Give outstanding push buffers a chance to complete */ -- spin_lock_irqsave(&chan->fence.lock, flags); - nouveau_fence_update(chan); -- spin_unlock_irqrestore(&chan->fence.lock, flags); - if (chan->fence.sequence != chan->fence.sequence_ack) { - struct nouveau_fence *fence = NULL; + static inline uint32_t +-nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, +- struct ttm_mem_reg *mem) ++nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo, ++ struct nouveau_channel *chan, struct ttm_mem_reg *mem) + { +- if (chan == nouveau_bdev(nvbo->bo.bdev)->channel) { ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ ++ if (nvbo->no_vm) { + if (mem->mem_type == TTM_PL_TT) + return NvDmaGART; + return NvDmaVRAM; +@@ -484,86 +479,181 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, + } -@@ -368,8 +366,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, - struct nouveau_channel *chan; + 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) ++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_bo *nvbo = nouveau_bo(bo); + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); +- struct ttm_mem_reg *old_mem = &bo->mem; +- struct nouveau_channel *chan; +- uint64_t src_offset, dst_offset; +- uint32_t page_count; ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ u64 length = (new_mem->num_pages << PAGE_SHIFT); ++ u64 src_offset, dst_offset; int ret; -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; +- chan = nvbo->channel; +- if (!chan || nvbo->tile_flags || nvbo->no_vm) +- chan = dev_priv->channel; - - if (dev_priv->engine.graph.accel_blocked) - return -ENODEV; - -@@ -418,7 +414,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, - struct drm_nouveau_channel_free *cfree = data; - struct nouveau_channel *chan; - -- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); - - nouveau_channel_free(chan); -diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c -index 149ed22..a1473ff 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_connector.c -+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c -@@ -37,12 +37,6 @@ - #include "nouveau_connector.h" - #include "nouveau_hw.h" - --static inline struct drm_encoder_slave_funcs * --get_slave_funcs(struct nouveau_encoder *enc) --{ -- return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; --} + src_offset = old_mem->mm_node->start << PAGE_SHIFT; + dst_offset = new_mem->mm_node->start << PAGE_SHIFT; +- if (chan != dev_priv->channel) { +- if (old_mem->mem_type == TTM_PL_TT) +- src_offset += dev_priv->vm_gart_base; +- else ++ if (!nvbo->no_vm) { ++ if (old_mem->mem_type == TTM_PL_VRAM) + src_offset += dev_priv->vm_vram_base; - - static struct nouveau_encoder * - find_encoder_by_type(struct drm_connector *connector, int type) - { -@@ -102,60 +96,12 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) - kfree(drm_connector); - } +- if (new_mem->mem_type == TTM_PL_TT) +- dst_offset += dev_priv->vm_gart_base; + else ++ src_offset += dev_priv->vm_gart_base; ++ ++ if (new_mem->mem_type == TTM_PL_VRAM) + dst_offset += dev_priv->vm_vram_base; ++ else ++ dst_offset += dev_priv->vm_gart_base; + } --static void --nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags) + ret = RING_SPACE(chan, 3); + if (ret) + return ret; +- BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); +- OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, old_mem)); +- OUT_RING(chan, nouveau_bo_mem_ctxdma(nvbo, chan, new_mem)); + +- if (dev_priv->card_type >= NV_50) { +- ret = RING_SPACE(chan, 4); ++ BEGIN_RING(chan, NvSubM2MF, 0x0184, 2); ++ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); ++ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); ++ ++ while (length) { ++ u32 amount, stride, height; ++ ++ amount = min(length, (u64)(16 * 1024 * 1024)); ++ stride = 64 * 4; ++ height = amount / stride; ++ ++ if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { ++ ret = RING_SPACE(chan, 8); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubM2MF, 0x0200, 7); ++ OUT_RING (chan, 0); ++ OUT_RING (chan, 0x20); ++ OUT_RING (chan, stride); ++ OUT_RING (chan, height); ++ OUT_RING (chan, 1); ++ OUT_RING (chan, 0); ++ OUT_RING (chan, 0); ++ } else { ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); ++ OUT_RING (chan, 1); ++ } ++ if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { ++ ret = RING_SPACE(chan, 8); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubM2MF, 0x021c, 7); ++ OUT_RING (chan, 0); ++ OUT_RING (chan, 0x20); ++ OUT_RING (chan, stride); ++ OUT_RING (chan, height); ++ OUT_RING (chan, 1); ++ OUT_RING (chan, 0); ++ OUT_RING (chan, 0); ++ } else { ++ ret = RING_SPACE(chan, 2); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); ++ OUT_RING (chan, 1); ++ } ++ ++ ret = RING_SPACE(chan, 14); + if (ret) + return ret; +- BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); +- OUT_RING(chan, 1); +- BEGIN_RING(chan, NvSubM2MF, 0x021c, 1); +- OUT_RING(chan, 1); ++ ++ BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); ++ OUT_RING (chan, upper_32_bits(src_offset)); ++ OUT_RING (chan, upper_32_bits(dst_offset)); ++ BEGIN_RING(chan, NvSubM2MF, 0x030c, 8); ++ OUT_RING (chan, lower_32_bits(src_offset)); ++ OUT_RING (chan, lower_32_bits(dst_offset)); ++ OUT_RING (chan, stride); ++ OUT_RING (chan, stride); ++ OUT_RING (chan, stride); ++ OUT_RING (chan, height); ++ OUT_RING (chan, 0x00000101); ++ OUT_RING (chan, 0x00000000); ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); ++ OUT_RING (chan, 0); ++ ++ length -= amount; ++ src_offset += amount; ++ dst_offset += amount; + } + ++ return 0; ++} ++ ++static int ++nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, ++ struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) ++{ ++ u32 src_offset = old_mem->mm_node->start << PAGE_SHIFT; ++ u32 dst_offset = new_mem->mm_node->start << PAGE_SHIFT; ++ u32 page_count = new_mem->num_pages; ++ int ret; ++ ++ ret = RING_SPACE(chan, 3); ++ if (ret) ++ return ret; ++ ++ BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2); ++ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem)); ++ OUT_RING (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem)); ++ + page_count = new_mem->num_pages; + while (page_count) { + int line_count = (page_count > 2047) ? 2047 : page_count; + +- if (dev_priv->card_type >= NV_50) { +- ret = RING_SPACE(chan, 3); +- if (ret) +- return ret; +- BEGIN_RING(chan, NvSubM2MF, 0x0238, 2); +- OUT_RING(chan, upper_32_bits(src_offset)); +- OUT_RING(chan, upper_32_bits(dst_offset)); +- } + ret = RING_SPACE(chan, 11); + if (ret) + return ret; ++ + BEGIN_RING(chan, NvSubM2MF, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); +- OUT_RING(chan, lower_32_bits(src_offset)); +- OUT_RING(chan, lower_32_bits(dst_offset)); +- OUT_RING(chan, PAGE_SIZE); /* src_pitch */ +- OUT_RING(chan, PAGE_SIZE); /* dst_pitch */ +- OUT_RING(chan, PAGE_SIZE); /* line_length */ +- OUT_RING(chan, line_count); +- OUT_RING(chan, (1<<8)|(1<<0)); +- OUT_RING(chan, 0); ++ OUT_RING (chan, src_offset); ++ OUT_RING (chan, dst_offset); ++ OUT_RING (chan, PAGE_SIZE); /* src_pitch */ ++ OUT_RING (chan, PAGE_SIZE); /* dst_pitch */ ++ OUT_RING (chan, PAGE_SIZE); /* line_length */ ++ OUT_RING (chan, line_count); ++ OUT_RING (chan, 0x00000101); ++ OUT_RING (chan, 0x00000000); + BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1); +- OUT_RING(chan, 0); ++ OUT_RING (chan, 0); + + page_count -= line_count; + src_offset += (PAGE_SIZE * line_count); + dst_offset += (PAGE_SIZE * line_count); + } + ++ 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) ++{ ++ struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); ++ struct nouveau_bo *nvbo = nouveau_bo(bo); ++ struct nouveau_channel *chan; ++ int ret; ++ ++ chan = nvbo->channel; ++ if (!chan || nvbo->no_vm) ++ chan = dev_priv->channel; ++ ++ if (dev_priv->card_type < NV_50) ++ ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); ++ else ++ ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem); ++ if (ret) ++ return ret; ++ + return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); + } + +@@ -710,13 +800,6 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + if (ret) + return ret; + +- /* Software copy if the card isn't up and running yet. */ +- if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || +- !dev_priv->channel) { +- ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); +- goto out; +- } +- + /* Fake bo copy. */ + if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { + BUG_ON(bo->mem.mm_node != NULL); +@@ -725,6 +808,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + goto out; + } + ++ /* Software copy if the card isn't up and running yet. */ ++ if (!dev_priv->channel) { ++ ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); ++ goto out; ++ } ++ + /* Hardware assisted copy. */ + if (new_mem->mem_type == TTM_PL_SYSTEM) + ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait_reserve, no_wait_gpu, new_mem); +diff --git a/drivers/gpu/drm/nouveau/nouveau_calc.c b/drivers/gpu/drm/nouveau/nouveau_calc.c +index 88f9bc0..23d9896 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_calc.c ++++ b/drivers/gpu/drm/nouveau/nouveau_calc.c +@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, + struct nv_sim_state sim_data; + int MClk = nouveau_hw_get_clock(dev, MPLL); + int NVClk = nouveau_hw_get_clock(dev, NVPLL); +- uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); ++ uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1); + + sim_data.pclk_khz = VClk; + sim_data.mclk_khz = MClk; +@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, + sim_data.mem_latency = 3; + sim_data.mem_page_miss = 10; + } else { +- sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; ++ sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1; + sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; + sim_data.mem_latency = cfg1 & 0xf; + sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); +@@ -234,7 +234,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, + } + + static void +-nv30_update_arb(int *burst, int *lwm) ++nv20_update_arb(int *burst, int *lwm) + { + unsigned int fifo_size, burst_size, graphics_lwm; + +@@ -251,14 +251,14 @@ nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm + { + struct drm_nouveau_private *dev_priv = dev->dev_private; + +- if (dev_priv->card_type < NV_30) ++ if (dev_priv->card_type < NV_20) + nv04_update_arb(dev, vclk, bpp, burst, lwm); + else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || + (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { + *burst = 128; + *lwm = 0x0480; + } else +- nv30_update_arb(burst, lwm); ++ nv20_update_arb(burst, lwm); + } + + static int +diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c +index 1fc57ef..9a31023 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_channel.c ++++ b/drivers/gpu/drm/nouveau/nouveau_channel.c +@@ -257,9 +257,7 @@ nouveau_channel_free(struct nouveau_channel *chan) + nouveau_debugfs_channel_fini(chan); + + /* Give outstanding push buffers a chance to complete */ +- spin_lock_irqsave(&chan->fence.lock, flags); + nouveau_fence_update(chan); +- spin_unlock_irqrestore(&chan->fence.lock, flags); + if (chan->fence.sequence != chan->fence.sequence_ack) { + struct nouveau_fence *fence = NULL; + +@@ -311,6 +309,7 @@ nouveau_channel_free(struct nouveau_channel *chan) + /* Release the channel's resources */ + nouveau_gpuobj_ref_del(dev, &chan->pushbuf); + if (chan->pushbuf_bo) { ++ nouveau_bo_unmap(chan->pushbuf_bo); + nouveau_bo_unpin(chan->pushbuf_bo); + nouveau_bo_ref(NULL, &chan->pushbuf_bo); + } +@@ -368,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, + struct nouveau_channel *chan; + int ret; + +- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; +- + if (dev_priv->engine.graph.accel_blocked) + return -ENODEV; + +@@ -418,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, + struct drm_nouveau_channel_free *cfree = data; + struct nouveau_channel *chan; + +- NOUVEAU_CHECK_INITIALISED_WITH_RETURN; + NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + + nouveau_channel_free(chan); +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 149ed22..a1473ff 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -37,12 +37,6 @@ + #include "nouveau_connector.h" + #include "nouveau_hw.h" + +-static inline struct drm_encoder_slave_funcs * +-get_slave_funcs(struct nouveau_encoder *enc) +-{ +- return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; +-} +- + static struct nouveau_encoder * + find_encoder_by_type(struct drm_connector *connector, int type) + { +@@ -102,60 +96,12 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) + kfree(drm_connector); + } + +-static void +-nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags) -{ - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - @@ -3076,24 +3762,23 @@ index 4ef38ab..0d2e668 100644 #endif /* __NOUVEAU_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c -index 65c441a..2e3c6ca 100644 +index 65c441a..2d00699 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c -@@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan) +@@ -91,13 +91,6 @@ nouveau_dma_init(struct nouveau_channel *chan) + if (ret) return ret; - /* Map M2MF notifier object - fbcon. */ +- /* Map M2MF notifier object - fbcon. */ - if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = nouveau_bo_map(chan->notifier_bo); - if (ret) - return ret; - } -+ ret = nouveau_bo_map(chan->notifier_bo); -+ if (ret) -+ return ret; - +- /* Insert NOPS for NOUVEAU_DMA_SKIPS */ ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); + if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index deeb21c..8a1b188 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -3380,7 +4065,7 @@ index 2737704..a8d3d17 100644 nouveau_unregister_dsm_handler(); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h -index c697191..c001574 100644 +index c697191..2eb622b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -123,14 +123,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) @@ -3398,7 +4083,11 @@ index c697191..c001574 100644 enum nouveau_flags { NV_NFORCE = 0x10000000, NV_NFORCE2 = 0x20000000 -@@ -149,7 +141,7 @@ struct nouveau_gpuobj { +@@ -146,10 +138,11 @@ enum nouveau_flags { + #define NVOBJ_FLAG_ZERO_FREE (1 << 2) + #define NVOBJ_FLAG_FAKE (1 << 3) + struct nouveau_gpuobj { ++ struct drm_device *dev; struct list_head list; struct nouveau_channel *im_channel; @@ -3407,7 +4096,7 @@ index c697191..c001574 100644 struct nouveau_bo *im_backing; uint32_t im_backing_start; uint32_t *im_backing_suspend; -@@ -196,7 +188,7 @@ struct nouveau_channel { +@@ -196,7 +189,7 @@ struct nouveau_channel { struct list_head pending; uint32_t sequence; uint32_t sequence_ack; @@ -3416,7 +4105,7 @@ index c697191..c001574 100644 } fence; /* DMA push buffer */ -@@ -206,7 +198,7 @@ struct nouveau_channel { +@@ -206,7 +199,7 @@ struct nouveau_channel { /* Notifier memory */ struct nouveau_bo *notifier_bo; @@ -3425,7 +4114,7 @@ index c697191..c001574 100644 /* PFIFO context */ struct nouveau_gpuobj_ref *ramfc; -@@ -224,7 +216,7 @@ struct nouveau_channel { +@@ -224,7 +217,7 @@ struct nouveau_channel { /* Objects */ struct nouveau_gpuobj_ref *ramin; /* Private instmem */ @@ -3434,7 +4123,7 @@ index c697191..c001574 100644 struct nouveau_gpuobj_ref *ramht; /* Hash table */ struct list_head ramht_refs; /* Objects referenced by RAMHT */ -@@ -277,8 +269,7 @@ struct nouveau_instmem_engine { +@@ -277,8 +270,7 @@ struct nouveau_instmem_engine { void (*clear)(struct drm_device *, struct nouveau_gpuobj *); int (*bind)(struct drm_device *, struct nouveau_gpuobj *); int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); @@ -3444,7 +4133,7 @@ index c697191..c001574 100644 }; struct nouveau_mc_engine { -@@ -303,10 +294,11 @@ struct nouveau_fb_engine { +@@ -303,10 +295,11 @@ struct nouveau_fb_engine { }; struct nouveau_fifo_engine { @@ -3458,7 +4147,7 @@ index c697191..c001574 100644 int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); -@@ -339,10 +331,11 @@ struct nouveau_pgraph_object_class { +@@ -339,10 +332,11 @@ struct nouveau_pgraph_object_class { struct nouveau_pgraph_engine { struct nouveau_pgraph_object_class *grclass; bool accel_blocked; @@ -3472,7 +4161,7 @@ index c697191..c001574 100644 int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); -@@ -358,6 +351,24 @@ struct nouveau_pgraph_engine { +@@ -358,6 +352,24 @@ struct nouveau_pgraph_engine { uint32_t size, uint32_t pitch); }; @@ -3497,7 +4186,7 @@ index c697191..c001574 100644 struct nouveau_engine { struct nouveau_instmem_engine instmem; struct nouveau_mc_engine mc; -@@ -365,6 +376,8 @@ struct nouveau_engine { +@@ -365,6 +377,8 @@ struct nouveau_engine { struct nouveau_fb_engine fb; struct nouveau_pgraph_engine graph; struct nouveau_fifo_engine fifo; @@ -3506,7 +4195,7 @@ index c697191..c001574 100644 }; struct nouveau_pll_vals { -@@ -397,7 +410,7 @@ enum nv04_fp_display_regs { +@@ -397,7 +411,7 @@ enum nv04_fp_display_regs { struct nv04_crtc_reg { unsigned char MiscOutReg; /* */ @@ -3515,7 +4204,7 @@ index c697191..c001574 100644 uint8_t CR58[0x10]; uint8_t Sequencer[5]; uint8_t Graphics[9]; -@@ -496,15 +509,11 @@ enum nouveau_card_type { +@@ -496,15 +510,11 @@ enum nouveau_card_type { NV_30 = 0x30, NV_40 = 0x40, NV_50 = 0x50, @@ -3532,7 +4221,7 @@ index c697191..c001574 100644 /* the card type, takes NV_* as values */ enum nouveau_card_type card_type; -@@ -528,13 +537,9 @@ struct drm_nouveau_private { +@@ -528,13 +538,9 @@ struct drm_nouveau_private { struct ttm_global_reference mem_global_ref; struct ttm_bo_global_ref bo_global_ref; struct ttm_bo_device bdev; @@ -3546,7 +4235,15 @@ index c697191..c001574 100644 int fifo_alloc_count; struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; -@@ -595,11 +600,7 @@ struct drm_nouveau_private { +@@ -579,6 +585,7 @@ struct drm_nouveau_private { + /* 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; +@@ -595,11 +602,7 @@ struct drm_nouveau_private { struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; int vm_vram_pt_nr; @@ -3559,7 +4256,7 @@ index c697191..c001574 100644 struct list_head gpuobj_list; -@@ -618,6 +619,11 @@ struct drm_nouveau_private { +@@ -618,6 +621,11 @@ struct drm_nouveau_private { struct backlight_device *backlight; struct nouveau_channel *evo; @@ -3571,7 +4268,7 @@ index c697191..c001574 100644 struct { struct dentry *channel_root; -@@ -652,14 +658,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) +@@ -652,14 +660,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) return 0; } @@ -3586,7 +4283,7 @@ index c697191..c001574 100644 #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ struct drm_nouveau_private *nv = dev->dev_private; \ if (!nouveau_channel_owner(dev, (cl), (id))) { \ -@@ -682,7 +680,6 @@ extern int nouveau_tv_disable; +@@ -682,7 +682,6 @@ extern int nouveau_tv_disable; extern char *nouveau_tv_norm; extern int nouveau_reg_debug; extern char *nouveau_vbios; @@ -3594,7 +4291,7 @@ index c697191..c001574 100644 extern int nouveau_ignorelid; extern int nouveau_nofbaccel; extern int nouveau_noaccel; -@@ -707,17 +704,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *); +@@ -707,17 +706,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *); extern int nouveau_card_init(struct drm_device *); /* nouveau_mem.c */ @@ -3613,7 +4310,7 @@ index c697191..c001574 100644 extern void nouveau_mem_close(struct drm_device *); extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, -@@ -857,11 +847,13 @@ void nouveau_register_dsm_handler(void); +@@ -857,11 +849,13 @@ void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); bool nouveau_acpi_rom_supported(struct pci_dev *pdev); @@ -3627,7 +4324,7 @@ index c697191..c001574 100644 #endif /* nouveau_backlight.c */ -@@ -924,6 +916,10 @@ extern void nv10_fb_takedown(struct drm_device *); +@@ -924,15 +918,23 @@ extern void nv10_fb_takedown(struct drm_device *); extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, uint32_t, uint32_t); @@ -3638,18 +4335,21 @@ index c697191..c001574 100644 /* nv40_fb.c */ extern int nv40_fb_init(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *); -@@ -934,6 +930,10 @@ extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, + extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); +- + /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); extern void nv50_fb_takedown(struct drm_device *); - ++extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *); ++ +/* nvc0_fb.c */ +extern int nvc0_fb_init(struct drm_device *); +extern void nvc0_fb_takedown(struct drm_device *); -+ + /* nv04_fifo.c */ extern int nv04_fifo_init(struct drm_device *); - extern void nv04_fifo_disable(struct drm_device *); -@@ -971,6 +971,20 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *); +@@ -971,6 +973,20 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *); extern int nv50_fifo_load_context(struct nouveau_channel *); extern int nv50_fifo_unload_context(struct drm_device *); @@ -3670,7 +4370,7 @@ index c697191..c001574 100644 /* nv04_graph.c */ extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; extern int nv04_graph_init(struct drm_device *); -@@ -1035,11 +1049,15 @@ extern int nv50_graph_unload_context(struct drm_device *); +@@ -1035,11 +1051,15 @@ extern int nv50_graph_unload_context(struct drm_device *); extern void nv50_graph_context_switch(struct drm_device *); extern int nv50_grctx_init(struct nouveau_grctx *); @@ -3691,7 +4391,7 @@ index c697191..c001574 100644 /* nv04_instmem.c */ extern int nv04_instmem_init(struct drm_device *); -@@ -1051,8 +1069,7 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, +@@ -1051,8 +1071,7 @@ extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); @@ -3701,7 +4401,7 @@ index c697191..c001574 100644 /* nv50_instmem.c */ extern int nv50_instmem_init(struct drm_device *); -@@ -1064,8 +1081,21 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, +@@ -1064,8 +1083,21 @@ extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); @@ -3725,7 +4425,7 @@ index c697191..c001574 100644 /* nv04_mc.c */ extern int nv04_mc_init(struct drm_device *); -@@ -1088,13 +1118,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, +@@ -1088,13 +1120,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); /* nv04_dac.c */ @@ -3742,7 +4442,7 @@ index c697191..c001574 100644 extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent); extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent, int head, bool dl); -@@ -1103,15 +1134,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); +@@ -1103,15 +1136,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode); /* nv04_tv.c */ extern int nv04_tv_identify(struct drm_device *dev, int i2c_index); @@ -3763,7 +4463,7 @@ index c697191..c001574 100644 /* nv04_crtc.c */ extern int nv04_crtc_create(struct drm_device *, int index); -@@ -1147,7 +1180,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +@@ -1147,7 +1182,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); extern int nouveau_fence_flush(void *obj, void *arg); extern void nouveau_fence_unref(void **obj); extern void *nouveau_fence_ref(void *obj); @@ -3771,7 +4471,7 @@ index c697191..c001574 100644 /* nouveau_gem.c */ extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, -@@ -1167,13 +1199,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *, +@@ -1167,13 +1201,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *, extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); @@ -3790,21 +4490,56 @@ index c697191..c001574 100644 /* nv50_calc. */ int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, -@@ -1220,6 +1254,14 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val) +@@ -1220,6 +1256,13 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val) iowrite32_native(val, dev_priv->mmio + reg); } -+static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) ++static inline u32 nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) +{ + u32 tmp = nv_rd32(dev, reg); -+ tmp &= ~mask; -+ tmp |= val; -+ nv_wr32(dev, reg, tmp); ++ nv_wr32(dev, reg, (tmp & ~mask) | val); ++ return tmp; +} + static inline u8 nv_rd08(struct drm_device *dev, unsigned reg) { struct drm_nouveau_private *dev_priv = dev->dev_private; +@@ -1249,17 +1292,8 @@ static inline void nv_wi32(struct drm_device *dev, unsigned offset, u32 val) + } + + /* object access */ +-static inline u32 nv_ro32(struct drm_device *dev, struct nouveau_gpuobj *obj, +- unsigned index) +-{ +- return nv_ri32(dev, obj->im_pramin->start + index * 4); +-} +- +-static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj, +- unsigned index, u32 val) +-{ +- nv_wi32(dev, obj->im_pramin->start + index * 4, val); +-} ++extern u32 nv_ro32(struct nouveau_gpuobj *, u32 offset); ++extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); + + /* + * Logging +@@ -1346,6 +1380,15 @@ nv_two_reg_pll(struct drm_device *dev) + return false; + } + ++static inline bool ++nv_match_device(struct drm_device *dev, unsigned device, ++ unsigned sub_vendor, unsigned sub_device) ++{ ++ return dev->pdev->device == device && ++ dev->pdev->subsystem_vendor == sub_vendor && ++ dev->pdev->subsystem_device == sub_device; ++} ++ + #define NV_SW 0x0000506e + #define NV_SW_DMA_SEMAPHORE 0x00000060 + #define NV_SW_SEMAPHORE_OFFSET 0x00000064 diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index e1df820..7c82d68 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -3988,7 +4723,7 @@ index faddf53..6b208ff 100644 } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c -index 69c76cf..547f2c2 100644 +index 69c76cf..62ac673 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, @@ -4012,6 +4747,24 @@ index 69c76cf..547f2c2 100644 NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); req->vram_available = dev_priv->fb_aper_free; +@@ -650,7 +647,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, + push[i].length); + } + } else +- if (dev_priv->card_type >= NV_20) { ++ if (dev_priv->chipset >= 0x25) { + ret = RING_SPACE(chan, req->nr_push * 2); + if (ret) { + NV_ERROR(dev, "cal_space: %d\n", ret); +@@ -725,7 +722,7 @@ out_next: + req->suffix0 = 0x00000000; + req->suffix1 = 0x00000000; + } else +- if (dev_priv->card_type >= NV_20) { ++ if (dev_priv->chipset >= 0x25) { + req->suffix0 = 0x00020000; + req->suffix1 = 0x00000000; + } else { @@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); int ret = -EINVAL; @@ -4205,37 +4958,53 @@ index f731c5f..0000000 - nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset), - le32_to_cpu(cv->data[i].value)); -} +diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h +index 5d39c4c..4a8ad13 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_grctx.h ++++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h +@@ -126,7 +126,7 @@ gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) + reg = (reg - 0x00400000) / 4; + reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; + +- nv_wo32(ctx->dev, ctx->data, reg, val); ++ nv_wo32(ctx->data, reg * 4, val); + } + #endif + diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c -index 7855b35..7b61368 100644 +index 7855b35..f8ec49b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c -@@ -865,8 +865,12 @@ nv_save_state_ext(struct drm_device *dev, int head, +@@ -865,8 +865,13 @@ nv_save_state_ext(struct drm_device *dev, int head, rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_21); - if (dev_priv->card_type >= NV_30) + -+ if (dev_priv->card_type >= NV_30) { ++ if (dev_priv->card_type >= NV_20) rd_cio_state(dev, head, regp, NV_CIO_CRE_47); ++ ++ if (dev_priv->card_type >= NV_30) + rd_cio_state(dev, head, regp, 0x9f); -+ } + rd_cio_state(dev, head, regp, NV_CIO_CRE_49); rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); -@@ -971,8 +975,11 @@ nv_load_state_ext(struct drm_device *dev, int head, +@@ -971,9 +976,13 @@ nv_load_state_ext(struct drm_device *dev, int head, wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); - if (dev_priv->card_type >= NV_30) + -+ if (dev_priv->card_type >= NV_30) { ++ if (dev_priv->card_type >= NV_20) wr_cio_state(dev, head, regp, NV_CIO_CRE_47); -+ wr_cio_state(dev, head, regp, 0x9f); -+ } ++ if (dev_priv->card_type >= NV_30) ++ wr_cio_state(dev, head, regp, 0x9f); ++ wr_cio_state(dev, head, regp, NV_CIO_CRE_49); wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); + wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 316a3c7..8461485 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -4388,7 +5157,7 @@ index c8eaf7a..f71cb32 100644 #endif /* __NOUVEAU_I2C_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c -index 53360f1..794b0ee 100644 +index 53360f1..b8658a0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -49,7 +49,7 @@ nouveau_irq_preinstall(struct drm_device *dev) @@ -4400,7 +5169,22 @@ index 53360f1..794b0ee 100644 INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); INIT_LIST_HEAD(&dev_priv->vbl_waiting); -@@ -586,11 +586,11 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) +@@ -226,6 +226,14 @@ nouveau_fifo_irq_handler(struct drm_device *dev) + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + } + ++ if (dev_priv->card_type == NV_50) { ++ if (status & 0x00000010) { ++ nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); ++ status &= ~0x00000010; ++ nv_wr32(dev, 0x002100, 0x00000010); ++ } ++ } ++ + if (status) { + NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", + status, chid); +@@ -586,11 +594,11 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) } if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { @@ -4414,8 +5198,140 @@ index 53360f1..794b0ee 100644 } if (status) { +@@ -605,40 +613,6 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); + } + +-static void +-nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t trap[6]; +- int i, ch; +- uint32_t idx = nv_rd32(dev, 0x100c90); +- if (idx & 0x80000000) { +- idx &= 0xffffff; +- if (display) { +- for (i = 0; i < 6; i++) { +- nv_wr32(dev, 0x100c90, idx | i << 24); +- trap[i] = nv_rd32(dev, 0x100c94); +- } +- for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { +- struct nouveau_channel *chan = dev_priv->fifos[ch]; +- +- if (!chan || !chan->ramin) +- continue; +- +- if (trap[1] == chan->ramin->instance >> 12) +- break; +- } +- NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n", +- name, (trap[5]&0x100?"read":"write"), +- trap[5]&0xff, trap[4]&0xffff, +- trap[3]&0xffff, trap[0], trap[2], ch); +- } +- nv_wr32(dev, 0x100c90, idx | 0x80000000); +- } else if (display) { +- NV_INFO(dev, "%s - no VM fault?\n", name); +- } +-} +- + static struct nouveau_enum_names nv50_mp_exec_error_names[] = + { + { 3, "STACK_UNDERFLOW" }, +@@ -711,7 +685,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, + tps++; + switch (type) { + case 6: /* texture error... unknown for now */ +- nv50_pfb_vm_trap(dev, display, name); ++ nv50_fb_vm_trap(dev, display, name); + if (display) { + NV_ERROR(dev, "magic set %d:\n", i); + for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) +@@ -734,7 +708,7 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, + uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); + uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); + uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); +- nv50_pfb_vm_trap(dev, display, name); ++ nv50_fb_vm_trap(dev, display, name); + /* 2d engine destination */ + if (ustatus & 0x00000010) { + if (display) { +@@ -817,7 +791,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + + /* Known to be triggered by screwed up NOTIFY and COND... */ + if (ustatus & 0x00000001) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); + nv_wr32(dev, 0x400500, 0); + if (nv_rd32(dev, 0x400808) & 0x80000000) { + if (display) { +@@ -842,7 +816,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + ustatus &= ~0x00000001; + } + if (ustatus & 0x00000002) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); + nv_wr32(dev, 0x400500, 0); + if (nv_rd32(dev, 0x40084c) & 0x80000000) { + if (display) { +@@ -884,15 +858,15 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); + } + if (ustatus & 0x00000001) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); + ustatus &= ~0x00000001; + } + if (ustatus & 0x00000002) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); + ustatus &= ~0x00000002; + } + if (ustatus & 0x00000004) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); + ustatus &= ~0x00000004; + } + NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", +@@ -917,7 +891,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); + } + if (ustatus & 0x00000001) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); + NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", + nv_rd32(dev, 0x400c00), + nv_rd32(dev, 0x400c08), +@@ -939,7 +913,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); + } + if (ustatus & 0x00000001) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); + NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", + nv_rd32(dev, 0x401804), + nv_rd32(dev, 0x401808), +@@ -964,7 +938,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); + } + if (ustatus & 0x00000001) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); + NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", + nv_rd32(dev, 0x405800), + nv_rd32(dev, 0x405804), +@@ -986,7 +960,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev) + * remaining, so try to handle it anyway. Perhaps related to that + * unknown DMA slot on tesla? */ + if (status & 0x20) { +- nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); ++ nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); + ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; + if (display) + NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c -index c1fd42b..db442c1 100644 +index c1fd42b..ee799c2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -35,162 +35,6 @@ @@ -4589,7 +5505,15 @@ index c1fd42b..db442c1 100644 while (size) { unsigned offset_h = upper_32_bits(phys); unsigned offset_l = lower_32_bits(phys); -@@ -331,36 +174,12 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, +@@ -326,41 +169,18 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, + virt += (end - pte); + + while (pte < end) { +- nv_wo32(dev, pgt, pte++, offset_l); +- nv_wo32(dev, pgt, pte++, offset_h); ++ nv_wo32(pgt, (pte * 4) + 0, offset_l); ++ nv_wo32(pgt, (pte * 4) + 4, offset_h); ++ pte += 2; } } } @@ -4631,7 +5555,7 @@ index c1fd42b..db442c1 100644 return 0; } -@@ -374,7 +193,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) +@@ -374,7 +194,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) virt -= dev_priv->vm_vram_base; pages = (size >> 16) << 1; @@ -4639,10 +5563,13 @@ index c1fd42b..db442c1 100644 while (pages) { pgt = dev_priv->vm_vram_pt[virt >> 29]; pte = (virt & 0x1ffe0000ULL) >> 15; -@@ -388,57 +206,19 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) - while (pte < end) - nv_wo32(dev, pgt, pte++, 0); - } +@@ -385,60 +204,24 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) + pages -= (end - pte); + virt += (end - pte) << 15; + +- while (pte < end) +- nv_wo32(dev, pgt, pte++, 0); +- } - dev_priv->engine.instmem.finish_access(dev); - - nv_wr32(dev, 0x100c80, 0x00050001); @@ -4664,7 +5591,11 @@ index c1fd42b..db442c1 100644 - NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); - NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); - return; -- } ++ while (pte < end) { ++ nv_wo32(pgt, (pte * 4), 0); ++ pte++; ++ } + } + dev_priv->engine.instmem.flush(dev); - nv_wr32(dev, 0x100c80, 0x00060001); @@ -4704,7 +5635,7 @@ index c1fd42b..db442c1 100644 { struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -449,8 +229,7 @@ void nouveau_mem_close(struct drm_device *dev) +@@ -449,8 +232,7 @@ void nouveau_mem_close(struct drm_device *dev) nouveau_ttm_global_release(dev_priv); @@ -4714,7 +5645,7 @@ index c1fd42b..db442c1 100644 struct drm_agp_mem *entry, *tempe; /* Remove AGP resources, but leave dev->agp -@@ -470,29 +249,29 @@ void nouveau_mem_close(struct drm_device *dev) +@@ -470,29 +252,29 @@ void nouveau_mem_close(struct drm_device *dev) dev->agp->enabled = 0; } @@ -4752,34 +5683,106 @@ index c1fd42b..db442c1 100644 return 4 * 1024 * 1024; } -@@ -536,12 +315,22 @@ nouveau_mem_detect(struct drm_device *dev) - } else - if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { - dev_priv->vram_size = nouveau_mem_detect_nforce(dev); -- } else { -- dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA); -- dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; -- if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) -+ } else -+ if (dev_priv->card_type < NV_50) { -+ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); -+ dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; -+ } else -+ if (dev_priv->card_type < NV_C0) { -+ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); -+ dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; -+ dev_priv->vram_size &= 0xffffffff00ll; -+ if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { - dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); - dev_priv->vram_sys_base <<= 12; -+ } -+ } else { -+ dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; +@@ -525,7 +307,61 @@ nouveau_mem_detect_nforce(struct drm_device *dev) + return 0; + } + +-/* returns the amount of FB ram in bytes */ ++static void ++nv50_vram_preinit(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ int i, parts, colbits, rowbitsa, rowbitsb, banks; ++ u64 rowsize, predicted; ++ u32 r0, r4, rt, ru; ++ ++ r0 = nv_rd32(dev, 0x100200); ++ r4 = nv_rd32(dev, 0x100204); ++ rt = nv_rd32(dev, 0x100250); ++ ru = nv_rd32(dev, 0x001540); ++ NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); ++ ++ for (i = 0, parts = 0; i < 8; i++) { ++ if (ru & (0x00010000 << i)) ++ parts++; ++ } ++ ++ colbits = (r4 & 0x0000f000) >> 12; ++ rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; ++ rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; ++ banks = ((r4 & 0x01000000) ? 8 : 4); ++ ++ rowsize = parts * banks * (1 << colbits) * 8; ++ predicted = rowsize << rowbitsa; ++ if (r0 & 0x00000004) ++ predicted += rowsize << rowbitsb; ++ ++ if (predicted != dev_priv->vram_size) { ++ NV_WARN(dev, "memory controller reports %dMiB VRAM\n", ++ (u32)(dev_priv->vram_size >> 20)); ++ NV_WARN(dev, "we calculated %dMiB VRAM\n", ++ (u32)(predicted >> 20)); ++ } ++ ++ dev_priv->vram_rblock_size = rowsize >> 12; ++ if (rt & 1) ++ dev_priv->vram_rblock_size *= 3; ++ ++ NV_DEBUG(dev, "rblock %lld bytes\n", ++ (u64)dev_priv->vram_rblock_size << 12); ++} ++ ++static void ++nvaa_vram_preinit(struct drm_device *dev) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ ++ /* To our knowledge, there's no large scale reordering of pages ++ * that occurs on IGP chipsets. ++ */ ++ dev_priv->vram_rblock_size = 1; ++} ++ + int + nouveau_mem_detect(struct drm_device *dev) + { +@@ -536,12 +372,31 @@ nouveau_mem_detect(struct drm_device *dev) + } else + if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { + dev_priv->vram_size = nouveau_mem_detect_nforce(dev); +- } else { +- dev_priv->vram_size = nv_rd32(dev, NV04_FIFO_DATA); +- dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; +- if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) ++ } else ++ if (dev_priv->card_type < NV_50) { ++ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); ++ dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; ++ } else ++ if (dev_priv->card_type < NV_C0) { ++ dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); ++ dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; ++ dev_priv->vram_size &= 0xffffffff00ll; ++ ++ switch (dev_priv->chipset) { ++ case 0xaa: ++ case 0xac: ++ case 0xaf: + dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); + dev_priv->vram_sys_base <<= 12; ++ nvaa_vram_preinit(dev); ++ break; ++ default: ++ nv50_vram_preinit(dev); ++ break; ++ } ++ } else { ++ dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; + dev_priv->vram_size *= nv_rd32(dev, 0x121c74); } NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); -@@ -555,18 +344,36 @@ nouveau_mem_detect(struct drm_device *dev) +@@ -555,18 +410,37 @@ nouveau_mem_detect(struct drm_device *dev) return -ENOMEM; } @@ -4796,7 +5799,8 @@ index c1fd42b..db442c1 100644 + /* First of all, disable fast writes, otherwise if it's + * already enabled in the AGP bridge and we disable the card's + * AGP controller we might be locking ourselves out of it. */ -+ if (nv_rd32(dev, NV04_PBUS_PCI_NV_19) & PCI_AGP_COMMAND_FW) { ++ if ((nv_rd32(dev, NV04_PBUS_PCI_NV_19) | ++ dev->agp->mode) & PCI_AGP_COMMAND_FW) { + struct drm_agp_info info; + struct drm_agp_mode mode; + @@ -4822,7 +5826,7 @@ index c1fd42b..db442c1 100644 /* power cycle pgraph, if enabled */ pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE); -@@ -578,11 +385,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev) +@@ -578,11 +452,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev) } /* and restore (gives effect of resetting AGP) */ @@ -4837,7 +5841,7 @@ index c1fd42b..db442c1 100644 int nouveau_mem_init_agp(struct drm_device *dev) { -@@ -592,11 +400,6 @@ nouveau_mem_init_agp(struct drm_device *dev) +@@ -592,11 +467,6 @@ nouveau_mem_init_agp(struct drm_device *dev) struct drm_agp_mode mode; int ret; @@ -4849,7 +5853,7 @@ index c1fd42b..db442c1 100644 if (!dev->agp->acquired) { ret = drm_agp_acquire(dev); if (ret) { -@@ -605,6 +408,8 @@ nouveau_mem_init_agp(struct drm_device *dev) +@@ -605,6 +475,8 @@ nouveau_mem_init_agp(struct drm_device *dev) } } @@ -4858,7 +5862,7 @@ index c1fd42b..db442c1 100644 ret = drm_agp_info(dev, &info); if (ret) { NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); -@@ -659,8 +464,6 @@ nouveau_mem_init(struct drm_device *dev) +@@ -659,8 +531,6 @@ nouveau_mem_init(struct drm_device *dev) return ret; } @@ -4867,7 +5871,7 @@ index c1fd42b..db442c1 100644 spin_lock_init(&dev_priv->tile.lock); dev_priv->fb_available_size = dev_priv->vram_size; -@@ -692,7 +495,7 @@ nouveau_mem_init(struct drm_device *dev) +@@ -692,7 +562,7 @@ nouveau_mem_init(struct drm_device *dev) /* GART */ #if !defined(__powerpc__) && !defined(__ia64__) @@ -4970,60 +5974,160 @@ index 9537f3e..3ec181f 100644 ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c -index e7c100b..4bf6b33 100644 +index e7c100b..6aedc3b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c -@@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - } - } +@@ -34,6 +34,7 @@ + #include "drm.h" + #include "nouveau_drv.h" + #include "nouveau_drm.h" ++#include "nouveau_ramht.h" -- instmem->prepare_access(dev, true); - co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); - do { - if (!nouveau_ramht_entry_valid(dev, ramht, co)) { -@@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - nv_wo32(dev, ramht, (co + 4)/4, ctx); + /* NVidia uses context objects to drive drawing operations. - list_add_tail(&ref->list, &chan->ramht_refs); +@@ -65,141 +66,6 @@ + The key into the hash table depends on the object handle and channel id and + is given as: + */ +-static uint32_t +-nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t hash = 0; +- int i; +- +- NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle); +- +- for (i = 32; i > 0; i -= dev_priv->ramht_bits) { +- hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); +- handle >>= dev_priv->ramht_bits; +- } +- +- if (dev_priv->card_type < NV_50) +- hash ^= channel << (dev_priv->ramht_bits - 4); +- hash <<= 3; +- +- NV_DEBUG(dev, "hash=0x%08x\n", hash); +- return hash; +-} +- +-static int +-nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, +- uint32_t offset) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- uint32_t ctx = nv_ro32(dev, ramht, (offset + 4)/4); +- +- if (dev_priv->card_type < NV_40) +- return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); +- return (ctx != 0); +-} +- +-static int +-nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; +- struct nouveau_channel *chan = ref->channel; +- struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; +- uint32_t ctx, co, ho; +- +- if (!ramht) { +- NV_ERROR(dev, "No hash table!\n"); +- return -EINVAL; +- } +- +- if (dev_priv->card_type < NV_40) { +- ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | +- (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | +- (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); +- } else +- if (dev_priv->card_type < NV_50) { +- ctx = (ref->instance >> 4) | +- (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | +- (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); +- } else { +- if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { +- ctx = (ref->instance << 10) | 2; +- } else { +- ctx = (ref->instance >> 4) | +- ((ref->gpuobj->engine << +- NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); +- } +- } +- +- instmem->prepare_access(dev, true); +- co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); +- do { +- if (!nouveau_ramht_entry_valid(dev, ramht, co)) { +- NV_DEBUG(dev, +- "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", +- chan->id, co, ref->handle, ctx); +- nv_wo32(dev, ramht, (co + 0)/4, ref->handle); +- nv_wo32(dev, ramht, (co + 4)/4, ctx); +- +- list_add_tail(&ref->list, &chan->ramht_refs); - instmem->finish_access(dev); -+ instmem->flush(dev); - return 0; - } - NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", -@@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - if (co >= dev_priv->ramht_size) - co = 0; - } while (co != ho); +- return 0; +- } +- NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", +- chan->id, co, nv_ro32(dev, ramht, co/4)); +- +- co += 8; +- if (co >= dev_priv->ramht_size) +- co = 0; +- } while (co != ho); - instmem->finish_access(dev); - - NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); - return -ENOMEM; -@@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - return; - } - +- +- NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); +- return -ENOMEM; +-} +- +-static void +-nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) +-{ +- struct drm_nouveau_private *dev_priv = dev->dev_private; +- struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; +- struct nouveau_channel *chan = ref->channel; +- struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; +- uint32_t co, ho; +- +- if (!ramht) { +- NV_ERROR(dev, "No hash table!\n"); +- return; +- } +- - instmem->prepare_access(dev, true); - co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); - do { - if (nouveau_ramht_entry_valid(dev, ramht, co) && -@@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); - - list_del(&ref->list); +- co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); +- do { +- if (nouveau_ramht_entry_valid(dev, ramht, co) && +- (ref->handle == nv_ro32(dev, ramht, (co/4)))) { +- NV_DEBUG(dev, +- "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", +- chan->id, co, ref->handle, +- nv_ro32(dev, ramht, (co + 4))); +- nv_wo32(dev, ramht, (co + 0)/4, 0x00000000); +- nv_wo32(dev, ramht, (co + 4)/4, 0x00000000); +- +- list_del(&ref->list); - instmem->finish_access(dev); -+ instmem->flush(dev); - return; - } - -@@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) - co = 0; - } while (co != ho); - list_del(&ref->list); +- return; +- } +- +- co += 8; +- if (co >= dev_priv->ramht_size) +- co = 0; +- } while (co != ho); +- list_del(&ref->list); - instmem->finish_access(dev); +- +- NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", +- chan->id, ref->handle); +-} - NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", - chan->id, ref->handle); -@@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, + int + nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, +@@ -209,7 +75,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; struct nouveau_gpuobj *gpuobj; @@ -5032,7 +6136,15 @@ index e7c100b..4bf6b33 100644 int ret; NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", -@@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, +@@ -222,6 +88,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, + if (!gpuobj) + return -ENOMEM; + NV_DEBUG(dev, "gpuobj %p\n", gpuobj); ++ gpuobj->dev = dev; + gpuobj->flags = flags; + gpuobj->im_channel = chan; + +@@ -233,25 +100,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, * available. */ if (chan) { @@ -5050,18 +6162,18 @@ index e7c100b..4bf6b33 100644 NV_DEBUG(dev, "global heap\n"); - pramin = dev_priv->ramin_heap; - } -- ++ pramin = &dev_priv->ramin_heap; + - if (!pramin) { - NV_ERROR(dev, "No PRAMIN heap!\n"); - return -EINVAL; - } -+ pramin = &dev_priv->ramin_heap; - +- - if (!chan) { ret = engine->instmem.populate(dev, gpuobj, &size); if (ret) { nouveau_gpuobj_del(dev, &gpuobj); -@@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, +@@ -260,9 +114,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, } /* Allocate a chunk of the PRAMIN aperture */ @@ -5075,31 +6187,33 @@ index e7c100b..4bf6b33 100644 if (!gpuobj->im_pramin) { nouveau_gpuobj_del(dev, &gpuobj); return -ENOMEM; -@@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, +@@ -279,10 +134,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { int i; - engine->instmem.prepare_access(dev, true); for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); +- nv_wo32(dev, gpuobj, i/4, 0); - engine->instmem.finish_access(dev); ++ nv_wo32(gpuobj, i, 0); + engine->instmem.flush(dev); } *gpuobj_ret = gpuobj; -@@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +@@ -370,10 +224,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) } if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { - engine->instmem.prepare_access(dev, true); for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); +- nv_wo32(dev, gpuobj, i/4, 0); - engine->instmem.finish_access(dev); ++ nv_wo32(gpuobj, i, 0); + engine->instmem.flush(dev); } if (gpuobj->dtor) -@@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) +@@ -386,7 +239,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj) if (gpuobj->flags & NVOBJ_FLAG_FAKE) kfree(gpuobj->im_pramin); else @@ -5108,7 +6222,14 @@ index e7c100b..4bf6b33 100644 } list_del(&gpuobj->list); -@@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, +@@ -583,13 +436,14 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, + if (!gpuobj) + return -ENOMEM; + NV_DEBUG(dev, "gpuobj %p\n", gpuobj); ++ gpuobj->dev = dev; + gpuobj->im_channel = NULL; + gpuobj->flags = flags | NVOBJ_FLAG_FAKE; + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); if (p_offset != ~0) { @@ -5117,19 +6238,20 @@ index e7c100b..4bf6b33 100644 GFP_KERNEL); if (!gpuobj->im_pramin) { nouveau_gpuobj_del(dev, &gpuobj); -@@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, +@@ -605,10 +459,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset, } if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { - dev_priv->engine.instmem.prepare_access(dev, true); for (i = 0; i < gpuobj->im_pramin->size; i += 4) - nv_wo32(dev, gpuobj, i/4, 0); +- nv_wo32(dev, gpuobj, i/4, 0); - dev_priv->engine.instmem.finish_access(dev); ++ nv_wo32(gpuobj, i, 0); + dev_priv->engine.instmem.flush(dev); } if (pref) { -@@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, +@@ -696,8 +549,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, return ret; } @@ -5138,8 +6260,43 @@ index e7c100b..4bf6b33 100644 if (dev_priv->card_type < NV_50) { uint32_t frame, adjust, pte_flags = 0; -@@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, - nv_wo32(dev, *gpuobj, 5, flags5); +@@ -706,14 +557,12 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, + adjust = offset & 0x00000fff; + frame = offset & ~0x00000fff; + +- nv_wo32(dev, *gpuobj, 0, ((1<<12) | (1<<13) | +- (adjust << 20) | +- (access << 14) | +- (target << 16) | +- class)); +- nv_wo32(dev, *gpuobj, 1, size - 1); +- nv_wo32(dev, *gpuobj, 2, frame | pte_flags); +- nv_wo32(dev, *gpuobj, 3, frame | pte_flags); ++ nv_wo32(*gpuobj, 0, ((1<<12) | (1<<13) | (adjust << 20) | ++ (access << 14) | (target << 16) | ++ class)); ++ nv_wo32(*gpuobj, 4, size - 1); ++ nv_wo32(*gpuobj, 8, frame | pte_flags); ++ nv_wo32(*gpuobj, 12, frame | pte_flags); + } else { + uint64_t limit = offset + size - 1; + uint32_t flags0, flags5; +@@ -726,15 +575,15 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, + flags5 = 0x00080000; + } + +- nv_wo32(dev, *gpuobj, 0, flags0 | class); +- nv_wo32(dev, *gpuobj, 1, lower_32_bits(limit)); +- nv_wo32(dev, *gpuobj, 2, lower_32_bits(offset)); +- nv_wo32(dev, *gpuobj, 3, ((upper_32_bits(limit) & 0xff) << 24) | +- (upper_32_bits(offset) & 0xff)); +- nv_wo32(dev, *gpuobj, 5, flags5); ++ nv_wo32(*gpuobj, 0, flags0 | class); ++ nv_wo32(*gpuobj, 4, lower_32_bits(limit)); ++ nv_wo32(*gpuobj, 8, lower_32_bits(offset)); ++ nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) | ++ (upper_32_bits(offset) & 0xff)); ++ nv_wo32(*gpuobj, 20, flags5); } - instmem->finish_access(dev); @@ -5147,15 +6304,40 @@ index e7c100b..4bf6b33 100644 (*gpuobj)->engine = NVOBJ_ENGINE_SW; (*gpuobj)->class = class; -@@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, +@@ -849,32 +698,31 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, return ret; } - dev_priv->engine.instmem.prepare_access(dev, true); if (dev_priv->card_type >= NV_50) { - nv_wo32(dev, *gpuobj, 0, class); - nv_wo32(dev, *gpuobj, 5, 0x00010000); -@@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, +- nv_wo32(dev, *gpuobj, 0, class); +- nv_wo32(dev, *gpuobj, 5, 0x00010000); ++ nv_wo32(*gpuobj, 0, class); ++ nv_wo32(*gpuobj, 20, 0x00010000); + } else { + switch (class) { + case NV_CLASS_NULL: +- nv_wo32(dev, *gpuobj, 0, 0x00001030); +- nv_wo32(dev, *gpuobj, 1, 0xFFFFFFFF); ++ nv_wo32(*gpuobj, 0, 0x00001030); ++ nv_wo32(*gpuobj, 4, 0xFFFFFFFF); + break; + default: + if (dev_priv->card_type >= NV_40) { +- nv_wo32(dev, *gpuobj, 0, class); ++ nv_wo32(*gpuobj, 0, class); + #ifdef __BIG_ENDIAN +- nv_wo32(dev, *gpuobj, 2, 0x01000000); ++ nv_wo32(*gpuobj, 8, 0x01000000); + #endif + } else { + #ifdef __BIG_ENDIAN +- nv_wo32(dev, *gpuobj, 0, class | 0x00080000); ++ nv_wo32(*gpuobj, 0, class | 0x00080000); + #else +- nv_wo32(dev, *gpuobj, 0, class); ++ nv_wo32(*gpuobj, 0, class); + #endif } } } @@ -5164,7 +6346,7 @@ index e7c100b..4bf6b33 100644 (*gpuobj)->engine = NVOBJ_ENGINE_GR; (*gpuobj)->class = class; -@@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) +@@ -920,6 +768,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) base = 0; /* PGRAPH context */ @@ -5172,7 +6354,7 @@ index e7c100b..4bf6b33 100644 if (dev_priv->card_type == NV_50) { /* Various fixed table thingos */ -@@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) +@@ -930,12 +779,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) size += 0x8000; /* RAMFC */ size += 0x1000; @@ -5185,7 +6367,7 @@ index e7c100b..4bf6b33 100644 ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0, &chan->ramin); if (ret) { -@@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) +@@ -944,8 +789,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) } pramin = chan->ramin->gpuobj; @@ -5195,7 +6377,7 @@ index e7c100b..4bf6b33 100644 if (ret) { NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); nouveau_gpuobj_ref_del(dev, &chan->ramin); -@@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, +@@ -969,15 +813,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); @@ -5216,7 +6398,7 @@ index e7c100b..4bf6b33 100644 } /* NV50 VM -@@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, +@@ -988,50 +828,42 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, if (dev_priv->card_type >= NV_50) { uint32_t vm_offset, pde; @@ -5233,9 +6415,14 @@ index e7c100b..4bf6b33 100644 return ret; - } for (i = 0; i < 0x4000; i += 8) { - nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); - nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); -@@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, +- nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000); +- nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe); ++ nv_wo32(chan->vm_pd, i + 0, 0x00000000); ++ nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); + } + +- pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 2; ++ pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8; ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->gart_info.sg_ctxdma, &chan->vm_gart_pt); @@ -5244,10 +6431,15 @@ index e7c100b..4bf6b33 100644 + if (ret) return ret; - } - nv_wo32(dev, chan->vm_pd, pde++, - chan->vm_gart_pt->instance | 0x03); - nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); -@@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan, +- nv_wo32(dev, chan->vm_pd, pde++, +- chan->vm_gart_pt->instance | 0x03); +- nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); ++ nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->instance | 3); ++ nv_wo32(chan->vm_pd, pde + 4, 0x00000000); + +- pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 2; ++ pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8; + for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { ret = nouveau_gpuobj_ref_add(dev, NULL, 0, dev_priv->vm_vram_pt[i], &chan->vm_vram_pt[i]); @@ -5257,9 +6449,13 @@ index e7c100b..4bf6b33 100644 return ret; - } - nv_wo32(dev, chan->vm_pd, pde++, - chan->vm_vram_pt[i]->instance | 0x61); - nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); +- nv_wo32(dev, chan->vm_pd, pde++, +- chan->vm_vram_pt[i]->instance | 0x61); +- nv_wo32(dev, chan->vm_pd, pde++, 0x00000000); ++ nv_wo32(chan->vm_pd, pde + 0, ++ chan->vm_vram_pt[i]->instance | 0x61); ++ nv_wo32(chan->vm_pd, pde + 4, 0x00000000); ++ pde += 8; } - instmem->finish_access(dev); @@ -5267,7 +6463,7 @@ index e7c100b..4bf6b33 100644 } /* RAMHT */ -@@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) +@@ -1130,8 +962,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]); @@ -5278,30 +6474,34 @@ index e7c100b..4bf6b33 100644 if (chan->ramin) nouveau_gpuobj_ref_del(dev, &chan->ramin); -@@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev) +@@ -1164,10 +996,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev) return -ENOMEM; } - dev_priv->engine.instmem.prepare_access(dev, false); - for (i = 0; i < gpuobj->im_pramin->size / 4; i++) - gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); +- for (i = 0; i < gpuobj->im_pramin->size / 4; i++) +- gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i); - dev_priv->engine.instmem.finish_access(dev); ++ for (i = 0; i < gpuobj->im_pramin->size; i += 4) ++ gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i); } return 0; -@@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev) +@@ -1212,10 +1042,9 @@ nouveau_gpuobj_resume(struct drm_device *dev) if (!gpuobj->im_backing_suspend) continue; - dev_priv->engine.instmem.prepare_access(dev, true); - for (i = 0; i < gpuobj->im_pramin->size / 4; i++) - nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); +- for (i = 0; i < gpuobj->im_pramin->size / 4; i++) +- nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]); - dev_priv->engine.instmem.finish_access(dev); ++ for (i = 0; i < gpuobj->im_pramin->size; i += 4) ++ nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]); + dev_priv->engine.instmem.flush(dev); } nouveau_gpuobj_suspend_cleanup(dev); -@@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, +@@ -1232,7 +1061,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct nouveau_channel *chan; int ret; @@ -5309,7 +6509,7 @@ index e7c100b..4bf6b33 100644 NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); if (init->handle == ~0) -@@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, +@@ -1283,7 +1111,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, struct nouveau_channel *chan; int ret; @@ -5317,123 +6517,344 @@ index e7c100b..4bf6b33 100644 NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref); -diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h -index 6ca80a3..21a6e45 100644 ---- a/drivers/gpu/drm/nouveau/nouveau_reg.h -+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h -@@ -1,19 +1,64 @@ - -+#define NV04_PFB_BOOT_0 0x00100000 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 -+# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 -+# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 -+# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 -+# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 -+# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 -+# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 -+#define NV04_PFB_DEBUG_0 0x00100080 -+# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 -+# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 -+# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 -+# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 -+# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 -+# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 -+# define NV04_PFB_DEBUG_0_CASOE 0x00100000 -+# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 -+# define NV04_PFB_DEBUG_0_REFINC 0x20000000 -+# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 -+#define NV04_PFB_CFG0 0x00100200 -+# define NV04_PFB_CFG0_SCRAMBLE 0x20000000 -+#define NV04_PFB_CFG1 0x00100204 -+#define NV04_PFB_FIFO_DATA 0x0010020c -+# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 -+# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 -+#define NV10_PFB_REFCTRL 0x00100210 -+# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) -+#define NV04_PFB_PAD 0x0010021c -+# define NV04_PFB_PAD_CKE_NORMAL (1 << 0) -+#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) -+#define NV10_PFB_TILE__SIZE 8 -+#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) -+#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) -+#define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16)) -+#define NV04_PFB_REF 0x001002d0 -+# define NV04_PFB_REF_CMD_REFRESH (1 << 0) -+#define NV04_PFB_PRE 0x001002d4 -+# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) -+#define NV10_PFB_CLOSE_PAGE2 0x0010033c -+#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) -+#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) -+#define NV40_PFB_TILE__SIZE_0 12 -+#define NV40_PFB_TILE__SIZE_1 15 -+#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) -+#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) -+#define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16)) -+#define NV40_PFB_UNK_800 0x00100800 - --#define NV03_BOOT_0 0x00100000 --# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 --# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 --# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 --# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 --# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 --# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 --# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 --# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 --# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 -- --#define NV04_FIFO_DATA 0x0010020c --# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 --# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 -+#define NV_PEXTDEV_BOOT_0 0x00101000 -+#define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c -+# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) -+#define NV_PEXTDEV_BOOT_3 0x0010100c - - #define NV_RAMIN 0x00700000 - -@@ -131,23 +176,6 @@ - #define NV04_PTIMER_TIME_1 0x00009410 - #define NV04_PTIMER_ALARM_0 0x00009420 +@@ -1293,3 +1120,17 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, --#define NV04_PFB_CFG0 0x00100200 --#define NV04_PFB_CFG1 0x00100204 --#define NV40_PFB_020C 0x0010020C --#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) --#define NV10_PFB_TILE__SIZE 8 --#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) --#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) --#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) --#define NV10_PFB_CLOSE_PAGE2 0x0010033C --#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) --#define NV40_PFB_TILE__SIZE_0 12 --#define NV40_PFB_TILE__SIZE_1 15 --#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) --#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) --#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) --#define NV40_PFB_UNK_800 0x00100800 -- - #define NV04_PGRAPH_DEBUG_0 0x00400080 - #define NV04_PGRAPH_DEBUG_1 0x00400084 - #define NV04_PGRAPH_DEBUG_2 0x00400088 -@@ -192,28 +220,21 @@ - # define NV_PGRAPH_INTR_ERROR (1<<20) - #define NV10_PGRAPH_CTX_CONTROL 0x00400144 - #define NV10_PGRAPH_CTX_USER 0x00400148 --#define NV10_PGRAPH_CTX_SWITCH1 0x0040014C --#define NV10_PGRAPH_CTX_SWITCH2 0x00400150 --#define NV10_PGRAPH_CTX_SWITCH3 0x00400154 --#define NV10_PGRAPH_CTX_SWITCH4 0x00400158 --#define NV10_PGRAPH_CTX_SWITCH5 0x0040015C -+#define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) + return 0; + } ++ ++u32 ++nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset) ++{ ++ struct drm_device *dev = gpuobj->dev; ++ return nv_ri32(dev, gpuobj->im_pramin->start + offset); ++} ++ ++void ++nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val) ++{ ++ struct drm_device *dev = gpuobj->dev; ++ nv_wi32(dev, gpuobj->im_pramin->start + offset, val); ++} +diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c +new file mode 100644 +index 0000000..e5cc93c +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c +@@ -0,0 +1,160 @@ ++/* ++ * Copyright 2010 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" ++ ++static uint32_t ++nouveau_ramht_hash_handle(struct drm_device *dev, int channel, uint32_t handle) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ uint32_t hash = 0; ++ int i; ++ ++ NV_DEBUG(dev, "ch%d handle=0x%08x\n", channel, handle); ++ ++ for (i = 32; i > 0; i -= dev_priv->ramht_bits) { ++ hash ^= (handle & ((1 << dev_priv->ramht_bits) - 1)); ++ handle >>= dev_priv->ramht_bits; ++ } ++ ++ if (dev_priv->card_type < NV_50) ++ hash ^= channel << (dev_priv->ramht_bits - 4); ++ hash <<= 3; ++ ++ NV_DEBUG(dev, "hash=0x%08x\n", hash); ++ return hash; ++} ++ ++static int ++nouveau_ramht_entry_valid(struct drm_device *dev, struct nouveau_gpuobj *ramht, ++ uint32_t offset) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ uint32_t ctx = nv_ro32(ramht, offset + 4); ++ ++ if (dev_priv->card_type < NV_40) ++ return ((ctx & NV_RAMHT_CONTEXT_VALID) != 0); ++ return (ctx != 0); ++} ++ ++int ++nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; ++ struct nouveau_channel *chan = ref->channel; ++ struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; ++ uint32_t ctx, co, ho; ++ ++ if (!ramht) { ++ NV_ERROR(dev, "No hash table!\n"); ++ return -EINVAL; ++ } ++ ++ if (dev_priv->card_type < NV_40) { ++ ctx = NV_RAMHT_CONTEXT_VALID | (ref->instance >> 4) | ++ (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | ++ (ref->gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); ++ } else ++ if (dev_priv->card_type < NV_50) { ++ ctx = (ref->instance >> 4) | ++ (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | ++ (ref->gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); ++ } else { ++ if (ref->gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { ++ ctx = (ref->instance << 10) | 2; ++ } else { ++ ctx = (ref->instance >> 4) | ++ ((ref->gpuobj->engine << ++ NV40_RAMHT_CONTEXT_ENGINE_SHIFT)); ++ } ++ } ++ ++ co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); ++ do { ++ if (!nouveau_ramht_entry_valid(dev, ramht, co)) { ++ NV_DEBUG(dev, ++ "insert ch%d 0x%08x: h=0x%08x, c=0x%08x\n", ++ chan->id, co, ref->handle, ctx); ++ nv_wo32(ramht, co + 0, ref->handle); ++ nv_wo32(ramht, co + 4, ctx); ++ ++ list_add_tail(&ref->list, &chan->ramht_refs); ++ instmem->flush(dev); ++ return 0; ++ } ++ NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n", ++ chan->id, co, nv_ro32(ramht, co)); ++ ++ co += 8; ++ if (co >= dev_priv->ramht_size) ++ co = 0; ++ } while (co != ho); ++ ++ NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id); ++ return -ENOMEM; ++} ++ ++void ++nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; ++ struct nouveau_channel *chan = ref->channel; ++ struct nouveau_gpuobj *ramht = chan->ramht ? chan->ramht->gpuobj : NULL; ++ uint32_t co, ho; ++ ++ if (!ramht) { ++ NV_ERROR(dev, "No hash table!\n"); ++ return; ++ } ++ ++ co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle); ++ do { ++ if (nouveau_ramht_entry_valid(dev, ramht, co) && ++ (ref->handle == nv_ro32(ramht, co))) { ++ NV_DEBUG(dev, ++ "remove ch%d 0x%08x: h=0x%08x, c=0x%08x\n", ++ chan->id, co, ref->handle, ++ nv_ro32(ramht, co + 4)); ++ nv_wo32(ramht, co + 0, 0x00000000); ++ nv_wo32(ramht, co + 4, 0x00000000); ++ ++ list_del(&ref->list); ++ instmem->flush(dev); ++ return; ++ } ++ ++ co += 8; ++ if (co >= dev_priv->ramht_size) ++ co = 0; ++ } while (co != ho); ++ list_del(&ref->list); ++ ++ NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", ++ chan->id, ref->handle); ++} +diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.h b/drivers/gpu/drm/nouveau/nouveau_ramht.h +new file mode 100644 +index 0000000..e10455c +--- /dev/null ++++ b/drivers/gpu/drm/nouveau/nouveau_ramht.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright 2010 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 ++ */ ++ ++#ifndef __NOUVEAU_RAMHT_H__ ++#define __NOUVEAU_RAMHT_H__ ++ ++extern int nouveau_ramht_insert(struct drm_device *, struct nouveau_gpuobj_ref *); ++extern void nouveau_ramht_remove(struct drm_device *, struct nouveau_gpuobj_ref *); ++ ++#endif +diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h +index 6ca80a3..21a6e45 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_reg.h ++++ b/drivers/gpu/drm/nouveau/nouveau_reg.h +@@ -1,19 +1,64 @@ + ++#define NV04_PFB_BOOT_0 0x00100000 ++# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003 ++# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000 ++# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001 ++# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002 ++# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003 ++# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004 ++# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020 ++# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028 ++# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100 ++# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000 ++#define NV04_PFB_DEBUG_0 0x00100080 ++# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001 ++# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010 ++# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00 ++# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000 ++# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000 ++# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000 ++# define NV04_PFB_DEBUG_0_CASOE 0x00100000 ++# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000 ++# define NV04_PFB_DEBUG_0_REFINC 0x20000000 ++# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000 ++#define NV04_PFB_CFG0 0x00100200 ++# define NV04_PFB_CFG0_SCRAMBLE 0x20000000 ++#define NV04_PFB_CFG1 0x00100204 ++#define NV04_PFB_FIFO_DATA 0x0010020c ++# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 ++# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 ++#define NV10_PFB_REFCTRL 0x00100210 ++# define NV10_PFB_REFCTRL_VALID_1 (1 << 31) ++#define NV04_PFB_PAD 0x0010021c ++# define NV04_PFB_PAD_CKE_NORMAL (1 << 0) ++#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) ++#define NV10_PFB_TILE__SIZE 8 ++#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) ++#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) ++#define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16)) ++#define NV04_PFB_REF 0x001002d0 ++# define NV04_PFB_REF_CMD_REFRESH (1 << 0) ++#define NV04_PFB_PRE 0x001002d4 ++# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) ++#define NV10_PFB_CLOSE_PAGE2 0x0010033c ++#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) ++#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) ++#define NV40_PFB_TILE__SIZE_0 12 ++#define NV40_PFB_TILE__SIZE_1 15 ++#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) ++#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) ++#define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16)) ++#define NV40_PFB_UNK_800 0x00100800 + +-#define NV03_BOOT_0 0x00100000 +-# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 +-# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 +-# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 +-# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002 +-# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003 +-# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000 +-# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001 +-# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002 +-# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003 +- +-#define NV04_FIFO_DATA 0x0010020c +-# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000 +-# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20 ++#define NV_PEXTDEV_BOOT_0 0x00101000 ++#define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c ++# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) ++#define NV_PEXTDEV_BOOT_3 0x0010100c + + #define NV_RAMIN 0x00700000 + +@@ -131,23 +176,6 @@ + #define NV04_PTIMER_TIME_1 0x00009410 + #define NV04_PTIMER_ALARM_0 0x00009420 + +-#define NV04_PFB_CFG0 0x00100200 +-#define NV04_PFB_CFG1 0x00100204 +-#define NV40_PFB_020C 0x0010020C +-#define NV10_PFB_TILE(i) (0x00100240 + (i*16)) +-#define NV10_PFB_TILE__SIZE 8 +-#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16)) +-#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16)) +-#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16)) +-#define NV10_PFB_CLOSE_PAGE2 0x0010033C +-#define NV40_PFB_TILE(i) (0x00100600 + (i*16)) +-#define NV40_PFB_TILE__SIZE_0 12 +-#define NV40_PFB_TILE__SIZE_1 15 +-#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16)) +-#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16)) +-#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16)) +-#define NV40_PFB_UNK_800 0x00100800 +- + #define NV04_PGRAPH_DEBUG_0 0x00400080 + #define NV04_PGRAPH_DEBUG_1 0x00400084 + #define NV04_PGRAPH_DEBUG_2 0x00400088 +@@ -192,28 +220,21 @@ + # define NV_PGRAPH_INTR_ERROR (1<<20) + #define NV10_PGRAPH_CTX_CONTROL 0x00400144 + #define NV10_PGRAPH_CTX_USER 0x00400148 +-#define NV10_PGRAPH_CTX_SWITCH1 0x0040014C +-#define NV10_PGRAPH_CTX_SWITCH2 0x00400150 +-#define NV10_PGRAPH_CTX_SWITCH3 0x00400154 +-#define NV10_PGRAPH_CTX_SWITCH4 0x00400158 +-#define NV10_PGRAPH_CTX_SWITCH5 0x0040015C ++#define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 -#define NV10_PGRAPH_CTX_CACHE1 0x00400160 +#define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ @@ -5479,7 +6900,7 @@ index 6ca80a3..21a6e45 100644 #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c -index 1d6ee8b..491767f 100644 +index 1d6ee8b..630988a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) @@ -5490,7 +6911,24 @@ index 1d6ee8b..491767f 100644 pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); nvbe->pte_start = pte; for (i = 0; i < nvbe->nr_pages; i++) { -@@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) +@@ -106,34 +105,23 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) + uint32_t offset_h = upper_32_bits(dma_offset); + + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { +- if (dev_priv->card_type < NV_50) +- nv_wo32(dev, gpuobj, pte++, offset_l | 3); +- else { +- nv_wo32(dev, gpuobj, pte++, offset_l | 0x21); +- nv_wo32(dev, gpuobj, pte++, offset_h & 0xff); ++ if (dev_priv->card_type < NV_50) { ++ nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); ++ pte += 1; ++ } else { ++ nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21); ++ nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff); ++ pte += 2; + } + dma_offset += NV_CTXDMA_PAGE_SIZE; } } @@ -5518,7 +6956,7 @@ index 1d6ee8b..491767f 100644 } nvbe->bound = true; -@@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be) +@@ -154,40 +142,28 @@ nouveau_sgdma_unbind(struct ttm_backend *be) if (!nvbe->bound) return 0; @@ -5526,7 +6964,22 @@ index 1d6ee8b..491767f 100644 pte = nvbe->pte_start; for (i = 0; i < nvbe->nr_pages; i++) { dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; -@@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be) + + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { +- if (dev_priv->card_type < NV_50) +- nv_wo32(dev, gpuobj, pte++, dma_offset | 3); +- else { +- nv_wo32(dev, gpuobj, pte++, dma_offset | 0x21); +- nv_wo32(dev, gpuobj, pte++, 0x00000000); ++ if (dev_priv->card_type < NV_50) { ++ nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3); ++ pte += 1; ++ } else { ++ nv_wo32(gpuobj, (pte * 4), dma_offset | 0x21); ++ nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000); ++ pte += 2; + } + dma_offset += NV_CTXDMA_PAGE_SIZE; } } @@ -5554,16 +7007,64 @@ index 1d6ee8b..491767f 100644 } nvbe->bound = false; -@@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev) - pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, +@@ -242,6 +218,7 @@ int + nouveau_sgdma_init(struct drm_device *dev) + { + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ struct pci_dev *pdev = dev->pdev; + struct nouveau_gpuobj *gpuobj = NULL; + uint32_t aper_size, obj_size; + int i, ret; +@@ -267,34 +244,42 @@ nouveau_sgdma_init(struct drm_device *dev) + + dev_priv->gart_info.sg_dummy_page = + alloc_page(GFP_KERNEL|__GFP_DMA32); ++ if (!dev_priv->gart_info.sg_dummy_page) { ++ nouveau_gpuobj_del(dev, &gpuobj); ++ return -ENOMEM; ++ } ++ + set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); + dev_priv->gart_info.sg_dummy_bus = +- pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, ++ pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); ++ if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { ++ nouveau_gpuobj_del(dev, &gpuobj); ++ return -EFAULT; ++ } - dev_priv->engine.instmem.prepare_access(dev, true); if (dev_priv->card_type < NV_50) { /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE -@@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev) - nv_wo32(dev, gpuobj, (i+4)/4, 0); + * on those cards? */ +- nv_wo32(dev, gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | +- (1 << 12) /* PT present */ | +- (0 << 13) /* PT *not* linear */ | +- (NV_DMA_ACCESS_RW << 14) | +- (NV_DMA_TARGET_PCI << 16)); +- nv_wo32(dev, gpuobj, 1, aper_size - 1); ++ nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | ++ (1 << 12) /* PT present */ | ++ (0 << 13) /* PT *not* linear */ | ++ (NV_DMA_ACCESS_RW << 14) | ++ (NV_DMA_TARGET_PCI << 16)); ++ nv_wo32(gpuobj, 4, aper_size - 1); + for (i = 2; i < 2 + (aper_size >> 12); i++) { +- nv_wo32(dev, gpuobj, i, +- dev_priv->gart_info.sg_dummy_bus | 3); ++ nv_wo32(gpuobj, i * 4, ++ dev_priv->gart_info.sg_dummy_bus | 3); + } + } else { + for (i = 0; i < obj_size; i += 8) { +- nv_wo32(dev, gpuobj, (i+0)/4, +- dev_priv->gart_info.sg_dummy_bus | 0x21); +- nv_wo32(dev, gpuobj, (i+4)/4, 0); ++ nv_wo32(gpuobj, i + 0, ++ dev_priv->gart_info.sg_dummy_bus | 0x21); ++ nv_wo32(gpuobj, i + 4, 0); } } - dev_priv->engine.instmem.finish_access(dev); @@ -5571,18 +7072,20 @@ index 1d6ee8b..491767f 100644 dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; dev_priv->gart_info.aper_base = 0; -@@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) +@@ -325,14 +310,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; int pte; - pte = (offset >> NV_CTXDMA_PAGE_SHIFT); +- pte = (offset >> NV_CTXDMA_PAGE_SHIFT); ++ pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2; if (dev_priv->card_type < NV_50) { - instmem->prepare_access(dev, false); - *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; +- *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; - instmem->finish_access(dev); ++ *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK; return 0; } @@ -6196,7 +7699,7 @@ index b02a231..989322b 100644 default: NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c -index eba687f..08c7e07 100644 +index eba687f..291a4cb 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) @@ -6228,8 +7731,25 @@ index eba687f..08c7e07 100644 regp->crtc_830 = mode->crtc_vdisplay - 3; regp->crtc_834 = mode->crtc_vdisplay - 1; +@@ -710,6 +718,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) + + drm_crtc_cleanup(crtc); + ++ nouveau_bo_unmap(nv_crtc->cursor.nvbo); + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + kfree(nv_crtc); + } +@@ -820,7 +829,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); + +- if (dev_priv->card_type >= NV_30) { ++ if (dev_priv->card_type >= NV_20) { + regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; + crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); + } diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c -index 1cb19e3..ea36270 100644 +index 1cb19e3..9cc560c 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) @@ -6271,7 +7791,16 @@ index 1cb19e3..ea36270 100644 /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ routput = (saved_routput & 0xfffffece) | head << 8; -@@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) +@@ -291,6 +291,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) + msleep(5); + + sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); ++ /* do it again just in case it's a residual current */ ++ sample &= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); + + temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, +@@ -304,8 +306,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); @@ -6282,7 +7811,7 @@ index 1cb19e3..ea36270 100644 return sample; } -@@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +@@ -315,9 +317,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; @@ -6297,7 +7826,7 @@ index 1cb19e3..ea36270 100644 NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; -@@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, +@@ -330,6 +335,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { @@ -6307,7 +7836,24 @@ index 1cb19e3..ea36270 100644 return true; } -@@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) +@@ -344,15 +352,9 @@ static void nv04_dac_prepare(struct drm_encoder *encoder) + helper->dpms(encoder, DRM_MODE_DPMS_OFF); + + nv04_dfp_disable(dev, head); +- +- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) +- * at LCD__INDEX which we don't alter +- */ +- if (!(crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] & 0x44)) +- crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0; ++ crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX] = 0; + } + +- + static void nv04_dac_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +@@ -428,6 +430,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) } } @@ -6325,7 +7871,7 @@ index 1cb19e3..ea36270 100644 static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; -@@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { +@@ -501,11 +514,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { .destroy = nv04_dac_destroy, }; @@ -6341,7 +7887,7 @@ index 1cb19e3..ea36270 100644 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); if (!nv_encoder) -@@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) +@@ -527,5 +542,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) encoder->possible_crtcs = entry->heads; encoder->possible_clones = 0; @@ -6349,7 +7895,7 @@ index 1cb19e3..ea36270 100644 return 0; } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c -index 41634d4..a5dcf76 100644 +index 41634d4..e331b4f 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -34,6 +34,8 @@ @@ -6398,30 +7944,118 @@ index 41634d4..a5dcf76 100644 static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) -@@ -413,10 +445,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) +@@ -221,26 +253,21 @@ static void nv04_dfp_prepare(struct drm_encoder *encoder) + + nv04_dfp_prepare_sel_clk(dev, nv_encoder, head); + +- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) +- * at LCD__INDEX which we don't alter +- */ +- if (!(*cr_lcd & 0x44)) { +- *cr_lcd = 0x3; +- +- if (nv_two_heads(dev)) { +- if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) +- *cr_lcd |= head ? 0x0 : 0x8; +- else { +- *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; +- if (nv_encoder->dcb->type == OUTPUT_LVDS) +- *cr_lcd |= 0x30; +- if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { +- /* avoid being connected to both crtcs */ +- *cr_lcd_oth &= ~0x30; +- NVWriteVgaCrtc(dev, head ^ 1, +- NV_CIO_CRE_LCD__INDEX, +- *cr_lcd_oth); +- } ++ *cr_lcd = 0x3; ++ ++ if (nv_two_heads(dev)) { ++ if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) ++ *cr_lcd |= head ? 0x0 : 0x8; ++ else { ++ *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; ++ if (nv_encoder->dcb->type == OUTPUT_LVDS) ++ *cr_lcd |= 0x30; ++ if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { ++ /* avoid being connected to both crtcs */ ++ *cr_lcd_oth &= ~0x30; ++ NVWriteVgaCrtc(dev, head ^ 1, ++ NV_CIO_CRE_LCD__INDEX, ++ *cr_lcd_oth); + } + } + } +@@ -412,10 +439,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct dcb_entry *dcbe = nv_encoder->dcb; int head = nouveau_crtc(encoder->crtc)->index; - +- - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); -- ++ struct drm_encoder *slave_encoder; + if (dcbe->type == OUTPUT_TMDS) run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); - else if (dcbe->type == OUTPUT_LVDS) -@@ -433,6 +461,11 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) +@@ -433,6 +457,12 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) else NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); + /* Init external transmitters */ -+ if (get_tmds_slave(encoder)) -+ get_slave_funcs(get_tmds_slave(encoder))->mode_set( -+ encoder, &nv_encoder->mode, &nv_encoder->mode); ++ slave_encoder = get_tmds_slave(encoder); ++ if (slave_encoder) ++ get_slave_funcs(slave_encoder)->mode_set( ++ slave_encoder, &nv_encoder->mode, &nv_encoder->mode); + helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", -@@ -554,10 +587,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) +@@ -440,6 +470,27 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + } + ++static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) ++{ ++#ifdef __powerpc__ ++ struct drm_device *dev = encoder->dev; ++ ++ /* BIOS scripts usually take care of the backlight, thanks ++ * Apple for your consistency. ++ */ ++ if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || ++ dev->pci_device == 0x0329) { ++ if (mode == DRM_MODE_DPMS_ON) { ++ nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); ++ nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 1); ++ } else { ++ nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); ++ nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 0); ++ } ++ } ++#endif ++} ++ + static inline bool is_powersaving_dpms(int mode) + { + return (mode != DRM_MODE_DPMS_ON); +@@ -487,6 +538,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) + LVDS_PANEL_OFF, 0); + } + ++ nv04_dfp_update_backlight(encoder, mode); + nv04_dfp_update_fp_control(encoder, mode); + + if (mode == DRM_MODE_DPMS_ON) +@@ -510,6 +562,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) + NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + mode, nv_encoder->dcb->index); + ++ nv04_dfp_update_backlight(encoder, mode); + nv04_dfp_update_fp_control(encoder, mode); + } + +@@ -554,10 +607,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) NV_DEBUG_KMS(encoder->dev, "\n"); @@ -6464,7 +8098,7 @@ index 41634d4..a5dcf76 100644 static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { .dpms = nv04_lvds_dpms, .save = nv04_dfp_save, -@@ -584,11 +649,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { +@@ -584,11 +669,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { .destroy = nv04_dfp_destroy, }; @@ -6479,7 +8113,7 @@ index 41634d4..a5dcf76 100644 int type; switch (entry->type) { -@@ -613,11 +679,16 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) +@@ -613,11 +699,16 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) nv_encoder->dcb = entry; nv_encoder->or = ffs(entry->or) - 1; @@ -6691,9 +8325,24 @@ index c7898b4..9e28cf7 100644 } diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c -index 66fe559..06cedd9 100644 +index 66fe559..bbb87ef 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c +@@ -38,10 +38,10 @@ + #define NV04_RAMFC_ENGINE 0x14 + #define NV04_RAMFC_PULL1_ENGINE 0x18 + +-#define RAMFC_WR(offset, val) nv_wo32(dev, chan->ramfc->gpuobj, \ +- NV04_RAMFC_##offset/4, (val)) +-#define RAMFC_RD(offset) nv_ro32(dev, chan->ramfc->gpuobj, \ +- NV04_RAMFC_##offset/4) ++#define RAMFC_WR(offset, val) nv_wo32(chan->ramfc->gpuobj, \ ++ NV04_RAMFC_##offset, (val)) ++#define RAMFC_RD(offset) nv_ro32(chan->ramfc->gpuobj, \ ++ NV04_RAMFC_##offset) + + void + nv04_fifo_disable(struct drm_device *dev) @@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev) NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; } @@ -7544,7 +9193,7 @@ index 2e58c33..0000000 - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c -index 74c8803..44fefb0 100644 +index 74c8803..703c188 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) @@ -7577,7 +9226,7 @@ index 74c8803..44fefb0 100644 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); -@@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) +@@ -110,12 +111,31 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); @@ -7593,10 +9242,14 @@ index 74c8803..44fefb0 100644 +get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) +{ + /* Zotac FX5200 */ -+ if (dev->pdev->device == 0x0322 && -+ dev->pdev->subsystem_vendor == 0x19da && -+ (dev->pdev->subsystem_device == 0x1035 || -+ dev->pdev->subsystem_device == 0x2035)) { ++ if (nv_match_device(dev, 0x0322, 0x19da, 0x1035) || ++ nv_match_device(dev, 0x0322, 0x19da, 0x2035)) { ++ *pin_mask = 0xc; ++ return false; ++ } ++ ++ /* MSI nForce2 IGP */ ++ if (nv_match_device(dev, 0x01f0, 0x1462, 0x5710)) { + *pin_mask = 0xc; + return false; + } @@ -7607,7 +9260,7 @@ index 74c8803..44fefb0 100644 static enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { -@@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) +@@ -124,12 +144,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct dcb_entry *dcb = tv_enc->base.dcb; @@ -7633,7 +9286,7 @@ index 74c8803..44fefb0 100644 switch (tv_enc->pin_mask) { case 0x2: -@@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) +@@ -154,7 +182,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) conf->tv_subconnector_property, tv_enc->subconnector); @@ -7644,7 +9297,7 @@ index 74c8803..44fefb0 100644 NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; -@@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, +@@ -296,6 +326,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, { struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); @@ -7654,7 +9307,7 @@ index 74c8803..44fefb0 100644 if (tv_norm->kind == CTV_ENC_MODE) adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; else -@@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, +@@ -307,6 +340,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; @@ -7663,7 +9316,7 @@ index 74c8803..44fefb0 100644 struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); -@@ -331,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) +@@ -331,8 +366,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) nv_load_ptv(dev, regs, 200); @@ -7674,7 +9327,27 @@ index 74c8803..44fefb0 100644 nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } -@@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = { +@@ -373,15 +408,10 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) + + } + +- /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) +- * at LCD__INDEX which we don't alter +- */ +- if (!(*cr_lcd & 0x44)) { +- if (tv_norm->kind == CTV_ENC_MODE) +- *cr_lcd = 0x1 | (head ? 0x0 : 0x8); +- else +- *cr_lcd = 0; +- } ++ if (tv_norm->kind == CTV_ENC_MODE) ++ *cr_lcd = 0x1 | (head ? 0x0 : 0x8); ++ else ++ *cr_lcd = 0; + + /* Set the DACCLK register */ + dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; +@@ -744,8 +774,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = { .destroy = nv17_tv_destroy, }; @@ -7686,7 +9359,7 @@ index 74c8803..44fefb0 100644 struct drm_encoder *encoder; struct nv17_tv_encoder *tv_enc = NULL; -@@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) +@@ -774,5 +806,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) encoder->possible_crtcs = entry->heads; encoder->possible_clones = 0; @@ -7695,9 +9368,573 @@ index 74c8803..44fefb0 100644 return 0; } diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c -index d6fc0a8..191c15c 100644 +index d6fc0a8..cc876ef 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c +@@ -37,49 +37,49 @@ nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x047c/4, 0x00000101); +- nv_wo32(dev, ctx, 0x0490/4, 0x00000111); +- nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); ++ nv_wo32(ctx, 0x033c, 0xffff0000); ++ nv_wo32(ctx, 0x03a0, 0x0fff0000); ++ nv_wo32(ctx, 0x03a4, 0x0fff0000); ++ nv_wo32(ctx, 0x047c, 0x00000101); ++ nv_wo32(ctx, 0x0490, 0x00000111); ++ nv_wo32(ctx, 0x04a8, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080000); ++ nv_wo32(ctx, i, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) +- nv_wo32(dev, ctx, i/4, 0x000105b8); ++ nv_wo32(ctx, i, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); ++ nv_wo32(ctx, i, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0604/4, 0x00004000); +- nv_wo32(dev, ctx, 0x0610/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0618/4, 0x00040000); +- nv_wo32(dev, ctx, 0x061c/4, 0x00010000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x05a4, 0x4b7fffff); ++ nv_wo32(ctx, 0x05fc, 0x00000001); ++ nv_wo32(ctx, 0x0604, 0x00004000); ++ nv_wo32(ctx, 0x0610, 0x00000001); ++ nv_wo32(ctx, 0x0618, 0x00040000); ++ nv_wo32(ctx, 0x061c, 0x00010000); + for (i = 0x1c1c; i <= 0x248c; i += 16) { +- nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); +- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); +- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); ++ nv_wo32(ctx, (i + 0), 0x10700ff9); ++ nv_wo32(ctx, (i + 4), 0x0436086c); ++ nv_wo32(ctx, (i + 8), 0x000c001b); + } +- nv_wo32(dev, ctx, 0x281c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2830/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x285c/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2860/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2864/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x286c/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2870/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2878/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x2880/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x34a4/4, 0x000fe000); +- nv_wo32(dev, ctx, 0x3530/4, 0x000003f8); +- nv_wo32(dev, ctx, 0x3540/4, 0x002fe000); ++ nv_wo32(ctx, 0x281c, 0x3f800000); ++ nv_wo32(ctx, 0x2830, 0x3f800000); ++ nv_wo32(ctx, 0x285c, 0x40000000); ++ nv_wo32(ctx, 0x2860, 0x3f800000); ++ nv_wo32(ctx, 0x2864, 0x3f000000); ++ nv_wo32(ctx, 0x286c, 0x40000000); ++ nv_wo32(ctx, 0x2870, 0x3f800000); ++ nv_wo32(ctx, 0x2878, 0xbf800000); ++ nv_wo32(ctx, 0x2880, 0xbf800000); ++ nv_wo32(ctx, 0x34a4, 0x000fe000); ++ nv_wo32(ctx, 0x3530, 0x000003f8); ++ nv_wo32(ctx, 0x3540, 0x002fe000); + for (i = 0x355c; i <= 0x3578; i += 4) +- nv_wo32(dev, ctx, i/4, 0x001c527c); ++ nv_wo32(ctx, i, 0x001c527c); + } + + static void +@@ -87,58 +87,58 @@ nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x035c/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x03c0/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x03c4/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x049c/4, 0x00000101); +- nv_wo32(dev, ctx, 0x04b0/4, 0x00000111); +- nv_wo32(dev, ctx, 0x04c8/4, 0x00000080); +- nv_wo32(dev, ctx, 0x04cc/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x04d0/4, 0x00000001); +- nv_wo32(dev, ctx, 0x04e4/4, 0x44400000); +- nv_wo32(dev, ctx, 0x04fc/4, 0x4b800000); ++ nv_wo32(ctx, 0x035c, 0xffff0000); ++ nv_wo32(ctx, 0x03c0, 0x0fff0000); ++ nv_wo32(ctx, 0x03c4, 0x0fff0000); ++ nv_wo32(ctx, 0x049c, 0x00000101); ++ nv_wo32(ctx, 0x04b0, 0x00000111); ++ nv_wo32(ctx, 0x04c8, 0x00000080); ++ nv_wo32(ctx, 0x04cc, 0xffff0000); ++ nv_wo32(ctx, 0x04d0, 0x00000001); ++ nv_wo32(ctx, 0x04e4, 0x44400000); ++ nv_wo32(ctx, 0x04fc, 0x4b800000); + for (i = 0x0510; i <= 0x051c; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x0530; i <= 0x053c; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080000); ++ nv_wo32(ctx, i, 0x00080000); + for (i = 0x0548; i <= 0x0554; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x0558; i <= 0x0564; i += 4) +- nv_wo32(dev, ctx, i/4, 0x000105b8); ++ nv_wo32(ctx, i, 0x000105b8); + for (i = 0x0568; i <= 0x0574; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); ++ nv_wo32(ctx, i, 0x00080008); + for (i = 0x0598; i <= 0x05d4; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x05e0/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x0620/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0624/4, 0x30201000); +- nv_wo32(dev, ctx, 0x0628/4, 0x70605040); +- nv_wo32(dev, ctx, 0x062c/4, 0xb0a09080); +- nv_wo32(dev, ctx, 0x0630/4, 0xf0e0d0c0); +- nv_wo32(dev, ctx, 0x0664/4, 0x00000001); +- nv_wo32(dev, ctx, 0x066c/4, 0x00004000); +- nv_wo32(dev, ctx, 0x0678/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0680/4, 0x00040000); +- nv_wo32(dev, ctx, 0x0684/4, 0x00010000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x05e0, 0x4b7fffff); ++ nv_wo32(ctx, 0x0620, 0x00000080); ++ nv_wo32(ctx, 0x0624, 0x30201000); ++ nv_wo32(ctx, 0x0628, 0x70605040); ++ nv_wo32(ctx, 0x062c, 0xb0a09080); ++ nv_wo32(ctx, 0x0630, 0xf0e0d0c0); ++ nv_wo32(ctx, 0x0664, 0x00000001); ++ nv_wo32(ctx, 0x066c, 0x00004000); ++ nv_wo32(ctx, 0x0678, 0x00000001); ++ nv_wo32(ctx, 0x0680, 0x00040000); ++ nv_wo32(ctx, 0x0684, 0x00010000); + for (i = 0x1b04; i <= 0x2374; i += 16) { +- nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); +- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); +- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); ++ nv_wo32(ctx, (i + 0), 0x10700ff9); ++ nv_wo32(ctx, (i + 4), 0x0436086c); ++ nv_wo32(ctx, (i + 8), 0x000c001b); + } +- nv_wo32(dev, ctx, 0x2704/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2718/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2744/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2748/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x274c/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x2754/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2758/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2760/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x2768/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x308c/4, 0x000fe000); +- nv_wo32(dev, ctx, 0x3108/4, 0x000003f8); +- nv_wo32(dev, ctx, 0x3468/4, 0x002fe000); ++ nv_wo32(ctx, 0x2704, 0x3f800000); ++ nv_wo32(ctx, 0x2718, 0x3f800000); ++ nv_wo32(ctx, 0x2744, 0x40000000); ++ nv_wo32(ctx, 0x2748, 0x3f800000); ++ nv_wo32(ctx, 0x274c, 0x3f000000); ++ nv_wo32(ctx, 0x2754, 0x40000000); ++ nv_wo32(ctx, 0x2758, 0x3f800000); ++ nv_wo32(ctx, 0x2760, 0xbf800000); ++ nv_wo32(ctx, 0x2768, 0xbf800000); ++ nv_wo32(ctx, 0x308c, 0x000fe000); ++ nv_wo32(ctx, 0x3108, 0x000003f8); ++ nv_wo32(ctx, 0x3468, 0x002fe000); + for (i = 0x3484; i <= 0x34a0; i += 4) +- nv_wo32(dev, ctx, i/4, 0x001c527c); ++ nv_wo32(ctx, i, 0x001c527c); + } + + static void +@@ -146,49 +146,49 @@ nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x033c/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x03a0/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x03a4/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x047c/4, 0x00000101); +- nv_wo32(dev, ctx, 0x0490/4, 0x00000111); +- nv_wo32(dev, ctx, 0x04a8/4, 0x44400000); ++ nv_wo32(ctx, 0x033c, 0xffff0000); ++ nv_wo32(ctx, 0x03a0, 0x0fff0000); ++ nv_wo32(ctx, 0x03a4, 0x0fff0000); ++ nv_wo32(ctx, 0x047c, 0x00000101); ++ nv_wo32(ctx, 0x0490, 0x00000111); ++ nv_wo32(ctx, 0x04a8, 0x44400000); + for (i = 0x04d4; i <= 0x04e0; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x04f4; i <= 0x0500; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080000); ++ nv_wo32(ctx, i, 0x00080000); + for (i = 0x050c; i <= 0x0518; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x051c; i <= 0x0528; i += 4) +- nv_wo32(dev, ctx, i/4, 0x000105b8); ++ nv_wo32(ctx, i, 0x000105b8); + for (i = 0x052c; i <= 0x0538; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); ++ nv_wo32(ctx, i, 0x00080008); + for (i = 0x055c; i <= 0x0598; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x05a4/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x05fc/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0604/4, 0x00004000); +- nv_wo32(dev, ctx, 0x0610/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0618/4, 0x00040000); +- nv_wo32(dev, ctx, 0x061c/4, 0x00010000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x05a4, 0x4b7fffff); ++ nv_wo32(ctx, 0x05fc, 0x00000001); ++ nv_wo32(ctx, 0x0604, 0x00004000); ++ nv_wo32(ctx, 0x0610, 0x00000001); ++ nv_wo32(ctx, 0x0618, 0x00040000); ++ nv_wo32(ctx, 0x061c, 0x00010000); + for (i = 0x1a9c; i <= 0x22fc; i += 16) { /*XXX: check!! */ +- nv_wo32(dev, ctx, (i + 0)/4, 0x10700ff9); +- nv_wo32(dev, ctx, (i + 4)/4, 0x0436086c); +- nv_wo32(dev, ctx, (i + 8)/4, 0x000c001b); ++ nv_wo32(ctx, (i + 0), 0x10700ff9); ++ nv_wo32(ctx, (i + 4), 0x0436086c); ++ nv_wo32(ctx, (i + 8), 0x000c001b); + } +- nv_wo32(dev, ctx, 0x269c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x26b0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x26dc/4, 0x40000000); +- nv_wo32(dev, ctx, 0x26e0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x26e4/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x26ec/4, 0x40000000); +- nv_wo32(dev, ctx, 0x26f0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x26f8/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x2700/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x3024/4, 0x000fe000); +- nv_wo32(dev, ctx, 0x30a0/4, 0x000003f8); +- nv_wo32(dev, ctx, 0x33fc/4, 0x002fe000); ++ nv_wo32(ctx, 0x269c, 0x3f800000); ++ nv_wo32(ctx, 0x26b0, 0x3f800000); ++ nv_wo32(ctx, 0x26dc, 0x40000000); ++ nv_wo32(ctx, 0x26e0, 0x3f800000); ++ nv_wo32(ctx, 0x26e4, 0x3f000000); ++ nv_wo32(ctx, 0x26ec, 0x40000000); ++ nv_wo32(ctx, 0x26f0, 0x3f800000); ++ nv_wo32(ctx, 0x26f8, 0xbf800000); ++ nv_wo32(ctx, 0x2700, 0xbf800000); ++ nv_wo32(ctx, 0x3024, 0x000fe000); ++ nv_wo32(ctx, 0x30a0, 0x000003f8); ++ nv_wo32(ctx, 0x33fc, 0x002fe000); + for (i = 0x341c; i <= 0x3438; i += 4) +- nv_wo32(dev, ctx, i/4, 0x001c527c); ++ nv_wo32(ctx, i, 0x001c527c); + } + + static void +@@ -196,57 +196,57 @@ nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x0410/4, 0x00000101); +- nv_wo32(dev, ctx, 0x0424/4, 0x00000111); +- nv_wo32(dev, ctx, 0x0428/4, 0x00000060); +- nv_wo32(dev, ctx, 0x0444/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0448/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x044c/4, 0x00000001); +- nv_wo32(dev, ctx, 0x0460/4, 0x44400000); +- nv_wo32(dev, ctx, 0x048c/4, 0xffff0000); ++ nv_wo32(ctx, 0x0410, 0x00000101); ++ nv_wo32(ctx, 0x0424, 0x00000111); ++ nv_wo32(ctx, 0x0428, 0x00000060); ++ nv_wo32(ctx, 0x0444, 0x00000080); ++ nv_wo32(ctx, 0x0448, 0xffff0000); ++ nv_wo32(ctx, 0x044c, 0x00000001); ++ nv_wo32(ctx, 0x0460, 0x44400000); ++ nv_wo32(ctx, 0x048c, 0xffff0000); + for (i = 0x04e0; i < 0x04e8; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x04ec/4, 0x00011100); ++ nv_wo32(ctx, i, 0x0fff0000); ++ nv_wo32(ctx, 0x04ec, 0x00011100); + for (i = 0x0508; i < 0x0548; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x0550/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x058c/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0590/4, 0x30201000); +- nv_wo32(dev, ctx, 0x0594/4, 0x70605040); +- nv_wo32(dev, ctx, 0x0598/4, 0xb8a89888); +- nv_wo32(dev, ctx, 0x059c/4, 0xf8e8d8c8); +- nv_wo32(dev, ctx, 0x05b0/4, 0xb0000000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x0550, 0x4b7fffff); ++ nv_wo32(ctx, 0x058c, 0x00000080); ++ nv_wo32(ctx, 0x0590, 0x30201000); ++ nv_wo32(ctx, 0x0594, 0x70605040); ++ nv_wo32(ctx, 0x0598, 0xb8a89888); ++ nv_wo32(ctx, 0x059c, 0xf8e8d8c8); ++ nv_wo32(ctx, 0x05b0, 0xb0000000); + for (i = 0x0600; i < 0x0640; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00010588); ++ nv_wo32(ctx, i, 0x00010588); + for (i = 0x0640; i < 0x0680; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x06c0; i < 0x0700; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0008aae4); ++ nv_wo32(ctx, i, 0x0008aae4); + for (i = 0x0700; i < 0x0740; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x0740; i < 0x0780; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); +- nv_wo32(dev, ctx, 0x085c/4, 0x00040000); +- nv_wo32(dev, ctx, 0x0860/4, 0x00010000); ++ nv_wo32(ctx, i, 0x00080008); ++ nv_wo32(ctx, 0x085c, 0x00040000); ++ nv_wo32(ctx, 0x0860, 0x00010000); + for (i = 0x0864; i < 0x0874; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00040004); ++ nv_wo32(ctx, i, 0x00040004); + for (i = 0x1f18; i <= 0x3088 ; i += 16) { +- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); +- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); +- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); ++ nv_wo32(ctx, i + 0, 0x10700ff9); ++ nv_wo32(ctx, i + 1, 0x0436086c); ++ nv_wo32(ctx, i + 2, 0x000c001b); + } + for (i = 0x30b8; i < 0x30c8; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0000ffff); +- nv_wo32(dev, ctx, 0x344c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3808/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x381c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3848/4, 0x40000000); +- nv_wo32(dev, ctx, 0x384c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3850/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x3858/4, 0x40000000); +- nv_wo32(dev, ctx, 0x385c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3864/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x386c/4, 0xbf800000); ++ nv_wo32(ctx, i, 0x0000ffff); ++ nv_wo32(ctx, 0x344c, 0x3f800000); ++ nv_wo32(ctx, 0x3808, 0x3f800000); ++ nv_wo32(ctx, 0x381c, 0x3f800000); ++ nv_wo32(ctx, 0x3848, 0x40000000); ++ nv_wo32(ctx, 0x384c, 0x3f800000); ++ nv_wo32(ctx, 0x3850, 0x3f000000); ++ nv_wo32(ctx, 0x3858, 0x40000000); ++ nv_wo32(ctx, 0x385c, 0x3f800000); ++ nv_wo32(ctx, 0x3864, 0xbf800000); ++ nv_wo32(ctx, 0x386c, 0xbf800000); + } + + static void +@@ -254,57 +254,57 @@ nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x040c/4, 0x01000101); +- nv_wo32(dev, ctx, 0x0420/4, 0x00000111); +- nv_wo32(dev, ctx, 0x0424/4, 0x00000060); +- nv_wo32(dev, ctx, 0x0440/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x0448/4, 0x00000001); +- nv_wo32(dev, ctx, 0x045c/4, 0x44400000); +- nv_wo32(dev, ctx, 0x0480/4, 0xffff0000); ++ nv_wo32(ctx, 0x040c, 0x01000101); ++ nv_wo32(ctx, 0x0420, 0x00000111); ++ nv_wo32(ctx, 0x0424, 0x00000060); ++ nv_wo32(ctx, 0x0440, 0x00000080); ++ nv_wo32(ctx, 0x0444, 0xffff0000); ++ nv_wo32(ctx, 0x0448, 0x00000001); ++ nv_wo32(ctx, 0x045c, 0x44400000); ++ nv_wo32(ctx, 0x0480, 0xffff0000); + for (i = 0x04d4; i < 0x04dc; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x04e0/4, 0x00011100); ++ nv_wo32(ctx, i, 0x0fff0000); ++ nv_wo32(ctx, 0x04e0, 0x00011100); + for (i = 0x04fc; i < 0x053c; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x0544/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x057c/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0580/4, 0x30201000); +- nv_wo32(dev, ctx, 0x0584/4, 0x70605040); +- nv_wo32(dev, ctx, 0x0588/4, 0xb8a89888); +- nv_wo32(dev, ctx, 0x058c/4, 0xf8e8d8c8); +- nv_wo32(dev, ctx, 0x05a0/4, 0xb0000000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x0544, 0x4b7fffff); ++ nv_wo32(ctx, 0x057c, 0x00000080); ++ nv_wo32(ctx, 0x0580, 0x30201000); ++ nv_wo32(ctx, 0x0584, 0x70605040); ++ nv_wo32(ctx, 0x0588, 0xb8a89888); ++ nv_wo32(ctx, 0x058c, 0xf8e8d8c8); ++ nv_wo32(ctx, 0x05a0, 0xb0000000); + for (i = 0x05f0; i < 0x0630; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00010588); ++ nv_wo32(ctx, i, 0x00010588); + for (i = 0x0630; i < 0x0670; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x06b0; i < 0x06f0; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0008aae4); ++ nv_wo32(ctx, i, 0x0008aae4); + for (i = 0x06f0; i < 0x0730; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x0730; i < 0x0770; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); +- nv_wo32(dev, ctx, 0x0850/4, 0x00040000); +- nv_wo32(dev, ctx, 0x0854/4, 0x00010000); ++ nv_wo32(ctx, i, 0x00080008); ++ nv_wo32(ctx, 0x0850, 0x00040000); ++ nv_wo32(ctx, 0x0854, 0x00010000); + for (i = 0x0858; i < 0x0868; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00040004); ++ nv_wo32(ctx, i, 0x00040004); + for (i = 0x15ac; i <= 0x271c ; i += 16) { +- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); +- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); +- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); ++ nv_wo32(ctx, i + 0, 0x10700ff9); ++ nv_wo32(ctx, i + 1, 0x0436086c); ++ nv_wo32(ctx, i + 2, 0x000c001b); + } + for (i = 0x274c; i < 0x275c; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0000ffff); +- nv_wo32(dev, ctx, 0x2ae0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2e9c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2eb0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2edc/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2ee0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2ee4/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x2eec/4, 0x40000000); +- nv_wo32(dev, ctx, 0x2ef0/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x2ef8/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x2f00/4, 0xbf800000); ++ nv_wo32(ctx, i, 0x0000ffff); ++ nv_wo32(ctx, 0x2ae0, 0x3f800000); ++ nv_wo32(ctx, 0x2e9c, 0x3f800000); ++ nv_wo32(ctx, 0x2eb0, 0x3f800000); ++ nv_wo32(ctx, 0x2edc, 0x40000000); ++ nv_wo32(ctx, 0x2ee0, 0x3f800000); ++ nv_wo32(ctx, 0x2ee4, 0x3f000000); ++ nv_wo32(ctx, 0x2eec, 0x40000000); ++ nv_wo32(ctx, 0x2ef0, 0x3f800000); ++ nv_wo32(ctx, 0x2ef8, 0xbf800000); ++ nv_wo32(ctx, 0x2f00, 0xbf800000); + } + + static void +@@ -312,57 +312,57 @@ nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) + { + int i; + +- nv_wo32(dev, ctx, 0x040c/4, 0x00000101); +- nv_wo32(dev, ctx, 0x0420/4, 0x00000111); +- nv_wo32(dev, ctx, 0x0424/4, 0x00000060); +- nv_wo32(dev, ctx, 0x0440/4, 0x00000080); +- nv_wo32(dev, ctx, 0x0444/4, 0xffff0000); +- nv_wo32(dev, ctx, 0x0448/4, 0x00000001); +- nv_wo32(dev, ctx, 0x045c/4, 0x44400000); +- nv_wo32(dev, ctx, 0x0488/4, 0xffff0000); ++ nv_wo32(ctx, 0x040c, 0x00000101); ++ nv_wo32(ctx, 0x0420, 0x00000111); ++ nv_wo32(ctx, 0x0424, 0x00000060); ++ nv_wo32(ctx, 0x0440, 0x00000080); ++ nv_wo32(ctx, 0x0444, 0xffff0000); ++ nv_wo32(ctx, 0x0448, 0x00000001); ++ nv_wo32(ctx, 0x045c, 0x44400000); ++ nv_wo32(ctx, 0x0488, 0xffff0000); + for (i = 0x04dc; i < 0x04e4; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0fff0000); +- nv_wo32(dev, ctx, 0x04e8/4, 0x00011100); ++ nv_wo32(ctx, i, 0x0fff0000); ++ nv_wo32(ctx, 0x04e8, 0x00011100); + for (i = 0x0504; i < 0x0544; i += 4) +- nv_wo32(dev, ctx, i/4, 0x07ff0000); +- nv_wo32(dev, ctx, 0x054c/4, 0x4b7fffff); +- nv_wo32(dev, ctx, 0x0588/4, 0x00000080); +- nv_wo32(dev, ctx, 0x058c/4, 0x30201000); +- nv_wo32(dev, ctx, 0x0590/4, 0x70605040); +- nv_wo32(dev, ctx, 0x0594/4, 0xb8a89888); +- nv_wo32(dev, ctx, 0x0598/4, 0xf8e8d8c8); +- nv_wo32(dev, ctx, 0x05ac/4, 0xb0000000); ++ nv_wo32(ctx, i, 0x07ff0000); ++ nv_wo32(ctx, 0x054c, 0x4b7fffff); ++ nv_wo32(ctx, 0x0588, 0x00000080); ++ nv_wo32(ctx, 0x058c, 0x30201000); ++ nv_wo32(ctx, 0x0590, 0x70605040); ++ nv_wo32(ctx, 0x0594, 0xb8a89888); ++ nv_wo32(ctx, 0x0598, 0xf8e8d8c8); ++ nv_wo32(ctx, 0x05ac, 0xb0000000); + for (i = 0x0604; i < 0x0644; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00010588); ++ nv_wo32(ctx, i, 0x00010588); + for (i = 0x0644; i < 0x0684; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00030303); ++ nv_wo32(ctx, i, 0x00030303); + for (i = 0x06c4; i < 0x0704; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0008aae4); ++ nv_wo32(ctx, i, 0x0008aae4); + for (i = 0x0704; i < 0x0744; i += 4) +- nv_wo32(dev, ctx, i/4, 0x01012000); ++ nv_wo32(ctx, i, 0x01012000); + for (i = 0x0744; i < 0x0784; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00080008); +- nv_wo32(dev, ctx, 0x0860/4, 0x00040000); +- nv_wo32(dev, ctx, 0x0864/4, 0x00010000); ++ nv_wo32(ctx, i, 0x00080008); ++ nv_wo32(ctx, 0x0860, 0x00040000); ++ nv_wo32(ctx, 0x0864, 0x00010000); + for (i = 0x0868; i < 0x0878; i += 4) +- nv_wo32(dev, ctx, i/4, 0x00040004); ++ nv_wo32(ctx, i, 0x00040004); + for (i = 0x1f1c; i <= 0x308c ; i += 16) { +- nv_wo32(dev, ctx, i/4 + 0, 0x10700ff9); +- nv_wo32(dev, ctx, i/4 + 1, 0x0436086c); +- nv_wo32(dev, ctx, i/4 + 2, 0x000c001b); ++ nv_wo32(ctx, i + 0, 0x10700ff9); ++ nv_wo32(ctx, i + 4, 0x0436086c); ++ nv_wo32(ctx, i + 8, 0x000c001b); + } + for (i = 0x30bc; i < 0x30cc; i += 4) +- nv_wo32(dev, ctx, i/4, 0x0000ffff); +- nv_wo32(dev, ctx, 0x3450/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x380c/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3820/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x384c/4, 0x40000000); +- nv_wo32(dev, ctx, 0x3850/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3854/4, 0x3f000000); +- nv_wo32(dev, ctx, 0x385c/4, 0x40000000); +- nv_wo32(dev, ctx, 0x3860/4, 0x3f800000); +- nv_wo32(dev, ctx, 0x3868/4, 0xbf800000); +- nv_wo32(dev, ctx, 0x3870/4, 0xbf800000); ++ nv_wo32(ctx, i, 0x0000ffff); ++ nv_wo32(ctx, 0x3450, 0x3f800000); ++ nv_wo32(ctx, 0x380c, 0x3f800000); ++ nv_wo32(ctx, 0x3820, 0x3f800000); ++ nv_wo32(ctx, 0x384c, 0x40000000); ++ nv_wo32(ctx, 0x3850, 0x3f800000); ++ nv_wo32(ctx, 0x3854, 0x3f000000); ++ nv_wo32(ctx, 0x385c, 0x40000000); ++ nv_wo32(ctx, 0x3860, 0x3f800000); ++ nv_wo32(ctx, 0x3868, 0xbf800000); ++ nv_wo32(ctx, 0x3870, 0xbf800000); + } + + int @@ -370,68 +370,54 @@ nv20_graph_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; @@ -7705,7 +9942,8 @@ index d6fc0a8..191c15c 100644 + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *); - unsigned int ctx_size; - unsigned int idoffs = 0x28/4; +- unsigned int idoffs = 0x28/4; ++ unsigned int idoffs = 0x28; int ret; switch (dev_priv->chipset) { @@ -7762,15 +10000,17 @@ index d6fc0a8..191c15c 100644 ctx_init(dev, chan->ramin_grctx->gpuobj); /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ - nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, - (chan->id << 24) | 0x1); /* CTX_USER */ +- nv_wo32(dev, chan->ramin_grctx->gpuobj, idoffs, +- (chan->id << 24) | 0x1); /* CTX_USER */ ++ nv_wo32(chan->ramin_grctx->gpuobj, idoffs, ++ (chan->id << 24) | 0x1); /* CTX_USER */ - nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, - chan->ramin_grctx->instance >> 4); - - dev_priv->engine.instmem.finish_access(dev); -+ nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, -+ chan->ramin_grctx->instance >> 4); ++ nv_wo32(pgraph->ctx_table->gpuobj, chan->id * 4, ++ chan->ramin_grctx->instance >> 4); return 0; } @@ -7786,7 +10026,7 @@ index d6fc0a8..191c15c 100644 - dev_priv->engine.instmem.prepare_access(dev, true); - nv_wo32(dev, dev_priv->ctx_table->gpuobj, chan->id, 0); - dev_priv->engine.instmem.finish_access(dev); -+ nv_wo32(dev, pgraph->ctx_table->gpuobj, chan->id, 0); ++ nv_wo32(pgraph->ctx_table->gpuobj, chan->id * 4, 0); } int @@ -8059,7 +10299,7 @@ index 500ccfd..2b67f18 100644 nv40_fifo_do_load_context(dev, pfifo->channels - 1); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c -index 704a25d..ef550ce 100644 +index 704a25d..f7b59ad 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -58,6 +58,7 @@ nv40_graph_create_context(struct nouveau_channel *chan) @@ -8085,14 +10325,16 @@ index 704a25d..ef550ce 100644 - } else { - nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj); - } +- nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, +- chan->ramin_grctx->gpuobj->im_pramin->start); +- dev_priv->engine.instmem.finish_access(dev); + ctx.dev = chan->dev; + ctx.mode = NOUVEAU_GRCTX_VALS; + ctx.data = chan->ramin_grctx->gpuobj; + nv40_grctx_init(&ctx); + - nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, - chan->ramin_grctx->gpuobj->im_pramin->start); -- dev_priv->engine.instmem.finish_access(dev); ++ nv_wo32(chan->ramin_grctx->gpuobj, 0, ++ chan->ramin_grctx->gpuobj->im_pramin->start); return 0; } @@ -8160,6 +10402,27 @@ index 704a25d..ef550ce 100644 } struct nouveau_pgraph_object_class nv40_graph_grclass[] = { +diff --git a/drivers/gpu/drm/nouveau/nv40_grctx.c b/drivers/gpu/drm/nouveau/nv40_grctx.c +index 9b5c974..ce58509 100644 +--- a/drivers/gpu/drm/nouveau/nv40_grctx.c ++++ b/drivers/gpu/drm/nouveau/nv40_grctx.c +@@ -596,13 +596,13 @@ nv40_graph_construct_shader(struct nouveau_grctx *ctx) + + offset += 0x0280/4; + for (i = 0; i < 16; i++, offset += 2) +- nv_wo32(dev, obj, offset, 0x3f800000); ++ nv_wo32(obj, offset * 4, 0x3f800000); + + for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { + for (i = 0; i < vs_nr_b0 * 6; i += 6) +- nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001); ++ nv_wo32(obj, (offset + b0_offset + i) * 4, 0x00000001); + for (i = 0; i < vs_nr_b1 * 4; i += 4) +- nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000); ++ nv_wo32(obj, (offset + b1_offset + i) * 4, 0x3f800000); + } + } + diff --git a/drivers/gpu/drm/nouveau/nv40_mc.c b/drivers/gpu/drm/nouveau/nv40_mc.c index 2a3495e..e4e72c1 100644 --- a/drivers/gpu/drm/nouveau/nv40_mc.c @@ -8174,7 +10437,7 @@ index 2a3495e..e4e72c1 100644 nv_wr32(dev, NV40_PMC_1704, 0); nv_wr32(dev, NV40_PMC_1708, 0); diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c -index b4e4a3b..a438e56 100644 +index b4e4a3b..2423c92 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -264,11 +264,16 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) @@ -8224,7 +10487,17 @@ index b4e4a3b..a438e56 100644 } return 0; -@@ -440,47 +457,15 @@ nv50_crtc_prepare(struct drm_crtc *crtc) +@@ -321,7 +338,9 @@ nv50_crtc_destroy(struct drm_crtc *crtc) + + 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); + nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + kfree(nv_crtc->mode); + kfree(nv_crtc); +@@ -440,47 +459,15 @@ nv50_crtc_prepare(struct drm_crtc *crtc) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -8272,7 +10545,7 @@ index b4e4a3b..a438e56 100644 struct drm_device *dev = crtc->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *evo = dev_priv->evo; -@@ -491,20 +476,14 @@ nv50_crtc_commit(struct drm_crtc *crtc) +@@ -491,20 +478,14 @@ nv50_crtc_commit(struct drm_crtc *crtc) nv50_crtc_blank(nv_crtc, false); @@ -8406,30 +10679,43 @@ index 1fd9537..1bc0859 100644 } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c -index 580a5d1..612fa6d 100644 +index 580a5d1..435d2b7 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c -@@ -71,14 +71,16 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, +@@ -42,6 +42,7 @@ nv50_evo_channel_del(struct nouveau_channel **pchan) + *pchan = NULL; + + nouveau_gpuobj_channel_takedown(chan); ++ nouveau_bo_unmap(chan->pushbuf_bo); + nouveau_bo_ref(NULL, &chan->pushbuf_bo); + + if (chan->user) +@@ -71,14 +72,16 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, return ret; } - dev_priv->engine.instmem.prepare_access(dev, true); - nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); - nv_wo32(dev, obj, 1, limit); - nv_wo32(dev, obj, 2, offset); - nv_wo32(dev, obj, 3, 0x00000000); - nv_wo32(dev, obj, 4, 0x00000000); +- nv_wo32(dev, obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); +- nv_wo32(dev, obj, 1, limit); +- nv_wo32(dev, obj, 2, offset); +- nv_wo32(dev, obj, 3, 0x00000000); +- nv_wo32(dev, obj, 4, 0x00000000); - nv_wo32(dev, obj, 5, 0x00010000); - dev_priv->engine.instmem.finish_access(dev); ++ nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); ++ nv_wo32(obj, 4, limit); ++ nv_wo32(obj, 8, offset); ++ nv_wo32(obj, 12, 0x00000000); ++ nv_wo32(obj, 16, 0x00000000); + if (dev_priv->card_type < NV_C0) -+ nv_wo32(dev, obj, 5, 0x00010000); ++ nv_wo32(obj, 20, 0x00010000); + else -+ nv_wo32(dev, obj, 5, 0x00020000); ++ nv_wo32(obj, 20, 0x00020000); + dev_priv->engine.instmem.flush(dev); return 0; } -@@ -110,8 +112,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) +@@ -110,8 +113,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) return ret; } @@ -8440,7 +10726,7 @@ index 580a5d1..612fa6d 100644 if (ret) { NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); nv50_evo_channel_del(pchan); -@@ -179,13 +181,25 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) +@@ -179,13 +182,25 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) } int @@ -8467,7 +10753,7 @@ index 580a5d1..612fa6d 100644 uint64_t start; int ret, i; -@@ -366,26 +380,13 @@ nv50_display_init(struct drm_device *dev) +@@ -366,26 +381,13 @@ nv50_display_init(struct drm_device *dev) NV50_PDISPLAY_INTR_EN_CLK_UNK40)); /* enable hotplug interrupts */ @@ -8495,7 +10781,7 @@ index 580a5d1..612fa6d 100644 } return 0; -@@ -465,6 +466,7 @@ int nv50_display_create(struct drm_device *dev) +@@ -465,6 +467,7 @@ int nv50_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct dcb_table *dcb = &dev_priv->vbios.dcb; @@ -8503,7 +10789,7 @@ index 580a5d1..612fa6d 100644 int ret, i; NV_DEBUG_KMS(dev, "\n"); -@@ -507,14 +509,18 @@ int nv50_display_create(struct drm_device *dev) +@@ -507,14 +510,18 @@ int nv50_display_create(struct drm_device *dev) continue; } @@ -8524,7 +10810,7 @@ index 580a5d1..612fa6d 100644 break; default: NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); -@@ -522,11 +528,13 @@ int nv50_display_create(struct drm_device *dev) +@@ -522,11 +529,13 @@ int nv50_display_create(struct drm_device *dev) } } @@ -8543,7 +10829,7 @@ index 580a5d1..612fa6d 100644 } ret = nv50_display_init(dev); -@@ -538,7 +546,8 @@ int nv50_display_create(struct drm_device *dev) +@@ -538,7 +547,8 @@ int nv50_display_create(struct drm_device *dev) return 0; } @@ -8553,7 +10839,7 @@ index 580a5d1..612fa6d 100644 { struct drm_nouveau_private *dev_priv = dev->dev_private; -@@ -548,135 +557,30 @@ int nv50_display_destroy(struct drm_device *dev) +@@ -548,135 +558,30 @@ int nv50_display_destroy(struct drm_device *dev) nv50_display_disable(dev); nv50_evo_channel_del(&dev_priv->evo); @@ -8696,7 +10982,7 @@ index 580a5d1..612fa6d 100644 case OUTPUT_LVDS: script = (mc >> 8) & 0xf; if (bios->fp_no_ddc) { -@@ -767,17 +671,88 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) +@@ -767,17 +672,88 @@ nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) static void nv50_display_unk10_handler(struct drm_device *dev) { @@ -8791,7 +11077,7 @@ index 580a5d1..612fa6d 100644 ack: nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); nv_wr32(dev, 0x610030, 0x80000000); -@@ -817,33 +792,103 @@ nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) +@@ -817,33 +793,103 @@ nv50_display_unk20_dp_hack(struct drm_device *dev, struct dcb_entry *dcb) static void nv50_display_unk20_handler(struct drm_device *dev) { @@ -8913,7 +11199,7 @@ index 580a5d1..612fa6d 100644 tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); tmp &= ~0x00000f0f; if (script & 0x0100) -@@ -853,24 +898,61 @@ nv50_display_unk20_handler(struct drm_device *dev) +@@ -853,24 +899,61 @@ nv50_display_unk20_handler(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); } @@ -9000,11 +11286,58 @@ index 581d405..c551f0b 100644 int nv50_crtc_blank(struct nouveau_crtc *, bool blank); int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); +diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c +index 32611bd..ad267c5 100644 +--- a/drivers/gpu/drm/nouveau/nv50_fb.c ++++ b/drivers/gpu/drm/nouveau/nv50_fb.c +@@ -36,3 +36,42 @@ void + nv50_fb_takedown(struct drm_device *dev) + { + } ++ ++void ++nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) ++{ ++ struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 trap[6], idx, chinst; ++ int i, ch; ++ ++ idx = nv_rd32(dev, 0x100c90); ++ if (!(idx & 0x80000000)) ++ return; ++ idx &= 0x00ffffff; ++ ++ for (i = 0; i < 6; i++) { ++ nv_wr32(dev, 0x100c90, idx | i << 24); ++ trap[i] = nv_rd32(dev, 0x100c94); ++ } ++ nv_wr32(dev, 0x100c90, idx | 0x80000000); ++ ++ if (!display) ++ return; ++ ++ chinst = (trap[2] << 16) | trap[1]; ++ for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { ++ struct nouveau_channel *chan = dev_priv->fifos[ch]; ++ ++ if (!chan || !chan->ramin) ++ continue; ++ ++ if (chinst == chan->ramin->instance >> 12) ++ break; ++ } ++ ++ NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " ++ "channel %d (0x%08x)\n", ++ name, (trap[5] & 0x100 ? "read" : "write"), ++ trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ++ trap[0], ch, chinst); ++} diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c -index e20c0e2..fb0281a 100644 +index e20c0e2..38dbcda 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c -@@ -28,41 +28,33 @@ +@@ -28,41 +28,35 @@ #include "drm.h" #include "nouveau_drv.h" @@ -9035,8 +11368,12 @@ index e20c0e2..fb0281a 100644 /* We never schedule channel 0 or 127 */ - dev_priv->engine.instmem.prepare_access(dev, true); for (i = 1, nr = 0; i < 127; i++) { - if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) - nv_wo32(dev, cur->gpuobj, nr++, i); +- if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) +- nv_wo32(dev, cur->gpuobj, nr++, i); ++ if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) { ++ nv_wo32(cur->gpuobj, (nr * 4), i); ++ nr++; ++ } } - dev_priv->engine.instmem.finish_access(dev); + dev_priv->engine.instmem.flush(dev); @@ -9053,7 +11390,7 @@ index e20c0e2..fb0281a 100644 { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->fifos[channel]; -@@ -70,37 +62,28 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) +@@ -70,37 +64,28 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel, bool nt) NV_DEBUG(dev, "ch%d\n", channel); @@ -9097,7 +11434,7 @@ index e20c0e2..fb0281a 100644 } static void -@@ -133,12 +116,12 @@ nv50_fifo_init_context_table(struct drm_device *dev) +@@ -133,12 +118,12 @@ nv50_fifo_init_context_table(struct drm_device *dev) for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { if (dev_priv->fifos[i]) @@ -9113,7 +11450,7 @@ index e20c0e2..fb0281a 100644 } static void -@@ -162,41 +145,38 @@ nv50_fifo_init_regs(struct drm_device *dev) +@@ -162,41 +147,38 @@ nv50_fifo_init_regs(struct drm_device *dev) nv_wr32(dev, 0x3270, 0); /* Enable dummy channels setup by nv50_instmem.c */ @@ -9167,7 +11504,7 @@ index e20c0e2..fb0281a 100644 return ret; } -@@ -216,18 +196,15 @@ void +@@ -216,18 +198,15 @@ void nv50_fifo_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -9190,7 +11527,7 @@ index e20c0e2..fb0281a 100644 } int -@@ -248,7 +225,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) +@@ -248,7 +227,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) NV_DEBUG(dev, "ch%d\n", chan->id); @@ -9199,31 +11536,50 @@ index e20c0e2..fb0281a 100644 uint32_t ramin_poffset = chan->ramin->gpuobj->im_pramin->start; uint32_t ramin_voffset = chan->ramin->gpuobj->im_backing_start; -@@ -281,10 +258,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) +@@ -281,39 +260,31 @@ nv50_fifo_create_context(struct nouveau_channel *chan) spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - dev_priv->engine.instmem.prepare_access(dev, true); - - nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); +- nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4); - nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4)); -+ nv_wo32(dev, ramfc, 0x80/4, (0 << 27) /* 4KiB */ | -+ (4 << 24) /* SEARCH_FULL */ | -+ (chan->ramht->instance >> 4)); - nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); - nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); - nv_wo32(dev, ramfc, 0x40/4, 0x00000000); -@@ -295,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - chan->dma.ib_base * 4); - nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); - +- nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff); +- nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff); +- nv_wo32(dev, ramfc, 0x40/4, 0x00000000); +- nv_wo32(dev, ramfc, 0x7c/4, 0x30000001); +- nv_wo32(dev, ramfc, 0x78/4, 0x00000000); +- nv_wo32(dev, ramfc, 0x3c/4, 0x403f6078); +- nv_wo32(dev, ramfc, 0x50/4, chan->pushbuf_base + +- chan->dma.ib_base * 4); +- nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16); +- - if (!IS_G80) { +- nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); +- nv_wo32(dev, chan->ramin->gpuobj, 1, +- chan->ramfc->instance >> 8); +- +- nv_wo32(dev, ramfc, 0x88/4, chan->cache->instance >> 10); +- nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); ++ nv_wo32(ramfc, 0x48, chan->pushbuf->instance >> 4); ++ nv_wo32(ramfc, 0x80, (0 << 27) /* 4KiB */ | ++ (4 << 24) /* SEARCH_FULL */ | ++ (chan->ramht->instance >> 4)); ++ nv_wo32(ramfc, 0x44, 0x2101ffff); ++ nv_wo32(ramfc, 0x60, 0x7fffffff); ++ nv_wo32(ramfc, 0x40, 0x00000000); ++ nv_wo32(ramfc, 0x7c, 0x30000001); ++ nv_wo32(ramfc, 0x78, 0x00000000); ++ nv_wo32(ramfc, 0x3c, 0x403f6078); ++ nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); ++ nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); ++ + if (dev_priv->chipset != 0x50) { - nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id); - nv_wo32(dev, chan->ramin->gpuobj, 1, - chan->ramfc->instance >> 8); -@@ -304,16 +281,10 @@ nv50_fifo_create_context(struct nouveau_channel *chan) - nv_wo32(dev, ramfc, 0x98/4, chan->ramin->instance >> 12); ++ nv_wo32(chan->ramin->gpuobj, 0, chan->id); ++ nv_wo32(chan->ramin->gpuobj, 4, chan->ramfc->instance >> 8); ++ ++ nv_wo32(ramfc, 0x88, chan->cache->instance >> 10); ++ nv_wo32(ramfc, 0x98, chan->ramin->instance >> 12); } - dev_priv->engine.instmem.finish_access(dev); @@ -9257,26 +11613,106 @@ index e20c0e2..fb0281a 100644 nouveau_gpuobj_ref_del(dev, &ramfc); nouveau_gpuobj_ref_del(dev, &chan->cache); -@@ -349,8 +321,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) +@@ -349,63 +321,59 @@ nv50_fifo_load_context(struct nouveau_channel *chan) NV_DEBUG(dev, "ch%d\n", chan->id); - dev_priv->engine.instmem.prepare_access(dev, false); - - nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); - nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); - nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); -@@ -396,7 +366,7 @@ nv50_fifo_load_context(struct nouveau_channel *chan) +- nv_wr32(dev, 0x3330, nv_ro32(dev, ramfc, 0x00/4)); +- nv_wr32(dev, 0x3334, nv_ro32(dev, ramfc, 0x04/4)); +- nv_wr32(dev, 0x3240, nv_ro32(dev, ramfc, 0x08/4)); +- nv_wr32(dev, 0x3320, nv_ro32(dev, ramfc, 0x0c/4)); +- nv_wr32(dev, 0x3244, nv_ro32(dev, ramfc, 0x10/4)); +- nv_wr32(dev, 0x3328, nv_ro32(dev, ramfc, 0x14/4)); +- nv_wr32(dev, 0x3368, nv_ro32(dev, ramfc, 0x18/4)); +- nv_wr32(dev, 0x336c, nv_ro32(dev, ramfc, 0x1c/4)); +- nv_wr32(dev, 0x3370, nv_ro32(dev, ramfc, 0x20/4)); +- nv_wr32(dev, 0x3374, nv_ro32(dev, ramfc, 0x24/4)); +- nv_wr32(dev, 0x3378, nv_ro32(dev, ramfc, 0x28/4)); +- nv_wr32(dev, 0x337c, nv_ro32(dev, ramfc, 0x2c/4)); +- nv_wr32(dev, 0x3228, nv_ro32(dev, ramfc, 0x30/4)); +- nv_wr32(dev, 0x3364, nv_ro32(dev, ramfc, 0x34/4)); +- nv_wr32(dev, 0x32a0, nv_ro32(dev, ramfc, 0x38/4)); +- nv_wr32(dev, 0x3224, nv_ro32(dev, ramfc, 0x3c/4)); +- nv_wr32(dev, 0x324c, nv_ro32(dev, ramfc, 0x40/4)); +- nv_wr32(dev, 0x2044, nv_ro32(dev, ramfc, 0x44/4)); +- nv_wr32(dev, 0x322c, nv_ro32(dev, ramfc, 0x48/4)); +- nv_wr32(dev, 0x3234, nv_ro32(dev, ramfc, 0x4c/4)); +- nv_wr32(dev, 0x3340, nv_ro32(dev, ramfc, 0x50/4)); +- nv_wr32(dev, 0x3344, nv_ro32(dev, ramfc, 0x54/4)); +- nv_wr32(dev, 0x3280, nv_ro32(dev, ramfc, 0x58/4)); +- nv_wr32(dev, 0x3254, nv_ro32(dev, ramfc, 0x5c/4)); +- nv_wr32(dev, 0x3260, nv_ro32(dev, ramfc, 0x60/4)); +- nv_wr32(dev, 0x3264, nv_ro32(dev, ramfc, 0x64/4)); +- nv_wr32(dev, 0x3268, nv_ro32(dev, ramfc, 0x68/4)); +- nv_wr32(dev, 0x326c, nv_ro32(dev, ramfc, 0x6c/4)); +- nv_wr32(dev, 0x32e4, nv_ro32(dev, ramfc, 0x70/4)); +- nv_wr32(dev, 0x3248, nv_ro32(dev, ramfc, 0x74/4)); +- nv_wr32(dev, 0x2088, nv_ro32(dev, ramfc, 0x78/4)); +- nv_wr32(dev, 0x2058, nv_ro32(dev, ramfc, 0x7c/4)); +- nv_wr32(dev, 0x2210, nv_ro32(dev, ramfc, 0x80/4)); +- +- cnt = nv_ro32(dev, ramfc, 0x84/4); ++ nv_wr32(dev, 0x3330, nv_ro32(ramfc, 0x00)); ++ nv_wr32(dev, 0x3334, nv_ro32(ramfc, 0x04)); ++ nv_wr32(dev, 0x3240, nv_ro32(ramfc, 0x08)); ++ nv_wr32(dev, 0x3320, nv_ro32(ramfc, 0x0c)); ++ nv_wr32(dev, 0x3244, nv_ro32(ramfc, 0x10)); ++ nv_wr32(dev, 0x3328, nv_ro32(ramfc, 0x14)); ++ nv_wr32(dev, 0x3368, nv_ro32(ramfc, 0x18)); ++ nv_wr32(dev, 0x336c, nv_ro32(ramfc, 0x1c)); ++ nv_wr32(dev, 0x3370, nv_ro32(ramfc, 0x20)); ++ nv_wr32(dev, 0x3374, nv_ro32(ramfc, 0x24)); ++ nv_wr32(dev, 0x3378, nv_ro32(ramfc, 0x28)); ++ nv_wr32(dev, 0x337c, nv_ro32(ramfc, 0x2c)); ++ nv_wr32(dev, 0x3228, nv_ro32(ramfc, 0x30)); ++ nv_wr32(dev, 0x3364, nv_ro32(ramfc, 0x34)); ++ nv_wr32(dev, 0x32a0, nv_ro32(ramfc, 0x38)); ++ nv_wr32(dev, 0x3224, nv_ro32(ramfc, 0x3c)); ++ nv_wr32(dev, 0x324c, nv_ro32(ramfc, 0x40)); ++ nv_wr32(dev, 0x2044, nv_ro32(ramfc, 0x44)); ++ nv_wr32(dev, 0x322c, nv_ro32(ramfc, 0x48)); ++ nv_wr32(dev, 0x3234, nv_ro32(ramfc, 0x4c)); ++ nv_wr32(dev, 0x3340, nv_ro32(ramfc, 0x50)); ++ nv_wr32(dev, 0x3344, nv_ro32(ramfc, 0x54)); ++ nv_wr32(dev, 0x3280, nv_ro32(ramfc, 0x58)); ++ nv_wr32(dev, 0x3254, nv_ro32(ramfc, 0x5c)); ++ nv_wr32(dev, 0x3260, nv_ro32(ramfc, 0x60)); ++ nv_wr32(dev, 0x3264, nv_ro32(ramfc, 0x64)); ++ nv_wr32(dev, 0x3268, nv_ro32(ramfc, 0x68)); ++ nv_wr32(dev, 0x326c, nv_ro32(ramfc, 0x6c)); ++ nv_wr32(dev, 0x32e4, nv_ro32(ramfc, 0x70)); ++ nv_wr32(dev, 0x3248, nv_ro32(ramfc, 0x74)); ++ nv_wr32(dev, 0x2088, nv_ro32(ramfc, 0x78)); ++ nv_wr32(dev, 0x2058, nv_ro32(ramfc, 0x7c)); ++ nv_wr32(dev, 0x2210, nv_ro32(ramfc, 0x80)); ++ ++ cnt = nv_ro32(ramfc, 0x84); + for (ptr = 0; ptr < cnt; ptr++) { + nv_wr32(dev, NV40_PFIFO_CACHE1_METHOD(ptr), +- nv_ro32(dev, cache, (ptr * 2) + 0)); ++ nv_ro32(cache, (ptr * 8) + 0)); + nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), +- nv_ro32(dev, cache, (ptr * 2) + 1)); ++ nv_ro32(cache, (ptr * 8) + 4)); + } + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); /* guessing that all the 0x34xx regs aren't on NV50 */ - if (!IS_G80) { +- nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); +- nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); +- nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); +- nv_wr32(dev, 0x3408, nv_ro32(dev, ramfc, 0x94/4)); +- nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); + if (dev_priv->chipset != 0x50) { - nv_wr32(dev, 0x340c, nv_ro32(dev, ramfc, 0x88/4)); - nv_wr32(dev, 0x3400, nv_ro32(dev, ramfc, 0x8c/4)); - nv_wr32(dev, 0x3404, nv_ro32(dev, ramfc, 0x90/4)); -@@ -404,8 +374,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) - nv_wr32(dev, 0x3410, nv_ro32(dev, ramfc, 0x98/4)); ++ nv_wr32(dev, 0x340c, nv_ro32(ramfc, 0x88)); ++ nv_wr32(dev, 0x3400, nv_ro32(ramfc, 0x8c)); ++ nv_wr32(dev, 0x3404, nv_ro32(ramfc, 0x90)); ++ nv_wr32(dev, 0x3408, nv_ro32(ramfc, 0x94)); ++ nv_wr32(dev, 0x3410, nv_ro32(ramfc, 0x98)); } - dev_priv->engine.instmem.finish_access(dev); @@ -9284,26 +11720,110 @@ index e20c0e2..fb0281a 100644 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); return 0; } -@@ -434,8 +402,6 @@ nv50_fifo_unload_context(struct drm_device *dev) +@@ -434,64 +402,63 @@ nv50_fifo_unload_context(struct drm_device *dev) ramfc = chan->ramfc->gpuobj; cache = chan->cache->gpuobj; - dev_priv->engine.instmem.prepare_access(dev, true); - - nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); - nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); - nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); -@@ -482,7 +448,7 @@ nv50_fifo_unload_context(struct drm_device *dev) +- nv_wo32(dev, ramfc, 0x00/4, nv_rd32(dev, 0x3330)); +- nv_wo32(dev, ramfc, 0x04/4, nv_rd32(dev, 0x3334)); +- nv_wo32(dev, ramfc, 0x08/4, nv_rd32(dev, 0x3240)); +- nv_wo32(dev, ramfc, 0x0c/4, nv_rd32(dev, 0x3320)); +- nv_wo32(dev, ramfc, 0x10/4, nv_rd32(dev, 0x3244)); +- nv_wo32(dev, ramfc, 0x14/4, nv_rd32(dev, 0x3328)); +- nv_wo32(dev, ramfc, 0x18/4, nv_rd32(dev, 0x3368)); +- nv_wo32(dev, ramfc, 0x1c/4, nv_rd32(dev, 0x336c)); +- nv_wo32(dev, ramfc, 0x20/4, nv_rd32(dev, 0x3370)); +- nv_wo32(dev, ramfc, 0x24/4, nv_rd32(dev, 0x3374)); +- nv_wo32(dev, ramfc, 0x28/4, nv_rd32(dev, 0x3378)); +- nv_wo32(dev, ramfc, 0x2c/4, nv_rd32(dev, 0x337c)); +- nv_wo32(dev, ramfc, 0x30/4, nv_rd32(dev, 0x3228)); +- nv_wo32(dev, ramfc, 0x34/4, nv_rd32(dev, 0x3364)); +- nv_wo32(dev, ramfc, 0x38/4, nv_rd32(dev, 0x32a0)); +- nv_wo32(dev, ramfc, 0x3c/4, nv_rd32(dev, 0x3224)); +- nv_wo32(dev, ramfc, 0x40/4, nv_rd32(dev, 0x324c)); +- nv_wo32(dev, ramfc, 0x44/4, nv_rd32(dev, 0x2044)); +- nv_wo32(dev, ramfc, 0x48/4, nv_rd32(dev, 0x322c)); +- nv_wo32(dev, ramfc, 0x4c/4, nv_rd32(dev, 0x3234)); +- nv_wo32(dev, ramfc, 0x50/4, nv_rd32(dev, 0x3340)); +- nv_wo32(dev, ramfc, 0x54/4, nv_rd32(dev, 0x3344)); +- nv_wo32(dev, ramfc, 0x58/4, nv_rd32(dev, 0x3280)); +- nv_wo32(dev, ramfc, 0x5c/4, nv_rd32(dev, 0x3254)); +- nv_wo32(dev, ramfc, 0x60/4, nv_rd32(dev, 0x3260)); +- nv_wo32(dev, ramfc, 0x64/4, nv_rd32(dev, 0x3264)); +- nv_wo32(dev, ramfc, 0x68/4, nv_rd32(dev, 0x3268)); +- nv_wo32(dev, ramfc, 0x6c/4, nv_rd32(dev, 0x326c)); +- nv_wo32(dev, ramfc, 0x70/4, nv_rd32(dev, 0x32e4)); +- nv_wo32(dev, ramfc, 0x74/4, nv_rd32(dev, 0x3248)); +- nv_wo32(dev, ramfc, 0x78/4, nv_rd32(dev, 0x2088)); +- nv_wo32(dev, ramfc, 0x7c/4, nv_rd32(dev, 0x2058)); +- nv_wo32(dev, ramfc, 0x80/4, nv_rd32(dev, 0x2210)); ++ nv_wo32(ramfc, 0x00, nv_rd32(dev, 0x3330)); ++ nv_wo32(ramfc, 0x04, nv_rd32(dev, 0x3334)); ++ nv_wo32(ramfc, 0x08, nv_rd32(dev, 0x3240)); ++ nv_wo32(ramfc, 0x0c, nv_rd32(dev, 0x3320)); ++ nv_wo32(ramfc, 0x10, nv_rd32(dev, 0x3244)); ++ nv_wo32(ramfc, 0x14, nv_rd32(dev, 0x3328)); ++ nv_wo32(ramfc, 0x18, nv_rd32(dev, 0x3368)); ++ nv_wo32(ramfc, 0x1c, nv_rd32(dev, 0x336c)); ++ nv_wo32(ramfc, 0x20, nv_rd32(dev, 0x3370)); ++ nv_wo32(ramfc, 0x24, nv_rd32(dev, 0x3374)); ++ nv_wo32(ramfc, 0x28, nv_rd32(dev, 0x3378)); ++ nv_wo32(ramfc, 0x2c, nv_rd32(dev, 0x337c)); ++ nv_wo32(ramfc, 0x30, nv_rd32(dev, 0x3228)); ++ nv_wo32(ramfc, 0x34, nv_rd32(dev, 0x3364)); ++ nv_wo32(ramfc, 0x38, nv_rd32(dev, 0x32a0)); ++ nv_wo32(ramfc, 0x3c, nv_rd32(dev, 0x3224)); ++ nv_wo32(ramfc, 0x40, nv_rd32(dev, 0x324c)); ++ nv_wo32(ramfc, 0x44, nv_rd32(dev, 0x2044)); ++ nv_wo32(ramfc, 0x48, nv_rd32(dev, 0x322c)); ++ nv_wo32(ramfc, 0x4c, nv_rd32(dev, 0x3234)); ++ nv_wo32(ramfc, 0x50, nv_rd32(dev, 0x3340)); ++ nv_wo32(ramfc, 0x54, nv_rd32(dev, 0x3344)); ++ nv_wo32(ramfc, 0x58, nv_rd32(dev, 0x3280)); ++ nv_wo32(ramfc, 0x5c, nv_rd32(dev, 0x3254)); ++ nv_wo32(ramfc, 0x60, nv_rd32(dev, 0x3260)); ++ nv_wo32(ramfc, 0x64, nv_rd32(dev, 0x3264)); ++ nv_wo32(ramfc, 0x68, nv_rd32(dev, 0x3268)); ++ nv_wo32(ramfc, 0x6c, nv_rd32(dev, 0x326c)); ++ nv_wo32(ramfc, 0x70, nv_rd32(dev, 0x32e4)); ++ nv_wo32(ramfc, 0x74, nv_rd32(dev, 0x3248)); ++ nv_wo32(ramfc, 0x78, nv_rd32(dev, 0x2088)); ++ nv_wo32(ramfc, 0x7c, nv_rd32(dev, 0x2058)); ++ nv_wo32(ramfc, 0x80, nv_rd32(dev, 0x2210)); + + put = (nv_rd32(dev, NV03_PFIFO_CACHE1_PUT) & 0x7ff) >> 2; + get = (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) & 0x7ff) >> 2; + ptr = 0; + while (put != get) { +- nv_wo32(dev, cache, ptr++, +- nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); +- nv_wo32(dev, cache, ptr++, +- nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); ++ nv_wo32(cache, ptr + 0, ++ nv_rd32(dev, NV40_PFIFO_CACHE1_METHOD(get))); ++ nv_wo32(cache, ptr + 4, ++ nv_rd32(dev, NV40_PFIFO_CACHE1_DATA(get))); + get = (get + 1) & 0x1ff; ++ ptr += 8; } /* guessing that all the 0x34xx regs aren't on NV50 */ - if (!IS_G80) { +- nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); +- nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); +- nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); +- nv_wo32(dev, ramfc, 0x90/4, nv_rd32(dev, 0x3404)); +- nv_wo32(dev, ramfc, 0x94/4, nv_rd32(dev, 0x3408)); +- nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); + if (dev_priv->chipset != 0x50) { - nv_wo32(dev, ramfc, 0x84/4, ptr >> 1); - nv_wo32(dev, ramfc, 0x88/4, nv_rd32(dev, 0x340c)); - nv_wo32(dev, ramfc, 0x8c/4, nv_rd32(dev, 0x3400)); -@@ -491,7 +457,7 @@ nv50_fifo_unload_context(struct drm_device *dev) - nv_wo32(dev, ramfc, 0x98/4, nv_rd32(dev, 0x3410)); ++ nv_wo32(ramfc, 0x84, ptr >> 3); ++ nv_wo32(ramfc, 0x88, nv_rd32(dev, 0x340c)); ++ nv_wo32(ramfc, 0x8c, nv_rd32(dev, 0x3400)); ++ nv_wo32(ramfc, 0x90, nv_rd32(dev, 0x3404)); ++ nv_wo32(ramfc, 0x94, nv_rd32(dev, 0x3408)); ++ nv_wo32(ramfc, 0x98, nv_rd32(dev, 0x3410)); } - dev_priv->engine.instmem.finish_access(dev); @@ -9355,7 +11875,7 @@ index bb47ad7..b2fab2b 100644 + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c -index b203d06..1413028 100644 +index b203d06..17a8d78 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -30,8 +30,6 @@ @@ -9446,23 +11966,21 @@ index b203d06..1413028 100644 int hdr, ret; NV_DEBUG(dev, "ch%d\n", chan->id); -@@ -223,10 +217,9 @@ nv50_graph_create_context(struct nouveau_channel *chan) +@@ -223,32 +217,25 @@ nv50_graph_create_context(struct nouveau_channel *chan) NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); if (ret) return ret; - ctx = chan->ramin_grctx->gpuobj; -+ obj = chan->ramin_grctx->gpuobj; - +- - hdr = IS_G80 ? 0x200 : 0x20; - dev_priv->engine.instmem.prepare_access(dev, true); -+ hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; - nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); - nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + - pgraph->grctx_size - 1); -@@ -234,21 +227,15 @@ nv50_graph_create_context(struct nouveau_channel *chan) - nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); - nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); - nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); +- nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002); +- nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance + +- pgraph->grctx_size - 1); +- nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance); +- nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0); +- nv_wo32(dev, ramin, (hdr + 0x10)/4, 0); +- nv_wo32(dev, ramin, (hdr + 0x14)/4, 0x00010000); - dev_priv->engine.instmem.finish_access(dev); - - dev_priv->engine.instmem.prepare_access(dev, true); @@ -9477,14 +11995,24 @@ index b203d06..1413028 100644 - } - nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12); - dev_priv->engine.instmem.finish_access(dev); - ++ obj = chan->ramin_grctx->gpuobj; ++ ++ hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; ++ nv_wo32(ramin, hdr + 0x00, 0x00190002); ++ nv_wo32(ramin, hdr + 0x04, chan->ramin_grctx->instance + ++ pgraph->grctx_size - 1); ++ nv_wo32(ramin, hdr + 0x08, chan->ramin_grctx->instance); ++ nv_wo32(ramin, hdr + 0x0c, 0); ++ nv_wo32(ramin, hdr + 0x10, 0); ++ nv_wo32(ramin, hdr + 0x14, 0x00010000); ++ + ctx.dev = chan->dev; + ctx.mode = NOUVEAU_GRCTX_VALS; + ctx.data = obj; + nv50_grctx_init(&ctx); + -+ nv_wo32(dev, obj, 0x00000/4, chan->ramin->instance >> 12); -+ ++ nv_wo32(obj, 0x00000, chan->ramin->instance >> 12); + + dev_priv->engine.instmem.flush(dev); return 0; } @@ -9503,14 +12031,3813 @@ index b203d06..1413028 100644 - dev_priv->engine.instmem.prepare_access(dev, true); for (i = hdr; i < hdr + 24; i += 4) - nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); +- nv_wo32(dev, chan->ramin->gpuobj, i/4, 0); - dev_priv->engine.instmem.finish_access(dev); ++ nv_wo32(chan->ramin->gpuobj, i, 0); + dev_priv->engine.instmem.flush(dev); nouveau_gpuobj_ref_del(dev, &chan->ramin_grctx); } +diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c +index 42a8fb2..336aab2 100644 +--- a/drivers/gpu/drm/nouveau/nv50_grctx.c ++++ b/drivers/gpu/drm/nouveau/nv50_grctx.c +@@ -103,6 +103,9 @@ + #include "nouveau_drv.h" + #include "nouveau_grctx.h" + ++#define IS_NVA3F(x) (((x) > 0xa0 && (x) < 0xaa) || (x) == 0xaf) ++#define IS_NVAAF(x) ((x) >= 0xaa && (x) <= 0xac) ++ + /* + * This code deals with PGRAPH contexts on NV50 family cards. Like NV40, it's + * the GPU itself that does context-switching, but it needs a special +@@ -182,6 +185,7 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + case 0xa8: + case 0xaa: + case 0xac: ++ case 0xaf: + break; + default: + NV_ERROR(ctx->dev, "I don't know how to make a ctxprog for " +@@ -268,6 +272,9 @@ nv50_grctx_init(struct nouveau_grctx *ctx) + */ + + static void ++nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx); ++ ++static void + nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +@@ -286,7 +293,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + gr_def(ctx, 0x400840, 0xffe806a8); + } + gr_def(ctx, 0x400844, 0x00000002); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) ++ if (IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, 0x400894, 0x00001000); + gr_def(ctx, 0x4008e8, 0x00000003); + gr_def(ctx, 0x4008ec, 0x00001000); +@@ -299,13 +306,15 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + + if (dev_priv->chipset >= 0xa0) + cp_ctx(ctx, 0x400b00, 0x1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { ++ if (IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, 0x400b10, 0x1); + gr_def(ctx, 0x400b10, 0x0001629d); + cp_ctx(ctx, 0x400b20, 0x1); + gr_def(ctx, 0x400b20, 0x0001629d); + } + ++ nv50_graph_construct_mmio_ddata(ctx); ++ + /* 0C00: VFETCH */ + cp_ctx(ctx, 0x400c08, 0x2); + gr_def(ctx, 0x400c08, 0x0000fe0c); +@@ -314,7 +323,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, 0x401008, 0x4); + gr_def(ctx, 0x401014, 0x00001000); +- } else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) { ++ } else if (!IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, 0x401008, 0x5); + gr_def(ctx, 0x401018, 0x00001000); + } else { +@@ -368,10 +377,13 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + case 0xa3: + case 0xa5: + case 0xa8: ++ case 0xaf: + gr_def(ctx, 0x401c00, 0x142500df); + break; + } + ++ /* 2000 */ ++ + /* 2400 */ + cp_ctx(ctx, 0x402400, 0x1); + if (dev_priv->chipset == 0x50) +@@ -380,12 +392,12 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + cp_ctx(ctx, 0x402408, 0x2); + gr_def(ctx, 0x402408, 0x00000600); + +- /* 2800 */ ++ /* 2800: CSCHED */ + cp_ctx(ctx, 0x402800, 0x1); + if (dev_priv->chipset == 0x50) + gr_def(ctx, 0x402800, 0x00000006); + +- /* 2C00 */ ++ /* 2C00: ZCULL */ + cp_ctx(ctx, 0x402c08, 0x6); + if (dev_priv->chipset != 0x50) + gr_def(ctx, 0x402c14, 0x01000000); +@@ -396,23 +408,23 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + cp_ctx(ctx, 0x402ca0, 0x2); + if (dev_priv->chipset < 0xa0) + gr_def(ctx, 0x402ca0, 0x00000400); +- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) ++ else if (!IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, 0x402ca0, 0x00000800); + else + gr_def(ctx, 0x402ca0, 0x00000400); + cp_ctx(ctx, 0x402cac, 0x4); + +- /* 3000 */ ++ /* 3000: ENG2D */ + cp_ctx(ctx, 0x403004, 0x1); + gr_def(ctx, 0x403004, 0x00000001); + +- /* 3404 */ ++ /* 3400 */ + if (dev_priv->chipset >= 0xa0) { + cp_ctx(ctx, 0x403404, 0x1); + gr_def(ctx, 0x403404, 0x00000001); + } + +- /* 5000 */ ++ /* 5000: CCACHE */ + cp_ctx(ctx, 0x405000, 0x1); + switch (dev_priv->chipset) { + case 0x50: +@@ -425,6 +437,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + case 0xa8: + case 0xaa: + case 0xac: ++ case 0xaf: + gr_def(ctx, 0x405000, 0x000e0080); + break; + case 0x86: +@@ -441,210 +454,6 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + cp_ctx(ctx, 0x405024, 0x1); + cp_ctx(ctx, 0x40502c, 0x1); + +- /* 5400 or maybe 4800 */ +- if (dev_priv->chipset == 0x50) { +- offset = 0x405400; +- cp_ctx(ctx, 0x405400, 0xea); +- } else if (dev_priv->chipset < 0x94) { +- offset = 0x405400; +- cp_ctx(ctx, 0x405400, 0xcb); +- } else if (dev_priv->chipset < 0xa0) { +- offset = 0x405400; +- cp_ctx(ctx, 0x405400, 0xcc); +- } else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- offset = 0x404800; +- cp_ctx(ctx, 0x404800, 0xda); +- } else { +- offset = 0x405400; +- cp_ctx(ctx, 0x405400, 0xd4); +- } +- gr_def(ctx, offset + 0x0c, 0x00000002); +- gr_def(ctx, offset + 0x10, 0x00000001); +- if (dev_priv->chipset >= 0x94) +- offset += 4; +- gr_def(ctx, offset + 0x1c, 0x00000001); +- gr_def(ctx, offset + 0x20, 0x00000100); +- gr_def(ctx, offset + 0x38, 0x00000002); +- gr_def(ctx, offset + 0x3c, 0x00000001); +- gr_def(ctx, offset + 0x40, 0x00000001); +- gr_def(ctx, offset + 0x50, 0x00000001); +- gr_def(ctx, offset + 0x54, 0x003fffff); +- gr_def(ctx, offset + 0x58, 0x00001fff); +- gr_def(ctx, offset + 0x60, 0x00000001); +- gr_def(ctx, offset + 0x64, 0x00000001); +- gr_def(ctx, offset + 0x6c, 0x00000001); +- gr_def(ctx, offset + 0x70, 0x00000001); +- gr_def(ctx, offset + 0x74, 0x00000001); +- gr_def(ctx, offset + 0x78, 0x00000004); +- gr_def(ctx, offset + 0x7c, 0x00000001); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- offset += 4; +- gr_def(ctx, offset + 0x80, 0x00000001); +- gr_def(ctx, offset + 0x84, 0x00000001); +- gr_def(ctx, offset + 0x88, 0x00000007); +- gr_def(ctx, offset + 0x8c, 0x00000001); +- gr_def(ctx, offset + 0x90, 0x00000007); +- gr_def(ctx, offset + 0x94, 0x00000001); +- gr_def(ctx, offset + 0x98, 0x00000001); +- gr_def(ctx, offset + 0x9c, 0x00000001); +- if (dev_priv->chipset == 0x50) { +- gr_def(ctx, offset + 0xb0, 0x00000001); +- gr_def(ctx, offset + 0xb4, 0x00000001); +- gr_def(ctx, offset + 0xbc, 0x00000001); +- gr_def(ctx, offset + 0xc0, 0x0000000a); +- gr_def(ctx, offset + 0xd0, 0x00000040); +- gr_def(ctx, offset + 0xd8, 0x00000002); +- gr_def(ctx, offset + 0xdc, 0x00000100); +- gr_def(ctx, offset + 0xe0, 0x00000001); +- gr_def(ctx, offset + 0xe4, 0x00000100); +- gr_def(ctx, offset + 0x100, 0x00000001); +- gr_def(ctx, offset + 0x124, 0x00000004); +- gr_def(ctx, offset + 0x13c, 0x00000001); +- gr_def(ctx, offset + 0x140, 0x00000100); +- gr_def(ctx, offset + 0x148, 0x00000001); +- gr_def(ctx, offset + 0x154, 0x00000100); +- gr_def(ctx, offset + 0x158, 0x00000001); +- gr_def(ctx, offset + 0x15c, 0x00000100); +- gr_def(ctx, offset + 0x164, 0x00000001); +- gr_def(ctx, offset + 0x170, 0x00000100); +- gr_def(ctx, offset + 0x174, 0x00000001); +- gr_def(ctx, offset + 0x17c, 0x00000001); +- gr_def(ctx, offset + 0x188, 0x00000002); +- gr_def(ctx, offset + 0x190, 0x00000001); +- gr_def(ctx, offset + 0x198, 0x00000001); +- gr_def(ctx, offset + 0x1ac, 0x00000003); +- offset += 0xd0; +- } else { +- gr_def(ctx, offset + 0xb0, 0x00000001); +- gr_def(ctx, offset + 0xb4, 0x00000100); +- gr_def(ctx, offset + 0xbc, 0x00000001); +- gr_def(ctx, offset + 0xc8, 0x00000100); +- gr_def(ctx, offset + 0xcc, 0x00000001); +- gr_def(ctx, offset + 0xd0, 0x00000100); +- gr_def(ctx, offset + 0xd8, 0x00000001); +- gr_def(ctx, offset + 0xe4, 0x00000100); +- } +- gr_def(ctx, offset + 0xf8, 0x00000004); +- gr_def(ctx, offset + 0xfc, 0x00000070); +- gr_def(ctx, offset + 0x100, 0x00000080); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- offset += 4; +- gr_def(ctx, offset + 0x114, 0x0000000c); +- if (dev_priv->chipset == 0x50) +- offset -= 4; +- gr_def(ctx, offset + 0x11c, 0x00000008); +- gr_def(ctx, offset + 0x120, 0x00000014); +- if (dev_priv->chipset == 0x50) { +- gr_def(ctx, offset + 0x124, 0x00000026); +- offset -= 0x18; +- } else { +- gr_def(ctx, offset + 0x128, 0x00000029); +- gr_def(ctx, offset + 0x12c, 0x00000027); +- gr_def(ctx, offset + 0x130, 0x00000026); +- gr_def(ctx, offset + 0x134, 0x00000008); +- gr_def(ctx, offset + 0x138, 0x00000004); +- gr_def(ctx, offset + 0x13c, 0x00000027); +- } +- gr_def(ctx, offset + 0x148, 0x00000001); +- gr_def(ctx, offset + 0x14c, 0x00000002); +- gr_def(ctx, offset + 0x150, 0x00000003); +- gr_def(ctx, offset + 0x154, 0x00000004); +- gr_def(ctx, offset + 0x158, 0x00000005); +- gr_def(ctx, offset + 0x15c, 0x00000006); +- gr_def(ctx, offset + 0x160, 0x00000007); +- gr_def(ctx, offset + 0x164, 0x00000001); +- gr_def(ctx, offset + 0x1a8, 0x000000cf); +- if (dev_priv->chipset == 0x50) +- offset -= 4; +- gr_def(ctx, offset + 0x1d8, 0x00000080); +- gr_def(ctx, offset + 0x1dc, 0x00000004); +- gr_def(ctx, offset + 0x1e0, 0x00000004); +- if (dev_priv->chipset == 0x50) +- offset -= 4; +- else +- gr_def(ctx, offset + 0x1e4, 0x00000003); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- gr_def(ctx, offset + 0x1ec, 0x00000003); +- offset += 8; +- } +- gr_def(ctx, offset + 0x1e8, 0x00000001); +- if (dev_priv->chipset == 0x50) +- offset -= 4; +- gr_def(ctx, offset + 0x1f4, 0x00000012); +- gr_def(ctx, offset + 0x1f8, 0x00000010); +- gr_def(ctx, offset + 0x1fc, 0x0000000c); +- gr_def(ctx, offset + 0x200, 0x00000001); +- gr_def(ctx, offset + 0x210, 0x00000004); +- gr_def(ctx, offset + 0x214, 0x00000002); +- gr_def(ctx, offset + 0x218, 0x00000004); +- if (dev_priv->chipset >= 0xa0) +- offset += 4; +- gr_def(ctx, offset + 0x224, 0x003fffff); +- gr_def(ctx, offset + 0x228, 0x00001fff); +- if (dev_priv->chipset == 0x50) +- offset -= 0x20; +- else if (dev_priv->chipset >= 0xa0) { +- gr_def(ctx, offset + 0x250, 0x00000001); +- gr_def(ctx, offset + 0x254, 0x00000001); +- gr_def(ctx, offset + 0x258, 0x00000002); +- offset += 0x10; +- } +- gr_def(ctx, offset + 0x250, 0x00000004); +- gr_def(ctx, offset + 0x254, 0x00000014); +- gr_def(ctx, offset + 0x258, 0x00000001); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- offset += 4; +- gr_def(ctx, offset + 0x264, 0x00000002); +- if (dev_priv->chipset >= 0xa0) +- offset += 8; +- gr_def(ctx, offset + 0x270, 0x00000001); +- gr_def(ctx, offset + 0x278, 0x00000002); +- gr_def(ctx, offset + 0x27c, 0x00001000); +- if (dev_priv->chipset == 0x50) +- offset -= 0xc; +- else { +- gr_def(ctx, offset + 0x280, 0x00000e00); +- gr_def(ctx, offset + 0x284, 0x00001000); +- gr_def(ctx, offset + 0x288, 0x00001e00); +- } +- gr_def(ctx, offset + 0x290, 0x00000001); +- gr_def(ctx, offset + 0x294, 0x00000001); +- gr_def(ctx, offset + 0x298, 0x00000001); +- gr_def(ctx, offset + 0x29c, 0x00000001); +- gr_def(ctx, offset + 0x2a0, 0x00000001); +- gr_def(ctx, offset + 0x2b0, 0x00000200); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- gr_def(ctx, offset + 0x2b4, 0x00000200); +- offset += 4; +- } +- if (dev_priv->chipset < 0xa0) { +- gr_def(ctx, offset + 0x2b8, 0x00000001); +- gr_def(ctx, offset + 0x2bc, 0x00000070); +- gr_def(ctx, offset + 0x2c0, 0x00000080); +- gr_def(ctx, offset + 0x2cc, 0x00000001); +- gr_def(ctx, offset + 0x2d0, 0x00000070); +- gr_def(ctx, offset + 0x2d4, 0x00000080); +- } else { +- gr_def(ctx, offset + 0x2b8, 0x00000001); +- gr_def(ctx, offset + 0x2bc, 0x000000f0); +- gr_def(ctx, offset + 0x2c0, 0x000000ff); +- gr_def(ctx, offset + 0x2cc, 0x00000001); +- gr_def(ctx, offset + 0x2d0, 0x000000f0); +- gr_def(ctx, offset + 0x2d4, 0x000000ff); +- gr_def(ctx, offset + 0x2dc, 0x00000009); +- offset += 4; +- } +- gr_def(ctx, offset + 0x2e4, 0x00000001); +- gr_def(ctx, offset + 0x2e8, 0x000000cf); +- gr_def(ctx, offset + 0x2f0, 0x00000001); +- gr_def(ctx, offset + 0x300, 0x000000cf); +- gr_def(ctx, offset + 0x308, 0x00000002); +- gr_def(ctx, offset + 0x310, 0x00000001); +- gr_def(ctx, offset + 0x318, 0x00000001); +- gr_def(ctx, offset + 0x320, 0x000000cf); +- gr_def(ctx, offset + 0x324, 0x000000cf); +- gr_def(ctx, offset + 0x328, 0x00000001); +- + /* 6000? */ + if (dev_priv->chipset == 0x50) + cp_ctx(ctx, 0x4063e0, 0x1); +@@ -661,7 +470,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + gr_def(ctx, 0x406818, 0x00000f80); + else + gr_def(ctx, 0x406818, 0x00001f80); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) ++ if (IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, 0x40681c, 0x00000030); + cp_ctx(ctx, 0x406830, 0x3); + } +@@ -706,7 +515,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + + if (dev_priv->chipset < 0xa0) + cp_ctx(ctx, 0x407094 + (i<<8), 1); +- else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) ++ else if (!IS_NVA3F(dev_priv->chipset)) + cp_ctx(ctx, 0x407094 + (i<<8), 3); + else { + cp_ctx(ctx, 0x407094 + (i<<8), 4); +@@ -799,6 +608,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + case 0xa8: + case 0xaa: + case 0xac: ++ case 0xaf: + gr_def(ctx, offset + 0x1c, 0x300c0000); + break; + } +@@ -825,7 +635,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + gr_def(ctx, base + 0x304, 0x00007070); + else if (dev_priv->chipset < 0xa0) + gr_def(ctx, base + 0x304, 0x00027070); +- else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) ++ else if (!IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, base + 0x304, 0x01127070); + else + gr_def(ctx, base + 0x304, 0x05127070); +@@ -849,7 +659,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + if (dev_priv->chipset < 0xa0) { + cp_ctx(ctx, base + 0x340, 9); + offset = base + 0x340; +- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { ++ } else if (!IS_NVA3F(dev_priv->chipset)) { + cp_ctx(ctx, base + 0x33c, 0xb); + offset = base + 0x344; + } else { +@@ -880,7 +690,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + gr_def(ctx, offset + 0x0, 0x000001f0); + gr_def(ctx, offset + 0x4, 0x00000001); + gr_def(ctx, offset + 0x8, 0x00000003); +- if (dev_priv->chipset == 0x50 || dev_priv->chipset >= 0xaa) ++ if (dev_priv->chipset == 0x50 || IS_NVAAF(dev_priv->chipset)) + gr_def(ctx, offset + 0xc, 0x00008000); + gr_def(ctx, offset + 0x14, 0x00039e00); + cp_ctx(ctx, offset + 0x1c, 2); +@@ -892,7 +702,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + + if (dev_priv->chipset >= 0xa0) { + cp_ctx(ctx, base + 0x54c, 2); +- if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) ++ if (!IS_NVA3F(dev_priv->chipset)) + gr_def(ctx, base + 0x54c, 0x003fe006); + else + gr_def(ctx, base + 0x54c, 0x003fe007); +@@ -948,6 +758,336 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + } + } + ++static void ++dd_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { ++ int i; ++ if (val && ctx->mode == NOUVEAU_GRCTX_VALS) ++ for (i = 0; i < num; i++) ++ nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + i), val); ++ ctx->ctxvals_pos += num; ++} ++ ++static void ++nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx) ++{ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ int base, num; ++ base = ctx->ctxvals_pos; ++ ++ /* tesla state */ ++ dd_emit(ctx, 1, 0); /* 00000001 UNK0F90 */ ++ dd_emit(ctx, 1, 0); /* 00000001 UNK135C */ ++ ++ /* SRC_TIC state */ ++ dd_emit(ctx, 1, 0); /* 00000007 SRC_TILE_MODE_Z */ ++ dd_emit(ctx, 1, 2); /* 00000007 SRC_TILE_MODE_Y */ ++ dd_emit(ctx, 1, 1); /* 00000001 SRC_LINEAR #1 */ ++ dd_emit(ctx, 1, 0); /* 000000ff SRC_ADDRESS_HIGH */ ++ dd_emit(ctx, 1, 0); /* 00000001 SRC_SRGB */ ++ if (dev_priv->chipset >= 0x94) ++ dd_emit(ctx, 1, 0); /* 00000003 eng2d UNK0258 */ ++ dd_emit(ctx, 1, 1); /* 00000fff SRC_DEPTH */ ++ dd_emit(ctx, 1, 0x100); /* 0000ffff SRC_HEIGHT */ ++ ++ /* turing state */ ++ dd_emit(ctx, 1, 0); /* 0000000f TEXTURES_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 0000000f SAMPLERS_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ ++ dd_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ ++ dd_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ ++ dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ ++ dd_emit(ctx, 1, 1); /* 0000ffff BLOCK_ALLOC_THREADS */ ++ dd_emit(ctx, 1, 1); /* 00000001 LANES32 */ ++ dd_emit(ctx, 1, 0); /* 000000ff UNK370 */ ++ dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_UNK */ ++ dd_emit(ctx, 1, 0); /* 000000ff USER_PARAM_COUNT */ ++ dd_emit(ctx, 1, 1); /* 000000ff UNK384 bits 8-15 */ ++ dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ ++ dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ ++ dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ ++ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_X */ ++ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_XMY */ ++ dd_emit(ctx, 1, 0); /* 00000001 BLOCKDIM_XMY_OVERFLOW */ ++ dd_emit(ctx, 1, 1); /* 0003ffff BLOCKDIM_XMYMZ */ ++ dd_emit(ctx, 1, 1); /* 000007ff BLOCKDIM_Y */ ++ dd_emit(ctx, 1, 1); /* 0000007f BLOCKDIM_Z */ ++ dd_emit(ctx, 1, 4); /* 000000ff CP_REG_ALLOC_TEMP */ ++ dd_emit(ctx, 1, 1); /* 00000001 BLOCKDIM_DIRTY */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ dd_emit(ctx, 1, 0); /* 00000003 UNK03E8 */ ++ dd_emit(ctx, 1, 1); /* 0000007f BLOCK_ALLOC_HALFWARPS */ ++ dd_emit(ctx, 1, 1); /* 00000007 LOCAL_WARPS_NO_CLAMP */ ++ dd_emit(ctx, 1, 7); /* 00000007 LOCAL_WARPS_LOG_ALLOC */ ++ dd_emit(ctx, 1, 1); /* 00000007 STACK_WARPS_NO_CLAMP */ ++ dd_emit(ctx, 1, 7); /* 00000007 STACK_WARPS_LOG_ALLOC */ ++ dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_PACKED */ ++ dd_emit(ctx, 1, 1); /* 00001fff BLOCK_ALLOC_REGSLOTS_STRIDED */ ++ dd_emit(ctx, 1, 1); /* 000007ff BLOCK_ALLOC_THREADS */ ++ ++ /* compat 2d state */ ++ if (dev_priv->chipset == 0x50) { ++ dd_emit(ctx, 4, 0); /* 0000ffff clip X, Y, W, H */ ++ ++ dd_emit(ctx, 1, 1); /* ffffffff chroma COLOR_FORMAT */ ++ ++ dd_emit(ctx, 1, 1); /* ffffffff pattern COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff pattern SHAPE */ ++ dd_emit(ctx, 1, 1); /* ffffffff pattern PATTERN_SELECT */ ++ ++ dd_emit(ctx, 1, 0xa); /* ffffffff surf2d SRC_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff surf2d DMA_SRC */ ++ dd_emit(ctx, 1, 0); /* 000000ff surf2d SRC_ADDRESS_HIGH */ ++ dd_emit(ctx, 1, 0); /* ffffffff surf2d SRC_ADDRESS_LOW */ ++ dd_emit(ctx, 1, 0x40); /* 0000ffff surf2d SRC_PITCH */ ++ dd_emit(ctx, 1, 0); /* 0000000f surf2d SRC_TILE_MODE_Z */ ++ dd_emit(ctx, 1, 2); /* 0000000f surf2d SRC_TILE_MODE_Y */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_HEIGHT */ ++ dd_emit(ctx, 1, 1); /* 00000001 surf2d SRC_LINEAR */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff surf2d SRC_WIDTH */ ++ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_X */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_B_Y */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_X */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_C_Y */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_X */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect CLIP_D_Y */ ++ dd_emit(ctx, 1, 1); /* ffffffff gdirect COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff gdirect OPERATION */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_X */ ++ dd_emit(ctx, 1, 0); /* 0000ffff gdirect POINT_Y */ ++ ++ dd_emit(ctx, 1, 0); /* 0000ffff blit SRC_Y */ ++ dd_emit(ctx, 1, 0); /* ffffffff blit OPERATION */ ++ ++ dd_emit(ctx, 1, 0); /* ffffffff ifc OPERATION */ ++ ++ dd_emit(ctx, 1, 0); /* ffffffff iifc INDEX_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff iifc LUT_OFFSET */ ++ dd_emit(ctx, 1, 4); /* ffffffff iifc COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff iifc OPERATION */ ++ } ++ ++ /* m2mf state */ ++ dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_COUNT */ ++ dd_emit(ctx, 1, 0); /* ffffffff m2mf LINE_LENGTH_IN */ ++ dd_emit(ctx, 2, 0); /* ffffffff m2mf OFFSET_IN, OFFSET_OUT */ ++ dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_OUT */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_OUT */ ++ dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_OUT_Z */ ++ dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_OUT */ ++ dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_OUT_X, Y */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_OUT */ ++ dd_emit(ctx, 1, 1); /* ffffffff m2mf TILING_DEPTH_IN */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_HEIGHT_IN */ ++ dd_emit(ctx, 1, 0); /* ffffffff m2mf TILING_POSITION_IN_Z */ ++ dd_emit(ctx, 1, 1); /* 00000001 m2mf LINEAR_IN */ ++ dd_emit(ctx, 2, 0); /* 0000ffff m2mf TILING_POSITION_IN_X, Y */ ++ dd_emit(ctx, 1, 0x100); /* ffffffff m2mf TILING_PITCH_IN */ ++ ++ /* more compat 2d state */ ++ if (dev_priv->chipset == 0x50) { ++ dd_emit(ctx, 1, 1); /* ffffffff line COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff line OPERATION */ ++ ++ dd_emit(ctx, 1, 1); /* ffffffff triangle COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff triangle OPERATION */ ++ ++ dd_emit(ctx, 1, 0); /* 0000000f sifm TILE_MODE_Z */ ++ dd_emit(ctx, 1, 2); /* 0000000f sifm TILE_MODE_Y */ ++ dd_emit(ctx, 1, 0); /* 000000ff sifm FORMAT_FILTER */ ++ dd_emit(ctx, 1, 1); /* 000000ff sifm FORMAT_ORIGIN */ ++ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_PITCH */ ++ dd_emit(ctx, 1, 1); /* 00000001 sifm SRC_LINEAR */ ++ dd_emit(ctx, 1, 0); /* 000000ff sifm SRC_OFFSET_HIGH */ ++ dd_emit(ctx, 1, 0); /* ffffffff sifm SRC_OFFSET */ ++ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_HEIGHT */ ++ dd_emit(ctx, 1, 0); /* 0000ffff sifm SRC_WIDTH */ ++ dd_emit(ctx, 1, 3); /* ffffffff sifm COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff sifm OPERATION */ ++ ++ dd_emit(ctx, 1, 0); /* ffffffff sifc OPERATION */ ++ } ++ ++ /* tesla state */ ++ dd_emit(ctx, 1, 0); /* 0000000f GP_TEXTURES_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 0000000f GP_SAMPLERS_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* ffffffff */ ++ dd_emit(ctx, 1, 4); /* 000000ff UNK12B0_0 */ ++ dd_emit(ctx, 1, 0x70); /* 000000ff UNK12B0_1 */ ++ dd_emit(ctx, 1, 0x80); /* 000000ff UNK12B0_3 */ ++ dd_emit(ctx, 1, 0); /* 000000ff UNK12B0_2 */ ++ dd_emit(ctx, 1, 0); /* 0000000f FP_TEXTURES_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 0000000f FP_SAMPLERS_LOG2 */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ dd_emit(ctx, 1, 0); /* ffffffff */ ++ dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ ++ } else { ++ dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ ++ } ++ dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ ++ if (dev_priv->chipset != 0x50) ++ dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ ++ dd_emit(ctx, 1, 8); /* 000000ff SEMANTIC_COLOR.COLR_NR */ ++ dd_emit(ctx, 1, 0x14); /* 000000ff SEMANTIC_COLOR.FFC0_ID */ ++ if (dev_priv->chipset == 0x50) { ++ dd_emit(ctx, 1, 0); /* 000000ff SEMANTIC_LAYER */ ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ } else { ++ dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_PTSZ.ENABLE */ ++ dd_emit(ctx, 1, 0x29); /* 000000ff SEMANTIC_PTSZ.PTSZ_ID */ ++ dd_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM */ ++ dd_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ ++ dd_emit(ctx, 1, 8); /* 0000000f SMENATIC_CLIP.CLIP_HIGH */ ++ dd_emit(ctx, 1, 4); /* 000000ff SEMANTIC_CLIP.CLIP_LO */ ++ dd_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ ++ dd_emit(ctx, 1, 0); /* 00000001 UNK1900 */ ++ } ++ dd_emit(ctx, 1, 0); /* 00000007 RT_CONTROL_MAP0 */ ++ dd_emit(ctx, 1, 1); /* 00000007 RT_CONTROL_MAP1 */ ++ dd_emit(ctx, 1, 2); /* 00000007 RT_CONTROL_MAP2 */ ++ dd_emit(ctx, 1, 3); /* 00000007 RT_CONTROL_MAP3 */ ++ dd_emit(ctx, 1, 4); /* 00000007 RT_CONTROL_MAP4 */ ++ dd_emit(ctx, 1, 5); /* 00000007 RT_CONTROL_MAP5 */ ++ dd_emit(ctx, 1, 6); /* 00000007 RT_CONTROL_MAP6 */ ++ dd_emit(ctx, 1, 7); /* 00000007 RT_CONTROL_MAP7 */ ++ dd_emit(ctx, 1, 1); /* 0000000f RT_CONTROL_COUNT */ ++ dd_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_UNK */ ++ dd_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ ++ dd_emit(ctx, 1, 0xcf); /* 000000ff RT_FORMAT */ ++ dd_emit(ctx, 7, 0); /* 000000ff RT_FORMAT */ ++ if (dev_priv->chipset != 0x50) ++ dd_emit(ctx, 3, 0); /* 1, 1, 1 */ ++ else ++ dd_emit(ctx, 2, 0); /* 1, 1 */ ++ dd_emit(ctx, 1, 0); /* ffffffff GP_ENABLE */ ++ dd_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT*/ ++ dd_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ ++ dd_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ dd_emit(ctx, 1, 3); /* 00000003 */ ++ dd_emit(ctx, 1, 0); /* 00000001 UNK1418. Alone. */ ++ } ++ if (dev_priv->chipset != 0x50) ++ dd_emit(ctx, 1, 3); /* 00000003 UNK15AC */ ++ dd_emit(ctx, 1, 1); /* ffffffff RASTERIZE_ENABLE */ ++ dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.EXPORTS_Z */ ++ if (dev_priv->chipset != 0x50) ++ dd_emit(ctx, 1, 0); /* 00000001 FP_CONTROL.MULTIPLE_RESULTS */ ++ dd_emit(ctx, 1, 0x12); /* 000000ff FP_INTERPOLANT_CTRL.COUNT */ ++ dd_emit(ctx, 1, 0x10); /* 000000ff FP_INTERPOLANT_CTRL.COUNT_NONFLAT */ ++ dd_emit(ctx, 1, 0xc); /* 000000ff FP_INTERPOLANT_CTRL.OFFSET */ ++ dd_emit(ctx, 1, 1); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.W */ ++ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.X */ ++ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Y */ ++ dd_emit(ctx, 1, 0); /* 00000001 FP_INTERPOLANT_CTRL.UMASK.Z */ ++ dd_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ ++ dd_emit(ctx, 1, 2); /* ffffffff REG_MODE */ ++ dd_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ ++ if (dev_priv->chipset >= 0xa0) ++ dd_emit(ctx, 1, 0); /* ffffffff */ ++ dd_emit(ctx, 1, 0); /* 00000001 GP_BUILTIN_RESULT_EN.LAYER_IDX */ ++ dd_emit(ctx, 1, 0); /* ffffffff STRMOUT_ENABLE */ ++ dd_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ ++ dd_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ ++ dd_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE*/ ++ if (dev_priv->chipset != 0x50) ++ dd_emit(ctx, 8, 0); /* 00000001 */ ++ if (dev_priv->chipset >= 0xa0) { ++ dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.COMP */ ++ dd_emit(ctx, 1, 1); /* 00000007 VTX_ATTR_DEFINE.SIZE */ ++ dd_emit(ctx, 1, 2); /* 00000007 VTX_ATTR_DEFINE.TYPE */ ++ dd_emit(ctx, 1, 0); /* 000000ff VTX_ATTR_DEFINE.ATTR */ ++ } ++ dd_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ dd_emit(ctx, 1, 0x14); /* 0000001f ZETA_FORMAT */ ++ dd_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ dd_emit(ctx, 1, 0); /* 0000000f VP_TEXTURES_LOG2 */ ++ dd_emit(ctx, 1, 0); /* 0000000f VP_SAMPLERS_LOG2 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_BACK */ ++ if (dev_priv->chipset >= 0xa0) ++ dd_emit(ctx, 1, 0); /* 00000003 VTX_ATTR_DEFINE.SIZE - 1 */ ++ dd_emit(ctx, 1, 0); /* 0000ffff CB_ADDR_INDEX */ ++ if (dev_priv->chipset >= 0xa0) ++ dd_emit(ctx, 1, 0); /* 00000003 */ ++ dd_emit(ctx, 1, 0); /* 00000001 CULL_FACE_ENABLE */ ++ dd_emit(ctx, 1, 1); /* 00000003 CULL_FACE */ ++ dd_emit(ctx, 1, 0); /* 00000001 FRONT_FACE */ ++ dd_emit(ctx, 1, 2); /* 00000003 POLYGON_MODE_FRONT */ ++ dd_emit(ctx, 1, 0x1000); /* 00007fff UNK141C */ ++ if (dev_priv->chipset != 0x50) { ++ dd_emit(ctx, 1, 0xe00); /* 7fff */ ++ dd_emit(ctx, 1, 0x1000); /* 7fff */ ++ dd_emit(ctx, 1, 0x1e00); /* 7fff */ ++ } ++ dd_emit(ctx, 1, 0); /* 00000001 BEGIN_END_ACTIVE */ ++ dd_emit(ctx, 1, 1); /* 00000001 POLYGON_MODE_??? */ ++ dd_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP / 4 rounded up */ ++ dd_emit(ctx, 1, 1); /* 000000ff FP_REG_ALLOC_TEMP... without /4? */ ++ dd_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP / 4 rounded up */ ++ dd_emit(ctx, 1, 1); /* 00000001 */ ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK0 nonempty */ ++ dd_emit(ctx, 1, 0); /* 00000001 VTX_ATTR_MASK_UNK1 nonempty */ ++ dd_emit(ctx, 1, 0x200); /* 0003ffff GP_VERTEX_OUTPUT_COUNT*GP_REG_ALLOC_RESULT */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ dd_emit(ctx, 1, 0x200); ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ if (dev_priv->chipset < 0xa0) { ++ dd_emit(ctx, 1, 1); /* 00000001 */ ++ dd_emit(ctx, 1, 0x70); /* 000000ff */ ++ dd_emit(ctx, 1, 0x80); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ dd_emit(ctx, 1, 1); /* 00000001 */ ++ dd_emit(ctx, 1, 0x70); /* 000000ff */ ++ dd_emit(ctx, 1, 0x80); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 000000ff */ ++ } else { ++ dd_emit(ctx, 1, 1); /* 00000001 */ ++ dd_emit(ctx, 1, 0xf0); /* 000000ff */ ++ dd_emit(ctx, 1, 0xff); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 00000001 */ ++ dd_emit(ctx, 1, 1); /* 00000001 */ ++ dd_emit(ctx, 1, 0xf0); /* 000000ff */ ++ dd_emit(ctx, 1, 0xff); /* 000000ff */ ++ dd_emit(ctx, 1, 0); /* 000000ff */ ++ dd_emit(ctx, 1, 9); /* 0000003f UNK114C.COMP,SIZE */ ++ } ++ ++ /* eng2d state */ ++ dd_emit(ctx, 1, 0); /* 00000001 eng2d COLOR_KEY_ENABLE */ ++ dd_emit(ctx, 1, 0); /* 00000007 eng2d COLOR_KEY_FORMAT */ ++ dd_emit(ctx, 1, 1); /* ffffffff eng2d DST_DEPTH */ ++ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DST_FORMAT */ ++ dd_emit(ctx, 1, 0); /* ffffffff eng2d DST_LAYER */ ++ dd_emit(ctx, 1, 1); /* 00000001 eng2d DST_LINEAR */ ++ dd_emit(ctx, 1, 0); /* 00000007 eng2d PATTERN_COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0); /* 00000007 eng2d OPERATION */ ++ dd_emit(ctx, 1, 0); /* 00000003 eng2d PATTERN_SELECT */ ++ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SIFC_FORMAT */ ++ dd_emit(ctx, 1, 0); /* 00000001 eng2d SIFC_BITMAP_ENABLE */ ++ dd_emit(ctx, 1, 2); /* 00000003 eng2d SIFC_BITMAP_UNK808 */ ++ dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DU_DX_FRACT */ ++ dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DU_DX_INT */ ++ dd_emit(ctx, 1, 0); /* ffffffff eng2d BLIT_DV_DY_FRACT */ ++ dd_emit(ctx, 1, 1); /* ffffffff eng2d BLIT_DV_DY_INT */ ++ dd_emit(ctx, 1, 0); /* 00000001 eng2d BLIT_CONTROL_FILTER */ ++ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d DRAW_COLOR_FORMAT */ ++ dd_emit(ctx, 1, 0xcf); /* 000000ff eng2d SRC_FORMAT */ ++ dd_emit(ctx, 1, 1); /* 00000001 eng2d SRC_LINEAR #2 */ ++ ++ num = ctx->ctxvals_pos - base; ++ ctx->ctxvals_pos = base; ++ if (IS_NVA3F(dev_priv->chipset)) ++ cp_ctx(ctx, 0x404800, num); ++ else ++ cp_ctx(ctx, 0x405400, num); ++} ++ + /* + * xfer areas. These are a pain. + * +@@ -990,28 +1130,33 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx) + * without the help of ctxprog. + */ + +-static inline void ++static void + xf_emit(struct nouveau_grctx *ctx, int num, uint32_t val) { + int i; + if (val && ctx->mode == NOUVEAU_GRCTX_VALS) + for (i = 0; i < num; i++) +- nv_wo32(ctx->dev, ctx->data, ctx->ctxvals_pos + (i << 3), val); ++ nv_wo32(ctx->data, 4 * (ctx->ctxvals_pos + (i << 3)), val); + ctx->ctxvals_pos += num << 3; + } + + /* Gene declarations... */ + ++static void nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx); + static void nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx); +-static void nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx); ++static void nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx); + static void nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx); + static void nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx); + +@@ -1030,102 +1175,32 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) + if (dev_priv->chipset < 0xa0) { + /* Strand 0 */ + ctx->ctxvals_pos = offset; +- switch (dev_priv->chipset) { +- case 0x50: +- xf_emit(ctx, 0x99, 0); +- break; +- case 0x84: +- case 0x86: +- xf_emit(ctx, 0x384, 0); +- break; +- case 0x92: +- case 0x94: +- case 0x96: +- case 0x98: +- xf_emit(ctx, 0x380, 0); +- break; +- } +- nv50_graph_construct_gene_m2mf (ctx); +- switch (dev_priv->chipset) { +- case 0x50: +- case 0x84: +- case 0x86: +- case 0x98: +- xf_emit(ctx, 0x4c4, 0); +- break; +- case 0x92: +- case 0x94: +- case 0x96: +- xf_emit(ctx, 0x984, 0); +- break; +- } +- nv50_graph_construct_gene_unk5(ctx); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 0xa, 0); +- else +- xf_emit(ctx, 0xb, 0); +- nv50_graph_construct_gene_unk4(ctx); +- nv50_graph_construct_gene_unk3(ctx); ++ nv50_graph_construct_gene_dispatch(ctx); ++ nv50_graph_construct_gene_m2mf(ctx); ++ nv50_graph_construct_gene_unk24xx(ctx); ++ nv50_graph_construct_gene_clipid(ctx); ++ nv50_graph_construct_gene_zcull(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 1 */ + ctx->ctxvals_pos = offset + 0x1; +- nv50_graph_construct_gene_unk6(ctx); +- nv50_graph_construct_gene_unk7(ctx); +- nv50_graph_construct_gene_unk8(ctx); +- switch (dev_priv->chipset) { +- case 0x50: +- case 0x92: +- xf_emit(ctx, 0xfb, 0); +- break; +- case 0x84: +- xf_emit(ctx, 0xd3, 0); +- break; +- case 0x94: +- case 0x96: +- xf_emit(ctx, 0xab, 0); +- break; +- case 0x86: +- case 0x98: +- xf_emit(ctx, 0x6b, 0); +- break; +- } +- xf_emit(ctx, 2, 0x4e3bfdf); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 0xb, 0); +- xf_emit(ctx, 2, 0x4e3bfdf); ++ nv50_graph_construct_gene_vfetch(ctx); ++ nv50_graph_construct_gene_eng2d(ctx); ++ nv50_graph_construct_gene_csched(ctx); ++ nv50_graph_construct_gene_ropm1(ctx); ++ nv50_graph_construct_gene_ropm2(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 2 */ + ctx->ctxvals_pos = offset + 0x2; +- switch (dev_priv->chipset) { +- case 0x50: +- case 0x92: +- xf_emit(ctx, 0xa80, 0); +- break; +- case 0x84: +- xf_emit(ctx, 0xa7e, 0); +- break; +- case 0x94: +- case 0x96: +- xf_emit(ctx, 0xa7c, 0); +- break; +- case 0x86: +- case 0x98: +- xf_emit(ctx, 0xa7a, 0); +- break; +- } +- xf_emit(ctx, 1, 0x3fffff); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x1fff); +- xf_emit(ctx, 0xe, 0); +- nv50_graph_construct_gene_unk9(ctx); +- nv50_graph_construct_gene_unk2(ctx); +- nv50_graph_construct_gene_unk1(ctx); +- nv50_graph_construct_gene_unk10(ctx); ++ nv50_graph_construct_gene_ccache(ctx); ++ nv50_graph_construct_gene_unk1cxx(ctx); ++ nv50_graph_construct_gene_strmout(ctx); ++ nv50_graph_construct_gene_unk14xx(ctx); ++ nv50_graph_construct_gene_unk10xx(ctx); ++ nv50_graph_construct_gene_unk34xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + +@@ -1150,86 +1225,46 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) + } else { + /* Strand 0 */ + ctx->ctxvals_pos = offset; +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x385, 0); +- else +- xf_emit(ctx, 0x384, 0); ++ nv50_graph_construct_gene_dispatch(ctx); + nv50_graph_construct_gene_m2mf(ctx); +- xf_emit(ctx, 0x950, 0); +- nv50_graph_construct_gene_unk10(ctx); +- xf_emit(ctx, 1, 0x0fac6881); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 3, 0); +- } +- nv50_graph_construct_gene_unk8(ctx); +- if (dev_priv->chipset == 0xa0) +- xf_emit(ctx, 0x189, 0); +- else if (dev_priv->chipset == 0xa3) +- xf_emit(ctx, 0xd5, 0); +- else if (dev_priv->chipset == 0xa5) +- xf_emit(ctx, 0x99, 0); +- else if (dev_priv->chipset == 0xaa) +- xf_emit(ctx, 0x65, 0); +- else +- xf_emit(ctx, 0x6d, 0); +- nv50_graph_construct_gene_unk9(ctx); ++ nv50_graph_construct_gene_unk34xx(ctx); ++ nv50_graph_construct_gene_csched(ctx); ++ nv50_graph_construct_gene_unk1cxx(ctx); ++ nv50_graph_construct_gene_strmout(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 1 */ + ctx->ctxvals_pos = offset + 1; +- nv50_graph_construct_gene_unk1(ctx); ++ nv50_graph_construct_gene_unk10xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 2 */ + ctx->ctxvals_pos = offset + 2; +- if (dev_priv->chipset == 0xa0) { +- nv50_graph_construct_gene_unk2(ctx); +- } +- xf_emit(ctx, 0x36, 0); +- nv50_graph_construct_gene_unk5(ctx); ++ if (dev_priv->chipset == 0xa0) ++ nv50_graph_construct_gene_unk14xx(ctx); ++ nv50_graph_construct_gene_unk24xx(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 3 */ + ctx->ctxvals_pos = offset + 3; +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- nv50_graph_construct_gene_unk6(ctx); ++ nv50_graph_construct_gene_vfetch(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 4 */ + ctx->ctxvals_pos = offset + 4; +- if (dev_priv->chipset == 0xa0) +- xf_emit(ctx, 0xa80, 0); +- else if (dev_priv->chipset == 0xa3) +- xf_emit(ctx, 0xa7c, 0); +- else +- xf_emit(ctx, 0xa7a, 0); +- xf_emit(ctx, 1, 0x3fffff); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x1fff); ++ nv50_graph_construct_gene_ccache(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + + /* Strand 5 */ + ctx->ctxvals_pos = offset + 5; +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 0xb, 0); +- xf_emit(ctx, 2, 0x4e3bfdf); +- xf_emit(ctx, 3, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 0x4e3bfdf); +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 0); ++ nv50_graph_construct_gene_ropm2(ctx); ++ nv50_graph_construct_gene_ropm1(ctx); ++ /* per-ROP context */ + for (i = 0; i < 8; i++) + if (units & (1<<(i+16))) + nv50_graph_construct_gene_ropc(ctx); +@@ -1238,10 +1273,9 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) + + /* Strand 6 */ + ctx->ctxvals_pos = offset + 6; +- nv50_graph_construct_gene_unk3(ctx); +- xf_emit(ctx, 0xb, 0); +- nv50_graph_construct_gene_unk4(ctx); +- nv50_graph_construct_gene_unk7(ctx); ++ nv50_graph_construct_gene_zcull(ctx); ++ nv50_graph_construct_gene_clipid(ctx); ++ nv50_graph_construct_gene_eng2d(ctx); + if (units & (1 << 0)) + nv50_graph_construct_xfer_tp(ctx); + if (units & (1 << 1)) +@@ -1269,7 +1303,7 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) + if (units & (1 << 9)) + nv50_graph_construct_xfer_tp(ctx); + } else { +- nv50_graph_construct_gene_unk2(ctx); ++ nv50_graph_construct_gene_unk14xx(ctx); + } + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; +@@ -1290,9 +1324,70 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx) + */ + + static void ++nv50_graph_construct_gene_dispatch(struct nouveau_grctx *ctx) ++{ ++ /* start of strand 0 */ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ /* SEEK */ ++ if (dev_priv->chipset == 0x50) ++ xf_emit(ctx, 5, 0); ++ else if (!IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 6, 0); ++ else ++ xf_emit(ctx, 4, 0); ++ /* SEEK */ ++ /* the PGRAPH's internal FIFO */ ++ if (dev_priv->chipset == 0x50) ++ xf_emit(ctx, 8*3, 0); ++ else ++ xf_emit(ctx, 0x100*3, 0); ++ /* and another bonus slot?!? */ ++ xf_emit(ctx, 3, 0); ++ /* and YET ANOTHER bonus slot? */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 3, 0); ++ /* SEEK */ ++ /* CTX_SWITCH: caches of gr objects bound to subchannels. 8 values, last used index */ ++ xf_emit(ctx, 9, 0); ++ /* SEEK */ ++ xf_emit(ctx, 9, 0); ++ /* SEEK */ ++ xf_emit(ctx, 9, 0); ++ /* SEEK */ ++ xf_emit(ctx, 9, 0); ++ /* SEEK */ ++ if (dev_priv->chipset < 0x90) ++ xf_emit(ctx, 4, 0); ++ /* SEEK */ ++ xf_emit(ctx, 2, 0); ++ /* SEEK */ ++ xf_emit(ctx, 6*2, 0); ++ xf_emit(ctx, 2, 0); ++ /* SEEK */ ++ xf_emit(ctx, 2, 0); ++ /* SEEK */ ++ xf_emit(ctx, 6*2, 0); ++ xf_emit(ctx, 2, 0); ++ /* SEEK */ ++ if (dev_priv->chipset == 0x50) ++ xf_emit(ctx, 0x1c, 0); ++ else if (dev_priv->chipset < 0xa0) ++ xf_emit(ctx, 0x1e, 0); ++ else ++ xf_emit(ctx, 0x22, 0); ++ /* SEEK */ ++ xf_emit(ctx, 0x15, 0); ++} ++ ++static void + nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) + { +- /* m2mf state */ ++ /* Strand 0, right after dispatch */ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ int smallm2mf = 0; ++ if (dev_priv->chipset < 0x92 || dev_priv->chipset == 0x98) ++ smallm2mf = 1; ++ /* SEEK */ + xf_emit (ctx, 1, 0); /* DMA_NOTIFY instance >> 4 */ + xf_emit (ctx, 1, 0); /* DMA_BUFFER_IN instance >> 4 */ + xf_emit (ctx, 1, 0); /* DMA_BUFFER_OUT instance >> 4 */ +@@ -1319,427 +1414,975 @@ nv50_graph_construct_gene_m2mf(struct nouveau_grctx *ctx) + xf_emit (ctx, 1, 0); /* TILING_POSITION_OUT */ + xf_emit (ctx, 1, 0); /* OFFSET_IN_HIGH */ + xf_emit (ctx, 1, 0); /* OFFSET_OUT_HIGH */ ++ /* SEEK */ ++ if (smallm2mf) ++ xf_emit(ctx, 0x40, 0); /* 20 * ffffffff, 3ffff */ ++ else ++ xf_emit(ctx, 0x100, 0); /* 80 * ffffffff, 3ffff */ ++ xf_emit(ctx, 4, 0); /* 1f/7f, 0, 1f/7f, 0 [1f for smallm2mf, 7f otherwise] */ ++ /* SEEK */ ++ if (smallm2mf) ++ xf_emit(ctx, 0x400, 0); /* ffffffff */ ++ else ++ xf_emit(ctx, 0x800, 0); /* ffffffff */ ++ xf_emit(ctx, 4, 0); /* ff/1ff, 0, 0, 0 [ff for smallm2mf, 1ff otherwise] */ ++ /* SEEK */ ++ xf_emit(ctx, 0x40, 0); /* 20 * bits ffffffff, 3ffff */ ++ xf_emit(ctx, 0x6, 0); /* 1f, 0, 1f, 0, 1f, 0 */ + } + + static void +-nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_ccache(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* end of area 2 on pre-NVA0, area 1 on NVAx */ +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 1, 0); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0x3ff); +- else +- xf_emit(ctx, 1, 0x7ff); ++ xf_emit(ctx, 2, 0); /* RO */ ++ xf_emit(ctx, 0x800, 0); /* ffffffff */ + switch (dev_priv->chipset) { + case 0x50: +- case 0x86: +- case 0x98: +- case 0xaa: +- case 0xac: +- xf_emit(ctx, 0x542, 0); ++ case 0x92: ++ case 0xa0: ++ xf_emit(ctx, 0x2b, 0); + break; + case 0x84: +- case 0x92: ++ xf_emit(ctx, 0x29, 0); ++ break; + case 0x94: + case 0x96: +- xf_emit(ctx, 0x942, 0); +- break; +- case 0xa0: + case 0xa3: +- xf_emit(ctx, 0x2042, 0); ++ xf_emit(ctx, 0x27, 0); + break; ++ case 0x86: ++ case 0x98: + case 0xa5: + case 0xa8: +- xf_emit(ctx, 0x842, 0); ++ case 0xaa: ++ case 0xac: ++ case 0xaf: ++ xf_emit(ctx, 0x25, 0); + break; + } +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x27); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x26); +- xf_emit(ctx, 3, 0); ++ /* CB bindings, 0x80 of them. first word is address >> 8, second is ++ * size >> 4 | valid << 24 */ ++ xf_emit(ctx, 0x100, 0); /* ffffffff CB_DEF */ ++ xf_emit(ctx, 1, 0); /* 0000007f CB_ADDR_BUFFER */ ++ xf_emit(ctx, 1, 0); /* 0 */ ++ xf_emit(ctx, 0x30, 0); /* ff SET_PROGRAM_CB */ ++ xf_emit(ctx, 1, 0); /* 3f last SET_PROGRAM_CB */ ++ xf_emit(ctx, 4, 0); /* RO */ ++ xf_emit(ctx, 0x100, 0); /* ffffffff */ ++ xf_emit(ctx, 8, 0); /* 1f, 0, 0, ... */ ++ xf_emit(ctx, 8, 0); /* ffffffff */ ++ xf_emit(ctx, 4, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 3 */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_CODE_CB */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TIC */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TSC */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ ++ xf_emit(ctx, 1, 0); /* 000000ff TIC_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff TIC_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0x3fffff); /* 003fffff TIC_LIMIT */ ++ xf_emit(ctx, 1, 0); /* 000000ff TSC_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff TSC_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0x1fff); /* 000fffff TSC_LIMIT */ ++ xf_emit(ctx, 1, 0); /* 000000ff VP_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff VP_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 00ffffff VP_START_ID */ ++ xf_emit(ctx, 1, 0); /* 000000ff CB_DEF_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff CB_DEF_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 000000ff GP_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff GP_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 00ffffff GP_START_ID */ ++ xf_emit(ctx, 1, 0); /* 000000ff FP_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 00ffffff FP_START_ID */ + } + + static void +-nv50_graph_construct_gene_unk10(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_unk10xx(struct nouveau_grctx *ctx) + { ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ int i; + /* end of area 2 on pre-NVA0, area 1 on NVAx */ +- xf_emit(ctx, 0x10, 0x04000000); +- xf_emit(ctx, 0x24, 0); +- xf_emit(ctx, 2, 0x04e3bfdf); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x1fe21); ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ ++ if (dev_priv->chipset == 0x50) ++ xf_emit(ctx, 1, 0x3ff); ++ else ++ xf_emit(ctx, 1, 0x7ff); /* 000007ff */ ++ xf_emit(ctx, 1, 0); /* 111/113 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ for (i = 0; i < 8; i++) { ++ switch (dev_priv->chipset) { ++ case 0x50: ++ case 0x86: ++ case 0x98: ++ case 0xaa: ++ case 0xac: ++ xf_emit(ctx, 0xa0, 0); /* ffffffff */ ++ break; ++ case 0x84: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ xf_emit(ctx, 0x120, 0); ++ break; ++ case 0xa5: ++ case 0xa8: ++ xf_emit(ctx, 0x100, 0); /* ffffffff */ ++ break; ++ case 0xa0: ++ case 0xa3: ++ case 0xaf: ++ xf_emit(ctx, 0x400, 0); /* ffffffff */ ++ break; ++ } ++ xf_emit(ctx, 4, 0); /* 3f, 0, 0, 0 */ ++ xf_emit(ctx, 4, 0); /* ffffffff */ ++ } ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_TEMP */ ++ xf_emit(ctx, 1, 1); /* 00000001 RASTERIZE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0x27); /* 000000ff UNK0FD4 */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++} ++ ++static void ++nv50_graph_construct_gene_unk34xx(struct nouveau_grctx *ctx) ++{ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ /* end of area 2 on pre-NVA0, area 1 on NVAx */ ++ xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000003 VIEWPORT_CLIP_MODE */ ++ xf_emit(ctx, 0x10, 0x04000000); /* 07ffffff VIEWPORT_CLIP_HORIZ*8, VIEWPORT_CLIP_VERT*8 */ ++ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ ++ xf_emit(ctx, 0x20, 0); /* ffffffff POLYGON_STIPPLE */ ++ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ ++ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0x1fe21); /* 0001ffff tesla UNK0FAC */ ++ if (dev_priv->chipset >= 0xa0) ++ xf_emit(ctx, 1, 0x0fac6881); ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 3, 0); ++ } + } + + static void +-nv50_graph_construct_gene_unk2(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_unk14xx(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + /* middle of area 2 on pre-NVA0, beginning of area 2 on NVA0, area 7 on >NVA0 */ + if (dev_priv->chipset != 0x50) { +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x804); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0x8100c12); ++ xf_emit(ctx, 5, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 2, 4); /* 7f, ff */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + } +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x10); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 3, 0); +- else +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x804); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x1a); ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 000000ff VP_CLIP_DISTANCE_ENABLE */ + if (dev_priv->chipset != 0x50) +- xf_emit(ctx, 1, 0x7f); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 6, 0); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0x3ff); +- else +- xf_emit(ctx, 1, 0x7ff); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 0x38, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 0x38, 0); +- xf_emit(ctx, 2, 0x88); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 0x16, 0); +- xf_emit(ctx, 1, 0x26); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x3f800000); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 4, 0); +- else +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x1a); +- xf_emit(ctx, 1, 0x10); ++ xf_emit(ctx, 1, 0); /* 3ff */ ++ xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1940 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ ++ xf_emit(ctx, 1, 0x804); /* 00000fff SEMANTIC_CLIP */ ++ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ + if (dev_priv->chipset != 0x50) +- xf_emit(ctx, 0x28, 0); ++ xf_emit(ctx, 1, 0x7f); /* 000000ff tesla UNK0FFC */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 1); /* 00000001 SHADE_MODEL */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0D7C */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0F8C */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ if (dev_priv->chipset == 0x50) ++ xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ + else +- xf_emit(ctx, 0x25, 0); +- xf_emit(ctx, 1, 0x52); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x26); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x1a); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x00ffff00); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ ++ xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_SCALE: X0, Y0, Z0, X1, Y1, ... */ ++ xf_emit(ctx, 3, 0); /* f, 0, 0 */ ++ xf_emit(ctx, 3, 0); /* ffffffff last VIEWPORT_SCALE? */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 1); /* 00000001 VIEWPORT_TRANSFORM_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ ++ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 0x30, 0); /* ffffffff VIEWPORT_TRANSLATE */ ++ xf_emit(ctx, 3, 0); /* f, 0, 0 */ ++ xf_emit(ctx, 3, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 2, 0x88); /* 000001ff tesla UNK19D8 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ ++ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ ++ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ ++ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ ++ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ ++ if (dev_priv->chipset != 0x50) { ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ } ++ xf_emit(ctx, 0x20, 0); /* 10xbits ffffffff, 3fffff. SCISSOR_* */ ++ xf_emit(ctx, 1, 0); /* f */ ++ xf_emit(ctx, 1, 0); /* 0? */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 003fffff */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0x26); /* 000000ff SEMANTIC_LAYER */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ + } + + static void +-nv50_graph_construct_gene_unk3(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_zcull(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* end of area 0 on pre-NVA0, beginning of area 6 on NVAx */ +- xf_emit(ctx, 1, 0x3f); +- xf_emit(ctx, 0xa, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 0x04000000); +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 4); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 0x10, 0); +- else +- xf_emit(ctx, 0x11, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x1001); +- xf_emit(ctx, 4, 0xffff); +- xf_emit(ctx, 0x20, 0); +- xf_emit(ctx, 0x10, 0x3f800000); +- xf_emit(ctx, 1, 0x10); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0); +- else +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 2, 0); ++ /* end of strand 0 on pre-NVA0, beginning of strand 6 on NVAx */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ ++ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ ++ xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ ++ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ ++ xf_emit(ctx, 1, 0); /* 0000ffff */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK0FB0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ if (dev_priv->chipset != 0x50) ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1108 */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ ++ /* SEEK */ ++ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ ++ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ ++ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ ++ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff/3ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 00000001 VIEWPORT_CLIP_RECTS_EN */ ++ xf_emit(ctx, 1, 3); /* 00000003 FP_CTRL_UNK196C */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1968 */ ++ if (dev_priv->chipset != 0x50) ++ xf_emit(ctx, 1, 0); /* 0fffffff tesla UNK1104 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK151C */ + } + + static void +-nv50_graph_construct_gene_unk4(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_clipid(struct nouveau_grctx *ctx) + { +- /* middle of area 0 on pre-NVA0, middle of area 6 on NVAx */ +- xf_emit(ctx, 2, 0x04000000); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 1, 0); ++ /* middle of strand 0 on pre-NVA0 [after 24xx], middle of area 6 on NVAx */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000007 UNK0FB4 */ ++ /* SEEK */ ++ xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_HORIZ */ ++ xf_emit(ctx, 4, 0); /* 07ffffff CLIPID_REGION_VERT */ ++ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ ++ xf_emit(ctx, 2, 0x04000000); /* 07ffffff UNK1508 */ ++ xf_emit(ctx, 1, 0); /* 00000001 CLIPID_ENABLE */ ++ xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_WIDTH */ ++ xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ID */ ++ xf_emit(ctx, 1, 0); /* 000000ff CLIPID_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff CLIPID_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0x80); /* 00003fff CLIPID_HEIGHT */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_CLIPID */ + } + + static void +-nv50_graph_construct_gene_unk5(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* middle of area 0 on pre-NVA0 [after m2mf], end of area 2 on NVAx */ +- xf_emit(ctx, 2, 4); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x1c4d, 0); ++ int i; ++ /* middle of strand 0 on pre-NVA0 [after m2mf], end of strand 2 on NVAx */ ++ /* SEEK */ ++ xf_emit(ctx, 0x33, 0); ++ /* SEEK */ ++ xf_emit(ctx, 2, 0); ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 4, 0); /* RO */ ++ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ ++ xf_emit(ctx, 1, 0); /* 1ff */ ++ xf_emit(ctx, 8, 0); /* 0? */ ++ xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ ++ ++ xf_emit(ctx, 4, 0); /* RO */ ++ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ ++ xf_emit(ctx, 1, 0); /* 1ff */ ++ xf_emit(ctx, 8, 0); /* 0? */ ++ xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ ++ } + else +- xf_emit(ctx, 0x1c4b, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0x8100c12); ++ { ++ xf_emit(ctx, 0xc, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ ++ xf_emit(ctx, 1, 0); /* 1ff */ ++ xf_emit(ctx, 8, 0); /* 0? */ ++ ++ /* SEEK */ ++ xf_emit(ctx, 0xc, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ ++ xf_emit(ctx, 1, 0); /* 1ff */ ++ xf_emit(ctx, 8, 0); /* 0? */ ++ } ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ + if (dev_priv->chipset != 0x50) +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 1); /* 00000001 */ ++ /* SEEK */ + if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0x80c14); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 1, 0x27); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x3c1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x16, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 2, 4); /* 000000ff */ ++ xf_emit(ctx, 1, 0x80c14); /* 01ffffff SEMANTIC_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 0x27); /* 000000ff SEMANTIC_PRIM_ID */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 1); /* 00000001 */ ++ for (i = 0; i < 10; i++) { ++ /* SEEK */ ++ xf_emit(ctx, 0x40, 0); /* ffffffff */ ++ xf_emit(ctx, 0x10, 0); /* 3, 0, 0.... */ ++ xf_emit(ctx, 0x10, 0); /* ffffffff */ ++ } ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_CTRL */ ++ xf_emit(ctx, 1, 1); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 4, 0); /* ffffffff NOPERSPECTIVE_BITMAP */ ++ xf_emit(ctx, 0x10, 0); /* 00ffffff POINT_COORD_REPLACE_MAP */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ if (dev_priv->chipset != 0x50) ++ xf_emit(ctx, 1, 0); /* 000003ff */ + } + + static void +-nv50_graph_construct_gene_unk6(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_vfetch(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* beginning of area 1 on pre-NVA0 [after m2mf], area 3 on NVAx */ +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0xf); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 8, 0); +- else +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x20); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x11, 0); ++ int acnt = 0x10, rep, i; ++ /* beginning of strand 1 on pre-NVA0, strand 3 on NVAx */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ acnt = 0x20; ++ /* SEEK */ ++ if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK13A4 */ ++ xf_emit(ctx, 1, 1); /* 00000fff tesla UNK1318 */ ++ } ++ xf_emit(ctx, 1, 0); /* ffffffff VERTEX_BUFFER_FIRST */ ++ xf_emit(ctx, 1, 0); /* 00000001 PRIMITIVE_RESTART_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK0DE8 */ ++ xf_emit(ctx, 1, 0); /* ffffffff PRIMITIVE_RESTART_INDEX */ ++ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATR_MASK_UNK0DD0 */ ++ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ ++ xf_emit(ctx, 1, 0x20); /* 0000ffff tesla UNK129C */ ++ xf_emit(ctx, 1, 0); /* 000000ff turing UNK370??? */ ++ xf_emit(ctx, 1, 0); /* 0000ffff turing USER_PARAM_COUNT */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0xb, 0); /* RO */ + else if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 0xf, 0); ++ xf_emit(ctx, 0x9, 0); /* RO */ + else +- xf_emit(ctx, 0xe, 0); +- xf_emit(ctx, 1, 0x1a); +- xf_emit(ctx, 0xd, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 8); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 0x8, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 00000001 EDGE_FLAG */ ++ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ ++ /* SEEK */ ++ xf_emit(ctx, 0xc, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 7f/ff */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ ++ xf_emit(ctx, 1, 4); /* 000001ff UNK1A28 */ ++ xf_emit(ctx, 1, 8); /* 000001ff UNK0DF0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0x3ff); ++ xf_emit(ctx, 1, 0x3ff); /* 3ff tesla UNK0D68 */ + else +- xf_emit(ctx, 1, 0x7ff); ++ xf_emit(ctx, 1, 0x7ff); /* 7ff tesla UNK0D68 */ + if (dev_priv->chipset == 0xa8) +- xf_emit(ctx, 1, 0x1e00); +- xf_emit(ctx, 0xc, 0); +- xf_emit(ctx, 1, 0xf); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 0x125, 0); +- else if (dev_priv->chipset < 0xa0) +- xf_emit(ctx, 0x126, 0); +- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) +- xf_emit(ctx, 0x124, 0); ++ xf_emit(ctx, 1, 0x1e00); /* 7fff */ ++ /* SEEK */ ++ xf_emit(ctx, 0xc, 0); /* RO or close */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ ++ if (dev_priv->chipset > 0x50 && dev_priv->chipset < 0xa0) ++ xf_emit(ctx, 2, 0); /* ffffffff */ + else +- xf_emit(ctx, 0x1f7, 0); +- xf_emit(ctx, 1, 0xf); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 3, 0); ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0FD8 */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 0x10, 0); /* 0? */ ++ xf_emit(ctx, 2, 0); /* weird... */ ++ xf_emit(ctx, 2, 0); /* RO */ ++ } else { ++ xf_emit(ctx, 8, 0); /* 0? */ ++ xf_emit(ctx, 1, 0); /* weird... */ ++ xf_emit(ctx, 2, 0); /* RO */ ++ } ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* ffffffff VB_ELEMENT_BASE */ ++ xf_emit(ctx, 1, 0); /* ffffffff UNK1438 */ ++ xf_emit(ctx, acnt, 0); /* 1 tesla UNK1000 */ ++ if (dev_priv->chipset >= 0xa0) ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1118? */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ ++ xf_emit(ctx, 1, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_UNK90C */ ++ xf_emit(ctx, 1, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* RO */ ++ xf_emit(ctx, 2, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK111C? */ ++ xf_emit(ctx, 1, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 000000ff UNK15F4_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff UNK15F4_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 000000ff UNK0F84_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff UNK0F84_ADDRESS_LOW */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* 00003fff VERTEX_ARRAY_ATTRIB_OFFSET */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* 00000fff VERTEX_ARRAY_STRIDE */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_ARRAY_LOW */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_ARRAY_HIGH */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* ffffffff VERTEX_LIMIT_LOW */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ xf_emit(ctx, acnt, 0); /* 000000ff VERTEX_LIMIT_HIGH */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, acnt, 0); /* f */ ++ xf_emit(ctx, 3, 0); /* f/1f */ ++ } ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 2, 0); /* RO */ ++ else ++ xf_emit(ctx, 5, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* ffff DMA_VTXBUF */ ++ /* SEEK */ ++ if (dev_priv->chipset < 0xa0) { ++ xf_emit(ctx, 0x41, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 0x11, 0); /* RO */ ++ } else if (!IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x50, 0); /* RO */ + else +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0xa1, 0); ++ xf_emit(ctx, 0x58, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, 1, 1); /* 1 UNK0DEC */ ++ /* SEEK */ ++ xf_emit(ctx, acnt*4, 0); /* ffffffff VTX_ATTR */ ++ xf_emit(ctx, 4, 0); /* f/1f, 0, 0, 0 */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x1d, 0); /* RO */ + else +- xf_emit(ctx, 0x5a, 0); +- xf_emit(ctx, 1, 0xf); ++ xf_emit(ctx, 0x16, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ ++ /* SEEK */ + if (dev_priv->chipset < 0xa0) +- xf_emit(ctx, 0x834, 0); +- else if (dev_priv->chipset == 0xa0) +- xf_emit(ctx, 0x1873, 0); +- else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x8ba, 0); ++ xf_emit(ctx, 8, 0); /* RO */ ++ else if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0xc, 0); /* RO */ ++ else ++ xf_emit(ctx, 7, 0); /* RO */ ++ /* SEEK */ ++ xf_emit(ctx, 0xa, 0); /* RO */ ++ if (dev_priv->chipset == 0xa0) ++ rep = 0xc; ++ else ++ rep = 4; ++ for (i = 0; i < rep; i++) { ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x20, 0); /* ffffffff */ ++ xf_emit(ctx, 0x200, 0); /* ffffffff */ ++ xf_emit(ctx, 4, 0); /* 7f/ff, 0, 0, 0 */ ++ xf_emit(ctx, 4, 0); /* ffffffff */ ++ } ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 113/111 */ ++ xf_emit(ctx, 1, 0xf); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, (acnt/8)-1, 0); /* ffffffff VP_ATTR_EN */ ++ xf_emit(ctx, acnt/8, 0); /* ffffffff VTX_ATTR_MASK_UNK0DD0 */ ++ xf_emit(ctx, 1, 0); /* 0000000f VP_GP_BUILTIN_ATTR_EN */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ /* SEEK */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 7, 0); /* weird... */ + else +- xf_emit(ctx, 0x833, 0); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 0xf, 0); ++ xf_emit(ctx, 5, 0); /* weird... */ + } + + static void +-nv50_graph_construct_gene_unk7(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_eng2d(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 6 on NVAx */ +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 2, 1); +- else +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0x100); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 8); +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 3, 1); +- xf_emit(ctx, 1, 0xcf); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 3, 1); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x15); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x4444480); +- xf_emit(ctx, 0x37, 0); ++ /* middle of strand 1 on pre-NVA0 [after vfetch], middle of strand 6 on NVAx */ ++ /* SEEK */ ++ xf_emit(ctx, 2, 0); /* 0001ffff CLIP_X, CLIP_Y */ ++ xf_emit(ctx, 2, 0); /* 0000ffff CLIP_W, CLIP_H */ ++ xf_emit(ctx, 1, 0); /* 00000001 CLIP_ENABLE */ ++ if (dev_priv->chipset < 0xa0) { ++ /* this is useless on everything but the original NV50, ++ * guess they forgot to nuke it. Or just didn't bother. */ ++ xf_emit(ctx, 2, 0); /* 0000ffff IFC_CLIP_X, Y */ ++ xf_emit(ctx, 2, 1); /* 0000ffff IFC_CLIP_W, H */ ++ xf_emit(ctx, 1, 0); /* 00000001 IFC_CLIP_ENABLE */ ++ } ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ ++ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ ++ xf_emit(ctx, 1, 0x11); /* 3f[NV50]/7f[NV84+] DST_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 0001ffff DRAW_POINT_X */ ++ xf_emit(ctx, 1, 8); /* 0000000f DRAW_UNK58C */ ++ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_X_FRACT */ ++ xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_X_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DST_Y_FRACT */ ++ xf_emit(ctx, 1, 0); /* 0001ffff SIFC_DST_Y_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DX_DU_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DX_DU_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff SIFC_DY_DV_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff SIFC_DY_DV_INT */ ++ xf_emit(ctx, 1, 1); /* 0000ffff SIFC_WIDTH */ ++ xf_emit(ctx, 1, 1); /* 0000ffff SIFC_HEIGHT */ ++ xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ ++ xf_emit(ctx, 1, 2); /* 00000003 SIFC_BITMAP_UNK808 */ ++ xf_emit(ctx, 1, 0); /* 00000003 SIFC_BITMAP_LINE_PACK_MODE */ ++ xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_LSB_FIRST */ ++ xf_emit(ctx, 1, 0); /* 00000001 SIFC_BITMAP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_X */ ++ xf_emit(ctx, 1, 0); /* 0000ffff BLIT_DST_Y */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ ++ xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_W */ ++ xf_emit(ctx, 1, 1); /* 0000ffff BLIT_DST_H */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_X_FRACT */ ++ xf_emit(ctx, 1, 0); /* 0001ffff BLIT_SRC_X_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_SRC_Y_FRACT */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK888 */ ++ xf_emit(ctx, 1, 4); /* 0000003f UNK884 */ ++ xf_emit(ctx, 1, 0); /* 00000007 UNK880 */ ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK0FB8 */ ++ xf_emit(ctx, 1, 0x15); /* 000000ff tesla UNK128C */ ++ xf_emit(ctx, 2, 0); /* 00000007, ffff0ff3 */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK260 */ ++ xf_emit(ctx, 1, 0x4444480); /* 1fffffff UNK870 */ ++ /* SEEK */ ++ xf_emit(ctx, 0x10, 0); ++ /* SEEK */ ++ xf_emit(ctx, 0x27, 0); + } + + static void +-nv50_graph_construct_gene_unk8(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_csched(struct nouveau_grctx *ctx) + { +- /* middle of area 1 on pre-NVA0 [after m2mf], middle of area 0 on NVAx */ +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x100); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x10001); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x10001); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x10001); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 2); ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ /* middle of strand 1 on pre-NVA0 [after eng2d], middle of strand 0 on NVAx */ ++ /* SEEK */ ++ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY... what is it doing here??? */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1924 */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* ffffffff turing UNK364 */ ++ xf_emit(ctx, 1, 0); /* 0000000f turing UNK36C */ ++ xf_emit(ctx, 1, 0); /* 0000ffff USER_PARAM_COUNT */ ++ xf_emit(ctx, 1, 0x100); /* 00ffffff turing UNK384 */ ++ xf_emit(ctx, 1, 0); /* 0000000f turing UNK2A0 */ ++ xf_emit(ctx, 1, 0); /* 0000ffff GRIDID */ ++ xf_emit(ctx, 1, 0x10001); /* ffffffff GRIDDIM_XY */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ ++ xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ ++ xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ ++ xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ ++ xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ ++ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ ++ /* SEEK */ ++ xf_emit(ctx, 0x40, 0); /* ffffffff USER_PARAM */ ++ switch (dev_priv->chipset) { ++ case 0x50: ++ case 0x92: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0x80, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 0x10*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0x84: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0x60, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0x94: ++ case 0x96: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0x40, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 8*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0x86: ++ case 0x98: ++ xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ ++ xf_emit(ctx, 0x10, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0xa0: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0xf0, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 0x1e*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0xa3: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0x60, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 0xc*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0xa5: ++ case 0xaf: ++ xf_emit(ctx, 8, 0); /* 7, 0, 0, 0, ... */ ++ xf_emit(ctx, 0x30, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 6*2, 0); /* ffffffff, 1f */ ++ break; ++ case 0xaa: ++ xf_emit(ctx, 0x12, 0); ++ break; ++ case 0xa8: ++ case 0xac: ++ xf_emit(ctx, 4, 0); /* f, 0, 0, 0 */ ++ xf_emit(ctx, 0x10, 0); /* fff */ ++ xf_emit(ctx, 2, 0); /* ff, fff */ ++ xf_emit(ctx, 2*2, 0); /* ffffffff, 1f */ ++ break; ++ } ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 0); /* 00000000 */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 0000001f */ ++ xf_emit(ctx, 4, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 4, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000003 turing UNK35C */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 000000ff */ + } + + static void +-nv50_graph_construct_gene_unk9(struct nouveau_grctx *ctx) ++nv50_graph_construct_gene_unk1cxx(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- /* middle of area 2 on pre-NVA0 [after m2mf], end of area 0 on NVAx */ +- xf_emit(ctx, 1, 0x3f800000); +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0x1a); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x12, 0); +- xf_emit(ctx, 1, 0x00ffff00); +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 0xf, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 3); ++ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ ++ xf_emit(ctx, 1, 0x3f800000); /* ffffffff LINE_WIDTH */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ ++ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ ++ xf_emit(ctx, 3, 0); /* 00000001 POLYGON_OFFSET_*_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 0000000f CULL_MODE */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ ++ xf_emit(ctx, 0x10, 0); /* 00000001 SCISSOR_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ ++ xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_UNITS */ ++ xf_emit(ctx, 1, 0); /* ffffffff POLYGON_OFFSET_FACTOR */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ ++ xf_emit(ctx, 2, 0); /* 07ffffff SCREEN_SCISSOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ ++ xf_emit(ctx, 8, 0); /* 00000001 RT_HORIZ_LINEAR */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 3); /* 00000003 UNK16B4 */ + else if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 0x04000000); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 5); +- xf_emit(ctx, 1, 0x52); +- if (dev_priv->chipset == 0x50) { +- xf_emit(ctx, 0x13, 0); +- } else { +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x11, 0); +- else +- xf_emit(ctx, 0x10, 0); ++ xf_emit(ctx, 1, 1); /* 00000001 UNK16B4 */ ++ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ ++ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ ++ xf_emit(ctx, 2, 0x04000000); /* 07ffffff tesla UNK0D6C */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 5); /* 0000000f UNK1408 */ ++ xf_emit(ctx, 1, 0x52); /* 000001ff SEMANTIC_PTSZ */ ++ xf_emit(ctx, 1, 0); /* ffffffff POINT_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 00000007 tesla UNK0FB4 */ ++ if (dev_priv->chipset != 0x50) { ++ xf_emit(ctx, 1, 0); /* 3ff */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK1110 */ + } +- xf_emit(ctx, 0x10, 0x3f800000); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 0x26, 0); +- xf_emit(ctx, 1, 0x8100c12); +- xf_emit(ctx, 1, 5); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 4, 0xffff); ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ ++ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ ++ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ ++ xf_emit(ctx, 1, 0x10); /* 000000ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 0x20, 0); /* 07ffffff VIEWPORT_HORIZ, then VIEWPORT_VERT. (W&0x3fff)<<13 | (X&0x1fff). */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK187C */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ ++ xf_emit(ctx, 1, 0x8100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 5); /* 0000000f tesla UNK1220 */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 000000ff tesla UNK1A20 */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ ++ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ + if (dev_priv->chipset != 0x50) +- xf_emit(ctx, 1, 3); ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ + if (dev_priv->chipset < 0xa0) +- xf_emit(ctx, 0x1f, 0); +- else if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0xc, 0); +- else +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x00ffff00); +- xf_emit(ctx, 1, 0x1a); ++ xf_emit(ctx, 0x1c, 0); /* RO */ ++ else if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x9, 0); ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ ++ xf_emit(ctx, 1, 0); /* 00000003 WINDOW_ORIGIN */ + if (dev_priv->chipset != 0x50) { +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 3); ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK1100 */ ++ xf_emit(ctx, 1, 0); /* 3ff */ + } ++ /* XXX: the following block could belong either to unk1cxx, or ++ * to STRMOUT. Rather hard to tell. */ + if (dev_priv->chipset < 0xa0) +- xf_emit(ctx, 0x26, 0); ++ xf_emit(ctx, 0x25, 0); + else +- xf_emit(ctx, 0x3c, 0); +- xf_emit(ctx, 1, 0x102); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 4, 4); +- if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 0x3b, 0); ++} ++ ++static void ++nv50_graph_construct_gene_strmout(struct nouveau_grctx *ctx) ++{ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ ++ xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ ++ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ ++ if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ ++ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ ++ } ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 4); /* 0000007f VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0x3ff); ++ xf_emit(ctx, 1, 0x3ff); /* 000003ff tesla UNK0D68 */ + else +- xf_emit(ctx, 1, 0x7ff); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x102); +- xf_emit(ctx, 9, 0); +- xf_emit(ctx, 4, 4); +- xf_emit(ctx, 0x2c, 0); ++ xf_emit(ctx, 1, 0x7ff); /* 000007ff tesla UNK0D68 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0x102); /* 0000ffff STRMOUT_BUFFER_CTRL */ ++ xf_emit(ctx, 1, 0); /* ffffffff STRMOUT_PRIMITIVE_COUNT */ ++ xf_emit(ctx, 4, 0); /* 000000ff STRMOUT_ADDRESS_HIGH */ ++ xf_emit(ctx, 4, 0); /* ffffffff STRMOUT_ADDRESS_LOW */ ++ xf_emit(ctx, 4, 4); /* 000000ff STRMOUT_NUM_ATTRIBS */ ++ if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 4, 0); /* ffffffff UNK1A8C */ ++ xf_emit(ctx, 4, 0); /* ffffffff UNK1780 */ ++ } ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_STRMOUT */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ ++ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ ++ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW QUERY_COUNTER */ ++ xf_emit(ctx, 2, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ /* SEEK */ ++ xf_emit(ctx, 0x20, 0); /* ffffffff STRMOUT_MAP */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 0); /* 00000000? */ ++ xf_emit(ctx, 2, 0); /* ffffffff */ ++} ++ ++static void ++nv50_graph_construct_gene_ropm1(struct nouveau_grctx *ctx) ++{ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ ++ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++} ++ ++static void ++nv50_graph_construct_gene_ropm2(struct nouveau_grctx *ctx) ++{ ++ struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 2, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ ++ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 7 */ ++ /* SEEK */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_QUERY */ ++ xf_emit(ctx, 1, 0); /* 000000ff QUERY_ADDRESS_HIGH */ ++ xf_emit(ctx, 2, 0); /* ffffffff QUERY_ADDRESS_LOW, COUNTER */ ++ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0D64 */ ++ xf_emit(ctx, 1, 0x4e3bfdf); /* ffffffff UNK0DF4 */ ++ xf_emit(ctx, 1, 0); /* 00000001 eng2d UNK260 */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0x11); /* 000000ff tesla UNK1968 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + } + + static void +@@ -1749,443 +2392,709 @@ nv50_graph_construct_gene_ropc(struct nouveau_grctx *ctx) + int magic2; + if (dev_priv->chipset == 0x50) { + magic2 = 0x00003e60; +- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { ++ } else if (!IS_NVA3F(dev_priv->chipset)) { + magic2 = 0x001ffe67; + } else { + magic2 = 0x00087e67; + } +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, magic2); +- xf_emit(ctx, 4, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 7, 0); +- if (dev_priv->chipset >= 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 0x15); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 4, 0); ++ xf_emit(ctx, 1, 0); /* f/7 MUTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ if (dev_priv->chipset >= 0xa0 && !IS_NVAAF(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0x15); /* 000000ff */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 0x10); /* 3ff/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x92 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa0) { +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0x400); +- xf_emit(ctx, 1, 0x300); +- xf_emit(ctx, 1, 0x1001); ++ xf_emit(ctx, 3, 0); /* ff, ffffffff, ffffffff */ ++ xf_emit(ctx, 1, 4); /* 7 */ ++ xf_emit(ctx, 1, 0x400); /* fffffff */ ++ xf_emit(ctx, 1, 0x300); /* ffff */ ++ xf_emit(ctx, 1, 0x1001); /* 1fff */ + if (dev_priv->chipset != 0xa0) { +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 0); ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0); /* 0000000f UNK15C8 */ + else +- xf_emit(ctx, 1, 0x15); ++ xf_emit(ctx, 1, 0x15); /* ff */ + } +- xf_emit(ctx, 3, 0); + } +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x13, 0); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 0x10, 0); +- xf_emit(ctx, 0x10, 0x3f800000); +- xf_emit(ctx, 0x19, 0); +- xf_emit(ctx, 1, 0x10); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x3f); +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1900 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ ++ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 0x10, 0); /* ffffffff DEPTH_RANGE_NEAR */ ++ xf_emit(ctx, 0x10, 0x3f800000); /* ffffffff DEPTH_RANGE_FAR */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_BACK_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_FUNC_REF */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 2, 0); /* ffffffff DEPTH_BOUNDS */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000007 DEPTH_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 000000ff CLEAR_STENCIL */ ++ xf_emit(ctx, 1, 0); /* 00000007 STENCIL_FRONT_FUNC_FUNC */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_FUNC_REF */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 1, 0x10); /* 7f/ff VIEW_VOLUME_CLIP_CTRL */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 0x3f); /* 0000003f UNK1590 */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 2, 0); /* ffff0ff3, ffff */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff CLEAR_DEPTH */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ + if (dev_priv->chipset >= 0xa0) { + xf_emit(ctx, 2, 0); + xf_emit(ctx, 1, 0x1001); + xf_emit(ctx, 0xb, 0); + } else { +- xf_emit(ctx, 0xc, 0); ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ + } +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x11); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 4, 0); +- else +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 3, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, magic2); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 0x18, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x16, 0); ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ if (dev_priv->chipset != 0x50) { ++ xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ ++ xf_emit(ctx, 1, 0); /* 000000ff */ ++ } ++ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ ++ xf_emit(ctx, 2, 1); /* 00000007 BLEND_EQUATION_RGB, ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK12E4 */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ ++ xf_emit(ctx, 2, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* 0000000f */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 2, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ } else if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 2, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 2, 0); /* 00000001 */ + } else { +- if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 0x1b, 0); +- else +- xf_emit(ctx, 0x15, 0); ++ xf_emit(ctx, 1, 0); /* 00000007 MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1430 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ + } +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 1); ++ xf_emit(ctx, 4, 0); /* ffffffff CLEAR_COLOR */ ++ xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR A R G B */ ++ xf_emit(ctx, 1, 0); /* 00000fff eng2d UNK2B0 */ + if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 4, 0); +- else +- xf_emit(ctx, 3, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 0x10, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 0x10, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 3, 0); ++ xf_emit(ctx, 2, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f LOGIC_OP */ ++ if (dev_priv->chipset >= 0xa0) ++ xf_emit(ctx, 1, 0); /* 00000001 UNK12E4? NVA3+ only? */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK15C4 */ ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1140 */ + } +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x5b, 0); ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ xf_emit(ctx, 1, 0); /* 00000007 PATTERN_COLOR_FORMAT */ ++ xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 PATTERN_MONO_FORMAT */ ++ xf_emit(ctx, 2, 0); /* ffffffff PATTERN_MONO_BITMAP */ ++ xf_emit(ctx, 1, 0); /* 00000003 PATTERN_SELECT */ ++ xf_emit(ctx, 1, 0); /* 000000ff ROP */ ++ xf_emit(ctx, 1, 0); /* ffffffff BETA1 */ ++ xf_emit(ctx, 1, 0); /* ffffffff BETA4 */ ++ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ ++ xf_emit(ctx, 0x50, 0); /* 10x ffffff, ffffff, ffffff, ffffff, 3 PATTERN */ + } + + static void +-nv50_graph_construct_xfer_tp_x1(struct nouveau_grctx *ctx) ++nv50_graph_construct_xfer_unk84xx(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int magic3; +- if (dev_priv->chipset == 0x50) ++ switch (dev_priv->chipset) { ++ case 0x50: + magic3 = 0x1000; +- else if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) ++ break; ++ case 0x86: ++ case 0x98: ++ case 0xa8: ++ case 0xaa: ++ case 0xac: ++ case 0xaf: + magic3 = 0x1e00; +- else ++ break; ++ default: + magic3 = 0; +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 4); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0x24, 0); ++ } ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 7f/ff[NVA0+] VP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 111/113[NVA0+] */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x1f, 0); /* ffffffff */ + else if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 0x14, 0); ++ xf_emit(ctx, 0x0f, 0); /* ffffffff */ + else +- xf_emit(ctx, 0x15, 0); +- xf_emit(ctx, 2, 4); ++ xf_emit(ctx, 0x10, 0); /* fffffff VP_RESULT_MAP_1 up */ ++ xf_emit(ctx, 2, 0); /* f/1f[NVA3], fffffff/ffffffff[NVA0+] */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ + if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 1, 0x03020100); ++ xf_emit(ctx, 1, 0x03020100); /* ffffffff */ + else +- xf_emit(ctx, 1, 0x00608080); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 2, 4); +- xf_emit(ctx, 1, 0x80); ++ xf_emit(ctx, 1, 0x00608080); /* fffffff VP_RESULT_MAP_0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 2, 0); /* 111/113, 7f/ff */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ + if (magic3) +- xf_emit(ctx, 1, magic3); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 0x24, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0x03020100); +- xf_emit(ctx, 1, 3); ++ xf_emit(ctx, 1, magic3); /* 00007fff tesla UNK141C */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 111/113 */ ++ xf_emit(ctx, 0x1f, 0); /* ffffffff GP_RESULT_MAP_1 up */ ++ xf_emit(ctx, 1, 0); /* 0000001f */ ++ xf_emit(ctx, 1, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 0x80); /* 0000ffff GP_VERTEX_OUTPUT_COUNT */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0x03020100); /* ffffffff GP_RESULT_MAP_0 */ ++ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ + if (magic3) +- xf_emit(ctx, 1, magic3); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 4); ++ xf_emit(ctx, 1, magic3); /* 7fff tesla UNK141C */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 111/113 */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ ++ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK13A0 */ ++ xf_emit(ctx, 1, 4); /* 7f/ff VP_REG_ALLOC_RESULT */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ xf_emit(ctx, 1, 0); /* 111/113 */ + if (dev_priv->chipset == 0x94 || dev_priv->chipset == 0x96) +- xf_emit(ctx, 0x1024, 0); ++ xf_emit(ctx, 0x1020, 0); /* 4 x (0x400 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ + else if (dev_priv->chipset < 0xa0) +- xf_emit(ctx, 0xa24, 0); +- else if (dev_priv->chipset == 0xa0 || dev_priv->chipset >= 0xaa) +- xf_emit(ctx, 0x214, 0); ++ xf_emit(ctx, 0xa20, 0); /* 4 x (0x280 x 0xffffffff, ff, 0, 0, 0, 4 x ffffffff) */ ++ else if (!IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x210, 0); /* ffffffff */ + else +- xf_emit(ctx, 0x414, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 2, 0); ++ xf_emit(ctx, 0x410, 0); /* ffffffff */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff GP_RESULT_MAP_SIZE */ ++ xf_emit(ctx, 1, 3); /* 00000003 GP_OUTPUT_PRIMITIVE_TYPE */ ++ xf_emit(ctx, 1, 0); /* 00000001 PROVOKING_VERTEX_LAST */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ + } + + static void +-nv50_graph_construct_xfer_tp_x2(struct nouveau_grctx *ctx) ++nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int magic1, magic2; + if (dev_priv->chipset == 0x50) { + magic1 = 0x3ff; + magic2 = 0x00003e60; +- } else if (dev_priv->chipset <= 0xa0 || dev_priv->chipset >= 0xaa) { ++ } else if (!IS_NVA3F(dev_priv->chipset)) { + magic1 = 0x7ff; + magic2 = 0x001ffe67; + } else { + magic1 = 0x7ff; + magic2 = 0x00087e67; + } +- xf_emit(ctx, 3, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0xc, 0); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 0xb, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 4, 0xffff); +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 1, 0); +- } else if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0xa, 0); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 0x18, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* ffffffff ALPHA_TEST_REF */ ++ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000000f UNK16A0 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_BACK_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_BACK_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 4, 0); /* ffffffff BLEND_COLOR */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK19C0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK0FDC */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ff[NV50]/3ff[NV84+] */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 3, 0); /* 00000007 STENCIL_FRONT_OP_FAIL, ZFAIL, ZPASS */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_BACK_ENABLE */ ++ xf_emit(ctx, 2, 0); /* 00007fff WINDOW_OFFSET_XY */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ ++ xf_emit(ctx, 1, 0); /* 7 */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff COLOR_KEY */ ++ xf_emit(ctx, 1, 0); /* 00000001 COLOR_KEY_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 COLOR_KEY_FORMAT */ ++ xf_emit(ctx, 2, 0); /* ffffffff SIFC_BITMAP_COLOR */ ++ xf_emit(ctx, 1, 1); /* 00000001 SIFC_BITMAP_WRITE_BIT0_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1298 */ ++ } else if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK16B4 */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ } else { ++ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ + } +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 3, 0xcf); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0xa, 0); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, magic2); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x11); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 2, 1); +- else +- xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_RGB */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_RGB */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_SRC_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_DST_ALPHA */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ ++ } ++ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ ++ xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ ++ xf_emit(ctx, 1, 0); /* 7 */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ xf_emit(ctx, 1, 0); /* 00000007 OPERATION */ ++ xf_emit(ctx, 1, 0xcf); /* 000000ff SIFC_FORMAT */ ++ xf_emit(ctx, 1, 0xcf); /* 000000ff DRAW_COLOR_FORMAT */ ++ xf_emit(ctx, 1, 0xcf); /* 000000ff SRC_FORMAT */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ xf_emit(ctx, 1, 0); /* 7/f[NVA3] MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 8, 1); /* 00000001 UNK19E0 */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ + if(dev_priv->chipset == 0x50) +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 1, 0); /* ff */ + else +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, magic1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 0x28, 0); +- xf_emit(ctx, 8, 8); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 8, 0x400); +- xf_emit(ctx, 8, 0x300); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x20); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 0x100); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x40); +- xf_emit(ctx, 1, 0x100); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 4, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, magic2); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 9, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x400); +- xf_emit(ctx, 1, 0x300); +- xf_emit(ctx, 1, 0x1001); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 4, 0); +- else +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 1, 0xf); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 0x15, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 3, 0); +- } else +- xf_emit(ctx, 0x17, 0); ++ xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DU_DX_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DU_DX_INT */ ++ xf_emit(ctx, 1, 0); /* 000fffff BLIT_DV_DY_FRACT */ ++ xf_emit(ctx, 1, 1); /* 0001ffff BLIT_DV_DY_INT */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, magic1); /* 3ff/7ff tesla UNK0D68 */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 8, 0); /* 0000ffff DMA_COLOR */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_GLOBAL */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_LOCAL */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_STACK */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_DST */ ++ xf_emit(ctx, 1, 0); /* 7 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 8, 0); /* 000000ff RT_ADDRESS_HIGH */ ++ xf_emit(ctx, 8, 0); /* ffffffff RT_LAYER_STRIDE */ ++ xf_emit(ctx, 8, 0); /* ffffffff RT_ADDRESS_LOW */ ++ xf_emit(ctx, 8, 8); /* 0000007f RT_TILE_MODE */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 8, 0x400); /* 0fffffff RT_HORIZ */ ++ xf_emit(ctx, 8, 0x300); /* 0000ffff RT_VERT */ ++ xf_emit(ctx, 1, 1); /* 00001fff RT_ARRAY_MODE */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, 0x20); /* 00000fff DST_TILE_MODE */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_HEIGHT */ ++ xf_emit(ctx, 1, 0); /* 000007ff DST_LAYER */ ++ xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ ++ xf_emit(ctx, 1, 0); /* ffffffff DST_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0); /* 000000ff DST_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0x40); /* 0007ffff DST_PITCH */ ++ xf_emit(ctx, 1, 0x100); /* 0001ffff DST_WIDTH */ ++ xf_emit(ctx, 1, 0); /* 0000ffff */ ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK15AC */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 2); /* 00000003 tesla UNK143C */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_ZETA */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 2, 0); /* ffff, ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 0001ffff GP_BUILTIN_RESULT_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 000000ff STENCIL_FRONT_MASK */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* ffffffff ZETA_LAYER_STRIDE */ ++ xf_emit(ctx, 1, 0); /* 000000ff ZETA_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff ZETA_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 4); /* 00000007 ZETA_TILE_MODE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ xf_emit(ctx, 1, 0x400); /* 0fffffff ZETA_HORIZ */ ++ xf_emit(ctx, 1, 0x300); /* 0000ffff ZETA_VERT */ ++ xf_emit(ctx, 1, 0x1001); /* 00001fff ZETA_ARRAY_MODE */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 0); /* 00000001 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 3f/7f RT_FORMAT */ ++ xf_emit(ctx, 1, 0x0fac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0xf); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 7, 0); /* 0000000f COLOR_MASK */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000003 UNK0F90 */ ++ xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ ++ xf_emit(ctx, 1, 0); /* 7 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ } ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ + if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 1, 0x0fac6881); +- xf_emit(ctx, 1, magic2); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 3, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 2, 1); +- else +- xf_emit(ctx, 1, 1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 2, 0); +- else if (dev_priv->chipset != 0x50) +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 1, 0x0fac6881); /* fffffff */ ++ xf_emit(ctx, 1, magic2); /* 001fffff tesla UNK0F78 */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_BOUNDS_EN */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE_ENABLE */ ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK0FB0 */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000001 STENCIL_FRONT_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK15B4 */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK19CC */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0); /* 00000001 SAMPLECNT_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 0000000f ZETA_FORMAT */ ++ xf_emit(ctx, 1, 1); /* 00000001 ZETA_ENABLE */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* 0000000f tesla UNK15C8 */ ++ } ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A3C */ ++ if (dev_priv->chipset >= 0xa0) { ++ xf_emit(ctx, 3, 0); /* 7/f, 1, ffff0ff3 */ ++ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ ++ xf_emit(ctx, 4, 0); /* 1, 1, 1, 3ff */ ++ xf_emit(ctx, 1, 4); /* 7 */ ++ xf_emit(ctx, 1, 0); /* 1 */ ++ xf_emit(ctx, 2, 1); /* 1 */ ++ xf_emit(ctx, 2, 0); /* 7, f */ ++ xf_emit(ctx, 1, 1); /* 1 */ ++ xf_emit(ctx, 1, 0); /* 7/f */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 0x9, 0); /* 1 */ ++ else ++ xf_emit(ctx, 0x8, 0); /* 1 */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 8, 1); /* 1 */ ++ xf_emit(ctx, 1, 0x11); /* 7f */ ++ xf_emit(ctx, 7, 0); /* 7f */ ++ xf_emit(ctx, 1, 0xfac6881); /* fffffff */ ++ xf_emit(ctx, 1, 0xf); /* f */ ++ xf_emit(ctx, 7, 0); /* f */ ++ xf_emit(ctx, 1, 0x11); /* 7f */ ++ xf_emit(ctx, 1, 1); /* 1 */ ++ xf_emit(ctx, 5, 0); /* 1, 7, 3ff, 3, 7 */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ } ++ } + } + + static void +-nv50_graph_construct_xfer_tp_x3(struct nouveau_grctx *ctx) ++nv50_graph_construct_xfer_tex(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 2, 0); /* 1 LINKED_TSC. yes, 2. */ ++ if (dev_priv->chipset != 0x50) ++ xf_emit(ctx, 1, 0); /* 3 */ ++ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DU_DX_INT */ ++ xf_emit(ctx, 1, 0); /* fffff BLIT_DU_DX_FRACT */ ++ xf_emit(ctx, 1, 1); /* 1ffff BLIT_DV_DY_INT */ ++ xf_emit(ctx, 1, 0); /* fffff BLIT_DV_DY_FRACT */ + if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 2, 0); ++ xf_emit(ctx, 1, 0); /* 3 BLIT_CONTROL */ + else +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0x2a712488); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x4085c000); +- xf_emit(ctx, 1, 0x40); +- xf_emit(ctx, 1, 0x100); +- xf_emit(ctx, 1, 0x10100); +- xf_emit(ctx, 1, 0x02800000); ++ xf_emit(ctx, 2, 0); /* 3ff, 1 */ ++ xf_emit(ctx, 1, 0x2a712488); /* ffffffff SRC_TIC_0 */ ++ xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_1 */ ++ xf_emit(ctx, 1, 0x4085c000); /* ffffffff SRC_TIC_2 */ ++ xf_emit(ctx, 1, 0x40); /* ffffffff SRC_TIC_3 */ ++ xf_emit(ctx, 1, 0x100); /* ffffffff SRC_TIC_4 */ ++ xf_emit(ctx, 1, 0x10100); /* ffffffff SRC_TIC_5 */ ++ xf_emit(ctx, 1, 0x02800000); /* ffffffff SRC_TIC_6 */ ++ xf_emit(ctx, 1, 0); /* ffffffff SRC_TIC_7 */ ++ if (dev_priv->chipset == 0x50) { ++ xf_emit(ctx, 1, 0); /* 00000001 turing UNK358 */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ ++ xf_emit(ctx, 1, 0); /* 00000003 turing UNK37C tesla UNK1690 */ ++ xf_emit(ctx, 1, 0); /* 00000003 BLIT_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000001 turing UNK32C tesla UNK0F94 */ ++ } else if (!IS_NVAAF(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34? */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1664 / turing UNK03E8 */ ++ xf_emit(ctx, 1, 0); /* 00000003 */ ++ xf_emit(ctx, 1, 0); /* 000003ff */ ++ } else { ++ xf_emit(ctx, 0x6, 0); ++ } ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_TEXTURE */ ++ xf_emit(ctx, 1, 0); /* 0000ffff DMA_SRC */ + } + + static void +-nv50_graph_construct_xfer_tp_x4(struct nouveau_grctx *ctx) ++nv50_graph_construct_xfer_unk8cxx(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- xf_emit(ctx, 2, 0x04e3bfdf); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x00ffff00); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 2, 1); +- else +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 0x00ffff00); +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0x30201000); +- xf_emit(ctx, 1, 0x70605040); +- xf_emit(ctx, 1, 0xb8a89888); +- xf_emit(ctx, 1, 0xf8e8d8c8); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x1a); +-} +- +-static void +-nv50_graph_construct_xfer_tp_x5(struct nouveau_grctx *ctx) +-{ +- struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 0xfac6881); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 2, 0); +- xf_emit(ctx, 1, 1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0xb, 0); +- else +- xf_emit(ctx, 0xa, 0); +- xf_emit(ctx, 8, 1); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0xfac6881); +- xf_emit(ctx, 1, 0xf); +- xf_emit(ctx, 7, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 1); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 6, 0); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 6, 0); +- } else { +- xf_emit(ctx, 0xb, 0); +- } ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 2, 0); /* 7, ffff0ff3 */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ ++ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0D64 */ ++ xf_emit(ctx, 1, 0x04e3bfdf); /* ffffffff UNK0DF4 */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK0F98 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1668 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_STIPPLE_ENABLE */ ++ xf_emit(ctx, 1, 0x00ffff00); /* 00ffffff LINE_STIPPLE_PATTERN */ ++ xf_emit(ctx, 1, 0); /* 00000001 POLYGON_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1658 */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINE_SMOOTH_ENABLE */ ++ xf_emit(ctx, 1, 0); /* ffff0ff3 */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 DEPTH_WRITE */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK15B4 */ ++ xf_emit(ctx, 1, 0); /* 00000001 POINT_SPRITE_ENABLE */ ++ xf_emit(ctx, 1, 1); /* 00000001 tesla UNK165C */ ++ xf_emit(ctx, 1, 0x30201000); /* ffffffff tesla UNK1670 */ ++ xf_emit(ctx, 1, 0x70605040); /* ffffffff tesla UNK1670 */ ++ xf_emit(ctx, 1, 0xb8a89888); /* ffffffff tesla UNK1670 */ ++ xf_emit(ctx, 1, 0xf8e8d8c8); /* ffffffff tesla UNK1670 */ ++ xf_emit(ctx, 1, 0); /* 00000001 VERTEX_TWO_SIDE_ENABLE */ ++ xf_emit(ctx, 1, 0x1a); /* 0000001f POLYGON_MODE */ + } + + static void +@@ -2193,108 +3102,136 @@ nv50_graph_construct_xfer_tp(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + if (dev_priv->chipset < 0xa0) { +- nv50_graph_construct_xfer_tp_x1(ctx); +- nv50_graph_construct_xfer_tp_x2(ctx); +- nv50_graph_construct_xfer_tp_x3(ctx); +- if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 0xf, 0); +- else +- xf_emit(ctx, 0x12, 0); +- nv50_graph_construct_xfer_tp_x4(ctx); ++ nv50_graph_construct_xfer_unk84xx(ctx); ++ nv50_graph_construct_xfer_tprop(ctx); ++ nv50_graph_construct_xfer_tex(ctx); ++ nv50_graph_construct_xfer_unk8cxx(ctx); + } else { +- nv50_graph_construct_xfer_tp_x3(ctx); +- if (dev_priv->chipset < 0xaa) +- xf_emit(ctx, 0xc, 0); +- else +- xf_emit(ctx, 0xa, 0); +- nv50_graph_construct_xfer_tp_x2(ctx); +- nv50_graph_construct_xfer_tp_x5(ctx); +- nv50_graph_construct_xfer_tp_x4(ctx); +- nv50_graph_construct_xfer_tp_x1(ctx); ++ nv50_graph_construct_xfer_tex(ctx); ++ nv50_graph_construct_xfer_tprop(ctx); ++ nv50_graph_construct_xfer_unk8cxx(ctx); ++ nv50_graph_construct_xfer_unk84xx(ctx); + } + } + + static void +-nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx) ++nv50_graph_construct_xfer_mpc(struct nouveau_grctx *ctx) + { + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; +- int i, mpcnt; +- if (dev_priv->chipset == 0x98 || dev_priv->chipset == 0xaa) +- mpcnt = 1; +- else if (dev_priv->chipset < 0xa0 || dev_priv->chipset >= 0xa8) +- mpcnt = 2; +- else +- mpcnt = 3; ++ int i, mpcnt = 2; ++ switch (dev_priv->chipset) { ++ case 0x98: ++ case 0xaa: ++ mpcnt = 1; ++ break; ++ case 0x50: ++ case 0x84: ++ case 0x86: ++ case 0x92: ++ case 0x94: ++ case 0x96: ++ case 0xa8: ++ case 0xac: ++ mpcnt = 2; ++ break; ++ case 0xa0: ++ case 0xa3: ++ case 0xa5: ++ case 0xaf: ++ mpcnt = 3; ++ break; ++ } + for (i = 0; i < mpcnt; i++) { +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x80); +- xf_emit(ctx, 1, 0x80007004); +- xf_emit(ctx, 1, 0x04000400); ++ xf_emit(ctx, 1, 0); /* ff */ ++ xf_emit(ctx, 1, 0x80); /* ffffffff tesla UNK1404 */ ++ xf_emit(ctx, 1, 0x80007004); /* ffffffff tesla UNK12B0 */ ++ xf_emit(ctx, 1, 0x04000400); /* ffffffff */ + if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 1, 0xc0); +- xf_emit(ctx, 1, 0x1000); +- xf_emit(ctx, 2, 0); +- if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset >= 0xa8) { +- xf_emit(ctx, 1, 0xe00); +- xf_emit(ctx, 1, 0x1e00); ++ xf_emit(ctx, 1, 0xc0); /* 00007fff tesla UNK152C */ ++ xf_emit(ctx, 1, 0x1000); /* 0000ffff tesla UNK0D60 */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A30 */ ++ if (dev_priv->chipset == 0x86 || dev_priv->chipset == 0x98 || dev_priv->chipset == 0xa8 || IS_NVAAF(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0xe00); /* 7fff */ ++ xf_emit(ctx, 1, 0x1e00); /* 7fff */ + } +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0); ++ xf_emit(ctx, 1, 1); /* 000000ff VP_REG_ALLOC_TEMP */ ++ xf_emit(ctx, 1, 0); /* 00000001 LINKED_TSC */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ + if (dev_priv->chipset == 0x50) +- xf_emit(ctx, 2, 0x1000); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 2); +- if (dev_priv->chipset >= 0xaa) +- xf_emit(ctx, 0xb, 0); ++ xf_emit(ctx, 2, 0x1000); /* 7fff tesla UNK141C */ ++ xf_emit(ctx, 1, 1); /* 000000ff GP_REG_ALLOC_TEMP */ ++ xf_emit(ctx, 1, 0); /* 00000001 GP_ENABLE */ ++ xf_emit(ctx, 1, 4); /* 000000ff FP_REG_ALLOC_TEMP */ ++ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ ++ if (IS_NVAAF(dev_priv->chipset)) ++ xf_emit(ctx, 0xb, 0); /* RO */ + else if (dev_priv->chipset >= 0xa0) +- xf_emit(ctx, 0xc, 0); ++ xf_emit(ctx, 0xc, 0); /* RO */ + else +- xf_emit(ctx, 0xa, 0); ++ xf_emit(ctx, 0xa, 0); /* RO */ + } +- xf_emit(ctx, 1, 0x08100c12); +- xf_emit(ctx, 1, 0); ++ xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ + if (dev_priv->chipset >= 0xa0) { +- xf_emit(ctx, 1, 0x1fe21); ++ xf_emit(ctx, 1, 0x1fe21); /* 0003ffff tesla UNK0FAC */ + } +- xf_emit(ctx, 5, 0); +- xf_emit(ctx, 4, 0xffff); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 2, 0x10001); +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 0x1fe21); +- xf_emit(ctx, 1, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 1); +- xf_emit(ctx, 4, 0); +- xf_emit(ctx, 1, 0x08100c12); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 8, 0); +- xf_emit(ctx, 1, 0xfac6881); +- xf_emit(ctx, 1, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) +- xf_emit(ctx, 1, 3); +- xf_emit(ctx, 3, 0); +- xf_emit(ctx, 1, 4); +- xf_emit(ctx, 9, 0); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 2, 1); +- xf_emit(ctx, 1, 2); +- xf_emit(ctx, 3, 1); +- xf_emit(ctx, 1, 0); +- if (dev_priv->chipset > 0xa0 && dev_priv->chipset < 0xaa) { +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 0x10, 1); +- xf_emit(ctx, 8, 2); +- xf_emit(ctx, 0x18, 1); +- xf_emit(ctx, 3, 0); ++ xf_emit(ctx, 3, 0); /* 7fff, 0, 0 */ ++ xf_emit(ctx, 1, 0); /* 00000001 tesla UNK1534 */ ++ xf_emit(ctx, 1, 0); /* 7/f MULTISAMPLE_SAMPLES_LOG2 */ ++ xf_emit(ctx, 4, 0xffff); /* 0000ffff MSAA_MASK */ ++ xf_emit(ctx, 1, 1); /* 00000001 LANES32 */ ++ xf_emit(ctx, 1, 0x10001); /* 00ffffff BLOCK_ALLOC */ ++ xf_emit(ctx, 1, 0x10001); /* ffffffff BLOCKDIM_XY */ ++ xf_emit(ctx, 1, 1); /* 0000ffff BLOCKDIM_Z */ ++ xf_emit(ctx, 1, 0); /* ffffffff SHARED_SIZE */ ++ xf_emit(ctx, 1, 0x1fe21); /* 1ffff/3ffff[NVA0+] tesla UNk0FAC */ ++ xf_emit(ctx, 1, 0); /* ffffffff tesla UNK1A34 */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ ++ xf_emit(ctx, 1, 0); /* ff/3ff */ ++ xf_emit(ctx, 1, 0); /* 1 LINKED_TSC */ ++ xf_emit(ctx, 1, 0); /* ff FP_ADDRESS_HIGH */ ++ xf_emit(ctx, 1, 0); /* ffffffff FP_ADDRESS_LOW */ ++ xf_emit(ctx, 1, 0x08100c12); /* 1fffffff FP_INTERPOLANT_CTRL */ ++ xf_emit(ctx, 1, 4); /* 00000007 FP_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 000000ff FRAG_COLOR_CLAMP_EN */ ++ xf_emit(ctx, 1, 2); /* 00000003 REG_MODE */ ++ xf_emit(ctx, 1, 0x11); /* 0000007f RT_FORMAT */ ++ xf_emit(ctx, 7, 0); /* 0000007f RT_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 00000007 */ ++ xf_emit(ctx, 1, 0xfac6881); /* 0fffffff RT_CONTROL */ ++ xf_emit(ctx, 1, 0); /* 00000003 MULTISAMPLE_CTRL */ ++ if (IS_NVA3F(dev_priv->chipset)) ++ xf_emit(ctx, 1, 3); /* 00000003 tesla UNK16B4 */ ++ xf_emit(ctx, 1, 0); /* 00000001 ALPHA_TEST_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000007 ALPHA_TEST_FUNC */ ++ xf_emit(ctx, 1, 0); /* 00000001 FRAMEBUFFER_SRGB */ ++ xf_emit(ctx, 1, 4); /* ffffffff tesla UNK1400 */ ++ xf_emit(ctx, 8, 0); /* 00000001 BLEND_ENABLE */ ++ xf_emit(ctx, 1, 0); /* 00000001 LOGIC_OP_ENABLE */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_RGB */ ++ xf_emit(ctx, 1, 2); /* 0000001f BLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 0000001f BLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000007 BLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 1, 1); /* 00000001 UNK133C */ ++ if (IS_NVA3F(dev_priv->chipset)) { ++ xf_emit(ctx, 1, 0); /* 00000001 UNK12E4 */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_RGB */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_RGB */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_RGB */ ++ xf_emit(ctx, 8, 2); /* 0000001f IBLEND_FUNC_SRC_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 0000001f IBLEND_FUNC_DST_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 00000007 IBLEND_EQUATION_ALPHA */ ++ xf_emit(ctx, 8, 1); /* 00000001 IBLEND_UNK00 */ ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK1928 */ ++ xf_emit(ctx, 1, 0); /* 00000001 UNK1140 */ + } +- xf_emit(ctx, 1, 4); ++ xf_emit(ctx, 1, 0); /* 00000003 tesla UNK0F90 */ ++ xf_emit(ctx, 1, 4); /* 000000ff FP_RESULT_COUNT */ ++ /* XXX: demagic this part some day */ + if (dev_priv->chipset == 0x50) + xf_emit(ctx, 0x3a0, 0); + else if (dev_priv->chipset < 0x94) +@@ -2303,9 +3240,9 @@ nv50_graph_construct_xfer_tp2(struct nouveau_grctx *ctx) + xf_emit(ctx, 0x39f, 0); + else + xf_emit(ctx, 0x3a3, 0); +- xf_emit(ctx, 1, 0x11); +- xf_emit(ctx, 1, 0); +- xf_emit(ctx, 1, 1); ++ xf_emit(ctx, 1, 0x11); /* 3f/7f DST_FORMAT */ ++ xf_emit(ctx, 1, 0); /* 7 OPERATION */ ++ xf_emit(ctx, 1, 1); /* 1 DST_LINEAR */ + xf_emit(ctx, 0x2d, 0); + } + +@@ -2323,52 +3260,56 @@ nv50_graph_construct_xfer2(struct nouveau_grctx *ctx) + if (dev_priv->chipset < 0xa0) { + for (i = 0; i < 8; i++) { + ctx->ctxvals_pos = offset + i; ++ /* that little bugger belongs to csched. No idea ++ * what it's doing here. */ + if (i == 0) +- xf_emit(ctx, 1, 0x08100c12); ++ xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ + if (units & (1 << i)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } + } else { + /* Strand 0: TPs 0, 1 */ + ctx->ctxvals_pos = offset; +- xf_emit(ctx, 1, 0x08100c12); ++ /* that little bugger belongs to csched. No idea ++ * what it's doing here. */ ++ xf_emit(ctx, 1, 0x08100c12); /* FP_INTERPOLANT_CTRL */ + if (units & (1 << 0)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 1)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + +- /* Strand 0: TPs 2, 3 */ ++ /* Strand 1: TPs 2, 3 */ + ctx->ctxvals_pos = offset + 1; + if (units & (1 << 2)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 3)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + +- /* Strand 0: TPs 4, 5, 6 */ ++ /* Strand 2: TPs 4, 5, 6 */ + ctx->ctxvals_pos = offset + 2; + if (units & (1 << 4)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 5)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 6)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + +- /* Strand 0: TPs 7, 8, 9 */ ++ /* Strand 3: TPs 7, 8, 9 */ + ctx->ctxvals_pos = offset + 3; + if (units & (1 << 7)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 8)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if (units & (1 << 9)) +- nv50_graph_construct_xfer_tp2(ctx); ++ nv50_graph_construct_xfer_mpc(ctx); + if ((ctx->ctxvals_pos-offset)/8 > size) + size = (ctx->ctxvals_pos-offset)/8; + } diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c -index 5f21df3..1fd5207 100644 +index 5f21df3..092057b 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -35,8 +35,6 @@ struct nv50_instmem_priv { @@ -9522,7 +15849,15 @@ index 5f21df3..1fd5207 100644 }; #define NV50_INSTMEM_PAGE_SHIFT 12 -@@ -147,7 +145,7 @@ nv50_instmem_init(struct drm_device *dev) +@@ -141,13 +139,15 @@ nv50_instmem_init(struct drm_device *dev) + chan->file_priv = (struct drm_file *)-2; + dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + ++ INIT_LIST_HEAD(&chan->ramht_refs); ++ + /* Channel's PRAMIN object + heap */ + ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, + NULL, &chan->ramin); if (ret) return ret; @@ -9531,7 +15866,7 @@ index 5f21df3..1fd5207 100644 return -ENOMEM; /* RAMFC + zero channel's PRAMIN up to start of VM pagedir */ -@@ -262,23 +260,18 @@ nv50_instmem_init(struct drm_device *dev) +@@ -262,30 +262,25 @@ nv50_instmem_init(struct drm_device *dev) /* Assume that praying isn't enough, check that we can re-read the * entire fake channel back from the PRAMIN BAR */ @@ -9556,7 +15891,15 @@ index 5f21df3..1fd5207 100644 NV_ERROR(dev, "Failed to init RAMIN heap\n"); } -@@ -321,7 +314,7 @@ nv50_instmem_takedown(struct drm_device *dev) + /*XXX: incorrect, but needed to make hash func "work" */ + dev_priv->ramht_offset = 0x10000; + dev_priv->ramht_bits = 9; +- dev_priv->ramht_size = (1 << dev_priv->ramht_bits); ++ dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; + return 0; + } + +@@ -321,7 +316,7 @@ nv50_instmem_takedown(struct drm_device *dev) nouveau_gpuobj_del(dev, &chan->vm_pd); nouveau_gpuobj_ref_del(dev, &chan->ramfc); nouveau_gpuobj_ref_del(dev, &chan->ramin); @@ -9565,7 +15908,7 @@ index 5f21df3..1fd5207 100644 dev_priv->fifos[0] = dev_priv->fifos[127] = NULL; kfree(chan); -@@ -436,14 +429,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +@@ -436,14 +431,14 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) return -EINVAL; @@ -9582,15 +15925,18 @@ index 5f21df3..1fd5207 100644 gpuobj->im_pramin->start, pte, pte_end); NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); -@@ -453,27 +446,15 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +@@ -453,27 +448,16 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) vram |= 0x30; } - dev_priv->engine.instmem.prepare_access(dev, true); while (pte < pte_end) { - nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); - nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); +- nv_wo32(dev, pramin_pt, pte++, lower_32_bits(vram)); +- nv_wo32(dev, pramin_pt, pte++, upper_32_bits(vram)); ++ nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); ++ nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); vram += NV50_INSTMEM_PAGE_SIZE; ++ pte += 2; } - dev_priv->engine.instmem.finish_access(dev); - @@ -9613,14 +15959,17 @@ index 5f21df3..1fd5207 100644 gpuobj->im_bound = 1; return 0; -@@ -492,36 +473,36 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +@@ -492,36 +476,37 @@ nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) pte = (gpuobj->im_pramin->start >> 12) << 1; pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - dev_priv->engine.instmem.prepare_access(dev, true); while (pte < pte_end) { - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); - nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); +- nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); +- nv_wo32(dev, priv->pramin_pt->gpuobj, pte++, 0x00000000); ++ nv_wo32(priv->pramin_pt->gpuobj, (pte * 4) + 0, 0x00000000); ++ nv_wo32(priv->pramin_pt->gpuobj, (pte * 4) + 4, 0x00000000); ++ pte += 2; } - dev_priv->engine.instmem.finish_access(dev); + dev_priv->engine.instmem.flush(dev); @@ -10096,10 +16445,10 @@ index 0000000..edf2b21 +} diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c new file mode 100644 -index 0000000..b66c913 +index 0000000..9238c73 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c -@@ -0,0 +1,231 @@ +@@ -0,0 +1,234 @@ +/* + * Copyright 2010 Red Hat Inc. + * @@ -10244,14 +16593,16 @@ index 0000000..b66c913 +nvc0_instmem_suspend(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 *buf; + int i; + + dev_priv->susres.ramin_copy = vmalloc(65536); + if (!dev_priv->susres.ramin_copy) + return -ENOMEM; ++ buf = dev_priv->susres.ramin_copy; + -+ for (i = 0x700000; i < 0x710000; i += 4) -+ dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); ++ for (i = 0; i < 65536; i += 4) ++ buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i); + return 0; +} + @@ -10259,14 +16610,15 @@ index 0000000..b66c913 +nvc0_instmem_resume(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; ++ u32 *buf = dev_priv->susres.ramin_copy; + u64 chan; + int i; + + chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; + nv_wr32(dev, 0x001700, chan >> 16); + -+ for (i = 0x700000; i < 0x710000; i += 4) -+ nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); ++ for (i = 0; i < 65536; i += 4) ++ nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]); + vfree(dev_priv->susres.ramin_copy); + dev_priv->susres.ramin_copy = NULL; + @@ -10323,7 +16675,7 @@ index 0000000..b66c913 + /*XXX: incorrect, but needed to make hash func "work" */ + dev_priv->ramht_offset = 0x10000; + dev_priv->ramht_bits = 9; -+ dev_priv->ramht_size = (1 << dev_priv->ramht_bits); ++ dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; + return 0; +} + @@ -10365,5 +16717,5 @@ index 5998c35..ad64673 100644 # define NV_PCRTC_INTR_0_VBLANK (1 << 0) #define NV_PCRTC_INTR_EN_0 0x00600140 -- -1.7.2 +1.7.2.2 diff --git a/kernel.spec b/kernel.spec index 0b9539b..5685f60 100644 --- a/kernel.spec +++ b/kernel.spec @@ -48,7 +48,7 @@ Summary: The Linux kernel # reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec). # scripts/rebase.sh should be made to do that for you, actually. # -%global baserelease 18 +%global baserelease 19 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -1900,6 +1900,9 @@ fi # and build. %changelog +* Mon Sep 04 2010 Ben Skeggs 2.6.35.4-19 +- nouveau: misc fixes from upstream + NVAF support + * Fri Sep 03 2010 Kyle McMartin - Restore appleir driver that got lost in the 2.6.35 rebase.