aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2011-05-15 21:53:27 -0400
committerDave Airlie <airlied@redhat.com>2011-05-15 21:53:27 -0400
commit46f2b6073430e14561f3aea1cee19b35223e0c04 (patch)
tree30de66b80dcf23c3287384fa6b668ee4cd985d1a /drivers
parent69f7876b2ab61e8114675d6092ad0b482e233612 (diff)
parentb4fa9d0f6563756036f61c74fb38e3e97a1defd4 (diff)
Merge remote branch 'nouveau/drm-nouveau-next' of /ssd/git/drm-nouveau-next into drm-core-next
* 'nouveau/drm-nouveau-next' of /ssd/git/drm-nouveau-next: (55 commits) drm/nouveau: make cursor_set implementation consistent with other drivers drm/nva3/clk: better pll calculation when no fractional fb div available drm/nouveau/pm: translate ramcfg strap through ram restrict table drm/nva3/pm: allow use of divisor 16 drm/nvc0/pm: parse clock for pll 0x0a (0x137020) from perf table drm/nvc0/pm: correct core/mem/shader perflvl parsing drm/nouveau/pm: remove memtiming support check when assigning to perflvl drm/nva3: support for memory timing map table drm/nouveau: Associate memtimings with performance levels on cards <= nv98 drm/nva3/pm: initial pass at set_clock() hook drm/nvc0/gr: calculate some more of our magic numbers drm/nv50: respect LVDS link count from EDID on SPWG panels drm/nouveau: recognise DCB connector type 0x41 as LVDS drm/nouveau: fix uninitialised variable warning drm/nouveau: Fix a crash at card takedown for NV40 and older cards drm/nouveau: Free nv04 instmem ramin heap at card takedown drm/nva3: somewhat improve clock reporting drm/nouveau: pull refclk from vbios on limits 0x40 boards drm/nv40/gr: oops, fix random bits getting set in engine obj drm/nv50: improve nv50_pm_get_clock() ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/nouveau/Makefile2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c20
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h208
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_grctx.h10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c68
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_object.c118
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_perf.c92
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_reg.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c217
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_volt.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv04_crtc.c9
-rw-r--r--drivers/gpu/drm/nouveau/nv04_graph.c383
-rw-r--r--drivers/gpu/drm/nouveau/nv04_instmem.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv10_graph.c212
-rw-r--r--drivers/gpu/drm/nouveau/nv20_graph.c510
-rw-r--r--drivers/gpu/drm/nouveau/nv40_fifo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv40_graph.c323
-rw-r--r--drivers/gpu/drm/nouveau/nv40_mpeg.c311
-rw-r--r--drivers/gpu/drm/nouveau/nv50_calc.c68
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c13
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c18
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c442
-rw-r--r--drivers/gpu/drm/nouveau/nv50_grctx.c10
-rw-r--r--drivers/gpu/drm/nouveau/nv50_mpeg.c256
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c15
-rw-r--r--drivers/gpu/drm/nouveau/nv50_vm.c12
-rw-r--r--drivers/gpu/drm/nouveau/nv84_crypt.c135
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.c226
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.fuc870
-rw-r--r--drivers/gpu/drm/nouveau/nva3_copy.fuc.h534
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c169
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_copy.c243
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_copy.fuc.h527
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fifo.c142
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.c600
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.h29
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grctx.c20
44 files changed, 5071 insertions, 1837 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index e12c97fd8db8..0583677e4581 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -20,6 +20,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
20 nv40_graph.o nv50_graph.o nvc0_graph.o \ 20 nv40_graph.o nv50_graph.o nvc0_graph.o \
21 nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ 21 nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
22 nv84_crypt.o \ 22 nv84_crypt.o \
23 nva3_copy.o nvc0_copy.o \
24 nv40_mpeg.o nv50_mpeg.o \
23 nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ 25 nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
24 nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ 26 nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \
25 nv50_cursor.o nv50_display.o \ 27 nv50_cursor.o nv50_display.o \
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 90aef64b76f2..729d5fd7c88d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -5049,11 +5049,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
5049 pll_lim->vco1.max_n = record[11]; 5049 pll_lim->vco1.max_n = record[11];
5050 pll_lim->min_p = record[12]; 5050 pll_lim->min_p = record[12];
5051 pll_lim->max_p = record[13]; 5051 pll_lim->max_p = record[13];
5052 /* where did this go to?? */ 5052 pll_lim->refclk = ROM16(entry[9]) * 1000;
5053 if ((entry[0] & 0xf0) == 0x80)
5054 pll_lim->refclk = 27000;
5055 else
5056 pll_lim->refclk = 100000;
5057 } 5053 }
5058 5054
5059 /* 5055 /*
@@ -6035,6 +6031,7 @@ parse_dcb_connector_table(struct nvbios *bios)
6035 case DCB_CONNECTOR_DVI_I: 6031 case DCB_CONNECTOR_DVI_I:
6036 case DCB_CONNECTOR_DVI_D: 6032 case DCB_CONNECTOR_DVI_D:
6037 case DCB_CONNECTOR_LVDS: 6033 case DCB_CONNECTOR_LVDS:
6034 case DCB_CONNECTOR_LVDS_SPWG:
6038 case DCB_CONNECTOR_DP: 6035 case DCB_CONNECTOR_DP:
6039 case DCB_CONNECTOR_eDP: 6036 case DCB_CONNECTOR_eDP:
6040 case DCB_CONNECTOR_HDMI_0: 6037 case DCB_CONNECTOR_HDMI_0:
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 8a54fa7edf5c..050c314119df 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -82,6 +82,7 @@ enum dcb_connector_type {
82 DCB_CONNECTOR_DVI_I = 0x30, 82 DCB_CONNECTOR_DVI_I = 0x30,
83 DCB_CONNECTOR_DVI_D = 0x31, 83 DCB_CONNECTOR_DVI_D = 0x31,
84 DCB_CONNECTOR_LVDS = 0x40, 84 DCB_CONNECTOR_LVDS = 0x40,
85 DCB_CONNECTOR_LVDS_SPWG = 0x41,
85 DCB_CONNECTOR_DP = 0x46, 86 DCB_CONNECTOR_DP = 0x46,
86 DCB_CONNECTOR_eDP = 0x47, 87 DCB_CONNECTOR_eDP = 0x47,
87 DCB_CONNECTOR_HDMI_0 = 0x60, 88 DCB_CONNECTOR_HDMI_0 = 0x60,
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 4cea35c57d15..a7583a8ddb01 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -268,9 +268,8 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
268 struct drm_device *dev = chan->dev; 268 struct drm_device *dev = chan->dev;
269 struct drm_nouveau_private *dev_priv = dev->dev_private; 269 struct drm_nouveau_private *dev_priv = dev->dev_private;
270 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 270 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
271 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
272 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
273 unsigned long flags; 271 unsigned long flags;
272 int i;
274 273
275 /* decrement the refcount, and we're done if there's still refs */ 274 /* decrement the refcount, and we're done if there's still refs */
276 if (likely(!atomic_dec_and_test(&chan->users))) { 275 if (likely(!atomic_dec_and_test(&chan->users))) {
@@ -294,19 +293,12 @@ nouveau_channel_put_unlocked(struct nouveau_channel **pchan)
294 /* boot it off the hardware */ 293 /* boot it off the hardware */
295 pfifo->reassign(dev, false); 294 pfifo->reassign(dev, false);
296 295
297 /* We want to give pgraph a chance to idle and get rid of all
298 * potential errors. We need to do this without the context
299 * switch lock held, otherwise the irq handler is unable to
300 * process them.
301 */
302 if (pgraph->channel(dev) == chan)
303 nouveau_wait_for_idle(dev);
304
305 /* destroy the engine specific contexts */ 296 /* destroy the engine specific contexts */
306 pfifo->destroy_context(chan); 297 pfifo->destroy_context(chan);
307 pgraph->destroy_context(chan); 298 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
308 if (pcrypt->destroy_context) 299 if (chan->engctx[i])
309 pcrypt->destroy_context(chan); 300 dev_priv->eng[i]->context_del(chan, i);
301 }
310 302
311 pfifo->reassign(dev, true); 303 pfifo->reassign(dev, true);
312 304
@@ -414,7 +406,7 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
414 struct nouveau_channel *chan; 406 struct nouveau_channel *chan;
415 int ret; 407 int ret;
416 408
417 if (dev_priv->engine.graph.accel_blocked) 409 if (!dev_priv->eng[NVOBJ_ENGINE_GR])
418 return -ENODEV; 410 return -ENODEV;
419 411
420 if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) 412 if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 7ae151109a66..1595d0b6e815 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -442,7 +442,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
442 } 442 }
443 443
444 /* LVDS always needs gpu scaling */ 444 /* LVDS always needs gpu scaling */
445 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS && 445 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
446 value == DRM_MODE_SCALE_NONE) 446 value == DRM_MODE_SCALE_NONE)
447 return -EINVAL; 447 return -EINVAL;
448 448
@@ -650,6 +650,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
650 ret = get_slave_funcs(encoder)->get_modes(encoder, connector); 650 ret = get_slave_funcs(encoder)->get_modes(encoder, connector);
651 651
652 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || 652 if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS ||
653 nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG ||
653 nv_connector->dcb->type == DCB_CONNECTOR_eDP) 654 nv_connector->dcb->type == DCB_CONNECTOR_eDP)
654 ret += nouveau_connector_scaler_modes_add(connector); 655 ret += nouveau_connector_scaler_modes_add(connector);
655 656
@@ -810,6 +811,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
810 type = DRM_MODE_CONNECTOR_HDMIA; 811 type = DRM_MODE_CONNECTOR_HDMIA;
811 break; 812 break;
812 case DCB_CONNECTOR_LVDS: 813 case DCB_CONNECTOR_LVDS:
814 case DCB_CONNECTOR_LVDS_SPWG:
813 type = DRM_MODE_CONNECTOR_LVDS; 815 type = DRM_MODE_CONNECTOR_LVDS;
814 funcs = &nouveau_connector_funcs_lvds; 816 funcs = &nouveau_connector_funcs_lvds;
815 break; 817 break;
@@ -838,7 +840,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
838 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); 840 drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
839 841
840 /* Check if we need dithering enabled */ 842 /* Check if we need dithering enabled */
841 if (dcb->type == DCB_CONNECTOR_LVDS) { 843 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
842 bool dummy, is_24bit = false; 844 bool dummy, is_24bit = false;
843 845
844 ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); 846 ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit);
@@ -883,7 +885,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
883 nv_connector->use_dithering ? 885 nv_connector->use_dithering ?
884 DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); 886 DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
885 887
886 if (dcb->type != DCB_CONNECTOR_LVDS) { 888 if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) {
887 if (dev_priv->card_type >= NV_50) 889 if (dev_priv->card_type >= NV_50)
888 connector->polled = DRM_CONNECTOR_POLL_HPD; 890 connector->polled = DRM_CONNECTOR_POLL_HPD;
889 else 891 else
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 764c15d537ba..eb514ea29377 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -276,7 +276,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
276 struct nouveau_fence *fence; 276 struct nouveau_fence *fence;
277 int ret; 277 int ret;
278 278
279 if (dev_priv->engine.graph.accel_blocked) 279 if (!dev_priv->channel)
280 return -ENODEV; 280 return -ENODEV;
281 281
282 s = kzalloc(sizeof(*s), GFP_KERNEL); 282 s = kzalloc(sizeof(*s), GFP_KERNEL);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 155ebdcbf06f..02c6f37d8bd7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -162,11 +162,10 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
162 struct drm_device *dev = pci_get_drvdata(pdev); 162 struct drm_device *dev = pci_get_drvdata(pdev);
163 struct drm_nouveau_private *dev_priv = dev->dev_private; 163 struct drm_nouveau_private *dev_priv = dev->dev_private;
164 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 164 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
165 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
166 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 165 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
167 struct nouveau_channel *chan; 166 struct nouveau_channel *chan;
168 struct drm_crtc *crtc; 167 struct drm_crtc *crtc;
169 int ret, i; 168 int ret, i, e;
170 169
171 if (pm_state.event == PM_EVENT_PRETHAW) 170 if (pm_state.event == PM_EVENT_PRETHAW)
172 return 0; 171 return 0;
@@ -206,12 +205,17 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
206 nouveau_channel_idle(chan); 205 nouveau_channel_idle(chan);
207 } 206 }
208 207
209 pgraph->fifo_access(dev, false);
210 nouveau_wait_for_idle(dev);
211 pfifo->reassign(dev, false); 208 pfifo->reassign(dev, false);
212 pfifo->disable(dev); 209 pfifo->disable(dev);
213 pfifo->unload_context(dev); 210 pfifo->unload_context(dev);
214 pgraph->unload_context(dev); 211
212 for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
213 if (dev_priv->eng[e]) {
214 ret = dev_priv->eng[e]->fini(dev, e);
215 if (ret)
216 goto out_abort;
217 }
218 }
215 219
216 ret = pinstmem->suspend(dev); 220 ret = pinstmem->suspend(dev);
217 if (ret) { 221 if (ret) {
@@ -242,9 +246,12 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
242 246
243out_abort: 247out_abort:
244 NV_INFO(dev, "Re-enabling acceleration..\n"); 248 NV_INFO(dev, "Re-enabling acceleration..\n");
249 for (e = e + 1; e < NVOBJ_ENGINE_NR; e++) {
250 if (dev_priv->eng[e])
251 dev_priv->eng[e]->init(dev, e);
252 }
245 pfifo->enable(dev); 253 pfifo->enable(dev);
246 pfifo->reassign(dev, true); 254 pfifo->reassign(dev, true);
247 pgraph->fifo_access(dev, true);
248 return ret; 255 return ret;
249} 256}
250 257
@@ -299,8 +306,10 @@ nouveau_pci_resume(struct pci_dev *pdev)
299 engine->mc.init(dev); 306 engine->mc.init(dev);
300 engine->timer.init(dev); 307 engine->timer.init(dev);
301 engine->fb.init(dev); 308 engine->fb.init(dev);
302 engine->graph.init(dev); 309 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
303 engine->crypt.init(dev); 310 if (dev_priv->eng[i])
311 dev_priv->eng[i]->init(dev, i);
312 }
304 engine->fifo.init(dev); 313 engine->fifo.init(dev);
305 314
306 nouveau_irq_postinstall(dev); 315 nouveau_irq_postinstall(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index a76514a209b3..9c56331941e2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -150,13 +150,12 @@ enum nouveau_flags {
150 150
151#define NVOBJ_ENGINE_SW 0 151#define NVOBJ_ENGINE_SW 0
152#define NVOBJ_ENGINE_GR 1 152#define NVOBJ_ENGINE_GR 1
153#define NVOBJ_ENGINE_PPP 2 153#define NVOBJ_ENGINE_CRYPT 2
154#define NVOBJ_ENGINE_COPY 3 154#define NVOBJ_ENGINE_COPY0 3
155#define NVOBJ_ENGINE_VP 4 155#define NVOBJ_ENGINE_COPY1 4
156#define NVOBJ_ENGINE_CRYPT 5 156#define NVOBJ_ENGINE_MPEG 5
157#define NVOBJ_ENGINE_BSP 6 157#define NVOBJ_ENGINE_DISPLAY 15
158#define NVOBJ_ENGINE_DISPLAY 0xcafe0001 158#define NVOBJ_ENGINE_NR 16
159#define NVOBJ_ENGINE_INT 0xdeadbeef
160 159
161#define NVOBJ_FLAG_DONT_MAP (1 << 0) 160#define NVOBJ_FLAG_DONT_MAP (1 << 0)
162#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) 161#define NVOBJ_FLAG_ZERO_ALLOC (1 << 1)
@@ -245,11 +244,8 @@ struct nouveau_channel {
245 struct nouveau_gpuobj *cache; 244 struct nouveau_gpuobj *cache;
246 void *fifo_priv; 245 void *fifo_priv;
247 246
248 /* PGRAPH context */ 247 /* Execution engine contexts */
249 /* XXX may be merge 2 pointers as private data ??? */ 248 void *engctx[NVOBJ_ENGINE_NR];
250 struct nouveau_gpuobj *ramin_grctx;
251 struct nouveau_gpuobj *crypt_ctx;
252 void *pgraph_ctx;
253 249
254 /* NV50 VM */ 250 /* NV50 VM */
255 struct nouveau_vm *vm; 251 struct nouveau_vm *vm;
@@ -298,6 +294,18 @@ struct nouveau_channel {
298 } debugfs; 294 } debugfs;
299}; 295};
300 296
297struct nouveau_exec_engine {
298 void (*destroy)(struct drm_device *, int engine);
299 int (*init)(struct drm_device *, int engine);
300 int (*fini)(struct drm_device *, int engine);
301 int (*context_new)(struct nouveau_channel *, int engine);
302 void (*context_del)(struct nouveau_channel *, int engine);
303 int (*object_new)(struct nouveau_channel *, int engine,
304 u32 handle, u16 class);
305 void (*set_tile_region)(struct drm_device *dev, int i);
306 void (*tlb_flush)(struct drm_device *, int engine);
307};
308
301struct nouveau_instmem_engine { 309struct nouveau_instmem_engine {
302 void *priv; 310 void *priv;
303 311
@@ -364,30 +372,6 @@ struct nouveau_fifo_engine {
364 void (*tlb_flush)(struct drm_device *dev); 372 void (*tlb_flush)(struct drm_device *dev);
365}; 373};
366 374
367struct nouveau_pgraph_engine {
368 bool accel_blocked;
369 bool registered;
370 int grctx_size;
371 void *priv;
372
373 /* NV2x/NV3x context table (0x400780) */
374 struct nouveau_gpuobj *ctx_table;
375
376 int (*init)(struct drm_device *);
377 void (*takedown)(struct drm_device *);
378
379 void (*fifo_access)(struct drm_device *, bool);
380
381 struct nouveau_channel *(*channel)(struct drm_device *);
382 int (*create_context)(struct nouveau_channel *);
383 void (*destroy_context)(struct nouveau_channel *);
384 int (*load_context)(struct nouveau_channel *);
385 int (*unload_context)(struct drm_device *);
386 void (*tlb_flush)(struct drm_device *dev);
387
388 void (*set_tile_region)(struct drm_device *dev, int i);
389};
390
391struct nouveau_display_engine { 375struct nouveau_display_engine {
392 void *priv; 376 void *priv;
393 int (*early_init)(struct drm_device *); 377 int (*early_init)(struct drm_device *);
@@ -426,6 +410,19 @@ struct nouveau_pm_voltage {
426 int nr_level; 410 int nr_level;
427}; 411};
428 412
413struct nouveau_pm_memtiming {
414 int id;
415 u32 reg_100220;
416 u32 reg_100224;
417 u32 reg_100228;
418 u32 reg_10022c;
419 u32 reg_100230;
420 u32 reg_100234;
421 u32 reg_100238;
422 u32 reg_10023c;
423 u32 reg_100240;
424};
425
429#define NOUVEAU_PM_MAX_LEVEL 8 426#define NOUVEAU_PM_MAX_LEVEL 8
430struct nouveau_pm_level { 427struct nouveau_pm_level {
431 struct device_attribute dev_attr; 428 struct device_attribute dev_attr;
@@ -436,11 +433,13 @@ struct nouveau_pm_level {
436 u32 memory; 433 u32 memory;
437 u32 shader; 434 u32 shader;
438 u32 unk05; 435 u32 unk05;
436 u32 unk0a;
439 437
440 u8 voltage; 438 u8 voltage;
441 u8 fanspeed; 439 u8 fanspeed;
442 440
443 u16 memscript; 441 u16 memscript;
442 struct nouveau_pm_memtiming *timing;
444}; 443};
445 444
446struct nouveau_pm_temp_sensor_constants { 445struct nouveau_pm_temp_sensor_constants {
@@ -457,17 +456,6 @@ struct nouveau_pm_threshold_temp {
457 s16 fan_boost; 456 s16 fan_boost;
458}; 457};
459 458
460struct nouveau_pm_memtiming {
461 u32 reg_100220;
462 u32 reg_100224;
463 u32 reg_100228;
464 u32 reg_10022c;
465 u32 reg_100230;
466 u32 reg_100234;
467 u32 reg_100238;
468 u32 reg_10023c;
469};
470
471struct nouveau_pm_memtimings { 459struct nouveau_pm_memtimings {
472 bool supported; 460 bool supported;
473 struct nouveau_pm_memtiming *timing; 461 struct nouveau_pm_memtiming *timing;
@@ -499,16 +487,6 @@ struct nouveau_pm_engine {
499 int (*temp_get)(struct drm_device *); 487 int (*temp_get)(struct drm_device *);
500}; 488};
501 489
502struct nouveau_crypt_engine {
503 bool registered;
504
505 int (*init)(struct drm_device *);
506 void (*takedown)(struct drm_device *);
507 int (*create_context)(struct nouveau_channel *);
508 void (*destroy_context)(struct nouveau_channel *);
509 void (*tlb_flush)(struct drm_device *dev);
510};
511
512struct nouveau_vram_engine { 490struct nouveau_vram_engine {
513 int (*init)(struct drm_device *); 491 int (*init)(struct drm_device *);
514 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, 492 int (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
@@ -523,12 +501,10 @@ struct nouveau_engine {
523 struct nouveau_mc_engine mc; 501 struct nouveau_mc_engine mc;
524 struct nouveau_timer_engine timer; 502 struct nouveau_timer_engine timer;
525 struct nouveau_fb_engine fb; 503 struct nouveau_fb_engine fb;
526 struct nouveau_pgraph_engine graph;
527 struct nouveau_fifo_engine fifo; 504 struct nouveau_fifo_engine fifo;
528 struct nouveau_display_engine display; 505 struct nouveau_display_engine display;
529 struct nouveau_gpio_engine gpio; 506 struct nouveau_gpio_engine gpio;
530 struct nouveau_pm_engine pm; 507 struct nouveau_pm_engine pm;
531 struct nouveau_crypt_engine crypt;
532 struct nouveau_vram_engine vram; 508 struct nouveau_vram_engine vram;
533}; 509};
534 510
@@ -637,6 +613,7 @@ struct drm_nouveau_private {
637 enum nouveau_card_type card_type; 613 enum nouveau_card_type card_type;
638 /* exact chipset, derived from NV_PMC_BOOT_0 */ 614 /* exact chipset, derived from NV_PMC_BOOT_0 */
639 int chipset; 615 int chipset;
616 int stepping;
640 int flags; 617 int flags;
641 618
642 void __iomem *mmio; 619 void __iomem *mmio;
@@ -647,6 +624,7 @@ struct drm_nouveau_private {
647 u32 ramin_base; 624 u32 ramin_base;
648 bool ramin_available; 625 bool ramin_available;
649 struct drm_mm ramin_heap; 626 struct drm_mm ramin_heap;
627 struct nouveau_exec_engine *eng[NVOBJ_ENGINE_NR];
650 struct list_head gpuobj_list; 628 struct list_head gpuobj_list;
651 struct list_head classes; 629 struct list_head classes;
652 630
@@ -745,10 +723,6 @@ struct drm_nouveau_private {
745 uint32_t crtc_owner; 723 uint32_t crtc_owner;
746 uint32_t dac_users[4]; 724 uint32_t dac_users[4];
747 725
748 struct nouveau_suspend_resume {
749 uint32_t *ramin_copy;
750 } susres;
751
752 struct backlight_device *backlight; 726 struct backlight_device *backlight;
753 727
754 struct { 728 struct {
@@ -757,8 +731,6 @@ struct drm_nouveau_private {
757 731
758 struct nouveau_fbdev *nfbdev; 732 struct nouveau_fbdev *nfbdev;
759 struct apertures_struct *apertures; 733 struct apertures_struct *apertures;
760
761 bool powered_down;
762}; 734};
763 735
764static inline struct drm_nouveau_private * 736static inline struct drm_nouveau_private *
@@ -883,17 +855,27 @@ extern void nouveau_channel_ref(struct nouveau_channel *chan,
883extern void nouveau_channel_idle(struct nouveau_channel *chan); 855extern void nouveau_channel_idle(struct nouveau_channel *chan);
884 856
885/* nouveau_object.c */ 857/* nouveau_object.c */
886#define NVOBJ_CLASS(d,c,e) do { \ 858#define NVOBJ_ENGINE_ADD(d, e, p) do { \
859 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
860 dev_priv->eng[NVOBJ_ENGINE_##e] = (p); \
861} while (0)
862
863#define NVOBJ_ENGINE_DEL(d, e) do { \
864 struct drm_nouveau_private *dev_priv = (d)->dev_private; \
865 dev_priv->eng[NVOBJ_ENGINE_##e] = NULL; \
866} while (0)
867
868#define NVOBJ_CLASS(d, c, e) do { \
887 int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ 869 int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \
888 if (ret) \ 870 if (ret) \
889 return ret; \ 871 return ret; \
890} while(0) 872} while (0)
891 873
892#define NVOBJ_MTHD(d,c,m,e) do { \ 874#define NVOBJ_MTHD(d, c, m, e) do { \
893 int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ 875 int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \
894 if (ret) \ 876 if (ret) \
895 return ret; \ 877 return ret; \
896} while(0) 878} while (0)
897 879
898extern int nouveau_gpuobj_early_init(struct drm_device *); 880extern int nouveau_gpuobj_early_init(struct drm_device *);
899extern int nouveau_gpuobj_init(struct drm_device *); 881extern int nouveau_gpuobj_init(struct drm_device *);
@@ -903,7 +885,7 @@ extern void nouveau_gpuobj_resume(struct drm_device *dev);
903extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); 885extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
904extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, 886extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
905 int (*exec)(struct nouveau_channel *, 887 int (*exec)(struct nouveau_channel *,
906 u32 class, u32 mthd, u32 data)); 888 u32 class, u32 mthd, u32 data));
907extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); 889extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32);
908extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); 890extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32);
909extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, 891extern int nouveau_gpuobj_channel_init(struct nouveau_channel *,
@@ -1137,81 +1119,50 @@ extern int nvc0_fifo_load_context(struct nouveau_channel *);
1137extern int nvc0_fifo_unload_context(struct drm_device *); 1119extern int nvc0_fifo_unload_context(struct drm_device *);
1138 1120
1139/* nv04_graph.c */ 1121/* nv04_graph.c */
1140extern int nv04_graph_init(struct drm_device *); 1122extern int nv04_graph_create(struct drm_device *);
1141extern void nv04_graph_takedown(struct drm_device *);
1142extern void nv04_graph_fifo_access(struct drm_device *, bool); 1123extern void nv04_graph_fifo_access(struct drm_device *, bool);
1143extern struct nouveau_channel *nv04_graph_channel(struct drm_device *); 1124extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
1144extern int nv04_graph_create_context(struct nouveau_channel *);
1145extern void nv04_graph_destroy_context(struct nouveau_channel *);
1146extern int nv04_graph_load_context(struct nouveau_channel *);
1147extern int nv04_graph_unload_context(struct drm_device *);
1148extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, 1125extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
1149 u32 class, u32 mthd, u32 data); 1126 u32 class, u32 mthd, u32 data);
1150extern struct nouveau_bitfield nv04_graph_nsource[]; 1127extern struct nouveau_bitfield nv04_graph_nsource[];
1151 1128
1152/* nv10_graph.c */ 1129/* nv10_graph.c */
1153extern int nv10_graph_init(struct drm_device *); 1130extern int nv10_graph_create(struct drm_device *);
1154extern void nv10_graph_takedown(struct drm_device *);
1155extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); 1131extern struct nouveau_channel *nv10_graph_channel(struct drm_device *);
1156extern int nv10_graph_create_context(struct nouveau_channel *);
1157extern void nv10_graph_destroy_context(struct nouveau_channel *);
1158extern int nv10_graph_load_context(struct nouveau_channel *);
1159extern int nv10_graph_unload_context(struct drm_device *);
1160extern void nv10_graph_set_tile_region(struct drm_device *dev, int i);
1161extern struct nouveau_bitfield nv10_graph_intr[]; 1132extern struct nouveau_bitfield nv10_graph_intr[];
1162extern struct nouveau_bitfield nv10_graph_nstatus[]; 1133extern struct nouveau_bitfield nv10_graph_nstatus[];
1163 1134
1164/* nv20_graph.c */ 1135/* nv20_graph.c */
1165extern int nv20_graph_create_context(struct nouveau_channel *); 1136extern int nv20_graph_create(struct drm_device *);
1166extern void nv20_graph_destroy_context(struct nouveau_channel *);
1167extern int nv20_graph_load_context(struct nouveau_channel *);
1168extern int nv20_graph_unload_context(struct drm_device *);
1169extern int nv20_graph_init(struct drm_device *);
1170extern void nv20_graph_takedown(struct drm_device *);
1171extern int nv30_graph_init(struct drm_device *);
1172extern void nv20_graph_set_tile_region(struct drm_device *dev, int i);
1173 1137
1174/* nv40_graph.c */ 1138/* nv40_graph.c */
1175extern int nv40_graph_init(struct drm_device *); 1139extern int nv40_graph_create(struct drm_device *);
1176extern void nv40_graph_takedown(struct drm_device *);
1177extern struct nouveau_channel *nv40_graph_channel(struct drm_device *);
1178extern int nv40_graph_create_context(struct nouveau_channel *);
1179extern void nv40_graph_destroy_context(struct nouveau_channel *);
1180extern int nv40_graph_load_context(struct nouveau_channel *);
1181extern int nv40_graph_unload_context(struct drm_device *);
1182extern void nv40_grctx_init(struct nouveau_grctx *); 1140extern void nv40_grctx_init(struct nouveau_grctx *);
1183extern void nv40_graph_set_tile_region(struct drm_device *dev, int i);
1184 1141
1185/* nv50_graph.c */ 1142/* nv50_graph.c */
1186extern int nv50_graph_init(struct drm_device *); 1143extern int nv50_graph_create(struct drm_device *);
1187extern void nv50_graph_takedown(struct drm_device *);
1188extern void nv50_graph_fifo_access(struct drm_device *, bool);
1189extern struct nouveau_channel *nv50_graph_channel(struct drm_device *);
1190extern int nv50_graph_create_context(struct nouveau_channel *);
1191extern void nv50_graph_destroy_context(struct nouveau_channel *);
1192extern int nv50_graph_load_context(struct nouveau_channel *);
1193extern int nv50_graph_unload_context(struct drm_device *);
1194extern int nv50_grctx_init(struct nouveau_grctx *); 1144extern int nv50_grctx_init(struct nouveau_grctx *);
1195extern void nv50_graph_tlb_flush(struct drm_device *dev);
1196extern void nv84_graph_tlb_flush(struct drm_device *dev);
1197extern struct nouveau_enum nv50_data_error_names[]; 1145extern struct nouveau_enum nv50_data_error_names[];
1146extern int nv50_graph_isr_chid(struct drm_device *dev, u64 inst);
1198 1147
1199/* nvc0_graph.c */ 1148/* nvc0_graph.c */
1200extern int nvc0_graph_init(struct drm_device *); 1149extern int nvc0_graph_create(struct drm_device *);
1201extern void nvc0_graph_takedown(struct drm_device *); 1150extern int nvc0_graph_isr_chid(struct drm_device *dev, u64 inst);
1202extern void nvc0_graph_fifo_access(struct drm_device *, bool);
1203extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *);
1204extern int nvc0_graph_create_context(struct nouveau_channel *);
1205extern void nvc0_graph_destroy_context(struct nouveau_channel *);
1206extern int nvc0_graph_load_context(struct nouveau_channel *);
1207extern int nvc0_graph_unload_context(struct drm_device *);
1208 1151
1209/* nv84_crypt.c */ 1152/* nv84_crypt.c */
1210extern int nv84_crypt_init(struct drm_device *dev); 1153extern int nv84_crypt_create(struct drm_device *);
1211extern void nv84_crypt_fini(struct drm_device *dev); 1154
1212extern int nv84_crypt_create_context(struct nouveau_channel *); 1155/* nva3_copy.c */
1213extern void nv84_crypt_destroy_context(struct nouveau_channel *); 1156extern int nva3_copy_create(struct drm_device *dev);
1214extern void nv84_crypt_tlb_flush(struct drm_device *dev); 1157
1158/* nvc0_copy.c */
1159extern int nvc0_copy_create(struct drm_device *dev, int engine);
1160
1161/* nv40_mpeg.c */
1162extern int nv40_mpeg_create(struct drm_device *dev);
1163
1164/* nv50_mpeg.c */
1165extern int nv50_mpeg_create(struct drm_device *dev);
1215 1166
1216/* nv04_instmem.c */ 1167/* nv04_instmem.c */
1217extern int nv04_instmem_init(struct drm_device *); 1168extern int nv04_instmem_init(struct drm_device *);
@@ -1402,8 +1353,8 @@ bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
1402/* nv50_calc. */ 1353/* nv50_calc. */
1403int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, 1354int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
1404 int *N1, int *M1, int *N2, int *M2, int *P); 1355 int *N1, int *M1, int *N2, int *M2, int *P);
1405int nv50_calc_pll2(struct drm_device *, struct pll_lims *, 1356int nva3_calc_pll(struct drm_device *, struct pll_lims *,
1406 int clk, int *N, int *fN, int *M, int *P); 1357 int clk, int *N, int *fN, int *M, int *P);
1407 1358
1408#ifndef ioread32_native 1359#ifndef ioread32_native
1409#ifdef __BIG_ENDIAN 1360#ifdef __BIG_ENDIAN
@@ -1579,6 +1530,13 @@ nv_match_device(struct drm_device *dev, unsigned device,
1579 dev->pdev->subsystem_device == sub_device; 1530 dev->pdev->subsystem_device == sub_device;
1580} 1531}
1581 1532
1533static inline void *
1534nv_engine(struct drm_device *dev, int engine)
1535{
1536 struct drm_nouveau_private *dev_priv = dev->dev_private;
1537 return (void *)dev_priv->eng[engine];
1538}
1539
1582/* returns 1 if device is one of the nv4x using the 0x4497 object class, 1540/* returns 1 if device is one of the nv4x using the 0x4497 object class,
1583 * helpful to determine a number of other hardware features 1541 * helpful to determine a number of other hardware features
1584 */ 1542 */
diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h
index 4a8ad1307fa4..86c2e374e938 100644
--- a/drivers/gpu/drm/nouveau/nouveau_grctx.h
+++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h
@@ -87,10 +87,10 @@ _cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name)
87 cp_out(ctx, CP_BRA | (mod << 18) | ip | flag | 87 cp_out(ctx, CP_BRA | (mod << 18) | ip | flag |
88 (state ? 0 : CP_BRA_IF_CLEAR)); 88 (state ? 0 : CP_BRA_IF_CLEAR));
89} 89}
90#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) 90#define cp_bra(c, f, s, n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
91#ifdef CP_BRA_MOD 91#ifdef CP_BRA_MOD
92#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) 92#define cp_cal(c, f, s, n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n)
93#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) 93#define cp_ret(c, f, s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0)
94#endif 94#endif
95 95
96static inline void 96static inline void
@@ -98,14 +98,14 @@ _cp_wait(struct nouveau_grctx *ctx, int flag, int state)
98{ 98{
99 cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0)); 99 cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0));
100} 100}
101#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) 101#define cp_wait(c, f, s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
102 102
103static inline void 103static inline void
104_cp_set(struct nouveau_grctx *ctx, int flag, int state) 104_cp_set(struct nouveau_grctx *ctx, int flag, int state)
105{ 105{
106 cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0)); 106 cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0));
107} 107}
108#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) 108#define cp_set(c, f, s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s)
109 109
110static inline void 110static inline void
111cp_pos(struct nouveau_grctx *ctx, int offset) 111cp_pos(struct nouveau_grctx *ctx, int offset)
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 5045f8b921d6..2960f583dc38 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -51,8 +51,7 @@ nv10_mem_update_tile_region(struct drm_device *dev,
51 struct drm_nouveau_private *dev_priv = dev->dev_private; 51 struct drm_nouveau_private *dev_priv = dev->dev_private;
52 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 52 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
53 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; 53 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
54 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 54 int i = tile - dev_priv->tile.reg, j;
55 int i = tile - dev_priv->tile.reg;
56 unsigned long save; 55 unsigned long save;
57 56
58 nouveau_fence_unref(&tile->fence); 57 nouveau_fence_unref(&tile->fence);
@@ -70,7 +69,10 @@ nv10_mem_update_tile_region(struct drm_device *dev,
70 nouveau_wait_for_idle(dev); 69 nouveau_wait_for_idle(dev);
71 70
72 pfb->set_tile_region(dev, i); 71 pfb->set_tile_region(dev, i);
73 pgraph->set_tile_region(dev, i); 72 for (j = 0; j < NVOBJ_ENGINE_NR; j++) {
73 if (dev_priv->eng[j] && dev_priv->eng[j]->set_tile_region)
74 dev_priv->eng[j]->set_tile_region(dev, i);
75 }
74 76
75 pfifo->cache_pull(dev, true); 77 pfifo->cache_pull(dev, true);
76 pfifo->reassign(dev, true); 78 pfifo->reassign(dev, true);
@@ -152,8 +154,6 @@ nouveau_mem_vram_fini(struct drm_device *dev)
152{ 154{
153 struct drm_nouveau_private *dev_priv = dev->dev_private; 155 struct drm_nouveau_private *dev_priv = dev->dev_private;
154 156
155 nouveau_bo_ref(NULL, &dev_priv->vga_ram);
156
157 ttm_bo_device_release(&dev_priv->ttm.bdev); 157 ttm_bo_device_release(&dev_priv->ttm.bdev);
158 158
159 nouveau_ttm_global_release(dev_priv); 159 nouveau_ttm_global_release(dev_priv);
@@ -597,10 +597,10 @@ nouveau_mem_timing_init(struct drm_device *dev)
597 if (!memtimings->timing) 597 if (!memtimings->timing)
598 return; 598 return;
599 599
600 /* Get "some number" from the timing reg for NV_40 600 /* Get "some number" from the timing reg for NV_40 and NV_50
601 * Used in calculations later */ 601 * Used in calculations later */
602 if(dev_priv->card_type == NV_40) { 602 if (dev_priv->card_type >= NV_40 && dev_priv->chipset < 0x98) {
603 magic_number = (nv_rd32(dev,0x100228) & 0x0f000000) >> 24; 603 magic_number = (nv_rd32(dev, 0x100228) & 0x0f000000) >> 24;
604 } 604 }
605 605
606 entry = mem + mem[1]; 606 entry = mem + mem[1];
@@ -643,51 +643,68 @@ nouveau_mem_timing_init(struct drm_device *dev)
643 /* XXX: I don't trust the -1's and +1's... they must come 643 /* XXX: I don't trust the -1's and +1's... they must come
644 * from somewhere! */ 644 * from somewhere! */
645 timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 | 645 timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
646 tUNK_18 << 16 | 646 max(tUNK_18, (u8) 1) << 16 |
647 (tUNK_1 + tUNK_19 + 1 + magic_number) << 8; 647 (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
648 if(dev_priv->chipset == 0xa8) { 648 if (dev_priv->chipset == 0xa8) {
649 timing->reg_100224 |= (tUNK_2 - 1); 649 timing->reg_100224 |= (tUNK_2 - 1);
650 } else { 650 } else {
651 timing->reg_100224 |= (tUNK_2 + 2 - magic_number); 651 timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
652 } 652 }
653 653
654 timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); 654 timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
655 if(dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) { 655 if (dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa)
656 timing->reg_100228 |= (tUNK_19 - 1) << 24; 656 timing->reg_100228 |= (tUNK_19 - 1) << 24;
657 } 657 else
658 timing->reg_100228 |= magic_number << 24;
658 659
659 if(dev_priv->card_type == NV_40) { 660 if (dev_priv->card_type == NV_40) {
660 /* NV40: don't know what the rest of the regs are.. 661 /* NV40: don't know what the rest of the regs are..
661 * And don't need to know either */ 662 * And don't need to know either */
662 timing->reg_100228 |= 0x20200000 | magic_number << 24; 663 timing->reg_100228 |= 0x20200000;
663 } else if(dev_priv->card_type >= NV_50) { 664 } else if (dev_priv->card_type >= NV_50) {
664 /* XXX: reg_10022c */ 665 if (dev_priv->chipset < 0x98 ||
665 timing->reg_10022c = tUNK_2 - 1; 666 (dev_priv->chipset == 0x98 &&
667 dev_priv->stepping <= 0xa1)) {
668 timing->reg_10022c = (0x14 + tUNK_2) << 24 |
669 0x16 << 16 |
670 (tUNK_2 - 1) << 8 |
671 (tUNK_2 - 1);
672 } else {
673 /* XXX: reg_10022c for recentish cards */
674 timing->reg_10022c = tUNK_2 - 1;
675 }
666 676
667 timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | 677 timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
668 tUNK_13 << 8 | tUNK_13); 678 tUNK_13 << 8 | tUNK_13);
669 679
670 timing->reg_100234 = (tRAS << 24 | tRC); 680 timing->reg_100234 = (tRAS << 24 | tRC);
671 timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; 681 timing->reg_100234 += max(tUNK_10, tUNK_11) << 16;
672 682
673 if(dev_priv->chipset < 0xa3) { 683 if (dev_priv->chipset < 0x98 ||
684 (dev_priv->chipset == 0x98 &&
685 dev_priv->stepping <= 0xa1)) {
674 timing->reg_100234 |= (tUNK_2 + 2) << 8; 686 timing->reg_100234 |= (tUNK_2 + 2) << 8;
675 } else { 687 } else {
676 /* XXX: +6? */ 688 /* XXX: +6? */
677 timing->reg_100234 |= (tUNK_19 + 6) << 8; 689 timing->reg_100234 |= (tUNK_19 + 6) << 8;
678 } 690 }
679 691
680 /* XXX; reg_100238, reg_10023c 692 /* XXX; reg_100238
681 * reg_100238: 0x00?????? 693 * reg_100238: 0x00?????? */
682 * reg_10023c: 0x!!??0202 for NV50+ cards (empirical evidence) */
683 timing->reg_10023c = 0x202; 694 timing->reg_10023c = 0x202;
684 if(dev_priv->chipset < 0xa3) { 695 if (dev_priv->chipset < 0x98 ||
696 (dev_priv->chipset == 0x98 &&
697 dev_priv->stepping <= 0xa1)) {
685 timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16; 698 timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
686 } else { 699 } else {
687 /* currently unknown 700 /* XXX: reg_10023c
701 * currently unknown
688 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */ 702 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
689 } 703 }
704
705 /* XXX: reg_100240? */
690 } 706 }
707 timing->id = i;
691 708
692 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, 709 NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
693 timing->reg_100220, timing->reg_100224, 710 timing->reg_100220, timing->reg_100224,
@@ -695,10 +712,11 @@ nouveau_mem_timing_init(struct drm_device *dev)
695 NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n", 712 NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n",
696 timing->reg_100230, timing->reg_100234, 713 timing->reg_100230, timing->reg_100234,
697 timing->reg_100238, timing->reg_10023c); 714 timing->reg_100238, timing->reg_10023c);
715 NV_DEBUG(dev, " 240: %08x\n", timing->reg_100240);
698 } 716 }
699 717
700 memtimings->nr_timing = entries; 718 memtimings->nr_timing = entries;
701 memtimings->supported = true; 719 memtimings->supported = (dev_priv->chipset <= 0x98);
702} 720}
703 721
704void 722void
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 67a16e01ffa6..8f97016f5b26 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -361,20 +361,6 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
361 return 0; 361 return 0;
362} 362}
363 363
364
365static uint32_t
366nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
367{
368 struct drm_nouveau_private *dev_priv = dev->dev_private;
369
370 /*XXX: dodgy hack for now */
371 if (dev_priv->card_type >= NV_50)
372 return 24;
373 if (dev_priv->card_type >= NV_40)
374 return 32;
375 return 16;
376}
377
378/* 364/*
379 DMA objects are used to reference a piece of memory in the 365 DMA objects are used to reference a piece of memory in the
380 framebuffer, PCI or AGP address space. Each object is 16 bytes big 366 framebuffer, PCI or AGP address space. Each object is 16 bytes big
@@ -606,11 +592,11 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
606 set to 0? 592 set to 0?
607*/ 593*/
608static int 594static int
609nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, 595nouveau_gpuobj_sw_new(struct nouveau_channel *chan, u32 handle, u16 class)
610 struct nouveau_gpuobj **gpuobj_ret)
611{ 596{
612 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 597 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
613 struct nouveau_gpuobj *gpuobj; 598 struct nouveau_gpuobj *gpuobj;
599 int ret;
614 600
615 gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); 601 gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
616 if (!gpuobj) 602 if (!gpuobj)
@@ -624,8 +610,10 @@ nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
624 spin_lock(&dev_priv->ramin_lock); 610 spin_lock(&dev_priv->ramin_lock);
625 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); 611 list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
626 spin_unlock(&dev_priv->ramin_lock); 612 spin_unlock(&dev_priv->ramin_lock);
627 *gpuobj_ret = gpuobj; 613
628 return 0; 614 ret = nouveau_ramht_insert(chan, handle, gpuobj);
615 nouveau_gpuobj_ref(NULL, &gpuobj);
616 return ret;
629} 617}
630 618
631int 619int
@@ -634,101 +622,30 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
634 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 622 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
635 struct drm_device *dev = chan->dev; 623 struct drm_device *dev = chan->dev;
636 struct nouveau_gpuobj_class *oc; 624 struct nouveau_gpuobj_class *oc;
637 struct nouveau_gpuobj *gpuobj;
638 int ret; 625 int ret;
639 626
640 NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); 627 NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
641 628
642 list_for_each_entry(oc, &dev_priv->classes, head) { 629 list_for_each_entry(oc, &dev_priv->classes, head) {
643 if (oc->id == class) 630 struct nouveau_exec_engine *eng = dev_priv->eng[oc->engine];
644 goto found;
645 }
646
647 NV_ERROR(dev, "illegal object class: 0x%x\n", class);
648 return -EINVAL;
649 631
650found: 632 if (oc->id != class)
651 switch (oc->engine) { 633 continue;
652 case NVOBJ_ENGINE_SW:
653 if (dev_priv->card_type < NV_C0) {
654 ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
655 if (ret)
656 return ret;
657 goto insert;
658 }
659 break;
660 case NVOBJ_ENGINE_GR:
661 if ((dev_priv->card_type >= NV_20 && !chan->ramin_grctx) ||
662 (dev_priv->card_type < NV_20 && !chan->pgraph_ctx)) {
663 struct nouveau_pgraph_engine *pgraph =
664 &dev_priv->engine.graph;
665 634
666 ret = pgraph->create_context(chan); 635 if (oc->engine == NVOBJ_ENGINE_SW)
667 if (ret) 636 return nouveau_gpuobj_sw_new(chan, handle, class);
668 return ret;
669 }
670 break;
671 case NVOBJ_ENGINE_CRYPT:
672 if (!chan->crypt_ctx) {
673 struct nouveau_crypt_engine *pcrypt =
674 &dev_priv->engine.crypt;
675 637
676 ret = pcrypt->create_context(chan); 638 if (!chan->engctx[oc->engine]) {
639 ret = eng->context_new(chan, oc->engine);
677 if (ret) 640 if (ret)
678 return ret; 641 return ret;
679 } 642 }
680 break;
681 }
682
683 /* we're done if this is fermi */
684 if (dev_priv->card_type >= NV_C0)
685 return 0;
686
687 ret = nouveau_gpuobj_new(dev, chan,
688 nouveau_gpuobj_class_instmem_size(dev, class),
689 16,
690 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
691 &gpuobj);
692 if (ret) {
693 NV_ERROR(dev, "error creating gpuobj: %d\n", ret);
694 return ret;
695 }
696 643
697 if (dev_priv->card_type >= NV_50) { 644 return eng->object_new(chan, oc->engine, handle, class);
698 nv_wo32(gpuobj, 0, class);
699 nv_wo32(gpuobj, 20, 0x00010000);
700 } else {
701 switch (class) {
702 case NV_CLASS_NULL:
703 nv_wo32(gpuobj, 0, 0x00001030);
704 nv_wo32(gpuobj, 4, 0xFFFFFFFF);
705 break;
706 default:
707 if (dev_priv->card_type >= NV_40) {
708 nv_wo32(gpuobj, 0, class);
709#ifdef __BIG_ENDIAN
710 nv_wo32(gpuobj, 8, 0x01000000);
711#endif
712 } else {
713#ifdef __BIG_ENDIAN
714 nv_wo32(gpuobj, 0, class | 0x00080000);
715#else
716 nv_wo32(gpuobj, 0, class);
717#endif
718 }
719 }
720 } 645 }
721 dev_priv->engine.instmem.flush(dev);
722
723 gpuobj->engine = oc->engine;
724 gpuobj->class = oc->id;
725 646
726insert: 647 NV_ERROR(dev, "illegal object class: 0x%x\n", class);
727 ret = nouveau_ramht_insert(chan, handle, gpuobj); 648 return -EINVAL;
728 if (ret)
729 NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret);
730 nouveau_gpuobj_ref(NULL, &gpuobj);
731 return ret;
732} 649}
733 650
734static int 651static int
@@ -746,9 +663,6 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
746 size = 0x2000; 663 size = 0x2000;
747 base = 0; 664 base = 0;
748 665
749 /* PGRAPH context */
750 size += dev_priv->engine.graph.grctx_size;
751
752 if (dev_priv->card_type == NV_50) { 666 if (dev_priv->card_type == NV_50) {
753 /* Various fixed table thingos */ 667 /* Various fixed table thingos */
754 size += 0x1400; /* mostly unknown stuff */ 668 size += 0x1400; /* mostly unknown stuff */
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c
index 670e3cb697ec..922fb6b664ed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_perf.c
+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c
@@ -72,6 +72,68 @@ legacy_perf_init(struct drm_device *dev)
72 pm->nr_perflvl = 1; 72 pm->nr_perflvl = 1;
73} 73}
74 74
75static struct nouveau_pm_memtiming *
76nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P,
77 u16 memclk, u8 *entry, u8 recordlen, u8 entries)
78{
79 struct drm_nouveau_private *dev_priv = dev->dev_private;
80 struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
81 struct nvbios *bios = &dev_priv->vbios;
82 u8 ramcfg;
83 int i;
84
85 /* perf v2 has a separate "timing map" table, we have to match
86 * the target memory clock to a specific entry, *then* use
87 * ramcfg to select the correct subentry
88 */
89 if (P->version == 2) {
90 u8 *tmap = ROMPTR(bios, P->data[4]);
91 if (!tmap) {
92 NV_DEBUG(dev, "no timing map pointer\n");
93 return NULL;
94 }
95
96 if (tmap[0] != 0x10) {
97 NV_WARN(dev, "timing map 0x%02x unknown\n", tmap[0]);
98 return NULL;
99 }
100
101 entry = tmap + tmap[1];
102 recordlen = tmap[2] + (tmap[4] * tmap[3]);
103 for (i = 0; i < tmap[5]; i++, entry += recordlen) {
104 if (memclk >= ROM16(entry[0]) &&
105 memclk <= ROM16(entry[2]))
106 break;
107 }
108
109 if (i == tmap[5]) {
110 NV_WARN(dev, "no match in timing map table\n");
111 return NULL;
112 }
113
114 entry += tmap[2];
115 recordlen = tmap[3];
116 entries = tmap[4];
117 }
118
119 ramcfg = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2;
120 if (bios->ram_restrict_tbl_ptr)
121 ramcfg = bios->data[bios->ram_restrict_tbl_ptr + ramcfg];
122
123 if (ramcfg >= entries) {
124 NV_WARN(dev, "ramcfg strap out of bounds!\n");
125 return NULL;
126 }
127
128 entry += ramcfg * recordlen;
129 if (entry[1] >= pm->memtimings.nr_timing) {
130 NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
131 return NULL;
132 }
133
134 return &pm->memtimings.timing[entry[1]];
135}
136
75void 137void
76nouveau_perf_init(struct drm_device *dev) 138nouveau_perf_init(struct drm_device *dev)
77{ 139{
@@ -124,6 +186,8 @@ nouveau_perf_init(struct drm_device *dev)
124 for (i = 0; i < entries; i++) { 186 for (i = 0; i < entries; i++) {
125 struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; 187 struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
126 188
189 perflvl->timing = NULL;
190
127 if (entry[0] == 0xff) { 191 if (entry[0] == 0xff) {
128 entry += recordlen; 192 entry += recordlen;
129 continue; 193 continue;
@@ -174,9 +238,21 @@ nouveau_perf_init(struct drm_device *dev)
174#define subent(n) entry[perf[2] + ((n) * perf[3])] 238#define subent(n) entry[perf[2] + ((n) * perf[3])]
175 perflvl->fanspeed = 0; /*XXX*/ 239 perflvl->fanspeed = 0; /*XXX*/
176 perflvl->voltage = entry[2]; 240 perflvl->voltage = entry[2];
177 perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000; 241 if (dev_priv->card_type == NV_50) {
178 perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000; 242 perflvl->core = ROM16(subent(0)) & 0xfff;
179 perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000; 243 perflvl->shader = ROM16(subent(1)) & 0xfff;
244 perflvl->memory = ROM16(subent(2)) & 0xfff;
245 } else {
246 perflvl->shader = ROM16(subent(3)) & 0xfff;
247 perflvl->core = perflvl->shader / 2;
248 perflvl->unk0a = ROM16(subent(4)) & 0xfff;
249 perflvl->memory = ROM16(subent(5)) & 0xfff;
250 }
251
252 perflvl->core *= 1000;
253 perflvl->shader *= 1000;
254 perflvl->memory *= 1000;
255 perflvl->unk0a *= 1000;
180 break; 256 break;
181 } 257 }
182 258
@@ -190,6 +266,16 @@ nouveau_perf_init(struct drm_device *dev)
190 } 266 }
191 } 267 }
192 268
269 /* get the corresponding memory timings */
270 if (version > 0x15) {
271 /* last 3 args are for < 0x40, ignored for >= 0x40 */
272 perflvl->timing =
273 nouveau_perf_timing(dev, &P,
274 perflvl->memory / 1000,
275 entry + perf[3],
276 perf[5], perf[4]);
277 }
278
193 snprintf(perflvl->name, sizeof(perflvl->name), 279 snprintf(perflvl->name, sizeof(perflvl->name),
194 "performance_level_%d", i); 280 "performance_level_%d", i);
195 perflvl->id = i; 281 perflvl->id = i;
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 4399e2f34db4..da8d994d5e8a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -156,7 +156,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
156static void 156static void
157nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) 157nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
158{ 158{
159 char c[16], s[16], v[16], f[16]; 159 char c[16], s[16], v[16], f[16], t[16];
160 160
161 c[0] = '\0'; 161 c[0] = '\0';
162 if (perflvl->core) 162 if (perflvl->core)
@@ -174,8 +174,12 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
174 if (perflvl->fanspeed) 174 if (perflvl->fanspeed)
175 snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); 175 snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
176 176
177 snprintf(ptr, len, "memory %dMHz%s%s%s%s\n", perflvl->memory / 1000, 177 t[0] = '\0';
178 c, s, v, f); 178 if (perflvl->timing)
179 snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
180
181 snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000,
182 c, s, v, f, t);
179} 183}
180 184
181static ssize_t 185static ssize_t
@@ -449,7 +453,7 @@ nouveau_hwmon_fini(struct drm_device *dev)
449#endif 453#endif
450} 454}
451 455
452#ifdef CONFIG_ACPI 456#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
453static int 457static int
454nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) 458nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data)
455{ 459{
@@ -476,10 +480,10 @@ nouveau_pm_init(struct drm_device *dev)
476 char info[256]; 480 char info[256];
477 int ret, i; 481 int ret, i;
478 482
483 nouveau_mem_timing_init(dev);
479 nouveau_volt_init(dev); 484 nouveau_volt_init(dev);
480 nouveau_perf_init(dev); 485 nouveau_perf_init(dev);
481 nouveau_temp_init(dev); 486 nouveau_temp_init(dev);
482 nouveau_mem_timing_init(dev);
483 487
484 NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); 488 NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
485 for (i = 0; i < pm->nr_perflvl; i++) { 489 for (i = 0; i < pm->nr_perflvl; i++) {
@@ -490,6 +494,7 @@ nouveau_pm_init(struct drm_device *dev)
490 /* determine current ("boot") performance level */ 494 /* determine current ("boot") performance level */
491 ret = nouveau_pm_perflvl_get(dev, &pm->boot); 495 ret = nouveau_pm_perflvl_get(dev, &pm->boot);
492 if (ret == 0) { 496 if (ret == 0) {
497 strncpy(pm->boot.name, "boot", 4);
493 pm->cur = &pm->boot; 498 pm->cur = &pm->boot;
494 499
495 nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); 500 nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info));
@@ -507,7 +512,7 @@ nouveau_pm_init(struct drm_device *dev)
507 512
508 nouveau_sysfs_init(dev); 513 nouveau_sysfs_init(dev);
509 nouveau_hwmon_init(dev); 514 nouveau_hwmon_init(dev);
510#ifdef CONFIG_ACPI 515#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
511 pm->acpi_nb.notifier_call = nouveau_pm_acpi_event; 516 pm->acpi_nb.notifier_call = nouveau_pm_acpi_event;
512 register_acpi_notifier(&pm->acpi_nb); 517 register_acpi_notifier(&pm->acpi_nb);
513#endif 518#endif
@@ -524,12 +529,12 @@ nouveau_pm_fini(struct drm_device *dev)
524 if (pm->cur != &pm->boot) 529 if (pm->cur != &pm->boot)
525 nouveau_pm_perflvl_set(dev, &pm->boot); 530 nouveau_pm_perflvl_set(dev, &pm->boot);
526 531
527 nouveau_mem_timing_fini(dev);
528 nouveau_temp_fini(dev); 532 nouveau_temp_fini(dev);
529 nouveau_perf_fini(dev); 533 nouveau_perf_fini(dev);
530 nouveau_volt_fini(dev); 534 nouveau_volt_fini(dev);
535 nouveau_mem_timing_fini(dev);
531 536
532#ifdef CONFIG_ACPI 537#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
533 unregister_acpi_notifier(&pm->acpi_nb); 538 unregister_acpi_notifier(&pm->acpi_nb);
534#endif 539#endif
535 nouveau_hwmon_fini(dev); 540 nouveau_hwmon_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h
index 04e8fb795269..f18cdfc3400f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_reg.h
+++ b/drivers/gpu/drm/nouveau/nouveau_reg.h
@@ -639,9 +639,9 @@
639# define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 639# define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240
640# define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 640# define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258
641 641
642#define NV50_AUXCH_DATA_OUT(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0) 642#define NV50_AUXCH_DATA_OUT(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4c0)
643#define NV50_AUXCH_DATA_OUT__SIZE 4 643#define NV50_AUXCH_DATA_OUT__SIZE 4
644#define NV50_AUXCH_DATA_IN(i,n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0) 644#define NV50_AUXCH_DATA_IN(i, n) ((n) * 4 + (i) * 0x50 + 0x0000e4d0)
645#define NV50_AUXCH_DATA_IN__SIZE 4 645#define NV50_AUXCH_DATA_IN__SIZE 4
646#define NV50_AUXCH_ADDR(i) ((i) * 0x50 + 0x0000e4e0) 646#define NV50_AUXCH_ADDR(i) ((i) * 0x50 + 0x0000e4e0)
647#define NV50_AUXCH_CTRL(i) ((i) * 0x50 + 0x0000e4e4) 647#define NV50_AUXCH_CTRL(i) ((i) * 0x50 + 0x0000e4e4)
@@ -829,7 +829,7 @@
829#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084 829#define NV50_PDISPLAY_SOR_BACKLIGHT 0x0061c084
830#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 830#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000
831#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff 831#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff
832#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) 832#define NV50_SOR_DP_CTRL(i, l) (0x0061c10c + (i) * 0x800 + (l) * 0x80)
833#define NV50_SOR_DP_CTRL_ENABLED 0x00000001 833#define NV50_SOR_DP_CTRL_ENABLED 0x00000001
834#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 834#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000
835#define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 835#define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000
@@ -841,10 +841,10 @@
841#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED 0x00000000 841#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_DISABLED 0x00000000
842#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1 0x01000000 842#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_1 0x01000000
843#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000 843#define NV50_SOR_DP_CTRL_TRAINING_PATTERN_2 0x02000000
844#define NV50_SOR_DP_UNK118(i,l) (0x0061c118 + (i) * 0x800 + (l) * 0x80) 844#define NV50_SOR_DP_UNK118(i, l) (0x0061c118 + (i) * 0x800 + (l) * 0x80)
845#define NV50_SOR_DP_UNK120(i,l) (0x0061c120 + (i) * 0x800 + (l) * 0x80) 845#define NV50_SOR_DP_UNK120(i, l) (0x0061c120 + (i) * 0x800 + (l) * 0x80)
846#define NV50_SOR_DP_UNK128(i,l) (0x0061c128 + (i) * 0x800 + (l) * 0x80) 846#define NV50_SOR_DP_UNK128(i, l) (0x0061c128 + (i) * 0x800 + (l) * 0x80)
847#define NV50_SOR_DP_UNK130(i,l) (0x0061c130 + (i) * 0x800 + (l) * 0x80) 847#define NV50_SOR_DP_UNK130(i, l) (0x0061c130 + (i) * 0x800 + (l) * 0x80)
848 848
849#define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000) 849#define NV50_PDISPLAY_USER(i) ((i) * 0x1000 + 0x00640000)
850#define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000) 850#define NV50_PDISPLAY_USER_PUT(i) ((i) * 0x1000 + 0x00640000)
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index a30adec5beaa..38ea662568c1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -65,14 +65,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
65 engine->timer.takedown = nv04_timer_takedown; 65 engine->timer.takedown = nv04_timer_takedown;
66 engine->fb.init = nv04_fb_init; 66 engine->fb.init = nv04_fb_init;
67 engine->fb.takedown = nv04_fb_takedown; 67 engine->fb.takedown = nv04_fb_takedown;
68 engine->graph.init = nv04_graph_init;
69 engine->graph.takedown = nv04_graph_takedown;
70 engine->graph.fifo_access = nv04_graph_fifo_access;
71 engine->graph.channel = nv04_graph_channel;
72 engine->graph.create_context = nv04_graph_create_context;
73 engine->graph.destroy_context = nv04_graph_destroy_context;
74 engine->graph.load_context = nv04_graph_load_context;
75 engine->graph.unload_context = nv04_graph_unload_context;
76 engine->fifo.channels = 16; 68 engine->fifo.channels = 16;
77 engine->fifo.init = nv04_fifo_init; 69 engine->fifo.init = nv04_fifo_init;
78 engine->fifo.takedown = nv04_fifo_fini; 70 engine->fifo.takedown = nv04_fifo_fini;
@@ -98,8 +90,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
98 engine->pm.clock_get = nv04_pm_clock_get; 90 engine->pm.clock_get = nv04_pm_clock_get;
99 engine->pm.clock_pre = nv04_pm_clock_pre; 91 engine->pm.clock_pre = nv04_pm_clock_pre;
100 engine->pm.clock_set = nv04_pm_clock_set; 92 engine->pm.clock_set = nv04_pm_clock_set;
101 engine->crypt.init = nouveau_stub_init;
102 engine->crypt.takedown = nouveau_stub_takedown;
103 engine->vram.init = nouveau_mem_detect; 93 engine->vram.init = nouveau_mem_detect;
104 engine->vram.flags_valid = nouveau_mem_flags_valid; 94 engine->vram.flags_valid = nouveau_mem_flags_valid;
105 break; 95 break;
@@ -123,15 +113,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
123 engine->fb.init_tile_region = nv10_fb_init_tile_region; 113 engine->fb.init_tile_region = nv10_fb_init_tile_region;
124 engine->fb.set_tile_region = nv10_fb_set_tile_region; 114 engine->fb.set_tile_region = nv10_fb_set_tile_region;
125 engine->fb.free_tile_region = nv10_fb_free_tile_region; 115 engine->fb.free_tile_region = nv10_fb_free_tile_region;
126 engine->graph.init = nv10_graph_init;
127 engine->graph.takedown = nv10_graph_takedown;
128 engine->graph.channel = nv10_graph_channel;
129 engine->graph.create_context = nv10_graph_create_context;
130 engine->graph.destroy_context = nv10_graph_destroy_context;
131 engine->graph.fifo_access = nv04_graph_fifo_access;
132 engine->graph.load_context = nv10_graph_load_context;
133 engine->graph.unload_context = nv10_graph_unload_context;
134 engine->graph.set_tile_region = nv10_graph_set_tile_region;
135 engine->fifo.channels = 32; 116 engine->fifo.channels = 32;
136 engine->fifo.init = nv10_fifo_init; 117 engine->fifo.init = nv10_fifo_init;
137 engine->fifo.takedown = nv04_fifo_fini; 118 engine->fifo.takedown = nv04_fifo_fini;
@@ -157,8 +138,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
157 engine->pm.clock_get = nv04_pm_clock_get; 138 engine->pm.clock_get = nv04_pm_clock_get;
158 engine->pm.clock_pre = nv04_pm_clock_pre; 139 engine->pm.clock_pre = nv04_pm_clock_pre;
159 engine->pm.clock_set = nv04_pm_clock_set; 140 engine->pm.clock_set = nv04_pm_clock_set;
160 engine->crypt.init = nouveau_stub_init;
161 engine->crypt.takedown = nouveau_stub_takedown;
162 engine->vram.init = nouveau_mem_detect; 141 engine->vram.init = nouveau_mem_detect;
163 engine->vram.flags_valid = nouveau_mem_flags_valid; 142 engine->vram.flags_valid = nouveau_mem_flags_valid;
164 break; 143 break;
@@ -182,15 +161,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
182 engine->fb.init_tile_region = nv10_fb_init_tile_region; 161 engine->fb.init_tile_region = nv10_fb_init_tile_region;
183 engine->fb.set_tile_region = nv10_fb_set_tile_region; 162 engine->fb.set_tile_region = nv10_fb_set_tile_region;
184 engine->fb.free_tile_region = nv10_fb_free_tile_region; 163 engine->fb.free_tile_region = nv10_fb_free_tile_region;
185 engine->graph.init = nv20_graph_init;
186 engine->graph.takedown = nv20_graph_takedown;
187 engine->graph.channel = nv10_graph_channel;
188 engine->graph.create_context = nv20_graph_create_context;
189 engine->graph.destroy_context = nv20_graph_destroy_context;
190 engine->graph.fifo_access = nv04_graph_fifo_access;
191 engine->graph.load_context = nv20_graph_load_context;
192 engine->graph.unload_context = nv20_graph_unload_context;
193 engine->graph.set_tile_region = nv20_graph_set_tile_region;
194 engine->fifo.channels = 32; 164 engine->fifo.channels = 32;
195 engine->fifo.init = nv10_fifo_init; 165 engine->fifo.init = nv10_fifo_init;
196 engine->fifo.takedown = nv04_fifo_fini; 166 engine->fifo.takedown = nv04_fifo_fini;
@@ -216,8 +186,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
216 engine->pm.clock_get = nv04_pm_clock_get; 186 engine->pm.clock_get = nv04_pm_clock_get;
217 engine->pm.clock_pre = nv04_pm_clock_pre; 187 engine->pm.clock_pre = nv04_pm_clock_pre;
218 engine->pm.clock_set = nv04_pm_clock_set; 188 engine->pm.clock_set = nv04_pm_clock_set;
219 engine->crypt.init = nouveau_stub_init;
220 engine->crypt.takedown = nouveau_stub_takedown;
221 engine->vram.init = nouveau_mem_detect; 189 engine->vram.init = nouveau_mem_detect;
222 engine->vram.flags_valid = nouveau_mem_flags_valid; 190 engine->vram.flags_valid = nouveau_mem_flags_valid;
223 break; 191 break;
@@ -241,15 +209,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
241 engine->fb.init_tile_region = nv30_fb_init_tile_region; 209 engine->fb.init_tile_region = nv30_fb_init_tile_region;
242 engine->fb.set_tile_region = nv10_fb_set_tile_region; 210 engine->fb.set_tile_region = nv10_fb_set_tile_region;
243 engine->fb.free_tile_region = nv30_fb_free_tile_region; 211 engine->fb.free_tile_region = nv30_fb_free_tile_region;
244 engine->graph.init = nv30_graph_init;
245 engine->graph.takedown = nv20_graph_takedown;
246 engine->graph.fifo_access = nv04_graph_fifo_access;
247 engine->graph.channel = nv10_graph_channel;
248 engine->graph.create_context = nv20_graph_create_context;
249 engine->graph.destroy_context = nv20_graph_destroy_context;
250 engine->graph.load_context = nv20_graph_load_context;
251 engine->graph.unload_context = nv20_graph_unload_context;
252 engine->graph.set_tile_region = nv20_graph_set_tile_region;
253 engine->fifo.channels = 32; 212 engine->fifo.channels = 32;
254 engine->fifo.init = nv10_fifo_init; 213 engine->fifo.init = nv10_fifo_init;
255 engine->fifo.takedown = nv04_fifo_fini; 214 engine->fifo.takedown = nv04_fifo_fini;
@@ -277,8 +236,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
277 engine->pm.clock_set = nv04_pm_clock_set; 236 engine->pm.clock_set = nv04_pm_clock_set;
278 engine->pm.voltage_get = nouveau_voltage_gpio_get; 237 engine->pm.voltage_get = nouveau_voltage_gpio_get;
279 engine->pm.voltage_set = nouveau_voltage_gpio_set; 238 engine->pm.voltage_set = nouveau_voltage_gpio_set;
280 engine->crypt.init = nouveau_stub_init;
281 engine->crypt.takedown = nouveau_stub_takedown;
282 engine->vram.init = nouveau_mem_detect; 239 engine->vram.init = nouveau_mem_detect;
283 engine->vram.flags_valid = nouveau_mem_flags_valid; 240 engine->vram.flags_valid = nouveau_mem_flags_valid;
284 break; 241 break;
@@ -303,15 +260,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
303 engine->fb.init_tile_region = nv30_fb_init_tile_region; 260 engine->fb.init_tile_region = nv30_fb_init_tile_region;
304 engine->fb.set_tile_region = nv40_fb_set_tile_region; 261 engine->fb.set_tile_region = nv40_fb_set_tile_region;
305 engine->fb.free_tile_region = nv30_fb_free_tile_region; 262 engine->fb.free_tile_region = nv30_fb_free_tile_region;
306 engine->graph.init = nv40_graph_init;
307 engine->graph.takedown = nv40_graph_takedown;
308 engine->graph.fifo_access = nv04_graph_fifo_access;
309 engine->graph.channel = nv40_graph_channel;
310 engine->graph.create_context = nv40_graph_create_context;
311 engine->graph.destroy_context = nv40_graph_destroy_context;
312 engine->graph.load_context = nv40_graph_load_context;
313 engine->graph.unload_context = nv40_graph_unload_context;
314 engine->graph.set_tile_region = nv40_graph_set_tile_region;
315 engine->fifo.channels = 32; 263 engine->fifo.channels = 32;
316 engine->fifo.init = nv40_fifo_init; 264 engine->fifo.init = nv40_fifo_init;
317 engine->fifo.takedown = nv04_fifo_fini; 265 engine->fifo.takedown = nv04_fifo_fini;
@@ -340,8 +288,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
340 engine->pm.voltage_get = nouveau_voltage_gpio_get; 288 engine->pm.voltage_get = nouveau_voltage_gpio_get;
341 engine->pm.voltage_set = nouveau_voltage_gpio_set; 289 engine->pm.voltage_set = nouveau_voltage_gpio_set;
342 engine->pm.temp_get = nv40_temp_get; 290 engine->pm.temp_get = nv40_temp_get;
343 engine->crypt.init = nouveau_stub_init;
344 engine->crypt.takedown = nouveau_stub_takedown;
345 engine->vram.init = nouveau_mem_detect; 291 engine->vram.init = nouveau_mem_detect;
346 engine->vram.flags_valid = nouveau_mem_flags_valid; 292 engine->vram.flags_valid = nouveau_mem_flags_valid;
347 break; 293 break;
@@ -368,19 +314,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
368 engine->timer.takedown = nv04_timer_takedown; 314 engine->timer.takedown = nv04_timer_takedown;
369 engine->fb.init = nv50_fb_init; 315 engine->fb.init = nv50_fb_init;
370 engine->fb.takedown = nv50_fb_takedown; 316 engine->fb.takedown = nv50_fb_takedown;
371 engine->graph.init = nv50_graph_init;
372 engine->graph.takedown = nv50_graph_takedown;
373 engine->graph.fifo_access = nv50_graph_fifo_access;
374 engine->graph.channel = nv50_graph_channel;
375 engine->graph.create_context = nv50_graph_create_context;
376 engine->graph.destroy_context = nv50_graph_destroy_context;
377 engine->graph.load_context = nv50_graph_load_context;
378 engine->graph.unload_context = nv50_graph_unload_context;
379 if (dev_priv->chipset == 0x50 ||
380 dev_priv->chipset == 0xac)
381 engine->graph.tlb_flush = nv50_graph_tlb_flush;
382 else
383 engine->graph.tlb_flush = nv84_graph_tlb_flush;
384 engine->fifo.channels = 128; 317 engine->fifo.channels = 128;
385 engine->fifo.init = nv50_fifo_init; 318 engine->fifo.init = nv50_fifo_init;
386 engine->fifo.takedown = nv50_fifo_takedown; 319 engine->fifo.takedown = nv50_fifo_takedown;
@@ -432,24 +365,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
432 engine->pm.temp_get = nv84_temp_get; 365 engine->pm.temp_get = nv84_temp_get;
433 else 366 else
434 engine->pm.temp_get = nv40_temp_get; 367 engine->pm.temp_get = nv40_temp_get;
435 switch (dev_priv->chipset) {
436 case 0x84:
437 case 0x86:
438 case 0x92:
439 case 0x94:
440 case 0x96:
441 case 0xa0:
442 engine->crypt.init = nv84_crypt_init;
443 engine->crypt.takedown = nv84_crypt_fini;
444 engine->crypt.create_context = nv84_crypt_create_context;
445 engine->crypt.destroy_context = nv84_crypt_destroy_context;
446 engine->crypt.tlb_flush = nv84_crypt_tlb_flush;
447 break;
448 default:
449 engine->crypt.init = nouveau_stub_init;
450 engine->crypt.takedown = nouveau_stub_takedown;
451 break;
452 }
453 engine->vram.init = nv50_vram_init; 368 engine->vram.init = nv50_vram_init;
454 engine->vram.get = nv50_vram_new; 369 engine->vram.get = nv50_vram_new;
455 engine->vram.put = nv50_vram_del; 370 engine->vram.put = nv50_vram_del;
@@ -472,14 +387,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
472 engine->timer.takedown = nv04_timer_takedown; 387 engine->timer.takedown = nv04_timer_takedown;
473 engine->fb.init = nvc0_fb_init; 388 engine->fb.init = nvc0_fb_init;
474 engine->fb.takedown = nvc0_fb_takedown; 389 engine->fb.takedown = nvc0_fb_takedown;
475 engine->graph.init = nvc0_graph_init;
476 engine->graph.takedown = nvc0_graph_takedown;
477 engine->graph.fifo_access = nvc0_graph_fifo_access;
478 engine->graph.channel = nvc0_graph_channel;
479 engine->graph.create_context = nvc0_graph_create_context;
480 engine->graph.destroy_context = nvc0_graph_destroy_context;
481 engine->graph.load_context = nvc0_graph_load_context;
482 engine->graph.unload_context = nvc0_graph_unload_context;
483 engine->fifo.channels = 128; 390 engine->fifo.channels = 128;
484 engine->fifo.init = nvc0_fifo_init; 391 engine->fifo.init = nvc0_fifo_init;
485 engine->fifo.takedown = nvc0_fifo_takedown; 392 engine->fifo.takedown = nvc0_fifo_takedown;
@@ -503,8 +410,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
503 engine->gpio.irq_register = nv50_gpio_irq_register; 410 engine->gpio.irq_register = nv50_gpio_irq_register;
504 engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 411 engine->gpio.irq_unregister = nv50_gpio_irq_unregister;
505 engine->gpio.irq_enable = nv50_gpio_irq_enable; 412 engine->gpio.irq_enable = nv50_gpio_irq_enable;
506 engine->crypt.init = nouveau_stub_init;
507 engine->crypt.takedown = nouveau_stub_takedown;
508 engine->vram.init = nvc0_vram_init; 413 engine->vram.init = nvc0_vram_init;
509 engine->vram.get = nvc0_vram_new; 414 engine->vram.get = nvc0_vram_new;
510 engine->vram.put = nv50_vram_del; 415 engine->vram.put = nv50_vram_del;
@@ -593,7 +498,7 @@ nouveau_card_init(struct drm_device *dev)
593{ 498{
594 struct drm_nouveau_private *dev_priv = dev->dev_private; 499 struct drm_nouveau_private *dev_priv = dev->dev_private;
595 struct nouveau_engine *engine; 500 struct nouveau_engine *engine;
596 int ret; 501 int ret, e = 0;
597 502
598 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); 503 vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
599 vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state, 504 vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
@@ -658,23 +563,80 @@ nouveau_card_init(struct drm_device *dev)
658 if (ret) 563 if (ret)
659 goto out_timer; 564 goto out_timer;
660 565
661 if (nouveau_noaccel) 566 switch (dev_priv->card_type) {
662 engine->graph.accel_blocked = true; 567 case NV_04:
663 else { 568 nv04_graph_create(dev);
664 /* PGRAPH */ 569 break;
665 ret = engine->graph.init(dev); 570 case NV_10:
666 if (ret) 571 nv10_graph_create(dev);
667 goto out_fb; 572 break;
573 case NV_20:
574 case NV_30:
575 nv20_graph_create(dev);
576 break;
577 case NV_40:
578 nv40_graph_create(dev);
579 break;
580 case NV_50:
581 nv50_graph_create(dev);
582 break;
583 case NV_C0:
584 nvc0_graph_create(dev);
585 break;
586 default:
587 break;
588 }
668 589
669 /* PCRYPT */ 590 switch (dev_priv->chipset) {
670 ret = engine->crypt.init(dev); 591 case 0x84:
671 if (ret) 592 case 0x86:
672 goto out_graph; 593 case 0x92:
594 case 0x94:
595 case 0x96:
596 case 0xa0:
597 nv84_crypt_create(dev);
598 break;
599 }
600
601 switch (dev_priv->card_type) {
602 case NV_50:
603 switch (dev_priv->chipset) {
604 case 0xa3:
605 case 0xa5:
606 case 0xa8:
607 case 0xaf:
608 nva3_copy_create(dev);
609 break;
610 }
611 break;
612 case NV_C0:
613 nvc0_copy_create(dev, 0);
614 nvc0_copy_create(dev, 1);
615 break;
616 default:
617 break;
618 }
619
620 if (dev_priv->card_type == NV_40)
621 nv40_mpeg_create(dev);
622 else
623 if (dev_priv->card_type == NV_50 &&
624 (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0))
625 nv50_mpeg_create(dev);
626
627 if (!nouveau_noaccel) {
628 for (e = 0; e < NVOBJ_ENGINE_NR; e++) {
629 if (dev_priv->eng[e]) {
630 ret = dev_priv->eng[e]->init(dev, e);
631 if (ret)
632 goto out_engine;
633 }
634 }
673 635
674 /* PFIFO */ 636 /* PFIFO */
675 ret = engine->fifo.init(dev); 637 ret = engine->fifo.init(dev);
676 if (ret) 638 if (ret)
677 goto out_crypt; 639 goto out_engine;
678 } 640 }
679 641
680 ret = engine->display.create(dev); 642 ret = engine->display.create(dev);
@@ -691,7 +653,7 @@ nouveau_card_init(struct drm_device *dev)
691 653
692 /* what about PVIDEO/PCRTC/PRAMDAC etc? */ 654 /* what about PVIDEO/PCRTC/PRAMDAC etc? */
693 655
694 if (!engine->graph.accel_blocked) { 656 if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
695 ret = nouveau_fence_init(dev); 657 ret = nouveau_fence_init(dev);
696 if (ret) 658 if (ret)
697 goto out_irq; 659 goto out_irq;
@@ -715,13 +677,16 @@ out_vblank:
715out_fifo: 677out_fifo:
716 if (!nouveau_noaccel) 678 if (!nouveau_noaccel)
717 engine->fifo.takedown(dev); 679 engine->fifo.takedown(dev);
718out_crypt: 680out_engine:
719 if (!nouveau_noaccel) 681 if (!nouveau_noaccel) {
720 engine->crypt.takedown(dev); 682 for (e = e - 1; e >= 0; e--) {
721out_graph: 683 if (!dev_priv->eng[e])
722 if (!nouveau_noaccel) 684 continue;
723 engine->graph.takedown(dev); 685 dev_priv->eng[e]->fini(dev, e);
724out_fb: 686 dev_priv->eng[e]->destroy(dev,e );
687 }
688 }
689
725 engine->fb.takedown(dev); 690 engine->fb.takedown(dev);
726out_timer: 691out_timer:
727 engine->timer.takedown(dev); 692 engine->timer.takedown(dev);
@@ -751,16 +716,21 @@ static void nouveau_card_takedown(struct drm_device *dev)
751{ 716{
752 struct drm_nouveau_private *dev_priv = dev->dev_private; 717 struct drm_nouveau_private *dev_priv = dev->dev_private;
753 struct nouveau_engine *engine = &dev_priv->engine; 718 struct nouveau_engine *engine = &dev_priv->engine;
719 int e;
754 720
755 if (!engine->graph.accel_blocked) { 721 if (dev_priv->channel) {
756 nouveau_fence_fini(dev); 722 nouveau_fence_fini(dev);
757 nouveau_channel_put_unlocked(&dev_priv->channel); 723 nouveau_channel_put_unlocked(&dev_priv->channel);
758 } 724 }
759 725
760 if (!nouveau_noaccel) { 726 if (!nouveau_noaccel) {
761 engine->fifo.takedown(dev); 727 engine->fifo.takedown(dev);
762 engine->crypt.takedown(dev); 728 for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
763 engine->graph.takedown(dev); 729 if (dev_priv->eng[e]) {
730 dev_priv->eng[e]->fini(dev, e);
731 dev_priv->eng[e]->destroy(dev,e );
732 }
733 }
764 } 734 }
765 engine->fb.takedown(dev); 735 engine->fb.takedown(dev);
766 engine->timer.takedown(dev); 736 engine->timer.takedown(dev);
@@ -768,6 +738,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
768 engine->mc.takedown(dev); 738 engine->mc.takedown(dev);
769 engine->display.late_takedown(dev); 739 engine->display.late_takedown(dev);
770 740
741 if (dev_priv->vga_ram) {
742 nouveau_bo_unpin(dev_priv->vga_ram);
743 nouveau_bo_ref(NULL, &dev_priv->vga_ram);
744 }
745
771 mutex_lock(&dev->struct_mutex); 746 mutex_lock(&dev->struct_mutex);
772 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); 747 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
773 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); 748 ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
@@ -861,7 +836,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
861#ifdef CONFIG_X86 836#ifdef CONFIG_X86
862 primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; 837 primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
863#endif 838#endif
864 839
865 remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); 840 remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
866 return 0; 841 return 0;
867} 842}
@@ -913,11 +888,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
913 888
914 /* Time to determine the card architecture */ 889 /* Time to determine the card architecture */
915 reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); 890 reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
891 dev_priv->stepping = 0; /* XXX: add stepping for pre-NV10? */
916 892
917 /* We're dealing with >=NV10 */ 893 /* We're dealing with >=NV10 */
918 if ((reg0 & 0x0f000000) > 0) { 894 if ((reg0 & 0x0f000000) > 0) {
919 /* Bit 27-20 contain the architecture in hex */ 895 /* Bit 27-20 contain the architecture in hex */
920 dev_priv->chipset = (reg0 & 0xff00000) >> 20; 896 dev_priv->chipset = (reg0 & 0xff00000) >> 20;
897 dev_priv->stepping = (reg0 & 0xff);
921 /* NV04 or NV05 */ 898 /* NV04 or NV05 */
922 } else if ((reg0 & 0xff00fff0) == 0x20004000) { 899 } else if ((reg0 & 0xff00fff0) == 0x20004000) {
923 if (reg0 & 0x00f00000) 900 if (reg0 & 0x00f00000)
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 2e06b55cfdc1..c48a9fc2b47b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -53,8 +53,7 @@ struct nouveau_vm {
53 int refcount; 53 int refcount;
54 54
55 struct list_head pgd_list; 55 struct list_head pgd_list;
56 atomic_t pgraph_refs; 56 atomic_t engref[16];
57 atomic_t pcrypt_refs;
58 57
59 struct nouveau_vm_pgt *pgt; 58 struct nouveau_vm_pgt *pgt;
60 u32 fpde; 59 u32 fpde;
diff --git a/drivers/gpu/drm/nouveau/nouveau_volt.c b/drivers/gpu/drm/nouveau/nouveau_volt.c
index 04fdc00a67d5..75e872741d92 100644
--- a/drivers/gpu/drm/nouveau/nouveau_volt.c
+++ b/drivers/gpu/drm/nouveau/nouveau_volt.c
@@ -159,8 +159,16 @@ nouveau_volt_init(struct drm_device *dev)
159 headerlen = volt[1]; 159 headerlen = volt[1];
160 recordlen = volt[2]; 160 recordlen = volt[2];
161 entries = volt[3]; 161 entries = volt[3];
162 vidshift = hweight8(volt[5]);
163 vidmask = volt[4]; 162 vidmask = volt[4];
163 /* no longer certain what volt[5] is, if it's related to
164 * the vid shift then it's definitely not a function of
165 * how many bits are set.
166 *
167 * after looking at a number of nva3+ vbios images, they
168 * all seem likely to have a static shift of 2.. lets
169 * go with that for now until proven otherwise.
170 */
171 vidshift = 2;
164 break; 172 break;
165 default: 173 default:
166 NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); 174 NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]);
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index 748b9d9c2949..3c78bc81357e 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -790,8 +790,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
790 if (atomic) { 790 if (atomic) {
791 drm_fb = passed_fb; 791 drm_fb = passed_fb;
792 fb = nouveau_framebuffer(passed_fb); 792 fb = nouveau_framebuffer(passed_fb);
793 } 793 } else {
794 else {
795 /* If not atomic, we can go ahead and pin, and unpin the 794 /* If not atomic, we can go ahead and pin, and unpin the
796 * old fb we were passed. 795 * old fb we were passed.
797 */ 796 */
@@ -944,14 +943,14 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
944 struct drm_gem_object *gem; 943 struct drm_gem_object *gem;
945 int ret = 0; 944 int ret = 0;
946 945
947 if (width != 64 || height != 64)
948 return -EINVAL;
949
950 if (!buffer_handle) { 946 if (!buffer_handle) {
951 nv_crtc->cursor.hide(nv_crtc, true); 947 nv_crtc->cursor.hide(nv_crtc, true);
952 return 0; 948 return 0;
953 } 949 }
954 950
951 if (width != 64 || height != 64)
952 return -EINVAL;
953
955 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); 954 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
956 if (!gem) 955 if (!gem)
957 return -ENOENT; 956 return -ENOENT;
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c
index af75015068d6..3626ee7db3ba 100644
--- a/drivers/gpu/drm/nouveau/nv04_graph.c
+++ b/drivers/gpu/drm/nouveau/nv04_graph.c
@@ -28,9 +28,11 @@
28#include "nouveau_drv.h" 28#include "nouveau_drv.h"
29#include "nouveau_hw.h" 29#include "nouveau_hw.h"
30#include "nouveau_util.h" 30#include "nouveau_util.h"
31#include "nouveau_ramht.h"
31 32
32static int nv04_graph_register(struct drm_device *dev); 33struct nv04_graph_engine {
33static void nv04_graph_isr(struct drm_device *dev); 34 struct nouveau_exec_engine base;
35};
34 36
35static uint32_t nv04_graph_ctx_regs[] = { 37static uint32_t nv04_graph_ctx_regs[] = {
36 0x0040053c, 38 0x0040053c,
@@ -350,7 +352,7 @@ struct graph_state {
350 uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; 352 uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
351}; 353};
352 354
353struct nouveau_channel * 355static struct nouveau_channel *
354nv04_graph_channel(struct drm_device *dev) 356nv04_graph_channel(struct drm_device *dev)
355{ 357{
356 struct drm_nouveau_private *dev_priv = dev->dev_private; 358 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -365,26 +367,6 @@ nv04_graph_channel(struct drm_device *dev)
365 return dev_priv->channels.ptr[chid]; 367 return dev_priv->channels.ptr[chid];
366} 368}
367 369
368static void
369nv04_graph_context_switch(struct drm_device *dev)
370{
371 struct drm_nouveau_private *dev_priv = dev->dev_private;
372 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
373 struct nouveau_channel *chan = NULL;
374 int chid;
375
376 nouveau_wait_for_idle(dev);
377
378 /* If previous context is valid, we need to save it */
379 pgraph->unload_context(dev);
380
381 /* Load context for next channel */
382 chid = dev_priv->engine.fifo.channel_id(dev);
383 chan = dev_priv->channels.ptr[chid];
384 if (chan)
385 nv04_graph_load_context(chan);
386}
387
388static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) 370static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
389{ 371{
390 int i; 372 int i;
@@ -397,48 +379,11 @@ static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
397 return NULL; 379 return NULL;
398} 380}
399 381
400int nv04_graph_create_context(struct nouveau_channel *chan) 382static int
401{ 383nv04_graph_load_context(struct nouveau_channel *chan)
402 struct graph_state *pgraph_ctx;
403 NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id);
404
405 chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
406 GFP_KERNEL);
407 if (pgraph_ctx == NULL)
408 return -ENOMEM;
409
410 *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
411
412 return 0;
413}
414
415void nv04_graph_destroy_context(struct nouveau_channel *chan)
416{
417 struct drm_device *dev = chan->dev;
418 struct drm_nouveau_private *dev_priv = dev->dev_private;
419 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
420 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
421 unsigned long flags;
422
423 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
424 pgraph->fifo_access(dev, false);
425
426 /* Unload the context if it's the currently active one */
427 if (pgraph->channel(dev) == chan)
428 pgraph->unload_context(dev);
429
430 /* Free the context resources */
431 kfree(pgraph_ctx);
432 chan->pgraph_ctx = NULL;
433
434 pgraph->fifo_access(dev, true);
435 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
436}
437
438int nv04_graph_load_context(struct nouveau_channel *chan)
439{ 384{
385 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
440 struct drm_device *dev = chan->dev; 386 struct drm_device *dev = chan->dev;
441 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
442 uint32_t tmp; 387 uint32_t tmp;
443 int i; 388 int i;
444 389
@@ -456,20 +401,19 @@ int nv04_graph_load_context(struct nouveau_channel *chan)
456 return 0; 401 return 0;
457} 402}
458 403
459int 404static int
460nv04_graph_unload_context(struct drm_device *dev) 405nv04_graph_unload_context(struct drm_device *dev)
461{ 406{
462 struct drm_nouveau_private *dev_priv = dev->dev_private; 407 struct drm_nouveau_private *dev_priv = dev->dev_private;
463 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
464 struct nouveau_channel *chan = NULL; 408 struct nouveau_channel *chan = NULL;
465 struct graph_state *ctx; 409 struct graph_state *ctx;
466 uint32_t tmp; 410 uint32_t tmp;
467 int i; 411 int i;
468 412
469 chan = pgraph->channel(dev); 413 chan = nv04_graph_channel(dev);
470 if (!chan) 414 if (!chan)
471 return 0; 415 return 0;
472 ctx = chan->pgraph_ctx; 416 ctx = chan->engctx[NVOBJ_ENGINE_GR];
473 417
474 for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) 418 for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
475 ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]); 419 ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]);
@@ -481,23 +425,85 @@ nv04_graph_unload_context(struct drm_device *dev)
481 return 0; 425 return 0;
482} 426}
483 427
484int nv04_graph_init(struct drm_device *dev) 428static int
429nv04_graph_context_new(struct nouveau_channel *chan, int engine)
485{ 430{
431 struct graph_state *pgraph_ctx;
432 NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id);
433
434 pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL);
435 if (pgraph_ctx == NULL)
436 return -ENOMEM;
437
438 *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
439
440 chan->engctx[engine] = pgraph_ctx;
441 return 0;
442}
443
444static void
445nv04_graph_context_del(struct nouveau_channel *chan, int engine)
446{
447 struct drm_device *dev = chan->dev;
486 struct drm_nouveau_private *dev_priv = dev->dev_private; 448 struct drm_nouveau_private *dev_priv = dev->dev_private;
487 uint32_t tmp; 449 struct graph_state *pgraph_ctx = chan->engctx[engine];
450 unsigned long flags;
451
452 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
453 nv04_graph_fifo_access(dev, false);
454
455 /* Unload the context if it's the currently active one */
456 if (nv04_graph_channel(dev) == chan)
457 nv04_graph_unload_context(dev);
458
459 nv04_graph_fifo_access(dev, true);
460 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
461
462 /* Free the context resources */
463 kfree(pgraph_ctx);
464 chan->engctx[engine] = NULL;
465}
466
467int
468nv04_graph_object_new(struct nouveau_channel *chan, int engine,
469 u32 handle, u16 class)
470{
471 struct drm_device *dev = chan->dev;
472 struct nouveau_gpuobj *obj = NULL;
488 int ret; 473 int ret;
489 474
475 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
476 if (ret)
477 return ret;
478 obj->engine = 1;
479 obj->class = class;
480
481#ifdef __BIG_ENDIAN
482 nv_wo32(obj, 0x00, 0x00080000 | class);
483#else
484 nv_wo32(obj, 0x00, class);
485#endif
486 nv_wo32(obj, 0x04, 0x00000000);
487 nv_wo32(obj, 0x08, 0x00000000);
488 nv_wo32(obj, 0x0c, 0x00000000);
489
490 ret = nouveau_ramht_insert(chan, handle, obj);
491 nouveau_gpuobj_ref(NULL, &obj);
492 return ret;
493}
494
495static int
496nv04_graph_init(struct drm_device *dev, int engine)
497{
498 struct drm_nouveau_private *dev_priv = dev->dev_private;
499 uint32_t tmp;
500
490 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & 501 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
491 ~NV_PMC_ENABLE_PGRAPH); 502 ~NV_PMC_ENABLE_PGRAPH);
492 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | 503 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
493 NV_PMC_ENABLE_PGRAPH); 504 NV_PMC_ENABLE_PGRAPH);
494 505
495 ret = nv04_graph_register(dev);
496 if (ret)
497 return ret;
498
499 /* Enable PGRAPH interrupts */ 506 /* Enable PGRAPH interrupts */
500 nouveau_irq_register(dev, 12, nv04_graph_isr);
501 nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); 507 nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
502 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 508 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
503 509
@@ -507,7 +513,7 @@ int nv04_graph_init(struct drm_device *dev)
507 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/ 513 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
508 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000); 514 nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000);
509 /*1231C000 blob, 001 haiku*/ 515 /*1231C000 blob, 001 haiku*/
510 //*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/ 516 /*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
511 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100); 517 nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100);
512 /*0x72111100 blob , 01 haiku*/ 518 /*0x72111100 blob , 01 haiku*/
513 /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/ 519 /*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
@@ -531,10 +537,12 @@ int nv04_graph_init(struct drm_device *dev)
531 return 0; 537 return 0;
532} 538}
533 539
534void nv04_graph_takedown(struct drm_device *dev) 540static int
541nv04_graph_fini(struct drm_device *dev, int engine)
535{ 542{
543 nv04_graph_unload_context(dev);
536 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); 544 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
537 nouveau_irq_unregister(dev, 12); 545 return 0;
538} 546}
539 547
540void 548void
@@ -969,13 +977,138 @@ nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan,
969 return 1; 977 return 1;
970} 978}
971 979
972static int 980static struct nouveau_bitfield nv04_graph_intr[] = {
973nv04_graph_register(struct drm_device *dev) 981 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
982 {}
983};
984
985static struct nouveau_bitfield nv04_graph_nstatus[] = {
986 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
987 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
988 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
989 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
990 {}
991};
992
993struct nouveau_bitfield nv04_graph_nsource[] = {
994 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
995 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
996 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
997 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
998 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
999 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
1000 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
1001 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
1002 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
1003 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
1004 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
1005 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
1006 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
1007 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
1008 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
1009 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
1010 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1011 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
1012 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
1013 {}
1014};
1015
1016static void
1017nv04_graph_context_switch(struct drm_device *dev)
974{ 1018{
975 struct drm_nouveau_private *dev_priv = dev->dev_private; 1019 struct drm_nouveau_private *dev_priv = dev->dev_private;
1020 struct nouveau_channel *chan = NULL;
1021 int chid;
976 1022
977 if (dev_priv->engine.graph.registered) 1023 nouveau_wait_for_idle(dev);
978 return 0; 1024
1025 /* If previous context is valid, we need to save it */
1026 nv04_graph_unload_context(dev);
1027
1028 /* Load context for next channel */
1029 chid = dev_priv->engine.fifo.channel_id(dev);
1030 chan = dev_priv->channels.ptr[chid];
1031 if (chan)
1032 nv04_graph_load_context(chan);
1033}
1034
1035static void
1036nv04_graph_isr(struct drm_device *dev)
1037{
1038 u32 stat;
1039
1040 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1041 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1042 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1043 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1044 u32 chid = (addr & 0x0f000000) >> 24;
1045 u32 subc = (addr & 0x0000e000) >> 13;
1046 u32 mthd = (addr & 0x00001ffc);
1047 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1048 u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
1049 u32 show = stat;
1050
1051 if (stat & NV_PGRAPH_INTR_NOTIFY) {
1052 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1053 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1054 show &= ~NV_PGRAPH_INTR_NOTIFY;
1055 }
1056 }
1057
1058 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1059 nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1060 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1061 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1062 nv04_graph_context_switch(dev);
1063 }
1064
1065 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1066 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1067
1068 if (show && nouveau_ratelimit()) {
1069 NV_INFO(dev, "PGRAPH -");
1070 nouveau_bitfield_print(nv04_graph_intr, show);
1071 printk(" nsource:");
1072 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1073 printk(" nstatus:");
1074 nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
1075 printk("\n");
1076 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1077 "mthd 0x%04x data 0x%08x\n",
1078 chid, subc, class, mthd, data);
1079 }
1080 }
1081}
1082
1083static void
1084nv04_graph_destroy(struct drm_device *dev, int engine)
1085{
1086 struct nv04_graph_engine *pgraph = nv_engine(dev, engine);
1087
1088 nouveau_irq_unregister(dev, 12);
1089
1090 NVOBJ_ENGINE_DEL(dev, GR);
1091 kfree(pgraph);
1092}
1093
1094int
1095nv04_graph_create(struct drm_device *dev)
1096{
1097 struct nv04_graph_engine *pgraph;
1098
1099 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
1100 if (!pgraph)
1101 return -ENOMEM;
1102
1103 pgraph->base.destroy = nv04_graph_destroy;
1104 pgraph->base.init = nv04_graph_init;
1105 pgraph->base.fini = nv04_graph_fini;
1106 pgraph->base.context_new = nv04_graph_context_new;
1107 pgraph->base.context_del = nv04_graph_context_del;
1108 pgraph->base.object_new = nv04_graph_object_new;
1109
1110 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1111 nouveau_irq_register(dev, 12, nv04_graph_isr);
979 1112
980 /* dvd subpicture */ 1113 /* dvd subpicture */
981 NVOBJ_CLASS(dev, 0x0038, GR); 1114 NVOBJ_CLASS(dev, 0x0038, GR);
@@ -1222,93 +1355,5 @@ nv04_graph_register(struct drm_device *dev)
1222 NVOBJ_CLASS(dev, 0x506e, SW); 1355 NVOBJ_CLASS(dev, 0x506e, SW);
1223 NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); 1356 NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref);
1224 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); 1357 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1225
1226 dev_priv->engine.graph.registered = true;
1227 return 0; 1358 return 0;
1228};
1229
1230static struct nouveau_bitfield nv04_graph_intr[] = {
1231 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1232 {}
1233};
1234
1235static struct nouveau_bitfield nv04_graph_nstatus[] =
1236{
1237 { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
1238 { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
1239 { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
1240 { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" },
1241 {}
1242};
1243
1244struct nouveau_bitfield nv04_graph_nsource[] =
1245{
1246 { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" },
1247 { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" },
1248 { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" },
1249 { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" },
1250 { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" },
1251 { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" },
1252 { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" },
1253 { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" },
1254 { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" },
1255 { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" },
1256 { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" },
1257 { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" },
1258 { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" },
1259 { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" },
1260 { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" },
1261 { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" },
1262 { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1263 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" },
1264 { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" },
1265 {}
1266};
1267
1268static void
1269nv04_graph_isr(struct drm_device *dev)
1270{
1271 u32 stat;
1272
1273 while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1274 u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
1275 u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
1276 u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
1277 u32 chid = (addr & 0x0f000000) >> 24;
1278 u32 subc = (addr & 0x0000e000) >> 13;
1279 u32 mthd = (addr & 0x00001ffc);
1280 u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
1281 u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff;
1282 u32 show = stat;
1283
1284 if (stat & NV_PGRAPH_INTR_NOTIFY) {
1285 if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
1286 if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
1287 show &= ~NV_PGRAPH_INTR_NOTIFY;
1288 }
1289 }
1290
1291 if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1292 nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1293 stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1294 show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1295 nv04_graph_context_switch(dev);
1296 }
1297
1298 nv_wr32(dev, NV03_PGRAPH_INTR, stat);
1299 nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
1300
1301 if (show && nouveau_ratelimit()) {
1302 NV_INFO(dev, "PGRAPH -");
1303 nouveau_bitfield_print(nv04_graph_intr, show);
1304 printk(" nsource:");
1305 nouveau_bitfield_print(nv04_graph_nsource, nsource);
1306 printk(" nstatus:");
1307 nouveau_bitfield_print(nv04_graph_nstatus, nstatus);
1308 printk("\n");
1309 NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x "
1310 "mthd 0x%04x data 0x%08x\n",
1311 chid, subc, class, mthd, data);
1312 }
1313 }
1314} 1359}
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c
index b8e3edb5c063..b8611b955313 100644
--- a/drivers/gpu/drm/nouveau/nv04_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv04_instmem.c
@@ -95,6 +95,9 @@ nv04_instmem_takedown(struct drm_device *dev)
95 nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); 95 nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL);
96 nouveau_gpuobj_ref(NULL, &dev_priv->ramro); 96 nouveau_gpuobj_ref(NULL, &dev_priv->ramro);
97 nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); 97 nouveau_gpuobj_ref(NULL, &dev_priv->ramfc);
98
99 if (drm_mm_initialized(&dev_priv->ramin_heap))
100 drm_mm_takedown(&dev_priv->ramin_heap);
98} 101}
99 102
100int 103int
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c
index 8c92edb7bbcd..0930c6cb88e0 100644
--- a/drivers/gpu/drm/nouveau/nv10_graph.c
+++ b/drivers/gpu/drm/nouveau/nv10_graph.c
@@ -28,10 +28,9 @@
28#include "nouveau_drv.h" 28#include "nouveau_drv.h"
29#include "nouveau_util.h" 29#include "nouveau_util.h"
30 30
31static int nv10_graph_register(struct drm_device *); 31struct nv10_graph_engine {
32static void nv10_graph_isr(struct drm_device *); 32 struct nouveau_exec_engine base;
33 33};
34#define NV10_FIFO_NUMBER 32
35 34
36struct pipe_state { 35struct pipe_state {
37 uint32_t pipe_0x0000[0x040/4]; 36 uint32_t pipe_0x0000[0x040/4];
@@ -414,9 +413,9 @@ struct graph_state {
414 413
415static void nv10_graph_save_pipe(struct nouveau_channel *chan) 414static void nv10_graph_save_pipe(struct nouveau_channel *chan)
416{ 415{
417 struct drm_device *dev = chan->dev; 416 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
418 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
419 struct pipe_state *pipe = &pgraph_ctx->pipe_state; 417 struct pipe_state *pipe = &pgraph_ctx->pipe_state;
418 struct drm_device *dev = chan->dev;
420 419
421 PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); 420 PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
422 PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); 421 PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
@@ -432,9 +431,9 @@ static void nv10_graph_save_pipe(struct nouveau_channel *chan)
432 431
433static void nv10_graph_load_pipe(struct nouveau_channel *chan) 432static void nv10_graph_load_pipe(struct nouveau_channel *chan)
434{ 433{
435 struct drm_device *dev = chan->dev; 434 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
436 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
437 struct pipe_state *pipe = &pgraph_ctx->pipe_state; 435 struct pipe_state *pipe = &pgraph_ctx->pipe_state;
436 struct drm_device *dev = chan->dev;
438 uint32_t xfmode0, xfmode1; 437 uint32_t xfmode0, xfmode1;
439 int i; 438 int i;
440 439
@@ -482,9 +481,9 @@ static void nv10_graph_load_pipe(struct nouveau_channel *chan)
482 481
483static void nv10_graph_create_pipe(struct nouveau_channel *chan) 482static void nv10_graph_create_pipe(struct nouveau_channel *chan)
484{ 483{
485 struct drm_device *dev = chan->dev; 484 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
486 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
487 struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; 485 struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
486 struct drm_device *dev = chan->dev;
488 uint32_t *fifo_pipe_state_addr; 487 uint32_t *fifo_pipe_state_addr;
489 int i; 488 int i;
490#define PIPE_INIT(addr) \ 489#define PIPE_INIT(addr) \
@@ -661,8 +660,6 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
661 uint32_t inst) 660 uint32_t inst)
662{ 661{
663 struct drm_device *dev = chan->dev; 662 struct drm_device *dev = chan->dev;
664 struct drm_nouveau_private *dev_priv = dev->dev_private;
665 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
666 uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; 663 uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
667 uint32_t ctx_user, ctx_switch[5]; 664 uint32_t ctx_user, ctx_switch[5];
668 int i, subchan = -1; 665 int i, subchan = -1;
@@ -711,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
711 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); 708 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
712 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); 709 nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
713 nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); 710 nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
714 pgraph->fifo_access(dev, true); 711 nv04_graph_fifo_access(dev, true);
715 pgraph->fifo_access(dev, false); 712 nv04_graph_fifo_access(dev, false);
716 713
717 /* Restore the FIFO state */ 714 /* Restore the FIFO state */
718 for (i = 0; i < ARRAY_SIZE(fifo); i++) 715 for (i = 0; i < ARRAY_SIZE(fifo); i++)
@@ -729,11 +726,12 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
729 nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); 726 nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user);
730} 727}
731 728
732int nv10_graph_load_context(struct nouveau_channel *chan) 729static int
730nv10_graph_load_context(struct nouveau_channel *chan)
733{ 731{
734 struct drm_device *dev = chan->dev; 732 struct drm_device *dev = chan->dev;
735 struct drm_nouveau_private *dev_priv = dev->dev_private; 733 struct drm_nouveau_private *dev_priv = dev->dev_private;
736 struct graph_state *pgraph_ctx = chan->pgraph_ctx; 734 struct graph_state *pgraph_ctx = chan->engctx[NVOBJ_ENGINE_GR];
737 uint32_t tmp; 735 uint32_t tmp;
738 int i; 736 int i;
739 737
@@ -757,21 +755,20 @@ int nv10_graph_load_context(struct nouveau_channel *chan)
757 return 0; 755 return 0;
758} 756}
759 757
760int 758static int
761nv10_graph_unload_context(struct drm_device *dev) 759nv10_graph_unload_context(struct drm_device *dev)
762{ 760{
763 struct drm_nouveau_private *dev_priv = dev->dev_private; 761 struct drm_nouveau_private *dev_priv = dev->dev_private;
764 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
765 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 762 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
766 struct nouveau_channel *chan; 763 struct nouveau_channel *chan;
767 struct graph_state *ctx; 764 struct graph_state *ctx;
768 uint32_t tmp; 765 uint32_t tmp;
769 int i; 766 int i;
770 767
771 chan = pgraph->channel(dev); 768 chan = nv10_graph_channel(dev);
772 if (!chan) 769 if (!chan)
773 return 0; 770 return 0;
774 ctx = chan->pgraph_ctx; 771 ctx = chan->engctx[NVOBJ_ENGINE_GR];
775 772
776 for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) 773 for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
777 ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]); 774 ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]);
@@ -805,7 +802,7 @@ nv10_graph_context_switch(struct drm_device *dev)
805 /* Load context for next channel */ 802 /* Load context for next channel */
806 chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; 803 chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
807 chan = dev_priv->channels.ptr[chid]; 804 chan = dev_priv->channels.ptr[chid];
808 if (chan && chan->pgraph_ctx) 805 if (chan && chan->engctx[NVOBJ_ENGINE_GR])
809 nv10_graph_load_context(chan); 806 nv10_graph_load_context(chan);
810} 807}
811 808
@@ -836,7 +833,8 @@ nv10_graph_channel(struct drm_device *dev)
836 return dev_priv->channels.ptr[chid]; 833 return dev_priv->channels.ptr[chid];
837} 834}
838 835
839int nv10_graph_create_context(struct nouveau_channel *chan) 836static int
837nv10_graph_context_new(struct nouveau_channel *chan, int engine)
840{ 838{
841 struct drm_device *dev = chan->dev; 839 struct drm_device *dev = chan->dev;
842 struct drm_nouveau_private *dev_priv = dev->dev_private; 840 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -844,11 +842,10 @@ int nv10_graph_create_context(struct nouveau_channel *chan)
844 842
845 NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id); 843 NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id);
846 844
847 chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), 845 pgraph_ctx = kzalloc(sizeof(*pgraph_ctx), GFP_KERNEL);
848 GFP_KERNEL);
849 if (pgraph_ctx == NULL) 846 if (pgraph_ctx == NULL)
850 return -ENOMEM; 847 return -ENOMEM;
851 848 chan->engctx[engine] = pgraph_ctx;
852 849
853 NV_WRITE_CTX(0x00400e88, 0x08000000); 850 NV_WRITE_CTX(0x00400e88, 0x08000000);
854 NV_WRITE_CTX(0x00400e9c, 0x4b7fffff); 851 NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
@@ -873,30 +870,30 @@ int nv10_graph_create_context(struct nouveau_channel *chan)
873 return 0; 870 return 0;
874} 871}
875 872
876void nv10_graph_destroy_context(struct nouveau_channel *chan) 873static void
874nv10_graph_context_del(struct nouveau_channel *chan, int engine)
877{ 875{
878 struct drm_device *dev = chan->dev; 876 struct drm_device *dev = chan->dev;
879 struct drm_nouveau_private *dev_priv = dev->dev_private; 877 struct drm_nouveau_private *dev_priv = dev->dev_private;
880 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 878 struct graph_state *pgraph_ctx = chan->engctx[engine];
881 struct graph_state *pgraph_ctx = chan->pgraph_ctx;
882 unsigned long flags; 879 unsigned long flags;
883 880
884 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 881 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
885 pgraph->fifo_access(dev, false); 882 nv04_graph_fifo_access(dev, false);
886 883
887 /* Unload the context if it's the currently active one */ 884 /* Unload the context if it's the currently active one */
888 if (pgraph->channel(dev) == chan) 885 if (nv10_graph_channel(dev) == chan)
889 pgraph->unload_context(dev); 886 nv10_graph_unload_context(dev);
887
888 nv04_graph_fifo_access(dev, true);
889 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
890 890
891 /* Free the context resources */ 891 /* Free the context resources */
892 chan->engctx[engine] = NULL;
892 kfree(pgraph_ctx); 893 kfree(pgraph_ctx);
893 chan->pgraph_ctx = NULL;
894
895 pgraph->fifo_access(dev, true);
896 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
897} 894}
898 895
899void 896static void
900nv10_graph_set_tile_region(struct drm_device *dev, int i) 897nv10_graph_set_tile_region(struct drm_device *dev, int i)
901{ 898{
902 struct drm_nouveau_private *dev_priv = dev->dev_private; 899 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -907,22 +904,18 @@ nv10_graph_set_tile_region(struct drm_device *dev, int i)
907 nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); 904 nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr);
908} 905}
909 906
910int nv10_graph_init(struct drm_device *dev) 907static int
908nv10_graph_init(struct drm_device *dev, int engine)
911{ 909{
912 struct drm_nouveau_private *dev_priv = dev->dev_private; 910 struct drm_nouveau_private *dev_priv = dev->dev_private;
913 uint32_t tmp; 911 u32 tmp;
914 int ret, i; 912 int i;
915 913
916 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & 914 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
917 ~NV_PMC_ENABLE_PGRAPH); 915 ~NV_PMC_ENABLE_PGRAPH);
918 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | 916 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
919 NV_PMC_ENABLE_PGRAPH); 917 NV_PMC_ENABLE_PGRAPH);
920 918
921 ret = nv10_graph_register(dev);
922 if (ret)
923 return ret;
924
925 nouveau_irq_register(dev, 12, nv10_graph_isr);
926 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); 919 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
927 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 920 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
928 921
@@ -963,18 +956,20 @@ int nv10_graph_init(struct drm_device *dev)
963 return 0; 956 return 0;
964} 957}
965 958
966void nv10_graph_takedown(struct drm_device *dev) 959static int
960nv10_graph_fini(struct drm_device *dev, int engine)
967{ 961{
962 nv10_graph_unload_context(dev);
968 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); 963 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
969 nouveau_irq_unregister(dev, 12); 964 return 0;
970} 965}
971 966
972static int 967static int
973nv17_graph_mthd_lma_window(struct nouveau_channel *chan, 968nv17_graph_mthd_lma_window(struct nouveau_channel *chan,
974 u32 class, u32 mthd, u32 data) 969 u32 class, u32 mthd, u32 data)
975{ 970{
971 struct graph_state *ctx = chan->engctx[NVOBJ_ENGINE_GR];
976 struct drm_device *dev = chan->dev; 972 struct drm_device *dev = chan->dev;
977 struct graph_state *ctx = chan->pgraph_ctx;
978 struct pipe_state *pipe = &ctx->pipe_state; 973 struct pipe_state *pipe = &ctx->pipe_state;
979 uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; 974 uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
980 uint32_t xfmode0, xfmode1; 975 uint32_t xfmode0, xfmode1;
@@ -1061,64 +1056,13 @@ nv17_graph_mthd_lma_enable(struct nouveau_channel *chan,
1061 return 0; 1056 return 0;
1062} 1057}
1063 1058
1064static int
1065nv10_graph_register(struct drm_device *dev)
1066{
1067 struct drm_nouveau_private *dev_priv = dev->dev_private;
1068
1069 if (dev_priv->engine.graph.registered)
1070 return 0;
1071
1072 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
1073 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1074 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
1075 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
1076 NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
1077 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
1078 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
1079 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
1080 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
1081 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
1082 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
1083 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
1084 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
1085 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
1086 NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
1087 NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
1088 NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
1089 NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
1090
1091 /* celcius */
1092 if (dev_priv->chipset <= 0x10) {
1093 NVOBJ_CLASS(dev, 0x0056, GR);
1094 } else
1095 if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) {
1096 NVOBJ_CLASS(dev, 0x0096, GR);
1097 } else {
1098 NVOBJ_CLASS(dev, 0x0099, GR);
1099 NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
1100 NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
1101 NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
1102 NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
1103 NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
1104 }
1105
1106 /* nvsw */
1107 NVOBJ_CLASS(dev, 0x506e, SW);
1108 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1109
1110 dev_priv->engine.graph.registered = true;
1111 return 0;
1112}
1113
1114struct nouveau_bitfield nv10_graph_intr[] = { 1059struct nouveau_bitfield nv10_graph_intr[] = {
1115 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, 1060 { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1116 { NV_PGRAPH_INTR_ERROR, "ERROR" }, 1061 { NV_PGRAPH_INTR_ERROR, "ERROR" },
1117 {} 1062 {}
1118}; 1063};
1119 1064
1120struct nouveau_bitfield nv10_graph_nstatus[] = 1065struct nouveau_bitfield nv10_graph_nstatus[] = {
1121{
1122 { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, 1066 { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" },
1123 { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, 1067 { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" },
1124 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, 1068 { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" },
@@ -1173,3 +1117,73 @@ nv10_graph_isr(struct drm_device *dev)
1173 } 1117 }
1174 } 1118 }
1175} 1119}
1120
1121static void
1122nv10_graph_destroy(struct drm_device *dev, int engine)
1123{
1124 struct nv10_graph_engine *pgraph = nv_engine(dev, engine);
1125
1126 nouveau_irq_unregister(dev, 12);
1127 kfree(pgraph);
1128}
1129
1130int
1131nv10_graph_create(struct drm_device *dev)
1132{
1133 struct drm_nouveau_private *dev_priv = dev->dev_private;
1134 struct nv10_graph_engine *pgraph;
1135
1136 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
1137 if (!pgraph)
1138 return -ENOMEM;
1139
1140 pgraph->base.destroy = nv10_graph_destroy;
1141 pgraph->base.init = nv10_graph_init;
1142 pgraph->base.fini = nv10_graph_fini;
1143 pgraph->base.context_new = nv10_graph_context_new;
1144 pgraph->base.context_del = nv10_graph_context_del;
1145 pgraph->base.object_new = nv04_graph_object_new;
1146 pgraph->base.set_tile_region = nv10_graph_set_tile_region;
1147
1148 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1149 nouveau_irq_register(dev, 12, nv10_graph_isr);
1150
1151 /* nvsw */
1152 NVOBJ_CLASS(dev, 0x506e, SW);
1153 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
1154
1155 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1156 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
1157 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
1158 NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */
1159 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
1160 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
1161 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
1162 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
1163 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
1164 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
1165 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
1166 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
1167 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
1168 NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */
1169 NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */
1170 NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */
1171 NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */
1172
1173 /* celcius */
1174 if (dev_priv->chipset <= 0x10) {
1175 NVOBJ_CLASS(dev, 0x0056, GR);
1176 } else
1177 if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) {
1178 NVOBJ_CLASS(dev, 0x0096, GR);
1179 } else {
1180 NVOBJ_CLASS(dev, 0x0099, GR);
1181 NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window);
1182 NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window);
1183 NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window);
1184 NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window);
1185 NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable);
1186 }
1187
1188 return 0;
1189}
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c
index 8464b76798d5..affc7d7dd029 100644
--- a/drivers/gpu/drm/nouveau/nv20_graph.c
+++ b/drivers/gpu/drm/nouveau/nv20_graph.c
@@ -24,6 +24,14 @@
24 * 24 *
25 */ 25 */
26 26
27struct nv20_graph_engine {
28 struct nouveau_exec_engine base;
29 struct nouveau_gpuobj *ctxtab;
30 void (*grctx_init)(struct nouveau_gpuobj *);
31 u32 grctx_size;
32 u32 grctx_user;
33};
34
27#define NV20_GRCTX_SIZE (3580*4) 35#define NV20_GRCTX_SIZE (3580*4)
28#define NV25_GRCTX_SIZE (3529*4) 36#define NV25_GRCTX_SIZE (3529*4)
29#define NV2A_GRCTX_SIZE (3500*4) 37#define NV2A_GRCTX_SIZE (3500*4)
@@ -32,12 +40,54 @@
32#define NV34_GRCTX_SIZE (18140) 40#define NV34_GRCTX_SIZE (18140)
33#define NV35_36_GRCTX_SIZE (22396) 41#define NV35_36_GRCTX_SIZE (22396)
34 42
35static int nv20_graph_register(struct drm_device *); 43int
36static int nv30_graph_register(struct drm_device *); 44nv20_graph_unload_context(struct drm_device *dev)
37static void nv20_graph_isr(struct drm_device *); 45{
46 struct drm_nouveau_private *dev_priv = dev->dev_private;
47 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
48 struct nouveau_channel *chan;
49 struct nouveau_gpuobj *grctx;
50 u32 tmp;
51
52 chan = nv10_graph_channel(dev);
53 if (!chan)
54 return 0;
55 grctx = chan->engctx[NVOBJ_ENGINE_GR];
56
57 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, grctx->pinst >> 4);
58 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
59 NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
60
61 nouveau_wait_for_idle(dev);
62
63 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
64 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
65 tmp |= (pfifo->channels - 1) << 24;
66 nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
67 return 0;
68}
69
70static void
71nv20_graph_rdi(struct drm_device *dev)
72{
73 struct drm_nouveau_private *dev_priv = dev->dev_private;
74 int i, writecount = 32;
75 uint32_t rdi_index = 0x2c80000;
76
77 if (dev_priv->chipset == 0x20) {
78 rdi_index = 0x3d0000;
79 writecount = 15;
80 }
81
82 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index);
83 for (i = 0; i < writecount; i++)
84 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0);
85
86 nouveau_wait_for_idle(dev);
87}
38 88
39static void 89static void
40nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 90nv20_graph_context_init(struct nouveau_gpuobj *ctx)
41{ 91{
42 int i; 92 int i;
43 93
@@ -87,7 +137,7 @@ nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
87} 137}
88 138
89static void 139static void
90nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 140nv25_graph_context_init(struct nouveau_gpuobj *ctx)
91{ 141{
92 int i; 142 int i;
93 143
@@ -146,7 +196,7 @@ nv25_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
146} 196}
147 197
148static void 198static void
149nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 199nv2a_graph_context_init(struct nouveau_gpuobj *ctx)
150{ 200{
151 int i; 201 int i;
152 202
@@ -196,7 +246,7 @@ nv2a_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
196} 246}
197 247
198static void 248static void
199nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 249nv30_31_graph_context_init(struct nouveau_gpuobj *ctx)
200{ 250{
201 int i; 251 int i;
202 252
@@ -254,7 +304,7 @@ nv30_31_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
254} 304}
255 305
256static void 306static void
257nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 307nv34_graph_context_init(struct nouveau_gpuobj *ctx)
258{ 308{
259 int i; 309 int i;
260 310
@@ -312,7 +362,7 @@ nv34_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
312} 362}
313 363
314static void 364static void
315nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) 365nv35_36_graph_context_init(struct nouveau_gpuobj *ctx)
316{ 366{
317 int i; 367 int i;
318 368
@@ -370,148 +420,57 @@ nv35_36_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx)
370} 420}
371 421
372int 422int
373nv20_graph_create_context(struct nouveau_channel *chan) 423nv20_graph_context_new(struct nouveau_channel *chan, int engine)
374{ 424{
425 struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine);
426 struct nouveau_gpuobj *grctx = NULL;
375 struct drm_device *dev = chan->dev; 427 struct drm_device *dev = chan->dev;
376 struct drm_nouveau_private *dev_priv = dev->dev_private;
377 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
378 void (*ctx_init)(struct drm_device *, struct nouveau_gpuobj *);
379 unsigned int idoffs = 0x28;
380 int ret; 428 int ret;
381 429
382 switch (dev_priv->chipset) { 430 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16,
383 case 0x20: 431 NVOBJ_FLAG_ZERO_ALLOC, &grctx);
384 ctx_init = nv20_graph_context_init;
385 idoffs = 0;
386 break;
387 case 0x25:
388 case 0x28:
389 ctx_init = nv25_graph_context_init;
390 break;
391 case 0x2a:
392 ctx_init = nv2a_graph_context_init;
393 idoffs = 0;
394 break;
395 case 0x30:
396 case 0x31:
397 ctx_init = nv30_31_graph_context_init;
398 break;
399 case 0x34:
400 ctx_init = nv34_graph_context_init;
401 break;
402 case 0x35:
403 case 0x36:
404 ctx_init = nv35_36_graph_context_init;
405 break;
406 default:
407 BUG_ON(1);
408 }
409
410 ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16,
411 NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx);
412 if (ret) 432 if (ret)
413 return ret; 433 return ret;
414 434
415 /* Initialise default context values */ 435 /* Initialise default context values */
416 ctx_init(dev, chan->ramin_grctx); 436 pgraph->grctx_init(grctx);
417 437
418 /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */ 438 /* nv20: nv_wo32(dev, chan->ramin_grctx->gpuobj, 10, chan->id<<24); */
419 nv_wo32(chan->ramin_grctx, idoffs, 439 /* CTX_USER */
420 (chan->id << 24) | 0x1); /* CTX_USER */ 440 nv_wo32(grctx, pgraph->grctx_user, (chan->id << 24) | 0x1);
421 441
422 nv_wo32(pgraph->ctx_table, chan->id * 4, chan->ramin_grctx->pinst >> 4); 442 nv_wo32(pgraph->ctxtab, chan->id * 4, grctx->pinst >> 4);
443 chan->engctx[engine] = grctx;
423 return 0; 444 return 0;
424} 445}
425 446
426void 447void
427nv20_graph_destroy_context(struct nouveau_channel *chan) 448nv20_graph_context_del(struct nouveau_channel *chan, int engine)
428{ 449{
450 struct nv20_graph_engine *pgraph = nv_engine(chan->dev, engine);
451 struct nouveau_gpuobj *grctx = chan->engctx[engine];
429 struct drm_device *dev = chan->dev; 452 struct drm_device *dev = chan->dev;
430 struct drm_nouveau_private *dev_priv = dev->dev_private; 453 struct drm_nouveau_private *dev_priv = dev->dev_private;
431 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
432 unsigned long flags; 454 unsigned long flags;
433 455
434 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 456 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
435 pgraph->fifo_access(dev, false); 457 nv04_graph_fifo_access(dev, false);
436 458
437 /* Unload the context if it's the currently active one */ 459 /* Unload the context if it's the currently active one */
438 if (pgraph->channel(dev) == chan) 460 if (nv10_graph_channel(dev) == chan)
439 pgraph->unload_context(dev); 461 nv20_graph_unload_context(dev);
440 462
441 pgraph->fifo_access(dev, true); 463 nv04_graph_fifo_access(dev, true);
442 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); 464 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
443 465
444 /* Free the context resources */ 466 /* Free the context resources */
445 nv_wo32(pgraph->ctx_table, chan->id * 4, 0); 467 nv_wo32(pgraph->ctxtab, chan->id * 4, 0);
446 nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
447}
448
449int
450nv20_graph_load_context(struct nouveau_channel *chan)
451{
452 struct drm_device *dev = chan->dev;
453 uint32_t inst;
454 468
455 if (!chan->ramin_grctx) 469 nouveau_gpuobj_ref(NULL, &grctx);
456 return -EINVAL; 470 chan->engctx[engine] = NULL;
457 inst = chan->ramin_grctx->pinst >> 4;
458
459 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
460 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
461 NV20_PGRAPH_CHANNEL_CTX_XFER_LOAD);
462 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
463
464 nouveau_wait_for_idle(dev);
465 return 0;
466}
467
468int
469nv20_graph_unload_context(struct drm_device *dev)
470{
471 struct drm_nouveau_private *dev_priv = dev->dev_private;
472 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
473 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
474 struct nouveau_channel *chan;
475 uint32_t inst, tmp;
476
477 chan = pgraph->channel(dev);
478 if (!chan)
479 return 0;
480 inst = chan->ramin_grctx->pinst >> 4;
481
482 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
483 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_XFER,
484 NV20_PGRAPH_CHANNEL_CTX_XFER_SAVE);
485
486 nouveau_wait_for_idle(dev);
487
488 nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
489 tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
490 tmp |= (pfifo->channels - 1) << 24;
491 nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
492 return 0;
493} 471}
494 472
495static void 473static void
496nv20_graph_rdi(struct drm_device *dev)
497{
498 struct drm_nouveau_private *dev_priv = dev->dev_private;
499 int i, writecount = 32;
500 uint32_t rdi_index = 0x2c80000;
501
502 if (dev_priv->chipset == 0x20) {
503 rdi_index = 0x3d0000;
504 writecount = 15;
505 }
506
507 nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, rdi_index);
508 for (i = 0; i < writecount; i++)
509 nv_wr32(dev, NV10_PGRAPH_RDI_DATA, 0);
510
511 nouveau_wait_for_idle(dev);
512}
513
514void
515nv20_graph_set_tile_region(struct drm_device *dev, int i) 474nv20_graph_set_tile_region(struct drm_device *dev, int i)
516{ 475{
517 struct drm_nouveau_private *dev_priv = dev->dev_private; 476 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -536,56 +495,22 @@ nv20_graph_set_tile_region(struct drm_device *dev, int i)
536} 495}
537 496
538int 497int
539nv20_graph_init(struct drm_device *dev) 498nv20_graph_init(struct drm_device *dev, int engine)
540{ 499{
500 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
541 struct drm_nouveau_private *dev_priv = dev->dev_private; 501 struct drm_nouveau_private *dev_priv = dev->dev_private;
542 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
543 uint32_t tmp, vramsz; 502 uint32_t tmp, vramsz;
544 int ret, i; 503 int i;
545
546 switch (dev_priv->chipset) {
547 case 0x20:
548 pgraph->grctx_size = NV20_GRCTX_SIZE;
549 break;
550 case 0x25:
551 case 0x28:
552 pgraph->grctx_size = NV25_GRCTX_SIZE;
553 break;
554 case 0x2a:
555 pgraph->grctx_size = NV2A_GRCTX_SIZE;
556 break;
557 default:
558 NV_ERROR(dev, "unknown chipset, disabling acceleration\n");
559 pgraph->accel_blocked = true;
560 return 0;
561 }
562 504
563 nv_wr32(dev, NV03_PMC_ENABLE, 505 nv_wr32(dev, NV03_PMC_ENABLE,
564 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); 506 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
565 nv_wr32(dev, NV03_PMC_ENABLE, 507 nv_wr32(dev, NV03_PMC_ENABLE,
566 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); 508 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH);
567 509
568 if (!pgraph->ctx_table) { 510 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4);
569 /* Create Context Pointer Table */
570 ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16,
571 NVOBJ_FLAG_ZERO_ALLOC,
572 &pgraph->ctx_table);
573 if (ret)
574 return ret;
575 }
576
577 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
578 pgraph->ctx_table->pinst >> 4);
579 511
580 nv20_graph_rdi(dev); 512 nv20_graph_rdi(dev);
581 513
582 ret = nv20_graph_register(dev);
583 if (ret) {
584 nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
585 return ret;
586 }
587
588 nouveau_irq_register(dev, 12, nv20_graph_isr);
589 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); 514 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
590 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 515 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
591 516
@@ -657,67 +582,20 @@ nv20_graph_init(struct drm_device *dev)
657 return 0; 582 return 0;
658} 583}
659 584
660void
661nv20_graph_takedown(struct drm_device *dev)
662{
663 struct drm_nouveau_private *dev_priv = dev->dev_private;
664 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
665
666 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
667 nouveau_irq_unregister(dev, 12);
668
669 nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
670}
671
672int 585int
673nv30_graph_init(struct drm_device *dev) 586nv30_graph_init(struct drm_device *dev, int engine)
674{ 587{
588 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
675 struct drm_nouveau_private *dev_priv = dev->dev_private; 589 struct drm_nouveau_private *dev_priv = dev->dev_private;
676 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 590 int i;
677 int ret, i;
678
679 switch (dev_priv->chipset) {
680 case 0x30:
681 case 0x31:
682 pgraph->grctx_size = NV30_31_GRCTX_SIZE;
683 break;
684 case 0x34:
685 pgraph->grctx_size = NV34_GRCTX_SIZE;
686 break;
687 case 0x35:
688 case 0x36:
689 pgraph->grctx_size = NV35_36_GRCTX_SIZE;
690 break;
691 default:
692 NV_ERROR(dev, "unknown chipset, disabling acceleration\n");
693 pgraph->accel_blocked = true;
694 return 0;
695 }
696 591
697 nv_wr32(dev, NV03_PMC_ENABLE, 592 nv_wr32(dev, NV03_PMC_ENABLE,
698 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); 593 nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH);
699 nv_wr32(dev, NV03_PMC_ENABLE, 594 nv_wr32(dev, NV03_PMC_ENABLE,
700 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); 595 nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH);
701 596
702 if (!pgraph->ctx_table) { 597 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctxtab->pinst >> 4);
703 /* Create Context Pointer Table */
704 ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16,
705 NVOBJ_FLAG_ZERO_ALLOC,
706 &pgraph->ctx_table);
707 if (ret)
708 return ret;
709 }
710
711 ret = nv30_graph_register(dev);
712 if (ret) {
713 nouveau_gpuobj_ref(NULL, &pgraph->ctx_table);
714 return ret;
715 }
716 598
717 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE,
718 pgraph->ctx_table->pinst >> 4);
719
720 nouveau_irq_register(dev, 12, nv20_graph_isr);
721 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); 599 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
722 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); 600 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
723 601
@@ -775,85 +653,11 @@ nv30_graph_init(struct drm_device *dev)
775 return 0; 653 return 0;
776} 654}
777 655
778static int 656int
779nv20_graph_register(struct drm_device *dev) 657nv20_graph_fini(struct drm_device *dev, int engine)
780{
781 struct drm_nouveau_private *dev_priv = dev->dev_private;
782
783 if (dev_priv->engine.graph.registered)
784 return 0;
785
786 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
787 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
788 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
789 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
790 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
791 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
792 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
793 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
794 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
795 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
796 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
797 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
798 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
799 NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */
800 NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */
801
802 /* kelvin */
803 if (dev_priv->chipset < 0x25)
804 NVOBJ_CLASS(dev, 0x0097, GR);
805 else
806 NVOBJ_CLASS(dev, 0x0597, GR);
807
808 /* nvsw */
809 NVOBJ_CLASS(dev, 0x506e, SW);
810 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
811
812 dev_priv->engine.graph.registered = true;
813 return 0;
814}
815
816static int
817nv30_graph_register(struct drm_device *dev)
818{ 658{
819 struct drm_nouveau_private *dev_priv = dev->dev_private; 659 nv20_graph_unload_context(dev);
820 660 nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
821 if (dev_priv->engine.graph.registered)
822 return 0;
823
824 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
825 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
826 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
827 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
828 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
829 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
830 NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */
831 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
832 NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */
833 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
834 NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */
835 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
836 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
837 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
838 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
839 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
840 NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */
841
842 /* rankine */
843 if (0x00000003 & (1 << (dev_priv->chipset & 0x0f)))
844 NVOBJ_CLASS(dev, 0x0397, GR);
845 else
846 if (0x00000010 & (1 << (dev_priv->chipset & 0x0f)))
847 NVOBJ_CLASS(dev, 0x0697, GR);
848 else
849 if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f)))
850 NVOBJ_CLASS(dev, 0x0497, GR);
851
852 /* nvsw */
853 NVOBJ_CLASS(dev, 0x506e, SW);
854 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
855
856 dev_priv->engine.graph.registered = true;
857 return 0; 661 return 0;
858} 662}
859 663
@@ -897,3 +701,135 @@ nv20_graph_isr(struct drm_device *dev)
897 } 701 }
898 } 702 }
899} 703}
704
705static void
706nv20_graph_destroy(struct drm_device *dev, int engine)
707{
708 struct nv20_graph_engine *pgraph = nv_engine(dev, engine);
709
710 nouveau_irq_unregister(dev, 12);
711 nouveau_gpuobj_ref(NULL, &pgraph->ctxtab);
712
713 NVOBJ_ENGINE_DEL(dev, GR);
714 kfree(pgraph);
715}
716
717int
718nv20_graph_create(struct drm_device *dev)
719{
720 struct drm_nouveau_private *dev_priv = dev->dev_private;
721 struct nv20_graph_engine *pgraph;
722 int ret;
723
724 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
725 if (!pgraph)
726 return -ENOMEM;
727
728 pgraph->base.destroy = nv20_graph_destroy;
729 pgraph->base.fini = nv20_graph_fini;
730 pgraph->base.context_new = nv20_graph_context_new;
731 pgraph->base.context_del = nv20_graph_context_del;
732 pgraph->base.object_new = nv04_graph_object_new;
733 pgraph->base.set_tile_region = nv20_graph_set_tile_region;
734
735 pgraph->grctx_user = 0x0028;
736 if (dev_priv->card_type == NV_20) {
737 pgraph->base.init = nv20_graph_init;
738 switch (dev_priv->chipset) {
739 case 0x20:
740 pgraph->grctx_init = nv20_graph_context_init;
741 pgraph->grctx_size = NV20_GRCTX_SIZE;
742 pgraph->grctx_user = 0x0000;
743 break;
744 case 0x25:
745 case 0x28:
746 pgraph->grctx_init = nv25_graph_context_init;
747 pgraph->grctx_size = NV25_GRCTX_SIZE;
748 break;
749 case 0x2a:
750 pgraph->grctx_init = nv2a_graph_context_init;
751 pgraph->grctx_size = NV2A_GRCTX_SIZE;
752 pgraph->grctx_user = 0x0000;
753 break;
754 default:
755 NV_ERROR(dev, "PGRAPH: unknown chipset\n");
756 return 0;
757 }
758 } else {
759 pgraph->base.init = nv30_graph_init;
760 switch (dev_priv->chipset) {
761 case 0x30:
762 case 0x31:
763 pgraph->grctx_init = nv30_31_graph_context_init;
764 pgraph->grctx_size = NV30_31_GRCTX_SIZE;
765 break;
766 case 0x34:
767 pgraph->grctx_init = nv34_graph_context_init;
768 pgraph->grctx_size = NV34_GRCTX_SIZE;
769 break;
770 case 0x35:
771 case 0x36:
772 pgraph->grctx_init = nv35_36_graph_context_init;
773 pgraph->grctx_size = NV35_36_GRCTX_SIZE;
774 break;
775 default:
776 NV_ERROR(dev, "PGRAPH: unknown chipset\n");
777 return 0;
778 }
779 }
780
781 /* Create Context Pointer Table */
782 ret = nouveau_gpuobj_new(dev, NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC,
783 &pgraph->ctxtab);
784 if (ret) {
785 kfree(pgraph);
786 return ret;
787 }
788
789 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
790 nouveau_irq_register(dev, 12, nv20_graph_isr);
791
792 /* nvsw */
793 NVOBJ_CLASS(dev, 0x506e, SW);
794 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
795
796 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
797 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
798 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
799 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
800 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
801 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
802 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
803 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
804 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
805 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
806 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
807 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
808 if (dev_priv->card_type == NV_20) {
809 NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */
810 NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */
811
812 /* kelvin */
813 if (dev_priv->chipset < 0x25)
814 NVOBJ_CLASS(dev, 0x0097, GR);
815 else
816 NVOBJ_CLASS(dev, 0x0597, GR);
817 } else {
818 NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */
819 NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */
820 NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */
821 NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */
822
823 /* rankine */
824 if (0x00000003 & (1 << (dev_priv->chipset & 0x0f)))
825 NVOBJ_CLASS(dev, 0x0397, GR);
826 else
827 if (0x00000010 & (1 << (dev_priv->chipset & 0x0f)))
828 NVOBJ_CLASS(dev, 0x0697, GR);
829 else
830 if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f)))
831 NVOBJ_CLASS(dev, 0x0497, GR);
832 }
833
834 return 0;
835}
diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c
index 49b9a35a9cd6..68cb2d991c88 100644
--- a/drivers/gpu/drm/nouveau/nv40_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv40_fifo.c
@@ -115,6 +115,7 @@ nv40_fifo_do_load_context(struct drm_device *dev, int chid)
115 nv_wr32(dev, 0x32e8, nv_ri32(dev, fc + 68)); 115 nv_wr32(dev, 0x32e8, nv_ri32(dev, fc + 68));
116 nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76)); 116 nv_wr32(dev, 0x2088, nv_ri32(dev, fc + 76));
117 nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80)); 117 nv_wr32(dev, 0x3300, nv_ri32(dev, fc + 80));
118 nv_wr32(dev, 0x330c, nv_ri32(dev, fc + 84));
118 119
119 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); 120 nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
120 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); 121 nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
@@ -186,6 +187,7 @@ nv40_fifo_unload_context(struct drm_device *dev)
186 tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16); 187 tmp |= (nv_rd32(dev, NV04_PFIFO_CACHE1_PUT) << 16);
187 nv_wi32(dev, fc + 72, tmp); 188 nv_wi32(dev, fc + 72, tmp);
188#endif 189#endif
190 nv_wi32(dev, fc + 84, nv_rd32(dev, 0x330c));
189 191
190 nv40_fifo_do_load_context(dev, pfifo->channels - 1); 192 nv40_fifo_do_load_context(dev, pfifo->channels - 1);
191 nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, 193 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 fceb44c0ec74..5beb01b8ace1 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -28,14 +28,18 @@
28#include "drm.h" 28#include "drm.h"
29#include "nouveau_drv.h" 29#include "nouveau_drv.h"
30#include "nouveau_grctx.h" 30#include "nouveau_grctx.h"
31#include "nouveau_ramht.h"
31 32
32static int nv40_graph_register(struct drm_device *); 33struct nv40_graph_engine {
33static void nv40_graph_isr(struct drm_device *); 34 struct nouveau_exec_engine base;
35 u32 grctx_size;
36};
34 37
35struct nouveau_channel * 38static struct nouveau_channel *
36nv40_graph_channel(struct drm_device *dev) 39nv40_graph_channel(struct drm_device *dev)
37{ 40{
38 struct drm_nouveau_private *dev_priv = dev->dev_private; 41 struct drm_nouveau_private *dev_priv = dev->dev_private;
42 struct nouveau_gpuobj *grctx;
39 uint32_t inst; 43 uint32_t inst;
40 int i; 44 int i;
41 45
@@ -45,74 +49,17 @@ nv40_graph_channel(struct drm_device *dev)
45 inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; 49 inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
46 50
47 for (i = 0; i < dev_priv->engine.fifo.channels; i++) { 51 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
48 struct nouveau_channel *chan = dev_priv->channels.ptr[i]; 52 if (!dev_priv->channels.ptr[i])
53 continue;
49 54
50 if (chan && chan->ramin_grctx && 55 grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
51 chan->ramin_grctx->pinst == inst) 56 if (grctx && grctx->pinst == inst)
52 return chan; 57 return dev_priv->channels.ptr[i];
53 } 58 }
54 59
55 return NULL; 60 return NULL;
56} 61}
57 62
58int
59nv40_graph_create_context(struct nouveau_channel *chan)
60{
61 struct drm_device *dev = chan->dev;
62 struct drm_nouveau_private *dev_priv = dev->dev_private;
63 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
64 struct nouveau_grctx ctx = {};
65 unsigned long flags;
66 int ret;
67
68 ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 16,
69 NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin_grctx);
70 if (ret)
71 return ret;
72
73 /* Initialise default context values */
74 ctx.dev = chan->dev;
75 ctx.mode = NOUVEAU_GRCTX_VALS;
76 ctx.data = chan->ramin_grctx;
77 nv40_grctx_init(&ctx);
78
79 nv_wo32(chan->ramin_grctx, 0, chan->ramin_grctx->pinst);
80
81 /* init grctx pointer in ramfc, and on PFIFO if channel is
82 * already active there
83 */
84 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
85 nv_wo32(chan->ramfc, 0x38, chan->ramin_grctx->pinst >> 4);
86 nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
87 if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
88 nv_wr32(dev, 0x0032e0, chan->ramin_grctx->pinst >> 4);
89 nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
90 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
91 return 0;
92}
93
94void
95nv40_graph_destroy_context(struct nouveau_channel *chan)
96{
97 struct drm_device *dev = chan->dev;
98 struct drm_nouveau_private *dev_priv = dev->dev_private;
99 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
100 unsigned long flags;
101
102 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
103 pgraph->fifo_access(dev, false);
104
105 /* Unload the context if it's the currently active one */
106 if (pgraph->channel(dev) == chan)
107 pgraph->unload_context(dev);
108
109 pgraph->fifo_access(dev, true);
110 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
111
112 /* Free the context resources */
113 nouveau_gpuobj_ref(NULL, &chan->ramin_grctx);
114}
115
116static int 63static int
117nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) 64nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
118{ 65{
@@ -154,57 +101,115 @@ nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
154 return 0; 101 return 0;
155} 102}
156 103
157/* Restore the context for a specific channel into PGRAPH */ 104static int
158int 105nv40_graph_unload_context(struct drm_device *dev)
159nv40_graph_load_context(struct nouveau_channel *chan)
160{ 106{
161 struct drm_device *dev = chan->dev;
162 uint32_t inst; 107 uint32_t inst;
163 int ret; 108 int ret;
164 109
165 if (!chan->ramin_grctx) 110 inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
166 return -EINVAL; 111 if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
167 inst = chan->ramin_grctx->pinst >> 4; 112 return 0;
113 inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
114
115 ret = nv40_graph_transfer_context(dev, inst, 1);
116
117 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
118 return ret;
119}
120
121static int
122nv40_graph_context_new(struct nouveau_channel *chan, int engine)
123{
124 struct nv40_graph_engine *pgraph = nv_engine(chan->dev, engine);
125 struct drm_device *dev = chan->dev;
126 struct drm_nouveau_private *dev_priv = dev->dev_private;
127 struct nouveau_gpuobj *grctx = NULL;
128 struct nouveau_grctx ctx = {};
129 unsigned long flags;
130 int ret;
168 131
169 ret = nv40_graph_transfer_context(dev, inst, 0); 132 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 16,
133 NVOBJ_FLAG_ZERO_ALLOC, &grctx);
170 if (ret) 134 if (ret)
171 return ret; 135 return ret;
172 136
173 /* 0x40032C, no idea of it's exact function. Could simply be a 137 /* Initialise default context values */
174 * record of the currently active PGRAPH context. It's currently 138 ctx.dev = chan->dev;
175 * unknown as to what bit 24 does. The nv ddx has it set, so we will 139 ctx.mode = NOUVEAU_GRCTX_VALS;
176 * set it here too. 140 ctx.data = grctx;
177 */ 141 nv40_grctx_init(&ctx);
178 nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); 142
179 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 143 nv_wo32(grctx, 0, grctx->vinst);
180 (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) | 144
181 NV40_PGRAPH_CTXCTL_CUR_LOADED); 145 /* init grctx pointer in ramfc, and on PFIFO if channel is
182 /* 0x32E0 records the instance address of the active FIFO's PGRAPH 146 * already active there
183 * context. If at any time this doesn't match 0x40032C, you will
184 * receive PGRAPH_INTR_CONTEXT_SWITCH
185 */ 147 */
186 nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst); 148 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
149 nv_wo32(chan->ramfc, 0x38, grctx->vinst >> 4);
150 nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
151 if ((nv_rd32(dev, 0x003204) & 0x0000001f) == chan->id)
152 nv_wr32(dev, 0x0032e0, grctx->vinst >> 4);
153 nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
154 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
155
156 chan->engctx[engine] = grctx;
187 return 0; 157 return 0;
188} 158}
189 159
190int 160static void
191nv40_graph_unload_context(struct drm_device *dev) 161nv40_graph_context_del(struct nouveau_channel *chan, int engine)
192{ 162{
193 uint32_t inst; 163 struct nouveau_gpuobj *grctx = chan->engctx[engine];
194 int ret; 164 struct drm_device *dev = chan->dev;
165 struct drm_nouveau_private *dev_priv = dev->dev_private;
166 unsigned long flags;
195 167
196 inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); 168 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
197 if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) 169 nv04_graph_fifo_access(dev, false);
198 return 0;
199 inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
200 170
201 ret = nv40_graph_transfer_context(dev, inst, 1); 171 /* Unload the context if it's the currently active one */
172 if (nv40_graph_channel(dev) == chan)
173 nv40_graph_unload_context(dev);
202 174
203 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); 175 nv04_graph_fifo_access(dev, true);
176 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
177
178 /* Free the context resources */
179 nouveau_gpuobj_ref(NULL, &grctx);
180 chan->engctx[engine] = NULL;
181}
182
183int
184nv40_graph_object_new(struct nouveau_channel *chan, int engine,
185 u32 handle, u16 class)
186{
187 struct drm_device *dev = chan->dev;
188 struct nouveau_gpuobj *obj = NULL;
189 int ret;
190
191 ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
192 if (ret)
193 return ret;
194 obj->engine = 1;
195 obj->class = class;
196
197 nv_wo32(obj, 0x00, class);
198 nv_wo32(obj, 0x04, 0x00000000);
199#ifndef __BIG_ENDIAN
200 nv_wo32(obj, 0x08, 0x00000000);
201#else
202 nv_wo32(obj, 0x08, 0x01000000);
203#endif
204 nv_wo32(obj, 0x0c, 0x00000000);
205 nv_wo32(obj, 0x10, 0x00000000);
206
207 ret = nouveau_ramht_insert(chan, handle, obj);
208 nouveau_gpuobj_ref(NULL, &obj);
204 return ret; 209 return ret;
205} 210}
206 211
207void 212static void
208nv40_graph_set_tile_region(struct drm_device *dev, int i) 213nv40_graph_set_tile_region(struct drm_device *dev, int i)
209{ 214{
210 struct drm_nouveau_private *dev_priv = dev->dev_private; 215 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -257,14 +262,14 @@ nv40_graph_set_tile_region(struct drm_device *dev, int i)
257 * C51 0x4e 262 * C51 0x4e
258 */ 263 */
259int 264int
260nv40_graph_init(struct drm_device *dev) 265nv40_graph_init(struct drm_device *dev, int engine)
261{ 266{
262 struct drm_nouveau_private *dev_priv = 267 struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
263 (struct drm_nouveau_private *)dev->dev_private; 268 struct drm_nouveau_private *dev_priv = dev->dev_private;
264 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; 269 struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
265 struct nouveau_grctx ctx = {}; 270 struct nouveau_grctx ctx = {};
266 uint32_t vramsz, *cp; 271 uint32_t vramsz, *cp;
267 int ret, i, j; 272 int i, j;
268 273
269 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & 274 nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
270 ~NV_PMC_ENABLE_PGRAPH); 275 ~NV_PMC_ENABLE_PGRAPH);
@@ -280,7 +285,7 @@ nv40_graph_init(struct drm_device *dev)
280 ctx.data = cp; 285 ctx.data = cp;
281 ctx.ctxprog_max = 256; 286 ctx.ctxprog_max = 256;
282 nv40_grctx_init(&ctx); 287 nv40_grctx_init(&ctx);
283 dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; 288 pgraph->grctx_size = ctx.ctxvals_pos * 4;
284 289
285 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); 290 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
286 for (i = 0; i < ctx.ctxprog_len; i++) 291 for (i = 0; i < ctx.ctxprog_len; i++)
@@ -288,14 +293,9 @@ nv40_graph_init(struct drm_device *dev)
288 293
289 kfree(cp); 294 kfree(cp);
290 295
291 ret = nv40_graph_register(dev);
292 if (ret)
293 return ret;
294
295 /* No context present currently */ 296 /* No context present currently */
296 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); 297 nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
297 298
298 nouveau_irq_register(dev, 12, nv40_graph_isr);
299 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); 299 nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
300 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); 300 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
301 301
@@ -428,47 +428,10 @@ nv40_graph_init(struct drm_device *dev)
428 return 0; 428 return 0;
429} 429}
430 430
431void nv40_graph_takedown(struct drm_device *dev)
432{
433 nouveau_irq_unregister(dev, 12);
434}
435
436static int 431static int
437nv40_graph_register(struct drm_device *dev) 432nv40_graph_fini(struct drm_device *dev, int engine)
438{ 433{
439 struct drm_nouveau_private *dev_priv = dev->dev_private; 434 nv40_graph_unload_context(dev);
440
441 if (dev_priv->engine.graph.registered)
442 return 0;
443
444 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
445 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
446 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
447 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
448 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
449 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
450 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
451 NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
452 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
453 NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
454 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
455 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
456 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
457 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
458 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
459 NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
460
461 /* curie */
462 if (nv44_graph_class(dev))
463 NVOBJ_CLASS(dev, 0x4497, GR);
464 else
465 NVOBJ_CLASS(dev, 0x4097, GR);
466
467 /* nvsw */
468 NVOBJ_CLASS(dev, 0x506e, SW);
469 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
470
471 dev_priv->engine.graph.registered = true;
472 return 0; 435 return 0;
473} 436}
474 437
@@ -476,17 +439,17 @@ static int
476nv40_graph_isr_chid(struct drm_device *dev, u32 inst) 439nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
477{ 440{
478 struct drm_nouveau_private *dev_priv = dev->dev_private; 441 struct drm_nouveau_private *dev_priv = dev->dev_private;
479 struct nouveau_channel *chan; 442 struct nouveau_gpuobj *grctx;
480 unsigned long flags; 443 unsigned long flags;
481 int i; 444 int i;
482 445
483 spin_lock_irqsave(&dev_priv->channels.lock, flags); 446 spin_lock_irqsave(&dev_priv->channels.lock, flags);
484 for (i = 0; i < dev_priv->engine.fifo.channels; i++) { 447 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
485 chan = dev_priv->channels.ptr[i]; 448 if (!dev_priv->channels.ptr[i])
486 if (!chan || !chan->ramin_grctx)
487 continue; 449 continue;
450 grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
488 451
489 if (inst == chan->ramin_grctx->pinst) 452 if (grctx && grctx->pinst == inst)
490 break; 453 break;
491 } 454 }
492 spin_unlock_irqrestore(&dev_priv->channels.lock, flags); 455 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
@@ -537,3 +500,63 @@ nv40_graph_isr(struct drm_device *dev)
537 } 500 }
538 } 501 }
539} 502}
503
504static void
505nv40_graph_destroy(struct drm_device *dev, int engine)
506{
507 struct nv40_graph_engine *pgraph = nv_engine(dev, engine);
508
509 nouveau_irq_unregister(dev, 12);
510
511 NVOBJ_ENGINE_DEL(dev, GR);
512 kfree(pgraph);
513}
514
515int
516nv40_graph_create(struct drm_device *dev)
517{
518 struct nv40_graph_engine *pgraph;
519
520 pgraph = kzalloc(sizeof(*pgraph), GFP_KERNEL);
521 if (!pgraph)
522 return -ENOMEM;
523
524 pgraph->base.destroy = nv40_graph_destroy;
525 pgraph->base.init = nv40_graph_init;
526 pgraph->base.fini = nv40_graph_fini;
527 pgraph->base.context_new = nv40_graph_context_new;
528 pgraph->base.context_del = nv40_graph_context_del;
529 pgraph->base.object_new = nv40_graph_object_new;
530 pgraph->base.set_tile_region = nv40_graph_set_tile_region;
531
532 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
533 nouveau_irq_register(dev, 12, nv40_graph_isr);
534
535 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
536 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
537 NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */
538 NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */
539 NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */
540 NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */
541 NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */
542 NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */
543 NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */
544 NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */
545 NVOBJ_CLASS(dev, 0x0043, GR); /* rop */
546 NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */
547 NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */
548 NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */
549 NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */
550 NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */
551
552 /* curie */
553 if (nv44_graph_class(dev))
554 NVOBJ_CLASS(dev, 0x4497, GR);
555 else
556 NVOBJ_CLASS(dev, 0x4097, GR);
557
558 /* nvsw */
559 NVOBJ_CLASS(dev, 0x506e, SW);
560 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip);
561 return 0;
562}
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c
new file mode 100644
index 000000000000..6d2af292a2e3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c
@@ -0,0 +1,311 @@
1/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "drmP.h"
26#include "nouveau_drv.h"
27#include "nouveau_ramht.h"
28
29struct nv40_mpeg_engine {
30 struct nouveau_exec_engine base;
31};
32
33static int
34nv40_mpeg_context_new(struct nouveau_channel *chan, int engine)
35{
36 struct drm_device *dev = chan->dev;
37 struct drm_nouveau_private *dev_priv = dev->dev_private;
38 struct nouveau_gpuobj *ctx = NULL;
39 unsigned long flags;
40 int ret;
41
42 NV_DEBUG(dev, "ch%d\n", chan->id);
43
44 ret = nouveau_gpuobj_new(dev, NULL, 264 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC |
45 NVOBJ_FLAG_ZERO_FREE, &ctx);
46 if (ret)
47 return ret;
48
49 nv_wo32(ctx, 0x78, 0x02001ec1);
50
51 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
52 nv_mask(dev, 0x002500, 0x00000001, 0x00000000);
53 if ((nv_rd32(dev, 0x003204) & 0x1f) == chan->id)
54 nv_wr32(dev, 0x00330c, ctx->pinst >> 4);
55 nv_wo32(chan->ramfc, 0x54, ctx->pinst >> 4);
56 nv_mask(dev, 0x002500, 0x00000001, 0x00000001);
57 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
58
59 chan->engctx[engine] = ctx;
60 return 0;
61}
62
63static void
64nv40_mpeg_context_del(struct nouveau_channel *chan, int engine)
65{
66 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
67 struct nouveau_gpuobj *ctx = chan->engctx[engine];
68 struct drm_device *dev = chan->dev;
69 unsigned long flags;
70 u32 inst = 0x80000000 | (ctx->pinst >> 4);
71
72 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
73 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
74 if (nv_rd32(dev, 0x00b318) == inst)
75 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
76 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
77 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
78
79 nouveau_gpuobj_ref(NULL, &ctx);
80 chan->engctx[engine] = NULL;
81}
82
83static int
84nv40_mpeg_object_new(struct nouveau_channel *chan, int engine,
85 u32 handle, u16 class)
86{
87 struct drm_device *dev = chan->dev;
88 struct nouveau_gpuobj *obj = NULL;
89 int ret;
90
91 ret = nouveau_gpuobj_new(dev, chan, 20, 16, NVOBJ_FLAG_ZERO_ALLOC |
92 NVOBJ_FLAG_ZERO_FREE, &obj);
93 if (ret)
94 return ret;
95 obj->engine = 2;
96 obj->class = class;
97
98 nv_wo32(obj, 0x00, class);
99
100 ret = nouveau_ramht_insert(chan, handle, obj);
101 nouveau_gpuobj_ref(NULL, &obj);
102 return ret;
103}
104
105static int
106nv40_mpeg_init(struct drm_device *dev, int engine)
107{
108 struct drm_nouveau_private *dev_priv = dev->dev_private;
109 struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
110 int i;
111
112 /* VPE init */
113 nv_mask(dev, 0x000200, 0x00000002, 0x00000000);
114 nv_mask(dev, 0x000200, 0x00000002, 0x00000002);
115 nv_wr32(dev, 0x00b0e0, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
116 nv_wr32(dev, 0x00b0e8, 0x00000020); /* nvidia: rd 0x01, wr 0x20 */
117
118 for (i = 0; i < dev_priv->engine.fb.num_tiles; i++)
119 pmpeg->base.set_tile_region(dev, i);
120
121 /* PMPEG init */
122 nv_wr32(dev, 0x00b32c, 0x00000000);
123 nv_wr32(dev, 0x00b314, 0x00000100);
124 nv_wr32(dev, 0x00b220, 0x00000044);
125 nv_wr32(dev, 0x00b300, 0x02001ec1);
126 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
127
128 nv_wr32(dev, 0x00b100, 0xffffffff);
129 nv_wr32(dev, 0x00b140, 0xffffffff);
130
131 if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
132 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
133 return -EBUSY;
134 }
135
136 return 0;
137}
138
139static int
140nv40_mpeg_fini(struct drm_device *dev, int engine)
141{
142 /*XXX: context save? */
143 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
144 nv_wr32(dev, 0x00b140, 0x00000000);
145 return 0;
146}
147
148static int
149nv40_mpeg_mthd_dma(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
150{
151 struct drm_device *dev = chan->dev;
152 u32 inst = data << 4;
153 u32 dma0 = nv_ri32(dev, inst + 0);
154 u32 dma1 = nv_ri32(dev, inst + 4);
155 u32 dma2 = nv_ri32(dev, inst + 8);
156 u32 base = (dma2 & 0xfffff000) | (dma0 >> 20);
157 u32 size = dma1 + 1;
158
159 /* only allow linear DMA objects */
160 if (!(dma0 & 0x00002000))
161 return -EINVAL;
162
163 if (mthd == 0x0190) {
164 /* DMA_CMD */
165 nv_mask(dev, 0x00b300, 0x00030000, (dma0 & 0x00030000));
166 nv_wr32(dev, 0x00b334, base);
167 nv_wr32(dev, 0x00b324, size);
168 } else
169 if (mthd == 0x01a0) {
170 /* DMA_DATA */
171 nv_mask(dev, 0x00b300, 0x000c0000, (dma0 & 0x00030000) << 2);
172 nv_wr32(dev, 0x00b360, base);
173 nv_wr32(dev, 0x00b364, size);
174 } else {
175 /* DMA_IMAGE, VRAM only */
176 if (dma0 & 0x000c0000)
177 return -EINVAL;
178
179 nv_wr32(dev, 0x00b370, base);
180 nv_wr32(dev, 0x00b374, size);
181 }
182
183 return 0;
184}
185
186static int
187nv40_mpeg_isr_chid(struct drm_device *dev, u32 inst)
188{
189 struct drm_nouveau_private *dev_priv = dev->dev_private;
190 struct nouveau_gpuobj *ctx;
191 unsigned long flags;
192 int i;
193
194 spin_lock_irqsave(&dev_priv->channels.lock, flags);
195 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
196 if (!dev_priv->channels.ptr[i])
197 continue;
198
199 ctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_MPEG];
200 if (ctx && ctx->pinst == inst)
201 break;
202 }
203 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
204 return i;
205}
206
207static void
208nv40_vpe_set_tile_region(struct drm_device *dev, int i)
209{
210 struct drm_nouveau_private *dev_priv = dev->dev_private;
211 struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
212
213 nv_wr32(dev, 0x00b008 + (i * 0x10), tile->pitch);
214 nv_wr32(dev, 0x00b004 + (i * 0x10), tile->limit);
215 nv_wr32(dev, 0x00b000 + (i * 0x10), tile->addr);
216}
217
218static void
219nv40_mpeg_isr(struct drm_device *dev)
220{
221 u32 inst = (nv_rd32(dev, 0x00b318) & 0x000fffff) << 4;
222 u32 chid = nv40_mpeg_isr_chid(dev, inst);
223 u32 stat = nv_rd32(dev, 0x00b100);
224 u32 type = nv_rd32(dev, 0x00b230);
225 u32 mthd = nv_rd32(dev, 0x00b234);
226 u32 data = nv_rd32(dev, 0x00b238);
227 u32 show = stat;
228
229 if (stat & 0x01000000) {
230 /* happens on initial binding of the object */
231 if (type == 0x00000020 && mthd == 0x0000) {
232 nv_mask(dev, 0x00b308, 0x00000000, 0x00000000);
233 show &= ~0x01000000;
234 }
235
236 if (type == 0x00000010) {
237 if (!nouveau_gpuobj_mthd_call2(dev, chid, 0x3174, mthd, data))
238 show &= ~0x01000000;
239 }
240 }
241
242 nv_wr32(dev, 0x00b100, stat);
243 nv_wr32(dev, 0x00b230, 0x00000001);
244
245 if (show && nouveau_ratelimit()) {
246 NV_INFO(dev, "PMPEG: Ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n",
247 chid, inst, stat, type, mthd, data);
248 }
249}
250
251static void
252nv40_vpe_isr(struct drm_device *dev)
253{
254 if (nv_rd32(dev, 0x00b100))
255 nv40_mpeg_isr(dev);
256
257 if (nv_rd32(dev, 0x00b800)) {
258 u32 stat = nv_rd32(dev, 0x00b800);
259 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
260 nv_wr32(dev, 0xb800, stat);
261 }
262}
263
264static void
265nv40_mpeg_destroy(struct drm_device *dev, int engine)
266{
267 struct nv40_mpeg_engine *pmpeg = nv_engine(dev, engine);
268
269 nouveau_irq_unregister(dev, 0);
270
271 NVOBJ_ENGINE_DEL(dev, MPEG);
272 kfree(pmpeg);
273}
274
275int
276nv40_mpeg_create(struct drm_device *dev)
277{
278 struct nv40_mpeg_engine *pmpeg;
279
280 pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
281 if (!pmpeg)
282 return -ENOMEM;
283
284 pmpeg->base.destroy = nv40_mpeg_destroy;
285 pmpeg->base.init = nv40_mpeg_init;
286 pmpeg->base.fini = nv40_mpeg_fini;
287 pmpeg->base.context_new = nv40_mpeg_context_new;
288 pmpeg->base.context_del = nv40_mpeg_context_del;
289 pmpeg->base.object_new = nv40_mpeg_object_new;
290
291 /* ISR vector, PMC_ENABLE bit, and TILE regs are shared between
292 * all VPE engines, for this driver's purposes the PMPEG engine
293 * will be treated as the "master" and handle the global VPE
294 * bits too
295 */
296 pmpeg->base.set_tile_region = nv40_vpe_set_tile_region;
297 nouveau_irq_register(dev, 0, nv40_vpe_isr);
298
299 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
300 NVOBJ_CLASS(dev, 0x3174, MPEG);
301 NVOBJ_MTHD (dev, 0x3174, 0x0190, nv40_mpeg_mthd_dma);
302 NVOBJ_MTHD (dev, 0x3174, 0x01a0, nv40_mpeg_mthd_dma);
303 NVOBJ_MTHD (dev, 0x3174, 0x01b0, nv40_mpeg_mthd_dma);
304
305#if 0
306 NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
307 NVOBJ_CLASS(dev, 0x4075, ME);
308#endif
309 return 0;
310
311}
diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c
index de81151648f8..8cf63a8b30cd 100644
--- a/drivers/gpu/drm/nouveau/nv50_calc.c
+++ b/drivers/gpu/drm/nouveau/nv50_calc.c
@@ -23,7 +23,6 @@
23 */ 23 */
24 24
25#include "drmP.h" 25#include "drmP.h"
26#include "drm_fixed.h"
27#include "nouveau_drv.h" 26#include "nouveau_drv.h"
28#include "nouveau_hw.h" 27#include "nouveau_hw.h"
29 28
@@ -47,45 +46,52 @@ nv50_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk,
47} 46}
48 47
49int 48int
50nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk, 49nva3_calc_pll(struct drm_device *dev, struct pll_lims *pll, int clk,
51 int *N, int *fN, int *M, int *P) 50 int *pN, int *pfN, int *pM, int *P)
52{ 51{
53 fixed20_12 fb_div, a, b; 52 u32 best_err = ~0, err;
54 u32 refclk = pll->refclk / 10; 53 int M, lM, hM, N, fN;
55 u32 max_vco_freq = pll->vco1.maxfreq / 10;
56 u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10;
57 clk /= 10;
58 54
59 *P = max_vco_freq / clk; 55 *P = pll->vco1.maxfreq / clk;
60 if (*P > pll->max_p) 56 if (*P > pll->max_p)
61 *P = pll->max_p; 57 *P = pll->max_p;
62 if (*P < pll->min_p) 58 if (*P < pll->min_p)
63 *P = pll->min_p; 59 *P = pll->min_p;
64 60
65 /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ 61 lM = (pll->refclk + pll->vco1.max_inputfreq) / pll->vco1.max_inputfreq;
66 a.full = dfixed_const(refclk + max_vco_inputfreq); 62 lM = max(lM, (int)pll->vco1.min_m);
67 b.full = dfixed_const(max_vco_inputfreq); 63 hM = (pll->refclk + pll->vco1.min_inputfreq) / pll->vco1.min_inputfreq;
68 a.full = dfixed_div(a, b); 64 hM = min(hM, (int)pll->vco1.max_m);
69 a.full = dfixed_floor(a);
70 *M = dfixed_trunc(a);
71 65
72 /* fb_div = (vco * *M) / refclk; */ 66 for (M = lM; M <= hM; M++) {
73 fb_div.full = dfixed_const(clk * *P); 67 u32 tmp = clk * *P * M;
74 fb_div.full = dfixed_mul(fb_div, a); 68 N = tmp / pll->refclk;
75 a.full = dfixed_const(refclk); 69 fN = tmp % pll->refclk;
76 fb_div.full = dfixed_div(fb_div, a); 70 if (!pfN && fN >= pll->refclk / 2)
71 N++;
77 72
78 /* *N = floor(fb_div); */ 73 if (N < pll->vco1.min_n)
79 a.full = dfixed_floor(fb_div); 74 continue;
80 *N = dfixed_trunc(fb_div); 75 if (N > pll->vco1.max_n)
76 break;
81 77
82 /* *fN = (fmod(fb_div, 1.0) * 8192) - 4096; */ 78 err = abs(clk - (pll->refclk * N / M / *P));
83 b.full = dfixed_const(8192); 79 if (err < best_err) {
84 a.full = dfixed_mul(a, b); 80 best_err = err;
85 fb_div.full = dfixed_mul(fb_div, b); 81 *pN = N;
86 fb_div.full = fb_div.full - a.full; 82 *pM = M;
87 *fN = dfixed_trunc(fb_div) - 4096; 83 }
88 *fN &= 0xffff;
89 84
90 return clk; 85 if (pfN) {
86 *pfN = (((fN << 13) / pll->refclk) - 4096) & 0xffff;
87 return clk;
88 }
89 }
90
91 if (unlikely(best_err == ~0)) {
92 NV_ERROR(dev, "unable to find matching pll values\n");
93 return -EINVAL;
94 }
95
96 return pll->refclk * *pN / *pM / *P;
91} 97}
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index a19ccaa025b3..ebabacf38da9 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -286,7 +286,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
286 nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); 286 nv_wr32(dev, pll.reg + 8, reg2 | (P << 28) | (M2 << 16) | N2);
287 } else 287 } else
288 if (dev_priv->chipset < NV_C0) { 288 if (dev_priv->chipset < NV_C0) {
289 ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); 289 ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P);
290 if (ret <= 0) 290 if (ret <= 0)
291 return 0; 291 return 0;
292 292
@@ -298,7 +298,7 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
298 nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); 298 nv_wr32(dev, pll.reg + 4, reg1 | (P << 16) | (M1 << 8) | N1);
299 nv_wr32(dev, pll.reg + 8, N2); 299 nv_wr32(dev, pll.reg + 8, N2);
300 } else { 300 } else {
301 ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); 301 ret = nva3_calc_pll(dev, &pll, pclk, &N1, &N2, &M1, &P);
302 if (ret <= 0) 302 if (ret <= 0)
303 return 0; 303 return 0;
304 304
@@ -349,14 +349,14 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
349 struct drm_gem_object *gem; 349 struct drm_gem_object *gem;
350 int ret = 0, i; 350 int ret = 0, i;
351 351
352 if (width != 64 || height != 64)
353 return -EINVAL;
354
355 if (!buffer_handle) { 352 if (!buffer_handle) {
356 nv_crtc->cursor.hide(nv_crtc, true); 353 nv_crtc->cursor.hide(nv_crtc, true);
357 return 0; 354 return 0;
358 } 355 }
359 356
357 if (width != 64 || height != 64)
358 return -EINVAL;
359
360 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); 360 gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
361 if (!gem) 361 if (!gem)
362 return -ENOENT; 362 return -ENOENT;
@@ -532,8 +532,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
532 if (atomic) { 532 if (atomic) {
533 drm_fb = passed_fb; 533 drm_fb = passed_fb;
534 fb = nouveau_framebuffer(passed_fb); 534 fb = nouveau_framebuffer(passed_fb);
535 } 535 } else {
536 else {
537 /* If not atomic, we can go ahead and pin, and unpin the 536 /* If not atomic, we can go ahead and pin, and unpin the
538 * old fb we were passed. 537 * old fb we were passed.
539 */ 538 */
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 75a376cc342a..74a3f6872701 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -517,13 +517,25 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,
517 if (bios->fp.if_is_24bit) 517 if (bios->fp.if_is_24bit)
518 script |= 0x0200; 518 script |= 0x0200;
519 } else { 519 } else {
520 /* determine number of lvds links */
521 if (nv_connector && nv_connector->edid &&
522 nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) {
523 /* http://www.spwg.org */
524 if (((u8 *)nv_connector->edid)[121] == 2)
525 script |= 0x0100;
526 } else
520 if (pxclk >= bios->fp.duallink_transition_clk) { 527 if (pxclk >= bios->fp.duallink_transition_clk) {
521 script |= 0x0100; 528 script |= 0x0100;
529 }
530
531 /* determine panel depth */
532 if (script & 0x0100) {
522 if (bios->fp.strapless_is_24bit & 2) 533 if (bios->fp.strapless_is_24bit & 2)
523 script |= 0x0200; 534 script |= 0x0200;
524 } else 535 } else {
525 if (bios->fp.strapless_is_24bit & 1) 536 if (bios->fp.strapless_is_24bit & 1)
526 script |= 0x0200; 537 script |= 0x0200;
538 }
527 539
528 if (nv_connector && nv_connector->edid && 540 if (nv_connector && nv_connector->edid &&
529 (nv_connector->edid->revision >= 4) && 541 (nv_connector->edid->revision >= 4) &&
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index b02a5b1e7d37..e25cbb46789a 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -31,10 +31,95 @@
31#include "nouveau_grctx.h" 31#include "nouveau_grctx.h"
32#include "nouveau_dma.h" 32#include "nouveau_dma.h"
33#include "nouveau_vm.h" 33#include "nouveau_vm.h"
34#include "nouveau_ramht.h"
34#include "nv50_evo.h" 35#include "nv50_evo.h"
35 36
36static int nv50_graph_register(struct drm_device *); 37struct nv50_graph_engine {
37static void nv50_graph_isr(struct drm_device *); 38 struct nouveau_exec_engine base;
39 u32 ctxprog[512];
40 u32 ctxprog_size;
41 u32 grctx_size;
42};
43
44static void
45nv50_graph_fifo_access(struct drm_device *dev, bool enabled)
46{
47 const uint32_t mask = 0x00010001;
48
49 if (enabled)
50 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask);
51 else
52 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask);
53}
54
55static struct nouveau_channel *
56nv50_graph_channel(struct drm_device *dev)
57{
58 struct drm_nouveau_private *dev_priv = dev->dev_private;
59 uint32_t inst;
60 int i;
61
62 /* Be sure we're not in the middle of a context switch or bad things
63 * will happen, such as unloading the wrong pgraph context.
64 */
65 if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000))
66 NV_ERROR(dev, "Ctxprog is still running\n");
67
68 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
69 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
70 return NULL;
71 inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
72
73 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
74 struct nouveau_channel *chan = dev_priv->channels.ptr[i];
75
76 if (chan && chan->ramin && chan->ramin->vinst == inst)
77 return chan;
78 }
79
80 return NULL;
81}
82
83static int
84nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst)
85{
86 uint32_t fifo = nv_rd32(dev, 0x400500);
87
88 nv_wr32(dev, 0x400500, fifo & ~1);
89 nv_wr32(dev, 0x400784, inst);
90 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x40);
91 nv_wr32(dev, 0x400320, nv_rd32(dev, 0x400320) | 0x11);
92 nv_wr32(dev, 0x400040, 0xffffffff);
93 (void)nv_rd32(dev, 0x400040);
94 nv_wr32(dev, 0x400040, 0x00000000);
95 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 1);
96
97 if (nouveau_wait_for_idle(dev))
98 nv_wr32(dev, 0x40032c, inst | (1<<31));
99 nv_wr32(dev, 0x400500, fifo);
100
101 return 0;
102}
103
104static int
105nv50_graph_unload_context(struct drm_device *dev)
106{
107 uint32_t inst;
108
109 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
110 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
111 return 0;
112 inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
113
114 nouveau_wait_for_idle(dev);
115 nv_wr32(dev, 0x400784, inst);
116 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
117 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01);
118 nouveau_wait_for_idle(dev);
119
120 nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst);
121 return 0;
122}
38 123
39static void 124static void
40nv50_graph_init_reset(struct drm_device *dev) 125nv50_graph_init_reset(struct drm_device *dev)
@@ -52,7 +137,6 @@ nv50_graph_init_intr(struct drm_device *dev)
52{ 137{
53 NV_DEBUG(dev, "\n"); 138 NV_DEBUG(dev, "\n");
54 139
55 nouveau_irq_register(dev, 12, nv50_graph_isr);
56 nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); 140 nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff);
57 nv_wr32(dev, 0x400138, 0xffffffff); 141 nv_wr32(dev, 0x400138, 0xffffffff);
58 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); 142 nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff);
@@ -135,34 +219,14 @@ nv50_graph_init_zcull(struct drm_device *dev)
135static int 219static int
136nv50_graph_init_ctxctl(struct drm_device *dev) 220nv50_graph_init_ctxctl(struct drm_device *dev)
137{ 221{
138 struct drm_nouveau_private *dev_priv = dev->dev_private; 222 struct nv50_graph_engine *pgraph = nv_engine(dev, NVOBJ_ENGINE_GR);
139 struct nouveau_grctx ctx = {};
140 uint32_t *cp;
141 int i; 223 int i;
142 224
143 NV_DEBUG(dev, "\n"); 225 NV_DEBUG(dev, "\n");
144 226
145 cp = kmalloc(512 * 4, GFP_KERNEL); 227 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
146 if (!cp) { 228 for (i = 0; i < pgraph->ctxprog_size; i++)
147 NV_ERROR(dev, "failed to allocate ctxprog\n"); 229 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, pgraph->ctxprog[i]);
148 dev_priv->engine.graph.accel_blocked = true;
149 return 0;
150 }
151
152 ctx.dev = dev;
153 ctx.mode = NOUVEAU_GRCTX_PROG;
154 ctx.data = cp;
155 ctx.ctxprog_max = 512;
156 if (!nv50_grctx_init(&ctx)) {
157 dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
158
159 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
160 for (i = 0; i < ctx.ctxprog_len; i++)
161 nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
162 } else {
163 dev_priv->engine.graph.accel_blocked = true;
164 }
165 kfree(cp);
166 230
167 nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */ 231 nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
168 nv_wr32(dev, 0x400320, 4); 232 nv_wr32(dev, 0x400320, 4);
@@ -171,8 +235,8 @@ nv50_graph_init_ctxctl(struct drm_device *dev)
171 return 0; 235 return 0;
172} 236}
173 237
174int 238static int
175nv50_graph_init(struct drm_device *dev) 239nv50_graph_init(struct drm_device *dev, int engine)
176{ 240{
177 int ret; 241 int ret;
178 242
@@ -186,105 +250,66 @@ nv50_graph_init(struct drm_device *dev)
186 if (ret) 250 if (ret)
187 return ret; 251 return ret;
188 252
189 ret = nv50_graph_register(dev);
190 if (ret)
191 return ret;
192 nv50_graph_init_intr(dev); 253 nv50_graph_init_intr(dev);
193 return 0; 254 return 0;
194} 255}
195 256
196void 257static int
197nv50_graph_takedown(struct drm_device *dev) 258nv50_graph_fini(struct drm_device *dev, int engine)
198{ 259{
199 NV_DEBUG(dev, "\n"); 260 NV_DEBUG(dev, "\n");
261 nv50_graph_unload_context(dev);
200 nv_wr32(dev, 0x40013c, 0x00000000); 262 nv_wr32(dev, 0x40013c, 0x00000000);
201 nouveau_irq_unregister(dev, 12); 263 return 0;
202}
203
204void
205nv50_graph_fifo_access(struct drm_device *dev, bool enabled)
206{
207 const uint32_t mask = 0x00010001;
208
209 if (enabled)
210 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | mask);
211 else
212 nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) & ~mask);
213}
214
215struct nouveau_channel *
216nv50_graph_channel(struct drm_device *dev)
217{
218 struct drm_nouveau_private *dev_priv = dev->dev_private;
219 uint32_t inst;
220 int i;
221
222 /* Be sure we're not in the middle of a context switch or bad things
223 * will happen, such as unloading the wrong pgraph context.
224 */
225 if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000))
226 NV_ERROR(dev, "Ctxprog is still running\n");
227
228 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
229 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
230 return NULL;
231 inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12;
232
233 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
234 struct nouveau_channel *chan = dev_priv->channels.ptr[i];
235
236 if (chan && chan->ramin && chan->ramin->vinst == inst)
237 return chan;
238 }
239
240 return NULL;
241} 264}
242 265
243int 266static int
244nv50_graph_create_context(struct nouveau_channel *chan) 267nv50_graph_context_new(struct nouveau_channel *chan, int engine)
245{ 268{
246 struct drm_device *dev = chan->dev; 269 struct drm_device *dev = chan->dev;
247 struct drm_nouveau_private *dev_priv = dev->dev_private; 270 struct drm_nouveau_private *dev_priv = dev->dev_private;
248 struct nouveau_gpuobj *ramin = chan->ramin; 271 struct nouveau_gpuobj *ramin = chan->ramin;
249 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 272 struct nouveau_gpuobj *grctx = NULL;
273 struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
250 struct nouveau_grctx ctx = {}; 274 struct nouveau_grctx ctx = {};
251 int hdr, ret; 275 int hdr, ret;
252 276
253 NV_DEBUG(dev, "ch%d\n", chan->id); 277 NV_DEBUG(dev, "ch%d\n", chan->id);
254 278
255 ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0, 279 ret = nouveau_gpuobj_new(dev, NULL, pgraph->grctx_size, 0,
256 NVOBJ_FLAG_ZERO_ALLOC | 280 NVOBJ_FLAG_ZERO_ALLOC |
257 NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); 281 NVOBJ_FLAG_ZERO_FREE, &grctx);
258 if (ret) 282 if (ret)
259 return ret; 283 return ret;
260 284
261 hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; 285 hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
262 nv_wo32(ramin, hdr + 0x00, 0x00190002); 286 nv_wo32(ramin, hdr + 0x00, 0x00190002);
263 nv_wo32(ramin, hdr + 0x04, chan->ramin_grctx->vinst + 287 nv_wo32(ramin, hdr + 0x04, grctx->vinst + grctx->size - 1);
264 pgraph->grctx_size - 1); 288 nv_wo32(ramin, hdr + 0x08, grctx->vinst);
265 nv_wo32(ramin, hdr + 0x08, chan->ramin_grctx->vinst);
266 nv_wo32(ramin, hdr + 0x0c, 0); 289 nv_wo32(ramin, hdr + 0x0c, 0);
267 nv_wo32(ramin, hdr + 0x10, 0); 290 nv_wo32(ramin, hdr + 0x10, 0);
268 nv_wo32(ramin, hdr + 0x14, 0x00010000); 291 nv_wo32(ramin, hdr + 0x14, 0x00010000);
269 292
270 ctx.dev = chan->dev; 293 ctx.dev = chan->dev;
271 ctx.mode = NOUVEAU_GRCTX_VALS; 294 ctx.mode = NOUVEAU_GRCTX_VALS;
272 ctx.data = chan->ramin_grctx; 295 ctx.data = grctx;
273 nv50_grctx_init(&ctx); 296 nv50_grctx_init(&ctx);
274 297
275 nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12); 298 nv_wo32(grctx, 0x00000, chan->ramin->vinst >> 12);
276 299
277 dev_priv->engine.instmem.flush(dev); 300 dev_priv->engine.instmem.flush(dev);
278 atomic_inc(&chan->vm->pgraph_refs); 301
302 atomic_inc(&chan->vm->engref[NVOBJ_ENGINE_GR]);
303 chan->engctx[NVOBJ_ENGINE_GR] = grctx;
279 return 0; 304 return 0;
280} 305}
281 306
282void 307static void
283nv50_graph_destroy_context(struct nouveau_channel *chan) 308nv50_graph_context_del(struct nouveau_channel *chan, int engine)
284{ 309{
310 struct nouveau_gpuobj *grctx = chan->engctx[engine];
285 struct drm_device *dev = chan->dev; 311 struct drm_device *dev = chan->dev;
286 struct drm_nouveau_private *dev_priv = dev->dev_private; 312 struct drm_nouveau_private *dev_priv = dev->dev_private;
287 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
288 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 313 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
289 int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; 314 int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20;
290 unsigned long flags; 315 unsigned long flags;
@@ -296,72 +321,49 @@ nv50_graph_destroy_context(struct nouveau_channel *chan)
296 321
297 spin_lock_irqsave(&dev_priv->context_switch_lock, flags); 322 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
298 pfifo->reassign(dev, false); 323 pfifo->reassign(dev, false);
299 pgraph->fifo_access(dev, false); 324 nv50_graph_fifo_access(dev, false);
300 325
301 if (pgraph->channel(dev) == chan) 326 if (nv50_graph_channel(dev) == chan)
302 pgraph->unload_context(dev); 327 nv50_graph_unload_context(dev);
303 328
304 for (i = hdr; i < hdr + 24; i += 4) 329 for (i = hdr; i < hdr + 24; i += 4)
305 nv_wo32(chan->ramin, i, 0); 330 nv_wo32(chan->ramin, i, 0);
306 dev_priv->engine.instmem.flush(dev); 331 dev_priv->engine.instmem.flush(dev);
307 332
308 pgraph->fifo_access(dev, true); 333 nv50_graph_fifo_access(dev, true);
309 pfifo->reassign(dev, true); 334 pfifo->reassign(dev, true);
310 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); 335 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
311 336
312 nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); 337 nouveau_gpuobj_ref(NULL, &grctx);
313 338
314 atomic_dec(&chan->vm->pgraph_refs); 339 atomic_dec(&chan->vm->engref[engine]);
340 chan->engctx[engine] = NULL;
315} 341}
316 342
317static int 343static int
318nv50_graph_do_load_context(struct drm_device *dev, uint32_t inst) 344nv50_graph_object_new(struct nouveau_channel *chan, int engine,
319{ 345 u32 handle, u16 class)
320 uint32_t fifo = nv_rd32(dev, 0x400500);
321
322 nv_wr32(dev, 0x400500, fifo & ~1);
323 nv_wr32(dev, 0x400784, inst);
324 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x40);
325 nv_wr32(dev, 0x400320, nv_rd32(dev, 0x400320) | 0x11);
326 nv_wr32(dev, 0x400040, 0xffffffff);
327 (void)nv_rd32(dev, 0x400040);
328 nv_wr32(dev, 0x400040, 0x00000000);
329 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 1);
330
331 if (nouveau_wait_for_idle(dev))
332 nv_wr32(dev, 0x40032c, inst | (1<<31));
333 nv_wr32(dev, 0x400500, fifo);
334
335 return 0;
336}
337
338int
339nv50_graph_load_context(struct nouveau_channel *chan)
340{
341 uint32_t inst = chan->ramin->vinst >> 12;
342
343 NV_DEBUG(chan->dev, "ch%d\n", chan->id);
344 return nv50_graph_do_load_context(chan->dev, inst);
345}
346
347int
348nv50_graph_unload_context(struct drm_device *dev)
349{ 346{
350 uint32_t inst; 347 struct drm_device *dev = chan->dev;
348 struct drm_nouveau_private *dev_priv = dev->dev_private;
349 struct nouveau_gpuobj *obj = NULL;
350 int ret;
351 351
352 inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); 352 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
353 if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) 353 if (ret)
354 return 0; 354 return ret;
355 inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; 355 obj->engine = 1;
356 obj->class = class;
356 357
357 nouveau_wait_for_idle(dev); 358 nv_wo32(obj, 0x00, class);
358 nv_wr32(dev, 0x400784, inst); 359 nv_wo32(obj, 0x04, 0x00000000);
359 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); 360 nv_wo32(obj, 0x08, 0x00000000);
360 nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01); 361 nv_wo32(obj, 0x0c, 0x00000000);
361 nouveau_wait_for_idle(dev); 362 dev_priv->engine.instmem.flush(dev);
362 363
363 nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst); 364 ret = nouveau_ramht_insert(chan, handle, obj);
364 return 0; 365 nouveau_gpuobj_ref(NULL, &obj);
366 return ret;
365} 367}
366 368
367static void 369static void
@@ -442,68 +444,15 @@ nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan,
442 return 0; 444 return 0;
443} 445}
444 446
445static int
446nv50_graph_register(struct drm_device *dev)
447{
448 struct drm_nouveau_private *dev_priv = dev->dev_private;
449
450 if (dev_priv->engine.graph.registered)
451 return 0;
452
453 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
454 NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem);
455 NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset);
456 NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val);
457 NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release);
458 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip);
459
460 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
461 NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */
462 NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */
463
464 /* tesla */
465 if (dev_priv->chipset == 0x50)
466 NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */
467 else
468 if (dev_priv->chipset < 0xa0)
469 NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */
470 else {
471 switch (dev_priv->chipset) {
472 case 0xa0:
473 case 0xaa:
474 case 0xac:
475 NVOBJ_CLASS(dev, 0x8397, GR);
476 break;
477 case 0xa3:
478 case 0xa5:
479 case 0xa8:
480 NVOBJ_CLASS(dev, 0x8597, GR);
481 break;
482 case 0xaf:
483 NVOBJ_CLASS(dev, 0x8697, GR);
484 break;
485 }
486 }
487
488 /* compute */
489 NVOBJ_CLASS(dev, 0x50c0, GR);
490 if (dev_priv->chipset > 0xa0 &&
491 dev_priv->chipset != 0xaa &&
492 dev_priv->chipset != 0xac)
493 NVOBJ_CLASS(dev, 0x85c0, GR);
494
495 dev_priv->engine.graph.registered = true;
496 return 0;
497}
498 447
499void 448static void
500nv50_graph_tlb_flush(struct drm_device *dev) 449nv50_graph_tlb_flush(struct drm_device *dev, int engine)
501{ 450{
502 nv50_vm_flush_engine(dev, 0); 451 nv50_vm_flush_engine(dev, 0);
503} 452}
504 453
505void 454static void
506nv84_graph_tlb_flush(struct drm_device *dev) 455nv84_graph_tlb_flush(struct drm_device *dev, int engine)
507{ 456{
508 struct drm_nouveau_private *dev_priv = dev->dev_private; 457 struct drm_nouveau_private *dev_priv = dev->dev_private;
509 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; 458 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
@@ -548,8 +497,7 @@ nv84_graph_tlb_flush(struct drm_device *dev)
548 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); 497 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
549} 498}
550 499
551static struct nouveau_enum nv50_mp_exec_error_names[] = 500static struct nouveau_enum nv50_mp_exec_error_names[] = {
552{
553 { 3, "STACK_UNDERFLOW", NULL }, 501 { 3, "STACK_UNDERFLOW", NULL },
554 { 4, "QUADON_ACTIVE", NULL }, 502 { 4, "QUADON_ACTIVE", NULL },
555 { 8, "TIMEOUT", NULL }, 503 { 8, "TIMEOUT", NULL },
@@ -663,7 +611,7 @@ nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
663 nv_rd32(dev, addr + 0x20); 611 nv_rd32(dev, addr + 0x20);
664 pc = nv_rd32(dev, addr + 0x24); 612 pc = nv_rd32(dev, addr + 0x24);
665 oplow = nv_rd32(dev, addr + 0x70); 613 oplow = nv_rd32(dev, addr + 0x70);
666 ophigh= nv_rd32(dev, addr + 0x74); 614 ophigh = nv_rd32(dev, addr + 0x74);
667 NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " 615 NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
668 "TP %d MP %d: ", tpid, i); 616 "TP %d MP %d: ", tpid, i);
669 nouveau_enum_print(nv50_mp_exec_error_names, status); 617 nouveau_enum_print(nv50_mp_exec_error_names, status);
@@ -991,7 +939,7 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid
991 return 1; 939 return 1;
992} 940}
993 941
994static int 942int
995nv50_graph_isr_chid(struct drm_device *dev, u64 inst) 943nv50_graph_isr_chid(struct drm_device *dev, u64 inst)
996{ 944{
997 struct drm_nouveau_private *dev_priv = dev->dev_private; 945 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -1073,3 +1021,101 @@ nv50_graph_isr(struct drm_device *dev)
1073 if (nv_rd32(dev, 0x400824) & (1 << 31)) 1021 if (nv_rd32(dev, 0x400824) & (1 << 31))
1074 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); 1022 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
1075} 1023}
1024
1025static void
1026nv50_graph_destroy(struct drm_device *dev, int engine)
1027{
1028 struct nv50_graph_engine *pgraph = nv_engine(dev, engine);
1029
1030 NVOBJ_ENGINE_DEL(dev, GR);
1031
1032 nouveau_irq_unregister(dev, 12);
1033 kfree(pgraph);
1034}
1035
1036int
1037nv50_graph_create(struct drm_device *dev)
1038{
1039 struct drm_nouveau_private *dev_priv = dev->dev_private;
1040 struct nv50_graph_engine *pgraph;
1041 struct nouveau_grctx ctx = {};
1042 int ret;
1043
1044 pgraph = kzalloc(sizeof(*pgraph),GFP_KERNEL);
1045 if (!pgraph)
1046 return -ENOMEM;
1047
1048 ctx.dev = dev;
1049 ctx.mode = NOUVEAU_GRCTX_PROG;
1050 ctx.data = pgraph->ctxprog;
1051 ctx.ctxprog_max = ARRAY_SIZE(pgraph->ctxprog);
1052
1053 ret = nv50_grctx_init(&ctx);
1054 if (ret) {
1055 NV_ERROR(dev, "PGRAPH: ctxprog build failed\n");
1056 kfree(pgraph);
1057 return 0;
1058 }
1059
1060 pgraph->grctx_size = ctx.ctxvals_pos * 4;
1061 pgraph->ctxprog_size = ctx.ctxprog_len;
1062
1063 pgraph->base.destroy = nv50_graph_destroy;
1064 pgraph->base.init = nv50_graph_init;
1065 pgraph->base.fini = nv50_graph_fini;
1066 pgraph->base.context_new = nv50_graph_context_new;
1067 pgraph->base.context_del = nv50_graph_context_del;
1068 pgraph->base.object_new = nv50_graph_object_new;
1069 if (dev_priv->chipset == 0x50 || dev_priv->chipset == 0xac)
1070 pgraph->base.tlb_flush = nv50_graph_tlb_flush;
1071 else
1072 pgraph->base.tlb_flush = nv84_graph_tlb_flush;
1073
1074 nouveau_irq_register(dev, 12, nv50_graph_isr);
1075
1076 /* NVSW really doesn't live here... */
1077 NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */
1078 NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem);
1079 NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset);
1080 NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val);
1081 NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release);
1082 NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip);
1083
1084 NVOBJ_ENGINE_ADD(dev, GR, &pgraph->base);
1085 NVOBJ_CLASS(dev, 0x0030, GR); /* null */
1086 NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */
1087 NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */
1088
1089 /* tesla */
1090 if (dev_priv->chipset == 0x50)
1091 NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */
1092 else
1093 if (dev_priv->chipset < 0xa0)
1094 NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */
1095 else {
1096 switch (dev_priv->chipset) {
1097 case 0xa0:
1098 case 0xaa:
1099 case 0xac:
1100 NVOBJ_CLASS(dev, 0x8397, GR);
1101 break;
1102 case 0xa3:
1103 case 0xa5:
1104 case 0xa8:
1105 NVOBJ_CLASS(dev, 0x8597, GR);
1106 break;
1107 case 0xaf:
1108 NVOBJ_CLASS(dev, 0x8697, GR);
1109 break;
1110 }
1111 }
1112
1113 /* compute */
1114 NVOBJ_CLASS(dev, 0x50c0, GR);
1115 if (dev_priv->chipset > 0xa0 &&
1116 dev_priv->chipset != 0xaa &&
1117 dev_priv->chipset != 0xac)
1118 NVOBJ_CLASS(dev, 0x85c0, GR);
1119
1120 return 0;
1121}
diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c
index 336aab2a24a6..de9abff12b90 100644
--- a/drivers/gpu/drm/nouveau/nv50_grctx.c
+++ b/drivers/gpu/drm/nouveau/nv50_grctx.c
@@ -747,7 +747,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
747 gr_def(ctx, offset + 0x64, 0x0000001f); 747 gr_def(ctx, offset + 0x64, 0x0000001f);
748 gr_def(ctx, offset + 0x68, 0x0000000f); 748 gr_def(ctx, offset + 0x68, 0x0000000f);
749 gr_def(ctx, offset + 0x6c, 0x0000000f); 749 gr_def(ctx, offset + 0x6c, 0x0000000f);
750 } else if(dev_priv->chipset < 0xa0) { 750 } else if (dev_priv->chipset < 0xa0) {
751 cp_ctx(ctx, offset + 0x50, 1); 751 cp_ctx(ctx, offset + 0x50, 1);
752 cp_ctx(ctx, offset + 0x70, 1); 752 cp_ctx(ctx, offset + 0x70, 1);
753 } else { 753 } else {
@@ -924,7 +924,7 @@ nv50_graph_construct_mmio_ddata(struct nouveau_grctx *ctx)
924 dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */ 924 dd_emit(ctx, 1, 0); /* 0000007f MULTISAMPLE_SAMPLES_LOG2 */
925 } else { 925 } else {
926 dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */ 926 dd_emit(ctx, 1, 0); /* 0000000f MULTISAMPLE_SAMPLES_LOG2 */
927 } 927 }
928 dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */ 928 dd_emit(ctx, 1, 0xc); /* 000000ff SEMANTIC_COLOR.BFC0_ID */
929 if (dev_priv->chipset != 0x50) 929 if (dev_priv->chipset != 0x50)
930 dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */ 930 dd_emit(ctx, 1, 0); /* 00000001 SEMANTIC_COLOR.CLMP_EN */
@@ -1803,9 +1803,7 @@ nv50_graph_construct_gene_unk24xx(struct nouveau_grctx *ctx)
1803 xf_emit(ctx, 1, 0); /* 1ff */ 1803 xf_emit(ctx, 1, 0); /* 1ff */
1804 xf_emit(ctx, 8, 0); /* 0? */ 1804 xf_emit(ctx, 8, 0); /* 0? */
1805 xf_emit(ctx, 9, 0); /* ffffffff, 7ff */ 1805 xf_emit(ctx, 9, 0); /* ffffffff, 7ff */
1806 } 1806 } else {
1807 else
1808 {
1809 xf_emit(ctx, 0xc, 0); /* RO */ 1807 xf_emit(ctx, 0xc, 0); /* RO */
1810 /* SEEK */ 1808 /* SEEK */
1811 xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */ 1809 xf_emit(ctx, 0xe10, 0); /* 190 * 9: 8*ffffffff, 7ff */
@@ -2836,7 +2834,7 @@ nv50_graph_construct_xfer_tprop(struct nouveau_grctx *ctx)
2836 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */ 2834 xf_emit(ctx, 1, 1); /* 00000001 DST_LINEAR */
2837 if (IS_NVA3F(dev_priv->chipset)) 2835 if (IS_NVA3F(dev_priv->chipset))
2838 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */ 2836 xf_emit(ctx, 1, 1); /* 0000001f tesla UNK169C */
2839 if(dev_priv->chipset == 0x50) 2837 if (dev_priv->chipset == 0x50)
2840 xf_emit(ctx, 1, 0); /* ff */ 2838 xf_emit(ctx, 1, 0); /* ff */
2841 else 2839 else
2842 xf_emit(ctx, 3, 0); /* 1, 7, 3ff */ 2840 xf_emit(ctx, 3, 0); /* 1, 7, 3ff */
diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c
new file mode 100644
index 000000000000..1dc5913f78c5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c
@@ -0,0 +1,256 @@
1/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "drmP.h"
26#include "nouveau_drv.h"
27#include "nouveau_ramht.h"
28
29struct nv50_mpeg_engine {
30 struct nouveau_exec_engine base;
31};
32
33static inline u32
34CTX_PTR(struct drm_device *dev, u32 offset)
35{
36 struct drm_nouveau_private *dev_priv = dev->dev_private;
37
38 if (dev_priv->chipset == 0x50)
39 offset += 0x0260;
40 else
41 offset += 0x0060;
42
43 return offset;
44}
45
46static int
47nv50_mpeg_context_new(struct nouveau_channel *chan, int engine)
48{
49 struct drm_device *dev = chan->dev;
50 struct drm_nouveau_private *dev_priv = dev->dev_private;
51 struct nouveau_gpuobj *ramin = chan->ramin;
52 struct nouveau_gpuobj *ctx = NULL;
53 int ret;
54
55 NV_DEBUG(dev, "ch%d\n", chan->id);
56
57 ret = nouveau_gpuobj_new(dev, chan, 128 * 4, 0, NVOBJ_FLAG_ZERO_ALLOC |
58 NVOBJ_FLAG_ZERO_FREE, &ctx);
59 if (ret)
60 return ret;
61
62 nv_wo32(ramin, CTX_PTR(dev, 0x00), 0x80190002);
63 nv_wo32(ramin, CTX_PTR(dev, 0x04), ctx->vinst + ctx->size - 1);
64 nv_wo32(ramin, CTX_PTR(dev, 0x08), ctx->vinst);
65 nv_wo32(ramin, CTX_PTR(dev, 0x0c), 0);
66 nv_wo32(ramin, CTX_PTR(dev, 0x10), 0);
67 nv_wo32(ramin, CTX_PTR(dev, 0x14), 0x00010000);
68
69 nv_wo32(ctx, 0x70, 0x00801ec1);
70 nv_wo32(ctx, 0x7c, 0x0000037c);
71 dev_priv->engine.instmem.flush(dev);
72
73 chan->engctx[engine] = ctx;
74 return 0;
75}
76
77static void
78nv50_mpeg_context_del(struct nouveau_channel *chan, int engine)
79{
80 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
81 struct nouveau_gpuobj *ctx = chan->engctx[engine];
82 struct drm_device *dev = chan->dev;
83 unsigned long flags;
84 u32 inst, i;
85
86 if (!chan->ramin)
87 return;
88
89 inst = chan->ramin->vinst >> 12;
90 inst |= 0x80000000;
91
92 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
93 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
94 if (nv_rd32(dev, 0x00b318) == inst)
95 nv_mask(dev, 0x00b318, 0x80000000, 0x00000000);
96 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
97 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
98
99 for (i = 0x00; i <= 0x14; i += 4)
100 nv_wo32(chan->ramin, CTX_PTR(dev, i), 0x00000000);
101 nouveau_gpuobj_ref(NULL, &ctx);
102 chan->engctx[engine] = NULL;
103}
104
105static int
106nv50_mpeg_object_new(struct nouveau_channel *chan, int engine,
107 u32 handle, u16 class)
108{
109 struct drm_device *dev = chan->dev;
110 struct drm_nouveau_private *dev_priv = dev->dev_private;
111 struct nouveau_gpuobj *obj = NULL;
112 int ret;
113
114 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
115 if (ret)
116 return ret;
117 obj->engine = 2;
118 obj->class = class;
119
120 nv_wo32(obj, 0x00, class);
121 nv_wo32(obj, 0x04, 0x00000000);
122 nv_wo32(obj, 0x08, 0x00000000);
123 nv_wo32(obj, 0x0c, 0x00000000);
124 dev_priv->engine.instmem.flush(dev);
125
126 ret = nouveau_ramht_insert(chan, handle, obj);
127 nouveau_gpuobj_ref(NULL, &obj);
128 return ret;
129}
130
131static void
132nv50_mpeg_tlb_flush(struct drm_device *dev, int engine)
133{
134 nv50_vm_flush_engine(dev, 0x08);
135}
136
137static int
138nv50_mpeg_init(struct drm_device *dev, int engine)
139{
140 nv_wr32(dev, 0x00b32c, 0x00000000);
141 nv_wr32(dev, 0x00b314, 0x00000100);
142 nv_wr32(dev, 0x00b0e0, 0x0000001a);
143
144 nv_wr32(dev, 0x00b220, 0x00000044);
145 nv_wr32(dev, 0x00b300, 0x00801ec1);
146 nv_wr32(dev, 0x00b390, 0x00000000);
147 nv_wr32(dev, 0x00b394, 0x00000000);
148 nv_wr32(dev, 0x00b398, 0x00000000);
149 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000001);
150
151 nv_wr32(dev, 0x00b100, 0xffffffff);
152 nv_wr32(dev, 0x00b140, 0xffffffff);
153
154 if (!nv_wait(dev, 0x00b200, 0x00000001, 0x00000000)) {
155 NV_ERROR(dev, "PMPEG init: 0x%08x\n", nv_rd32(dev, 0x00b200));
156 return -EBUSY;
157 }
158
159 return 0;
160}
161
162static int
163nv50_mpeg_fini(struct drm_device *dev, int engine)
164{
165 /*XXX: context save for s/r */
166 nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
167 nv_wr32(dev, 0x00b140, 0x00000000);
168 return 0;
169}
170
171static void
172nv50_mpeg_isr(struct drm_device *dev)
173{
174 u32 stat = nv_rd32(dev, 0x00b100);
175 u32 type = nv_rd32(dev, 0x00b230);
176 u32 mthd = nv_rd32(dev, 0x00b234);
177 u32 data = nv_rd32(dev, 0x00b238);
178 u32 show = stat;
179
180 if (stat & 0x01000000) {
181 /* happens on initial binding of the object */
182 if (type == 0x00000020 && mthd == 0x0000) {
183 nv_wr32(dev, 0x00b308, 0x00000100);
184 show &= ~0x01000000;
185 }
186 }
187
188 if (show && nouveau_ratelimit()) {
189 NV_INFO(dev, "PMPEG - 0x%08x 0x%08x 0x%08x 0x%08x\n",
190 stat, type, mthd, data);
191 }
192
193 nv_wr32(dev, 0x00b100, stat);
194 nv_wr32(dev, 0x00b230, 0x00000001);
195 nv50_fb_vm_trap(dev, 1);
196}
197
198static void
199nv50_vpe_isr(struct drm_device *dev)
200{
201 if (nv_rd32(dev, 0x00b100))
202 nv50_mpeg_isr(dev);
203
204 if (nv_rd32(dev, 0x00b800)) {
205 u32 stat = nv_rd32(dev, 0x00b800);
206 NV_INFO(dev, "PMSRCH: 0x%08x\n", stat);
207 nv_wr32(dev, 0xb800, stat);
208 }
209}
210
211static void
212nv50_mpeg_destroy(struct drm_device *dev, int engine)
213{
214 struct nv50_mpeg_engine *pmpeg = nv_engine(dev, engine);
215
216 nouveau_irq_unregister(dev, 0);
217
218 NVOBJ_ENGINE_DEL(dev, MPEG);
219 kfree(pmpeg);
220}
221
222int
223nv50_mpeg_create(struct drm_device *dev)
224{
225 struct drm_nouveau_private *dev_priv = dev->dev_private;
226 struct nv50_mpeg_engine *pmpeg;
227
228 pmpeg = kzalloc(sizeof(*pmpeg), GFP_KERNEL);
229 if (!pmpeg)
230 return -ENOMEM;
231
232 pmpeg->base.destroy = nv50_mpeg_destroy;
233 pmpeg->base.init = nv50_mpeg_init;
234 pmpeg->base.fini = nv50_mpeg_fini;
235 pmpeg->base.context_new = nv50_mpeg_context_new;
236 pmpeg->base.context_del = nv50_mpeg_context_del;
237 pmpeg->base.object_new = nv50_mpeg_object_new;
238 pmpeg->base.tlb_flush = nv50_mpeg_tlb_flush;
239
240 if (dev_priv->chipset == 0x50) {
241 nouveau_irq_register(dev, 0, nv50_vpe_isr);
242 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
243 NVOBJ_CLASS(dev, 0x3174, MPEG);
244#if 0
245 NVOBJ_ENGINE_ADD(dev, ME, &pme->base);
246 NVOBJ_CLASS(dev, 0x4075, ME);
247#endif
248 } else {
249 nouveau_irq_register(dev, 0, nv50_mpeg_isr);
250 NVOBJ_ENGINE_ADD(dev, MPEG, &pmpeg->base);
251 NVOBJ_CLASS(dev, 0x8274, MPEG);
252 }
253
254 return 0;
255
256}
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 7dbb305d7e63..8a2810011bda 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -47,6 +47,21 @@ nv50_pm_clock_get(struct drm_device *dev, u32 id)
47 47
48 reg0 = nv_rd32(dev, pll.reg + 0); 48 reg0 = nv_rd32(dev, pll.reg + 0);
49 reg1 = nv_rd32(dev, pll.reg + 4); 49 reg1 = nv_rd32(dev, pll.reg + 4);
50
51 if ((reg0 & 0x80000000) == 0) {
52 if (id == PLL_SHADER) {
53 NV_DEBUG(dev, "Shader PLL is disabled. "
54 "Shader clock is twice the core\n");
55 ret = nv50_pm_clock_get(dev, PLL_CORE);
56 if (ret > 0)
57 return ret << 1;
58 } else if (id == PLL_MEMORY) {
59 NV_DEBUG(dev, "Memory PLL is disabled. "
60 "Memory clock is equal to the ref_clk\n");
61 return pll.refclk;
62 }
63 }
64
50 P = (reg0 & 0x00070000) >> 16; 65 P = (reg0 & 0x00070000) >> 16;
51 N = (reg1 & 0x0000ff00) >> 8; 66 N = (reg1 & 0x0000ff00) >> 8;
52 M = (reg1 & 0x000000ff); 67 M = (reg1 & 0x000000ff);
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 6c2694490741..1a0dd491a0e4 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -151,8 +151,7 @@ nv50_vm_flush(struct nouveau_vm *vm)
151 struct drm_nouveau_private *dev_priv = vm->dev->dev_private; 151 struct drm_nouveau_private *dev_priv = vm->dev->dev_private;
152 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 152 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
153 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 153 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
154 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 154 int i;
155 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt;
156 155
157 pinstmem->flush(vm->dev); 156 pinstmem->flush(vm->dev);
158 157
@@ -163,11 +162,10 @@ nv50_vm_flush(struct nouveau_vm *vm)
163 } 162 }
164 163
165 pfifo->tlb_flush(vm->dev); 164 pfifo->tlb_flush(vm->dev);
166 165 for (i = 0; i < NVOBJ_ENGINE_NR; i++) {
167 if (atomic_read(&vm->pgraph_refs)) 166 if (atomic_read(&vm->engref[i]))
168 pgraph->tlb_flush(vm->dev); 167 dev_priv->eng[i]->tlb_flush(vm->dev, i);
169 if (atomic_read(&vm->pcrypt_refs)) 168 }
170 pcrypt->tlb_flush(vm->dev);
171} 169}
172 170
173void 171void
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
index fabc7fd30b1d..75b809a51748 100644
--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -26,46 +26,48 @@
26#include "nouveau_drv.h" 26#include "nouveau_drv.h"
27#include "nouveau_util.h" 27#include "nouveau_util.h"
28#include "nouveau_vm.h" 28#include "nouveau_vm.h"
29#include "nouveau_ramht.h"
29 30
30static void nv84_crypt_isr(struct drm_device *); 31struct nv84_crypt_engine {
32 struct nouveau_exec_engine base;
33};
31 34
32int 35static int
33nv84_crypt_create_context(struct nouveau_channel *chan) 36nv84_crypt_context_new(struct nouveau_channel *chan, int engine)
34{ 37{
35 struct drm_device *dev = chan->dev; 38 struct drm_device *dev = chan->dev;
36 struct drm_nouveau_private *dev_priv = dev->dev_private; 39 struct drm_nouveau_private *dev_priv = dev->dev_private;
37 struct nouveau_gpuobj *ramin = chan->ramin; 40 struct nouveau_gpuobj *ramin = chan->ramin;
41 struct nouveau_gpuobj *ctx;
38 int ret; 42 int ret;
39 43
40 NV_DEBUG(dev, "ch%d\n", chan->id); 44 NV_DEBUG(dev, "ch%d\n", chan->id);
41 45
42 ret = nouveau_gpuobj_new(dev, chan, 256, 0, 46 ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
43 NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, 47 NVOBJ_FLAG_ZERO_FREE, &ctx);
44 &chan->crypt_ctx);
45 if (ret) 48 if (ret)
46 return ret; 49 return ret;
47 50
48 nv_wo32(ramin, 0xa0, 0x00190000); 51 nv_wo32(ramin, 0xa0, 0x00190000);
49 nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); 52 nv_wo32(ramin, 0xa4, ctx->vinst + ctx->size - 1);
50 nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); 53 nv_wo32(ramin, 0xa8, ctx->vinst);
51 nv_wo32(ramin, 0xac, 0); 54 nv_wo32(ramin, 0xac, 0);
52 nv_wo32(ramin, 0xb0, 0); 55 nv_wo32(ramin, 0xb0, 0);
53 nv_wo32(ramin, 0xb4, 0); 56 nv_wo32(ramin, 0xb4, 0);
54
55 dev_priv->engine.instmem.flush(dev); 57 dev_priv->engine.instmem.flush(dev);
56 atomic_inc(&chan->vm->pcrypt_refs); 58
59 atomic_inc(&chan->vm->engref[engine]);
60 chan->engctx[engine] = ctx;
57 return 0; 61 return 0;
58} 62}
59 63
60void 64static void
61nv84_crypt_destroy_context(struct nouveau_channel *chan) 65nv84_crypt_context_del(struct nouveau_channel *chan, int engine)
62{ 66{
67 struct nouveau_gpuobj *ctx = chan->engctx[engine];
63 struct drm_device *dev = chan->dev; 68 struct drm_device *dev = chan->dev;
64 u32 inst; 69 u32 inst;
65 70
66 if (!chan->crypt_ctx)
67 return;
68
69 inst = (chan->ramin->vinst >> 12); 71 inst = (chan->ramin->vinst >> 12);
70 inst |= 0x80000000; 72 inst |= 0x80000000;
71 73
@@ -80,43 +82,39 @@ nv84_crypt_destroy_context(struct nouveau_channel *chan)
80 nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); 82 nv_mask(dev, 0x10218c, 0x80000000, 0x00000000);
81 nv_wr32(dev, 0x10200c, 0x00000010); 83 nv_wr32(dev, 0x10200c, 0x00000010);
82 84
83 nouveau_gpuobj_ref(NULL, &chan->crypt_ctx); 85 nouveau_gpuobj_ref(NULL, &ctx);
84 atomic_dec(&chan->vm->pcrypt_refs);
85}
86 86
87void 87 atomic_dec(&chan->vm->engref[engine]);
88nv84_crypt_tlb_flush(struct drm_device *dev) 88 chan->engctx[engine] = NULL;
89{
90 nv50_vm_flush_engine(dev, 0x0a);
91} 89}
92 90
93int 91static int
94nv84_crypt_init(struct drm_device *dev) 92nv84_crypt_object_new(struct nouveau_channel *chan, int engine,
93 u32 handle, u16 class)
95{ 94{
95 struct drm_device *dev = chan->dev;
96 struct drm_nouveau_private *dev_priv = dev->dev_private; 96 struct drm_nouveau_private *dev_priv = dev->dev_private;
97 struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; 97 struct nouveau_gpuobj *obj = NULL;
98 98 int ret;
99 if (!pcrypt->registered) {
100 NVOBJ_CLASS(dev, 0x74c1, CRYPT);
101 pcrypt->registered = true;
102 }
103 99
104 nv_mask(dev, 0x000200, 0x00004000, 0x00000000); 100 ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
105 nv_mask(dev, 0x000200, 0x00004000, 0x00004000); 101 if (ret)
102 return ret;
103 obj->engine = 5;
104 obj->class = class;
106 105
107 nouveau_irq_register(dev, 14, nv84_crypt_isr); 106 nv_wo32(obj, 0x00, class);
108 nv_wr32(dev, 0x102130, 0xffffffff); 107 dev_priv->engine.instmem.flush(dev);
109 nv_wr32(dev, 0x102140, 0xffffffbf);
110 108
111 nv_wr32(dev, 0x10200c, 0x00000010); 109 ret = nouveau_ramht_insert(chan, handle, obj);
112 return 0; 110 nouveau_gpuobj_ref(NULL, &obj);
111 return ret;
113} 112}
114 113
115void 114static void
116nv84_crypt_fini(struct drm_device *dev) 115nv84_crypt_tlb_flush(struct drm_device *dev, int engine)
117{ 116{
118 nv_wr32(dev, 0x102140, 0x00000000); 117 nv50_vm_flush_engine(dev, 0x0a);
119 nouveau_irq_unregister(dev, 14);
120} 118}
121 119
122static void 120static void
@@ -138,3 +136,58 @@ nv84_crypt_isr(struct drm_device *dev)
138 136
139 nv50_fb_vm_trap(dev, show); 137 nv50_fb_vm_trap(dev, show);
140} 138}
139
140static int
141nv84_crypt_fini(struct drm_device *dev, int engine)
142{
143 nv_wr32(dev, 0x102140, 0x00000000);
144 return 0;
145}
146
147static int
148nv84_crypt_init(struct drm_device *dev, int engine)
149{
150 nv_mask(dev, 0x000200, 0x00004000, 0x00000000);
151 nv_mask(dev, 0x000200, 0x00004000, 0x00004000);
152
153 nv_wr32(dev, 0x102130, 0xffffffff);
154 nv_wr32(dev, 0x102140, 0xffffffbf);
155
156 nv_wr32(dev, 0x10200c, 0x00000010);
157 return 0;
158}
159
160static void
161nv84_crypt_destroy(struct drm_device *dev, int engine)
162{
163 struct nv84_crypt_engine *pcrypt = nv_engine(dev, engine);
164
165 NVOBJ_ENGINE_DEL(dev, CRYPT);
166
167 nouveau_irq_unregister(dev, 14);
168 kfree(pcrypt);
169}
170
171int
172nv84_crypt_create(struct drm_device *dev)
173{
174 struct nv84_crypt_engine *pcrypt;
175
176 pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL);
177 if (!pcrypt)
178 return -ENOMEM;
179
180 pcrypt->base.destroy = nv84_crypt_destroy;
181 pcrypt->base.init = nv84_crypt_init;
182 pcrypt->base.fini = nv84_crypt_fini;
183 pcrypt->base.context_new = nv84_crypt_context_new;
184 pcrypt->base.context_del = nv84_crypt_context_del;
185 pcrypt->base.object_new = nv84_crypt_object_new;
186 pcrypt->base.tlb_flush = nv84_crypt_tlb_flush;
187
188 nouveau_irq_register(dev, 14, nv84_crypt_isr);
189
190 NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base);
191 NVOBJ_CLASS (dev, 0x74c1, CRYPT);
192 return 0;
193}
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c
new file mode 100644
index 000000000000..b86820a61220
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.c
@@ -0,0 +1,226 @@
1/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <linux/firmware.h>
26#include "drmP.h"
27#include "nouveau_drv.h"
28#include "nouveau_util.h"
29#include "nouveau_vm.h"
30#include "nouveau_ramht.h"
31#include "nva3_copy.fuc.h"
32
33struct nva3_copy_engine {
34 struct nouveau_exec_engine base;
35};
36
37static int
38nva3_copy_context_new(struct nouveau_channel *chan, int engine)
39{
40 struct drm_device *dev = chan->dev;
41 struct drm_nouveau_private *dev_priv = dev->dev_private;
42 struct nouveau_gpuobj *ramin = chan->ramin;
43 struct nouveau_gpuobj *ctx = NULL;
44 int ret;
45
46 NV_DEBUG(dev, "ch%d\n", chan->id);
47
48 ret = nouveau_gpuobj_new(dev, chan, 256, 0, NVOBJ_FLAG_ZERO_ALLOC |
49 NVOBJ_FLAG_ZERO_FREE, &ctx);
50 if (ret)
51 return ret;
52
53 nv_wo32(ramin, 0xc0, 0x00190000);
54 nv_wo32(ramin, 0xc4, ctx->vinst + ctx->size - 1);
55 nv_wo32(ramin, 0xc8, ctx->vinst);
56 nv_wo32(ramin, 0xcc, 0x00000000);
57 nv_wo32(ramin, 0xd0, 0x00000000);
58 nv_wo32(ramin, 0xd4, 0x00000000);
59 dev_priv->engine.instmem.flush(dev);
60
61 atomic_inc(&chan->vm->engref[engine]);
62 chan->engctx[engine] = ctx;
63 return 0;
64}
65
66static int
67nva3_copy_object_new(struct nouveau_channel *chan, int engine,
68 u32 handle, u16 class)
69{
70 struct nouveau_gpuobj *ctx = chan->engctx[engine];
71
72 /* fuc engine doesn't need an object, our ramht code does.. */
73 ctx->engine = 3;
74 ctx->class = class;
75 return nouveau_ramht_insert(chan, handle, ctx);
76}
77
78static void
79nva3_copy_context_del(struct nouveau_channel *chan, int engine)
80{
81 struct nouveau_gpuobj *ctx = chan->engctx[engine];
82 struct drm_device *dev = chan->dev;
83 u32 inst;
84
85 inst = (chan->ramin->vinst >> 12);
86 inst |= 0x40000000;
87
88 /* disable fifo access */
89 nv_wr32(dev, 0x104048, 0x00000000);
90 /* mark channel as unloaded if it's currently active */
91 if (nv_rd32(dev, 0x104050) == inst)
92 nv_mask(dev, 0x104050, 0x40000000, 0x00000000);
93 /* mark next channel as invalid if it's about to be loaded */
94 if (nv_rd32(dev, 0x104054) == inst)
95 nv_mask(dev, 0x104054, 0x40000000, 0x00000000);
96 /* restore fifo access */
97 nv_wr32(dev, 0x104048, 0x00000003);
98
99 for (inst = 0xc0; inst <= 0xd4; inst += 4)
100 nv_wo32(chan->ramin, inst, 0x00000000);
101
102 nouveau_gpuobj_ref(NULL, &ctx);
103
104 atomic_dec(&chan->vm->engref[engine]);
105 chan->engctx[engine] = ctx;
106}
107
108static void
109nva3_copy_tlb_flush(struct drm_device *dev, int engine)
110{
111 nv50_vm_flush_engine(dev, 0x0d);
112}
113
114static int
115nva3_copy_init(struct drm_device *dev, int engine)
116{
117 int i;
118
119 nv_mask(dev, 0x000200, 0x00002000, 0x00000000);
120 nv_mask(dev, 0x000200, 0x00002000, 0x00002000);
121 nv_wr32(dev, 0x104014, 0xffffffff); /* disable all interrupts */
122
123 /* upload ucode */
124 nv_wr32(dev, 0x1041c0, 0x01000000);
125 for (i = 0; i < sizeof(nva3_pcopy_data) / 4; i++)
126 nv_wr32(dev, 0x1041c4, nva3_pcopy_data[i]);
127
128 nv_wr32(dev, 0x104180, 0x01000000);
129 for (i = 0; i < sizeof(nva3_pcopy_code) / 4; i++) {
130 if ((i & 0x3f) == 0)
131 nv_wr32(dev, 0x104188, i >> 6);
132 nv_wr32(dev, 0x104184, nva3_pcopy_code[i]);
133 }
134
135 /* start it running */
136 nv_wr32(dev, 0x10410c, 0x00000000);
137 nv_wr32(dev, 0x104104, 0x00000000); /* ENTRY */
138 nv_wr32(dev, 0x104100, 0x00000002); /* TRIGGER */
139 return 0;
140}
141
142static int
143nva3_copy_fini(struct drm_device *dev, int engine)
144{
145 nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
146
147 /* trigger fuc context unload */
148 nv_wait(dev, 0x104008, 0x0000000c, 0x00000000);
149 nv_mask(dev, 0x104054, 0x40000000, 0x00000000);
150 nv_wr32(dev, 0x104000, 0x00000008);
151 nv_wait(dev, 0x104008, 0x00000008, 0x00000000);
152
153 nv_wr32(dev, 0x104014, 0xffffffff);
154 return 0;
155}
156
157static struct nouveau_enum nva3_copy_isr_error_name[] = {
158 { 0x0001, "ILLEGAL_MTHD" },
159 { 0x0002, "INVALID_ENUM" },
160 { 0x0003, "INVALID_BITFIELD" },
161 {}
162};
163
164static void
165nva3_copy_isr(struct drm_device *dev)
166{
167 u32 dispatch = nv_rd32(dev, 0x10401c);
168 u32 stat = nv_rd32(dev, 0x104008) & dispatch & ~(dispatch >> 16);
169 u32 inst = nv_rd32(dev, 0x104050) & 0x3fffffff;
170 u32 ssta = nv_rd32(dev, 0x104040) & 0x0000ffff;
171 u32 addr = nv_rd32(dev, 0x104040) >> 16;
172 u32 mthd = (addr & 0x07ff) << 2;
173 u32 subc = (addr & 0x3800) >> 11;
174 u32 data = nv_rd32(dev, 0x104044);
175 int chid = nv50_graph_isr_chid(dev, inst);
176
177 if (stat & 0x00000040) {
178 NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
179 nouveau_enum_print(nva3_copy_isr_error_name, ssta);
180 printk("] ch %d [0x%08x] subc %d mthd 0x%04x data 0x%08x\n",
181 chid, inst, subc, mthd, data);
182 nv_wr32(dev, 0x104004, 0x00000040);
183 stat &= ~0x00000040;
184 }
185
186 if (stat) {
187 NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
188 nv_wr32(dev, 0x104004, stat);
189 }
190 nv50_fb_vm_trap(dev, 1);
191}
192
193static void
194nva3_copy_destroy(struct drm_device *dev, int engine)
195{
196 struct nva3_copy_engine *pcopy = nv_engine(dev, engine);
197
198 nouveau_irq_unregister(dev, 22);
199
200 NVOBJ_ENGINE_DEL(dev, COPY0);
201 kfree(pcopy);
202}
203
204int
205nva3_copy_create(struct drm_device *dev)
206{
207 struct nva3_copy_engine *pcopy;
208
209 pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
210 if (!pcopy)
211 return -ENOMEM;
212
213 pcopy->base.destroy = nva3_copy_destroy;
214 pcopy->base.init = nva3_copy_init;
215 pcopy->base.fini = nva3_copy_fini;
216 pcopy->base.context_new = nva3_copy_context_new;
217 pcopy->base.context_del = nva3_copy_context_del;
218 pcopy->base.object_new = nva3_copy_object_new;
219 pcopy->base.tlb_flush = nva3_copy_tlb_flush;
220
221 nouveau_irq_register(dev, 22, nva3_copy_isr);
222
223 NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
224 NVOBJ_CLASS(dev, 0x85b5, COPY0);
225 return 0;
226}
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc
new file mode 100644
index 000000000000..eaf35f8321ee
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc
@@ -0,0 +1,870 @@
1/* fuc microcode for copy engine on nva3- chipsets
2 *
3 * Copyright 2011 Red Hat Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors: Ben Skeggs
24 */
25
26/* To build for nva3:nvc0
27 * m4 -DNVA3 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nva3_copy.fuc.h
28 *
29 * To build for nvc0-
30 * m4 -DNVC0 nva3_copy.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_copy.fuc.h
31 */
32
33ifdef(`NVA3',
34.section nva3_pcopy_data,
35.section nvc0_pcopy_data
36)
37
38ctx_object: .b32 0
39ifdef(`NVA3',
40ctx_dma:
41ctx_dma_query: .b32 0
42ctx_dma_src: .b32 0
43ctx_dma_dst: .b32 0
44,)
45.equ ctx_dma_count 3
46ctx_query_address_high: .b32 0
47ctx_query_address_low: .b32 0
48ctx_query_counter: .b32 0
49ctx_src_address_high: .b32 0
50ctx_src_address_low: .b32 0
51ctx_src_pitch: .b32 0
52ctx_src_tile_mode: .b32 0
53ctx_src_xsize: .b32 0
54ctx_src_ysize: .b32 0
55ctx_src_zsize: .b32 0
56ctx_src_zoff: .b32 0
57ctx_src_xoff: .b32 0
58ctx_src_yoff: .b32 0
59ctx_src_cpp: .b32 0
60ctx_dst_address_high: .b32 0
61ctx_dst_address_low: .b32 0
62ctx_dst_pitch: .b32 0
63ctx_dst_tile_mode: .b32 0
64ctx_dst_xsize: .b32 0
65ctx_dst_ysize: .b32 0
66ctx_dst_zsize: .b32 0
67ctx_dst_zoff: .b32 0
68ctx_dst_xoff: .b32 0
69ctx_dst_yoff: .b32 0
70ctx_dst_cpp: .b32 0
71ctx_format: .b32 0
72ctx_swz_const0: .b32 0
73ctx_swz_const1: .b32 0
74ctx_xcnt: .b32 0
75ctx_ycnt: .b32 0
76.align 256
77
78dispatch_table:
79// mthd 0x0000, NAME
80.b16 0x000 1
81.b32 ctx_object ~0xffffffff
82// mthd 0x0100, NOP
83.b16 0x040 1
84.b32 0x00010000 + cmd_nop ~0xffffffff
85// mthd 0x0140, PM_TRIGGER
86.b16 0x050 1
87.b32 0x00010000 + cmd_pm_trigger ~0xffffffff
88ifdef(`NVA3', `
89// mthd 0x0180-0x018c, DMA_
90.b16 0x060 ctx_dma_count
91dispatch_dma:
92.b32 0x00010000 + cmd_dma ~0xffffffff
93.b32 0x00010000 + cmd_dma ~0xffffffff
94.b32 0x00010000 + cmd_dma ~0xffffffff
95',)
96// mthd 0x0200-0x0218, SRC_TILE
97.b16 0x80 7
98.b32 ctx_src_tile_mode ~0x00000fff
99.b32 ctx_src_xsize ~0x0007ffff
100.b32 ctx_src_ysize ~0x00001fff
101.b32 ctx_src_zsize ~0x000007ff
102.b32 ctx_src_zoff ~0x00000fff
103.b32 ctx_src_xoff ~0x0007ffff
104.b32 ctx_src_yoff ~0x00001fff
105// mthd 0x0220-0x0238, DST_TILE
106.b16 0x88 7
107.b32 ctx_dst_tile_mode ~0x00000fff
108.b32 ctx_dst_xsize ~0x0007ffff
109.b32 ctx_dst_ysize ~0x00001fff
110.b32 ctx_dst_zsize ~0x000007ff
111.b32 ctx_dst_zoff ~0x00000fff
112.b32 ctx_dst_xoff ~0x0007ffff
113.b32 ctx_dst_yoff ~0x00001fff
114// mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH
115.b16 0xc0 2
116.b32 0x00010000 + cmd_exec ~0xffffffff
117.b32 0x00010000 + cmd_wrcache_flush ~0xffffffff
118// mthd 0x030c-0x0340, various stuff
119.b16 0xc3 14
120.b32 ctx_src_address_high ~0x000000ff
121.b32 ctx_src_address_low ~0xfffffff0
122.b32 ctx_dst_address_high ~0x000000ff
123.b32 ctx_dst_address_low ~0xfffffff0
124.b32 ctx_src_pitch ~0x0007ffff
125.b32 ctx_dst_pitch ~0x0007ffff
126.b32 ctx_xcnt ~0x0000ffff
127.b32 ctx_ycnt ~0x00001fff
128.b32 ctx_format ~0x0333ffff
129.b32 ctx_swz_const0 ~0xffffffff
130.b32 ctx_swz_const1 ~0xffffffff
131.b32 ctx_query_address_high ~0x000000ff
132.b32 ctx_query_address_low ~0xffffffff
133.b32 ctx_query_counter ~0xffffffff
134.b16 0x800 0
135
136ifdef(`NVA3',
137.section nva3_pcopy_code,
138.section nvc0_pcopy_code
139)
140
141main:
142 clear b32 $r0
143 mov $sp $r0
144
145 // setup i0 handler and route fifo and ctxswitch to it
146 mov $r1 ih
147 mov $iv0 $r1
148 mov $r1 0x400
149 movw $r2 0xfff3
150 sethi $r2 0
151 iowr I[$r2 + 0x300] $r2
152
153 // enable interrupts
154 or $r2 0xc
155 iowr I[$r1] $r2
156 bset $flags ie0
157
158 // enable fifo access and context switching
159 mov $r1 0x1200
160 mov $r2 3
161 iowr I[$r1] $r2
162
163 // sleep forever, waking for interrupts
164 bset $flags $p0
165 spin:
166 sleep $p0
167 bra spin
168
169// i0 handler
170ih:
171 iord $r1 I[$r0 + 0x200]
172
173 and $r2 $r1 0x00000008
174 bra e ih_no_chsw
175 call chsw
176 ih_no_chsw:
177 and $r2 $r1 0x00000004
178 bra e ih_no_cmd
179 call dispatch
180
181 ih_no_cmd:
182 and $r1 $r1 0x0000000c
183 iowr I[$r0 + 0x100] $r1
184 iret
185
186// $p1 direction (0 = unload, 1 = load)
187// $r3 channel
188swctx:
189 mov $r4 0x7700
190 mov $xtargets $r4
191ifdef(`NVA3', `
192 // target 7 hardcoded to ctx dma object
193 mov $xdbase $r0
194', ` // NVC0
195 // read SCRATCH3 to decide if we are PCOPY0 or PCOPY1
196 mov $r4 0x2100
197 iord $r4 I[$r4 + 0]
198 and $r4 1
199 shl b32 $r4 4
200 add b32 $r4 0x30
201
202 // channel is in vram
203 mov $r15 0x61c
204 shl b32 $r15 6
205 mov $r5 0x114
206 iowrs I[$r15] $r5
207
208 // read 16-byte PCOPYn info, containing context pointer, from channel
209 shl b32 $r5 $r3 4
210 add b32 $r5 2
211 mov $xdbase $r5
212 mov $r5 $sp
213 // get a chunk of stack space, aligned to 256 byte boundary
214 sub b32 $r5 0x100
215 mov $r6 0xff
216 not b32 $r6
217 and $r5 $r6
218 sethi $r5 0x00020000
219 xdld $r4 $r5
220 xdwait
221 sethi $r5 0
222
223 // set context pointer, from within channel VM
224 mov $r14 0
225 iowrs I[$r15] $r14
226 ld b32 $r4 D[$r5 + 0]
227 shr b32 $r4 8
228 ld b32 $r6 D[$r5 + 4]
229 shl b32 $r6 24
230 or $r4 $r6
231 mov $xdbase $r4
232')
233 // 256-byte context, at start of data segment
234 mov b32 $r4 $r0
235 sethi $r4 0x60000
236
237 // swap!
238 bra $p1 swctx_load
239 xdst $r0 $r4
240 bra swctx_done
241 swctx_load:
242 xdld $r0 $r4
243 swctx_done:
244 xdwait
245 ret
246
247chsw:
248 // read current channel
249 mov $r2 0x1400
250 iord $r3 I[$r2]
251
252 // if it's active, unload it and return
253 xbit $r15 $r3 0x1e
254 bra e chsw_no_unload
255 bclr $flags $p1
256 call swctx
257 bclr $r3 0x1e
258 iowr I[$r2] $r3
259 mov $r4 1
260 iowr I[$r2 + 0x200] $r4
261 ret
262
263 // read next channel
264 chsw_no_unload:
265 iord $r3 I[$r2 + 0x100]
266
267 // is there a channel waiting to be loaded?
268 xbit $r13 $r3 0x1e
269 bra e chsw_finish_load
270 bset $flags $p1
271 call swctx
272ifdef(`NVA3',
273 // load dma objects back into TARGET regs
274 mov $r5 ctx_dma
275 mov $r6 ctx_dma_count
276 chsw_load_ctx_dma:
277 ld b32 $r7 D[$r5 + $r6 * 4]
278 add b32 $r8 $r6 0x180
279 shl b32 $r8 8
280 iowr I[$r8] $r7
281 sub b32 $r6 1
282 bra nc chsw_load_ctx_dma
283,)
284
285 chsw_finish_load:
286 mov $r3 2
287 iowr I[$r2 + 0x200] $r3
288 ret
289
290dispatch:
291 // read incoming fifo command
292 mov $r3 0x1900
293 iord $r2 I[$r3 + 0x100]
294 iord $r3 I[$r3 + 0x000]
295 and $r4 $r2 0x7ff
296 // $r2 will be used to store exception data
297 shl b32 $r2 0x10
298
299 // lookup method in the dispatch table, ILLEGAL_MTHD if not found
300 mov $r5 dispatch_table
301 clear b32 $r6
302 clear b32 $r7
303 dispatch_loop:
304 ld b16 $r6 D[$r5 + 0]
305 ld b16 $r7 D[$r5 + 2]
306 add b32 $r5 4
307 cmpu b32 $r4 $r6
308 bra c dispatch_illegal_mthd
309 add b32 $r7 $r6
310 cmpu b32 $r4 $r7
311 bra c dispatch_valid_mthd
312 sub b32 $r7 $r6
313 shl b32 $r7 3
314 add b32 $r5 $r7
315 bra dispatch_loop
316
317 // ensure no bits set in reserved fields, INVALID_BITFIELD
318 dispatch_valid_mthd:
319 sub b32 $r4 $r6
320 shl b32 $r4 3
321 add b32 $r4 $r5
322 ld b32 $r5 D[$r4 + 4]
323 and $r5 $r3
324 cmpu b32 $r5 0
325 bra ne dispatch_invalid_bitfield
326
327 // depending on dispatch flags: execute method, or save data as state
328 ld b16 $r5 D[$r4 + 0]
329 ld b16 $r6 D[$r4 + 2]
330 cmpu b32 $r6 0
331 bra ne dispatch_cmd
332 st b32 D[$r5] $r3
333 bra dispatch_done
334 dispatch_cmd:
335 bclr $flags $p1
336 call $r5
337 bra $p1 dispatch_error
338 bra dispatch_done
339
340 dispatch_invalid_bitfield:
341 or $r2 2
342 dispatch_illegal_mthd:
343 or $r2 1
344
345 // store exception data in SCRATCH0/SCRATCH1, signal hostirq
346 dispatch_error:
347 mov $r4 0x1000
348 iowr I[$r4 + 0x000] $r2
349 iowr I[$r4 + 0x100] $r3
350 mov $r2 0x40
351 iowr I[$r0] $r2
352 hostirq_wait:
353 iord $r2 I[$r0 + 0x200]
354 and $r2 0x40
355 cmpu b32 $r2 0
356 bra ne hostirq_wait
357
358 dispatch_done:
359 mov $r2 0x1d00
360 mov $r3 1
361 iowr I[$r2] $r3
362 ret
363
364// No-operation
365//
366// Inputs:
367// $r1: irqh state
368// $r2: hostirq state
369// $r3: data
370// $r4: dispatch table entry
371// Outputs:
372// $r1: irqh state
373// $p1: set on error
374// $r2: hostirq state
375// $r3: data
376cmd_nop:
377 ret
378
379// PM_TRIGGER
380//
381// Inputs:
382// $r1: irqh state
383// $r2: hostirq state
384// $r3: data
385// $r4: dispatch table entry
386// Outputs:
387// $r1: irqh state
388// $p1: set on error
389// $r2: hostirq state
390// $r3: data
391cmd_pm_trigger:
392 mov $r2 0x2200
393 clear b32 $r3
394 sethi $r3 0x20000
395 iowr I[$r2] $r3
396 ret
397
398ifdef(`NVA3',
399// SET_DMA_* method handler
400//
401// Inputs:
402// $r1: irqh state
403// $r2: hostirq state
404// $r3: data
405// $r4: dispatch table entry
406// Outputs:
407// $r1: irqh state
408// $p1: set on error
409// $r2: hostirq state
410// $r3: data
411cmd_dma:
412 sub b32 $r4 dispatch_dma
413 shr b32 $r4 1
414 bset $r3 0x1e
415 st b32 D[$r4 + ctx_dma] $r3
416 add b32 $r4 0x600
417 shl b32 $r4 6
418 iowr I[$r4] $r3
419 ret
420,)
421
422// Calculates the hw swizzle mask and adjusts the surface's xcnt to match
423//
424cmd_exec_set_format:
425 // zero out a chunk of the stack to store the swizzle into
426 add $sp -0x10
427 st b32 D[$sp + 0x00] $r0
428 st b32 D[$sp + 0x04] $r0
429 st b32 D[$sp + 0x08] $r0
430 st b32 D[$sp + 0x0c] $r0
431
432 // extract cpp, src_ncomp and dst_ncomp from FORMAT
433 ld b32 $r4 D[$r0 + ctx_format]
434 extr $r5 $r4 16:17
435 add b32 $r5 1
436 extr $r6 $r4 20:21
437 add b32 $r6 1
438 extr $r7 $r4 24:25
439 add b32 $r7 1
440
441 // convert FORMAT swizzle mask to hw swizzle mask
442 bclr $flags $p2
443 clear b32 $r8
444 clear b32 $r9
445 ncomp_loop:
446 and $r10 $r4 0xf
447 shr b32 $r4 4
448 clear b32 $r11
449 bpc_loop:
450 cmpu b8 $r10 4
451 bra nc cmp_c0
452 mulu $r12 $r10 $r5
453 add b32 $r12 $r11
454 bset $flags $p2
455 bra bpc_next
456 cmp_c0:
457 bra ne cmp_c1
458 mov $r12 0x10
459 add b32 $r12 $r11
460 bra bpc_next
461 cmp_c1:
462 cmpu b8 $r10 6
463 bra nc cmp_zero
464 mov $r12 0x14
465 add b32 $r12 $r11
466 bra bpc_next
467 cmp_zero:
468 mov $r12 0x80
469 bpc_next:
470 st b8 D[$sp + $r8] $r12
471 add b32 $r8 1
472 add b32 $r11 1
473 cmpu b32 $r11 $r5
474 bra c bpc_loop
475 add b32 $r9 1
476 cmpu b32 $r9 $r7
477 bra c ncomp_loop
478
479 // SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang)
480 mulu $r6 $r5
481 st b32 D[$r0 + ctx_src_cpp] $r6
482 ld b32 $r8 D[$r0 + ctx_xcnt]
483 mulu $r6 $r8
484 bra $p2 dst_xcnt
485 clear b32 $r6
486
487 dst_xcnt:
488 mulu $r7 $r5
489 st b32 D[$r0 + ctx_dst_cpp] $r7
490 mulu $r7 $r8
491
492 mov $r5 0x810
493 shl b32 $r5 6
494 iowr I[$r5 + 0x000] $r6
495 iowr I[$r5 + 0x100] $r7
496 add b32 $r5 0x800
497 ld b32 $r6 D[$r0 + ctx_dst_cpp]
498 sub b32 $r6 1
499 shl b32 $r6 8
500 ld b32 $r7 D[$r0 + ctx_src_cpp]
501 sub b32 $r7 1
502 or $r6 $r7
503 iowr I[$r5 + 0x000] $r6
504 add b32 $r5 0x100
505 ld b32 $r6 D[$sp + 0x00]
506 iowr I[$r5 + 0x000] $r6
507 ld b32 $r6 D[$sp + 0x04]
508 iowr I[$r5 + 0x100] $r6
509 ld b32 $r6 D[$sp + 0x08]
510 iowr I[$r5 + 0x200] $r6
511 ld b32 $r6 D[$sp + 0x0c]
512 iowr I[$r5 + 0x300] $r6
513 add b32 $r5 0x400
514 ld b32 $r6 D[$r0 + ctx_swz_const0]
515 iowr I[$r5 + 0x000] $r6
516 ld b32 $r6 D[$r0 + ctx_swz_const1]
517 iowr I[$r5 + 0x100] $r6
518 add $sp 0x10
519 ret
520
521// Setup to handle a tiled surface
522//
523// Calculates a number of parameters the hardware requires in order
524// to correctly handle tiling.
525//
526// Offset calculation is performed as follows (Tp/Th/Td from TILE_MODE):
527// nTx = round_up(w * cpp, 1 << Tp) >> Tp
528// nTy = round_up(h, 1 << Th) >> Th
529// Txo = (x * cpp) & ((1 << Tp) - 1)
530// Tx = (x * cpp) >> Tp
531// Tyo = y & ((1 << Th) - 1)
532// Ty = y >> Th
533// Tzo = z & ((1 << Td) - 1)
534// Tz = z >> Td
535//
536// off = (Tzo << Tp << Th) + (Tyo << Tp) + Txo
537// off += ((Tz * nTy * nTx)) + (Ty * nTx) + Tx) << Td << Th << Tp;
538//
539// Inputs:
540// $r4: hw command (0x104800)
541// $r5: ctx offset adjustment for src/dst selection
542// $p2: set if dst surface
543//
544cmd_exec_set_surface_tiled:
545 // translate TILE_MODE into Tp, Th, Td shift values
546 ld b32 $r7 D[$r5 + ctx_src_tile_mode]
547 extr $r9 $r7 8:11
548 extr $r8 $r7 4:7
549ifdef(`NVA3',
550 add b32 $r8 2
551,
552 add b32 $r8 3
553)
554 extr $r7 $r7 0:3
555 cmp b32 $r7 0xe
556 bra ne xtile64
557 mov $r7 4
558 bra xtileok
559 xtile64:
560 xbit $r7 $flags $p2
561 add b32 $r7 17
562 bset $r4 $r7
563 mov $r7 6
564 xtileok:
565
566 // Op = (x * cpp) & ((1 << Tp) - 1)
567 // Tx = (x * cpp) >> Tp
568 ld b32 $r10 D[$r5 + ctx_src_xoff]
569 ld b32 $r11 D[$r5 + ctx_src_cpp]
570 mulu $r10 $r11
571 mov $r11 1
572 shl b32 $r11 $r7
573 sub b32 $r11 1
574 and $r12 $r10 $r11
575 shr b32 $r10 $r7
576
577 // Tyo = y & ((1 << Th) - 1)
578 // Ty = y >> Th
579 ld b32 $r13 D[$r5 + ctx_src_yoff]
580 mov $r14 1
581 shl b32 $r14 $r8
582 sub b32 $r14 1
583 and $r11 $r13 $r14
584 shr b32 $r13 $r8
585
586 // YTILE = ((1 << Th) << 12) | ((1 << Th) - Tyo)
587 add b32 $r14 1
588 shl b32 $r15 $r14 12
589 sub b32 $r14 $r11
590 or $r15 $r14
591 xbit $r6 $flags $p2
592 add b32 $r6 0x208
593 shl b32 $r6 8
594 iowr I[$r6 + 0x000] $r15
595
596 // Op += Tyo << Tp
597 shl b32 $r11 $r7
598 add b32 $r12 $r11
599
600 // nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp)
601 ld b32 $r15 D[$r5 + ctx_src_xsize]
602 ld b32 $r11 D[$r5 + ctx_src_cpp]
603 mulu $r15 $r11
604 mov $r11 1
605 shl b32 $r11 $r7
606 sub b32 $r11 1
607 add b32 $r15 $r11
608 shr b32 $r15 $r7
609 push $r15
610
611 // nTy = (h + ((1 << Th) - 1)) >> Th
612 ld b32 $r15 D[$r5 + ctx_src_ysize]
613 mov $r11 1
614 shl b32 $r11 $r8
615 sub b32 $r11 1
616 add b32 $r15 $r11
617 shr b32 $r15 $r8
618 push $r15
619
620 // Tys = Tp + Th
621 // CFG_YZ_TILE_SIZE = ((1 << Th) >> 2) << Td
622 add b32 $r7 $r8
623 sub b32 $r8 2
624 mov $r11 1
625 shl b32 $r11 $r8
626 shl b32 $r11 $r9
627
628 // Tzo = z & ((1 << Td) - 1)
629 // Tz = z >> Td
630 // Op += Tzo << Tys
631 // Ts = Tys + Td
632 ld b32 $r8 D[$r5 + ctx_src_zoff]
633 mov $r14 1
634 shl b32 $r14 $r9
635 sub b32 $r14 1
636 and $r15 $r8 $r14
637 shl b32 $r15 $r7
638 add b32 $r12 $r15
639 add b32 $r7 $r9
640 shr b32 $r8 $r9
641
642 // Ot = ((Tz * nTy * nTx) + (Ty * nTx) + Tx) << Ts
643 pop $r15
644 pop $r9
645 mulu $r13 $r9
646 add b32 $r10 $r13
647 mulu $r8 $r9
648 mulu $r8 $r15
649 add b32 $r10 $r8
650 shl b32 $r10 $r7
651
652 // PITCH = (nTx - 1) << Ts
653 sub b32 $r9 1
654 shl b32 $r9 $r7
655 iowr I[$r6 + 0x200] $r9
656
657 // SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff
658 // CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16
659 ld b32 $r7 D[$r5 + ctx_src_address_low]
660 ld b32 $r8 D[$r5 + ctx_src_address_high]
661 add b32 $r10 $r12
662 add b32 $r7 $r10
663 adc b32 $r8 0
664 shl b32 $r8 16
665 or $r8 $r11
666 sub b32 $r6 0x600
667 iowr I[$r6 + 0x000] $r7
668 add b32 $r6 0x400
669 iowr I[$r6 + 0x000] $r8
670 ret
671
672// Setup to handle a linear surface
673//
674// Nothing to see here.. Sets ADDRESS and PITCH, pretty non-exciting
675//
676cmd_exec_set_surface_linear:
677 xbit $r6 $flags $p2
678 add b32 $r6 0x202
679 shl b32 $r6 8
680 ld b32 $r7 D[$r5 + ctx_src_address_low]
681 iowr I[$r6 + 0x000] $r7
682 add b32 $r6 0x400
683 ld b32 $r7 D[$r5 + ctx_src_address_high]
684 shl b32 $r7 16
685 iowr I[$r6 + 0x000] $r7
686 add b32 $r6 0x400
687 ld b32 $r7 D[$r5 + ctx_src_pitch]
688 iowr I[$r6 + 0x000] $r7
689 ret
690
691// wait for regs to be available for use
692cmd_exec_wait:
693 push $r0
694 push $r1
695 mov $r0 0x800
696 shl b32 $r0 6
697 loop:
698 iord $r1 I[$r0]
699 and $r1 1
700 bra ne loop
701 pop $r1
702 pop $r0
703 ret
704
705cmd_exec_query:
706 // if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI }
707 xbit $r4 $r3 13
708 bra ne query_counter
709 call cmd_exec_wait
710 mov $r4 0x80c
711 shl b32 $r4 6
712 ld b32 $r5 D[$r0 + ctx_query_address_low]
713 add b32 $r5 4
714 iowr I[$r4 + 0x000] $r5
715 iowr I[$r4 + 0x100] $r0
716 mov $r5 0xc
717 iowr I[$r4 + 0x200] $r5
718 add b32 $r4 0x400
719 ld b32 $r5 D[$r0 + ctx_query_address_high]
720 shl b32 $r5 16
721 iowr I[$r4 + 0x000] $r5
722 add b32 $r4 0x500
723 mov $r5 0x00000b00
724 sethi $r5 0x00010000
725 iowr I[$r4 + 0x000] $r5
726 mov $r5 0x00004040
727 shl b32 $r5 1
728 sethi $r5 0x80800000
729 iowr I[$r4 + 0x100] $r5
730 mov $r5 0x00001110
731 sethi $r5 0x13120000
732 iowr I[$r4 + 0x200] $r5
733 mov $r5 0x00001514
734 sethi $r5 0x17160000
735 iowr I[$r4 + 0x300] $r5
736 mov $r5 0x00002601
737 sethi $r5 0x00010000
738 mov $r4 0x800
739 shl b32 $r4 6
740 iowr I[$r4 + 0x000] $r5
741
742 // write COUNTER
743 query_counter:
744 call cmd_exec_wait
745 mov $r4 0x80c
746 shl b32 $r4 6
747 ld b32 $r5 D[$r0 + ctx_query_address_low]
748 iowr I[$r4 + 0x000] $r5
749 iowr I[$r4 + 0x100] $r0
750 mov $r5 0x4
751 iowr I[$r4 + 0x200] $r5
752 add b32 $r4 0x400
753 ld b32 $r5 D[$r0 + ctx_query_address_high]
754 shl b32 $r5 16
755 iowr I[$r4 + 0x000] $r5
756 add b32 $r4 0x500
757 mov $r5 0x00000300
758 iowr I[$r4 + 0x000] $r5
759 mov $r5 0x00001110
760 sethi $r5 0x13120000
761 iowr I[$r4 + 0x100] $r5
762 ld b32 $r5 D[$r0 + ctx_query_counter]
763 add b32 $r4 0x500
764 iowr I[$r4 + 0x000] $r5
765 mov $r5 0x00002601
766 sethi $r5 0x00010000
767 mov $r4 0x800
768 shl b32 $r4 6
769 iowr I[$r4 + 0x000] $r5
770 ret
771
772// Execute a copy operation
773//
774// Inputs:
775// $r1: irqh state
776// $r2: hostirq state
777// $r3: data
778// 000002000 QUERY_SHORT
779// 000001000 QUERY
780// 000000100 DST_LINEAR
781// 000000010 SRC_LINEAR
782// 000000001 FORMAT
783// $r4: dispatch table entry
784// Outputs:
785// $r1: irqh state
786// $p1: set on error
787// $r2: hostirq state
788// $r3: data
789cmd_exec:
790 call cmd_exec_wait
791
792 // if format requested, call function to calculate it, otherwise
793 // fill in cpp/xcnt for both surfaces as if (cpp == 1)
794 xbit $r15 $r3 0
795 bra e cmd_exec_no_format
796 call cmd_exec_set_format
797 mov $r4 0x200
798 bra cmd_exec_init_src_surface
799 cmd_exec_no_format:
800 mov $r6 0x810
801 shl b32 $r6 6
802 mov $r7 1
803 st b32 D[$r0 + ctx_src_cpp] $r7
804 st b32 D[$r0 + ctx_dst_cpp] $r7
805 ld b32 $r7 D[$r0 + ctx_xcnt]
806 iowr I[$r6 + 0x000] $r7
807 iowr I[$r6 + 0x100] $r7
808 clear b32 $r4
809
810 cmd_exec_init_src_surface:
811 bclr $flags $p2
812 clear b32 $r5
813 xbit $r15 $r3 4
814 bra e src_tiled
815 call cmd_exec_set_surface_linear
816 bra cmd_exec_init_dst_surface
817 src_tiled:
818 call cmd_exec_set_surface_tiled
819 bset $r4 7
820
821 cmd_exec_init_dst_surface:
822 bset $flags $p2
823 mov $r5 ctx_dst_address_high - ctx_src_address_high
824 xbit $r15 $r3 8
825 bra e dst_tiled
826 call cmd_exec_set_surface_linear
827 bra cmd_exec_kick
828 dst_tiled:
829 call cmd_exec_set_surface_tiled
830 bset $r4 8
831
832 cmd_exec_kick:
833 mov $r5 0x800
834 shl b32 $r5 6
835 ld b32 $r6 D[$r0 + ctx_ycnt]
836 iowr I[$r5 + 0x100] $r6
837 mov $r6 0x0041
838 // SRC_TARGET = 1, DST_TARGET = 2
839 sethi $r6 0x44000000
840 or $r4 $r6
841 iowr I[$r5] $r4
842
843 // if requested, queue up a QUERY write after the copy has completed
844 xbit $r15 $r3 12
845 bra e cmd_exec_done
846 call cmd_exec_query
847
848 cmd_exec_done:
849 ret
850
851// Flush write cache
852//
853// Inputs:
854// $r1: irqh state
855// $r2: hostirq state
856// $r3: data
857// $r4: dispatch table entry
858// Outputs:
859// $r1: irqh state
860// $p1: set on error
861// $r2: hostirq state
862// $r3: data
863cmd_wrcache_flush:
864 mov $r2 0x2200
865 clear b32 $r3
866 sethi $r3 0x10000
867 iowr I[$r2] $r3
868 ret
869
870.align 0x100
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h
new file mode 100644
index 000000000000..2731de22ebe9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h
@@ -0,0 +1,534 @@
1uint32_t nva3_pcopy_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29 0x00000000,
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57 0x00000000,
58 0x00000000,
59 0x00000000,
60 0x00000000,
61 0x00000000,
62 0x00000000,
63 0x00000000,
64 0x00000000,
65 0x00000000,
66 0x00010000,
67 0x00000000,
68 0x00000000,
69 0x00010040,
70 0x00010160,
71 0x00000000,
72 0x00010050,
73 0x00010162,
74 0x00000000,
75 0x00030060,
76 0x00010170,
77 0x00000000,
78 0x00010170,
79 0x00000000,
80 0x00010170,
81 0x00000000,
82 0x00070080,
83 0x00000028,
84 0xfffff000,
85 0x0000002c,
86 0xfff80000,
87 0x00000030,
88 0xffffe000,
89 0x00000034,
90 0xfffff800,
91 0x00000038,
92 0xfffff000,
93 0x0000003c,
94 0xfff80000,
95 0x00000040,
96 0xffffe000,
97 0x00070088,
98 0x00000054,
99 0xfffff000,
100 0x00000058,
101 0xfff80000,
102 0x0000005c,
103 0xffffe000,
104 0x00000060,
105 0xfffff800,
106 0x00000064,
107 0xfffff000,
108 0x00000068,
109 0xfff80000,
110 0x0000006c,
111 0xffffe000,
112 0x000200c0,
113 0x00010492,
114 0x00000000,
115 0x0001051b,
116 0x00000000,
117 0x000e00c3,
118 0x0000001c,
119 0xffffff00,
120 0x00000020,
121 0x0000000f,
122 0x00000048,
123 0xffffff00,
124 0x0000004c,
125 0x0000000f,
126 0x00000024,
127 0xfff80000,
128 0x00000050,
129 0xfff80000,
130 0x00000080,
131 0xffff0000,
132 0x00000084,
133 0xffffe000,
134 0x00000074,
135 0xfccc0000,
136 0x00000078,
137 0x00000000,
138 0x0000007c,
139 0x00000000,
140 0x00000010,
141 0xffffff00,
142 0x00000014,
143 0x00000000,
144 0x00000018,
145 0x00000000,
146 0x00000800,
147};
148
149uint32_t nva3_pcopy_code[] = {
150 0x04fe04bd,
151 0x3517f000,
152 0xf10010fe,
153 0xf1040017,
154 0xf0fff327,
155 0x22d00023,
156 0x0c25f0c0,
157 0xf40012d0,
158 0x17f11031,
159 0x27f01200,
160 0x0012d003,
161 0xf40031f4,
162 0x0ef40028,
163 0x8001cffd,
164 0xf40812c4,
165 0x21f4060b,
166 0x0412c472,
167 0xf4060bf4,
168 0x11c4c321,
169 0x4001d00c,
170 0x47f101f8,
171 0x4bfe7700,
172 0x0007fe00,
173 0xf00204b9,
174 0x01f40643,
175 0x0604fa09,
176 0xfa060ef4,
177 0x03f80504,
178 0x27f100f8,
179 0x23cf1400,
180 0x1e3fc800,
181 0xf4170bf4,
182 0x21f40132,
183 0x1e3af052,
184 0xf00023d0,
185 0x24d00147,
186 0xcf00f880,
187 0x3dc84023,
188 0x220bf41e,
189 0xf40131f4,
190 0x57f05221,
191 0x0367f004,
192 0xa07856bc,
193 0xb6018068,
194 0x87d00884,
195 0x0162b600,
196 0xf0f018f4,
197 0x23d00237,
198 0xf100f880,
199 0xcf190037,
200 0x33cf4032,
201 0xff24e400,
202 0x1024b607,
203 0x010057f1,
204 0x74bd64bd,
205 0x58005658,
206 0x50b60157,
207 0x0446b804,
208 0xbb4d08f4,
209 0x47b80076,
210 0x0f08f404,
211 0xb60276bb,
212 0x57bb0374,
213 0xdf0ef400,
214 0xb60246bb,
215 0x45bb0344,
216 0x01459800,
217 0xb00453fd,
218 0x1bf40054,
219 0x00455820,
220 0xb0014658,
221 0x1bf40064,
222 0x00538009,
223 0xf4300ef4,
224 0x55f90132,
225 0xf40c01f4,
226 0x25f0250e,
227 0x0125f002,
228 0x100047f1,
229 0xd00042d0,
230 0x27f04043,
231 0x0002d040,
232 0xf08002cf,
233 0x24b04024,
234 0xf71bf400,
235 0x1d0027f1,
236 0xd00137f0,
237 0x00f80023,
238 0x27f100f8,
239 0x34bd2200,
240 0xd00233f0,
241 0x00f80023,
242 0x012842b7,
243 0xf00145b6,
244 0x43801e39,
245 0x0040b701,
246 0x0644b606,
247 0xf80043d0,
248 0xf030f400,
249 0xb00001b0,
250 0x01b00101,
251 0x0301b002,
252 0xc71d0498,
253 0x50b63045,
254 0x3446c701,
255 0xc70160b6,
256 0x70b63847,
257 0x0232f401,
258 0x94bd84bd,
259 0xb60f4ac4,
260 0xb4bd0445,
261 0xf404a430,
262 0xa5ff0f18,
263 0x00cbbbc0,
264 0xf40231f4,
265 0x1bf4220e,
266 0x10c7f00c,
267 0xf400cbbb,
268 0xa430160e,
269 0x0c18f406,
270 0xbb14c7f0,
271 0x0ef400cb,
272 0x80c7f107,
273 0x01c83800,
274 0xb60180b6,
275 0xb5b801b0,
276 0xc308f404,
277 0xb80190b6,
278 0x08f40497,
279 0x0065fdb2,
280 0x98110680,
281 0x68fd2008,
282 0x0502f400,
283 0x75fd64bd,
284 0x1c078000,
285 0xf10078fd,
286 0xb6081057,
287 0x56d00654,
288 0x4057d000,
289 0x080050b7,
290 0xb61c0698,
291 0x64b60162,
292 0x11079808,
293 0xfd0172b6,
294 0x56d00567,
295 0x0050b700,
296 0x0060b401,
297 0xb40056d0,
298 0x56d00160,
299 0x0260b440,
300 0xb48056d0,
301 0x56d00360,
302 0x0050b7c0,
303 0x1e069804,
304 0x980056d0,
305 0x56d01f06,
306 0x1030f440,
307 0x579800f8,
308 0x6879c70a,
309 0xb66478c7,
310 0x77c70280,
311 0x0e76b060,
312 0xf0091bf4,
313 0x0ef40477,
314 0x027cf00f,
315 0xfd1170b6,
316 0x77f00947,
317 0x0f5a9806,
318 0xfd115b98,
319 0xb7f000ab,
320 0x04b7bb01,
321 0xff01b2b6,
322 0xa7bbc4ab,
323 0x105d9805,
324 0xbb01e7f0,
325 0xe2b604e8,
326 0xb4deff01,
327 0xb605d8bb,
328 0xef9401e0,
329 0x02ebbb0c,
330 0xf005fefd,
331 0x60b7026c,
332 0x64b60208,
333 0x006fd008,
334 0xbb04b7bb,
335 0x5f9800cb,
336 0x115b980b,
337 0xf000fbfd,
338 0xb7bb01b7,
339 0x01b2b604,
340 0xbb00fbbb,
341 0xf0f905f7,
342 0xf00c5f98,
343 0xb8bb01b7,
344 0x01b2b604,
345 0xbb00fbbb,
346 0xf0f905f8,
347 0xb60078bb,
348 0xb7f00282,
349 0x04b8bb01,
350 0x9804b9bb,
351 0xe7f00e58,
352 0x04e9bb01,
353 0xff01e2b6,
354 0xf7bbf48e,
355 0x00cfbb04,
356 0xbb0079bb,
357 0xf0fc0589,
358 0xd9fd90fc,
359 0x00adbb00,
360 0xfd0089fd,
361 0xa8bb008f,
362 0x04a7bb00,
363 0xbb0192b6,
364 0x69d00497,
365 0x08579880,
366 0xbb075898,
367 0x7abb00ac,
368 0x0081b600,
369 0xfd1084b6,
370 0x62b7058b,
371 0x67d00600,
372 0x0060b700,
373 0x0068d004,
374 0x6cf000f8,
375 0x0260b702,
376 0x0864b602,
377 0xd0085798,
378 0x60b70067,
379 0x57980400,
380 0x1074b607,
381 0xb70067d0,
382 0x98040060,
383 0x67d00957,
384 0xf900f800,
385 0xf110f900,
386 0xb6080007,
387 0x01cf0604,
388 0x0114f000,
389 0xfcfa1bf4,
390 0xf800fc10,
391 0x0d34c800,
392 0xf5701bf4,
393 0xf103ab21,
394 0xb6080c47,
395 0x05980644,
396 0x0450b605,
397 0xd00045d0,
398 0x57f04040,
399 0x8045d00c,
400 0x040040b7,
401 0xb6040598,
402 0x45d01054,
403 0x0040b700,
404 0x0057f105,
405 0x0153f00b,
406 0xf10045d0,
407 0xb6404057,
408 0x53f10154,
409 0x45d08080,
410 0x1057f140,
411 0x1253f111,
412 0x8045d013,
413 0x151457f1,
414 0x171653f1,
415 0xf1c045d0,
416 0xf0260157,
417 0x47f10153,
418 0x44b60800,
419 0x0045d006,
420 0x03ab21f5,
421 0x080c47f1,
422 0x980644b6,
423 0x45d00505,
424 0x4040d000,
425 0xd00457f0,
426 0x40b78045,
427 0x05980400,
428 0x1054b604,
429 0xb70045d0,
430 0xf1050040,
431 0xd0030057,
432 0x57f10045,
433 0x53f11110,
434 0x45d01312,
435 0x06059840,
436 0x050040b7,
437 0xf10045d0,
438 0xf0260157,
439 0x47f10153,
440 0x44b60800,
441 0x0045d006,
442 0x21f500f8,
443 0x3fc803ab,
444 0x0e0bf400,
445 0x018921f5,
446 0x020047f1,
447 0xf11e0ef4,
448 0xb6081067,
449 0x77f00664,
450 0x11078001,
451 0x981c0780,
452 0x67d02007,
453 0x4067d000,
454 0x32f444bd,
455 0xc854bd02,
456 0x0bf4043f,
457 0x8221f50a,
458 0x0a0ef403,
459 0x027621f5,
460 0xf40749f0,
461 0x57f00231,
462 0x083fc82c,
463 0xf50a0bf4,
464 0xf4038221,
465 0x21f50a0e,
466 0x49f00276,
467 0x0057f108,
468 0x0654b608,
469 0xd0210698,
470 0x67f04056,
471 0x0063f141,
472 0x0546fd44,
473 0xc80054d0,
474 0x0bf40c3f,
475 0xc521f507,
476 0xf100f803,
477 0xbd220027,
478 0x0133f034,
479 0xf80023d0,
480 0x00000000,
481 0x00000000,
482 0x00000000,
483 0x00000000,
484 0x00000000,
485 0x00000000,
486 0x00000000,
487 0x00000000,
488 0x00000000,
489 0x00000000,
490 0x00000000,
491 0x00000000,
492 0x00000000,
493 0x00000000,
494 0x00000000,
495 0x00000000,
496 0x00000000,
497 0x00000000,
498 0x00000000,
499 0x00000000,
500 0x00000000,
501 0x00000000,
502 0x00000000,
503 0x00000000,
504 0x00000000,
505 0x00000000,
506 0x00000000,
507 0x00000000,
508 0x00000000,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000,
514 0x00000000,
515 0x00000000,
516 0x00000000,
517 0x00000000,
518 0x00000000,
519 0x00000000,
520 0x00000000,
521 0x00000000,
522 0x00000000,
523 0x00000000,
524 0x00000000,
525 0x00000000,
526 0x00000000,
527 0x00000000,
528 0x00000000,
529 0x00000000,
530 0x00000000,
531 0x00000000,
532 0x00000000,
533 0x00000000,
534};
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index dbbafed36406..e4b2b9e934b2 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -27,32 +27,74 @@
27#include "nouveau_bios.h" 27#include "nouveau_bios.h"
28#include "nouveau_pm.h" 28#include "nouveau_pm.h"
29 29
30/*XXX: boards using limits 0x40 need fixing, the register layout 30/* This is actually a lot more complex than it appears here, but hopefully
31 * is correct here, but, there's some other funny magic 31 * this should be able to deal with what the VBIOS leaves for us..
32 * that modifies things, so it's not likely we'll set/read 32 *
33 * the correct timings yet.. working on it... 33 * If not, well, I'll jump off that bridge when I come to it.
34 */ 34 */
35 35
36struct nva3_pm_state { 36struct nva3_pm_state {
37 struct pll_lims pll; 37 enum pll_types type;
38 int N, M, P; 38 u32 src0;
39 u32 src1;
40 u32 ctrl;
41 u32 coef;
42 u32 old_pnm;
43 u32 new_pnm;
44 u32 new_div;
39}; 45};
40 46
47static int
48nva3_pm_pll_offset(u32 id)
49{
50 static const u32 pll_map[] = {
51 0x00, PLL_CORE,
52 0x01, PLL_SHADER,
53 0x02, PLL_MEMORY,
54 0x00, 0x00
55 };
56 const u32 *map = pll_map;
57
58 while (map[1]) {
59 if (id == map[1])
60 return map[0];
61 map += 2;
62 }
63
64 return -ENOENT;
65}
66
41int 67int
42nva3_pm_clock_get(struct drm_device *dev, u32 id) 68nva3_pm_clock_get(struct drm_device *dev, u32 id)
43{ 69{
70 u32 src0, src1, ctrl, coef;
44 struct pll_lims pll; 71 struct pll_lims pll;
45 int P, N, M, ret; 72 int ret, off;
46 u32 reg; 73 int P, N, M;
47 74
48 ret = get_pll_limits(dev, id, &pll); 75 ret = get_pll_limits(dev, id, &pll);
49 if (ret) 76 if (ret)
50 return ret; 77 return ret;
51 78
52 reg = nv_rd32(dev, pll.reg + 4); 79 off = nva3_pm_pll_offset(id);
53 P = (reg & 0x003f0000) >> 16; 80 if (off < 0)
54 N = (reg & 0x0000ff00) >> 8; 81 return off;
55 M = (reg & 0x000000ff); 82
83 src0 = nv_rd32(dev, 0x4120 + (off * 4));
84 src1 = nv_rd32(dev, 0x4160 + (off * 4));
85 ctrl = nv_rd32(dev, pll.reg + 0);
86 coef = nv_rd32(dev, pll.reg + 4);
87 NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
88 id, src0, src1, ctrl, coef);
89
90 if (ctrl & 0x00000008) {
91 u32 div = ((src1 & 0x003c0000) >> 18) + 1;
92 return (pll.refclk * 2) / div;
93 }
94
95 P = (coef & 0x003f0000) >> 16;
96 N = (coef & 0x0000ff00) >> 8;
97 M = (coef & 0x000000ff);
56 return pll.refclk * N / M / P; 98 return pll.refclk * N / M / P;
57} 99}
58 100
@@ -60,36 +102,103 @@ void *
60nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, 102nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
61 u32 id, int khz) 103 u32 id, int khz)
62{ 104{
63 struct nva3_pm_state *state; 105 struct nva3_pm_state *pll;
64 int dummy, ret; 106 struct pll_lims limits;
107 int N, M, P, diff;
108 int ret, off;
109
110 ret = get_pll_limits(dev, id, &limits);
111 if (ret < 0)
112 return (ret == -ENOENT) ? NULL : ERR_PTR(ret);
113
114 off = nva3_pm_pll_offset(id);
115 if (id < 0)
116 return ERR_PTR(-EINVAL);
65 117
66 state = kzalloc(sizeof(*state), GFP_KERNEL); 118
67 if (!state) 119 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
120 if (!pll)
68 return ERR_PTR(-ENOMEM); 121 return ERR_PTR(-ENOMEM);
122 pll->type = id;
123 pll->src0 = 0x004120 + (off * 4);
124 pll->src1 = 0x004160 + (off * 4);
125 pll->ctrl = limits.reg + 0;
126 pll->coef = limits.reg + 4;
69 127
70 ret = get_pll_limits(dev, id, &state->pll); 128 /* If target clock is within [-2, 3) MHz of a divisor, we'll
71 if (ret < 0) { 129 * use that instead of calculating MNP values
72 kfree(state); 130 */
73 return (ret == -ENOENT) ? NULL : ERR_PTR(ret); 131 pll->new_div = min((limits.refclk * 2) / (khz - 2999), 16);
132 if (pll->new_div) {
133 diff = khz - ((limits.refclk * 2) / pll->new_div);
134 if (diff < -2000 || diff >= 3000)
135 pll->new_div = 0;
74 } 136 }
75 137
76 ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, 138 if (!pll->new_div) {
77 &state->M, &state->P); 139 ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P);
78 if (ret < 0) { 140 if (ret < 0)
79 kfree(state); 141 return ERR_PTR(ret);
80 return ERR_PTR(ret); 142
143 pll->new_pnm = (P << 16) | (N << 8) | M;
144 pll->new_div = 2 - 1;
145 } else {
146 pll->new_pnm = 0;
147 pll->new_div--;
81 } 148 }
82 149
83 return state; 150 if ((nv_rd32(dev, pll->src1) & 0x00000101) != 0x00000101)
151 pll->old_pnm = nv_rd32(dev, pll->coef);
152 return pll;
84} 153}
85 154
86void 155void
87nva3_pm_clock_set(struct drm_device *dev, void *pre_state) 156nva3_pm_clock_set(struct drm_device *dev, void *pre_state)
88{ 157{
89 struct nva3_pm_state *state = pre_state; 158 struct nva3_pm_state *pll = pre_state;
90 u32 reg = state->pll.reg; 159 u32 ctrl = 0;
160
161 /* For the memory clock, NVIDIA will build a "script" describing
162 * the reclocking process and ask PDAEMON to execute it.
163 */
164 if (pll->type == PLL_MEMORY) {
165 nv_wr32(dev, 0x100210, 0);
166 nv_wr32(dev, 0x1002dc, 1);
167 nv_wr32(dev, 0x004018, 0x00001000);
168 ctrl = 0x18000100;
169 }
170
171 if (pll->old_pnm || !pll->new_pnm) {
172 nv_mask(dev, pll->src1, 0x003c0101, 0x00000101 |
173 (pll->new_div << 18));
174 nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
175 nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
176 }
177
178 if (pll->new_pnm) {
179 nv_mask(dev, pll->src0, 0x00000101, 0x00000101);
180 nv_wr32(dev, pll->coef, pll->new_pnm);
181 nv_wr32(dev, pll->ctrl, 0x0001001d | ctrl);
182 nv_mask(dev, pll->ctrl, 0x00000010, 0x00000000);
183 nv_mask(dev, pll->ctrl, 0x00020010, 0x00020010);
184 nv_wr32(dev, pll->ctrl, 0x00010015 | ctrl);
185 nv_mask(dev, pll->src1, 0x00000100, 0x00000000);
186 nv_mask(dev, pll->src1, 0x00000001, 0x00000000);
187 if (pll->type == PLL_MEMORY)
188 nv_wr32(dev, 0x4018, 0x10005000);
189 } else {
190 nv_mask(dev, pll->ctrl, 0x00000001, 0x00000000);
191 nv_mask(dev, pll->src0, 0x00000100, 0x00000000);
192 nv_mask(dev, pll->src0, 0x00000001, 0x00000000);
193 if (pll->type == PLL_MEMORY)
194 nv_wr32(dev, 0x4018, 0x1000d000);
195 }
196
197 if (pll->type == PLL_MEMORY) {
198 nv_wr32(dev, 0x1002dc, 0);
199 nv_wr32(dev, 0x100210, 0x80000000);
200 }
91 201
92 nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); 202 kfree(pll);
93 kfree(state);
94} 203}
95 204
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c
new file mode 100644
index 000000000000..208fa7ab3f42
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.c
@@ -0,0 +1,243 @@
1/*
2 * Copyright 2011 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include <linux/firmware.h>
26#include "drmP.h"
27#include "nouveau_drv.h"
28#include "nouveau_util.h"
29#include "nouveau_vm.h"
30#include "nouveau_ramht.h"
31#include "nvc0_copy.fuc.h"
32
33struct nvc0_copy_engine {
34 struct nouveau_exec_engine base;
35 u32 irq;
36 u32 pmc;
37 u32 fuc;
38 u32 ctx;
39};
40
41static int
42nvc0_copy_context_new(struct nouveau_channel *chan, int engine)
43{
44 struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
45 struct drm_device *dev = chan->dev;
46 struct drm_nouveau_private *dev_priv = dev->dev_private;
47 struct nouveau_gpuobj *ramin = chan->ramin;
48 struct nouveau_gpuobj *ctx = NULL;
49 int ret;
50
51 ret = nouveau_gpuobj_new(dev, NULL, 256, 256,
52 NVOBJ_FLAG_VM | NVOBJ_FLAG_VM_USER |
53 NVOBJ_FLAG_ZERO_ALLOC, &ctx);
54 if (ret)
55 return ret;
56
57 nv_wo32(ramin, pcopy->ctx + 0, lower_32_bits(ctx->vinst));
58 nv_wo32(ramin, pcopy->ctx + 4, upper_32_bits(ctx->vinst));
59 dev_priv->engine.instmem.flush(dev);
60
61 chan->engctx[engine] = ctx;
62 return 0;
63}
64
65static int
66nvc0_copy_object_new(struct nouveau_channel *chan, int engine,
67 u32 handle, u16 class)
68{
69 return 0;
70}
71
72static void
73nvc0_copy_context_del(struct nouveau_channel *chan, int engine)
74{
75 struct nvc0_copy_engine *pcopy = nv_engine(chan->dev, engine);
76 struct nouveau_gpuobj *ctx = chan->engctx[engine];
77 struct drm_device *dev = chan->dev;
78 u32 inst;
79
80 inst = (chan->ramin->vinst >> 12);
81 inst |= 0x40000000;
82
83 /* disable fifo access */
84 nv_wr32(dev, pcopy->fuc + 0x048, 0x00000000);
85 /* mark channel as unloaded if it's currently active */
86 if (nv_rd32(dev, pcopy->fuc + 0x050) == inst)
87 nv_mask(dev, pcopy->fuc + 0x050, 0x40000000, 0x00000000);
88 /* mark next channel as invalid if it's about to be loaded */
89 if (nv_rd32(dev, pcopy->fuc + 0x054) == inst)
90 nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
91 /* restore fifo access */
92 nv_wr32(dev, pcopy->fuc + 0x048, 0x00000003);
93
94 nv_wo32(chan->ramin, pcopy->ctx + 0, 0x00000000);
95 nv_wo32(chan->ramin, pcopy->ctx + 4, 0x00000000);
96 nouveau_gpuobj_ref(NULL, &ctx);
97
98 chan->engctx[engine] = ctx;
99}
100
101static int
102nvc0_copy_init(struct drm_device *dev, int engine)
103{
104 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
105 int i;
106
107 nv_mask(dev, 0x000200, pcopy->pmc, 0x00000000);
108 nv_mask(dev, 0x000200, pcopy->pmc, pcopy->pmc);
109 nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
110
111 nv_wr32(dev, pcopy->fuc + 0x1c0, 0x01000000);
112 for (i = 0; i < sizeof(nvc0_pcopy_data) / 4; i++)
113 nv_wr32(dev, pcopy->fuc + 0x1c4, nvc0_pcopy_data[i]);
114
115 nv_wr32(dev, pcopy->fuc + 0x180, 0x01000000);
116 for (i = 0; i < sizeof(nvc0_pcopy_code) / 4; i++) {
117 if ((i & 0x3f) == 0)
118 nv_wr32(dev, pcopy->fuc + 0x188, i >> 6);
119 nv_wr32(dev, pcopy->fuc + 0x184, nvc0_pcopy_code[i]);
120 }
121
122 nv_wr32(dev, pcopy->fuc + 0x084, engine - NVOBJ_ENGINE_COPY0);
123 nv_wr32(dev, pcopy->fuc + 0x10c, 0x00000000);
124 nv_wr32(dev, pcopy->fuc + 0x104, 0x00000000); /* ENTRY */
125 nv_wr32(dev, pcopy->fuc + 0x100, 0x00000002); /* TRIGGER */
126 return 0;
127}
128
129static int
130nvc0_copy_fini(struct drm_device *dev, int engine)
131{
132 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
133
134 nv_mask(dev, pcopy->fuc + 0x048, 0x00000003, 0x00000000);
135
136 /* trigger fuc context unload */
137 nv_wait(dev, pcopy->fuc + 0x008, 0x0000000c, 0x00000000);
138 nv_mask(dev, pcopy->fuc + 0x054, 0x40000000, 0x00000000);
139 nv_wr32(dev, pcopy->fuc + 0x000, 0x00000008);
140 nv_wait(dev, pcopy->fuc + 0x008, 0x00000008, 0x00000000);
141
142 nv_wr32(dev, pcopy->fuc + 0x014, 0xffffffff);
143 return 0;
144}
145
146static struct nouveau_enum nvc0_copy_isr_error_name[] = {
147 { 0x0001, "ILLEGAL_MTHD" },
148 { 0x0002, "INVALID_ENUM" },
149 { 0x0003, "INVALID_BITFIELD" },
150 {}
151};
152
153static void
154nvc0_copy_isr(struct drm_device *dev, int engine)
155{
156 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
157 u32 disp = nv_rd32(dev, pcopy->fuc + 0x01c);
158 u32 stat = nv_rd32(dev, pcopy->fuc + 0x008) & disp & ~(disp >> 16);
159 u64 inst = (u64)(nv_rd32(dev, pcopy->fuc + 0x050) & 0x0fffffff) << 12;
160 u32 chid = nvc0_graph_isr_chid(dev, inst);
161 u32 ssta = nv_rd32(dev, pcopy->fuc + 0x040) & 0x0000ffff;
162 u32 addr = nv_rd32(dev, pcopy->fuc + 0x040) >> 16;
163 u32 mthd = (addr & 0x07ff) << 2;
164 u32 subc = (addr & 0x3800) >> 11;
165 u32 data = nv_rd32(dev, pcopy->fuc + 0x044);
166
167 if (stat & 0x00000040) {
168 NV_INFO(dev, "PCOPY: DISPATCH_ERROR [");
169 nouveau_enum_print(nvc0_copy_isr_error_name, ssta);
170 printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n",
171 chid, inst, subc, mthd, data);
172 nv_wr32(dev, pcopy->fuc + 0x004, 0x00000040);
173 stat &= ~0x00000040;
174 }
175
176 if (stat) {
177 NV_INFO(dev, "PCOPY: unhandled intr 0x%08x\n", stat);
178 nv_wr32(dev, pcopy->fuc + 0x004, stat);
179 }
180}
181
182static void
183nvc0_copy_isr_0(struct drm_device *dev)
184{
185 nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY0);
186}
187
188static void
189nvc0_copy_isr_1(struct drm_device *dev)
190{
191 nvc0_copy_isr(dev, NVOBJ_ENGINE_COPY1);
192}
193
194static void
195nvc0_copy_destroy(struct drm_device *dev, int engine)
196{
197 struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
198
199 nouveau_irq_unregister(dev, pcopy->irq);
200
201 if (engine == NVOBJ_ENGINE_COPY0)
202 NVOBJ_ENGINE_DEL(dev, COPY0);
203 else
204 NVOBJ_ENGINE_DEL(dev, COPY1);
205 kfree(pcopy);
206}
207
208int
209nvc0_copy_create(struct drm_device *dev, int engine)
210{
211 struct nvc0_copy_engine *pcopy;
212
213 pcopy = kzalloc(sizeof(*pcopy), GFP_KERNEL);
214 if (!pcopy)
215 return -ENOMEM;
216
217 pcopy->base.destroy = nvc0_copy_destroy;
218 pcopy->base.init = nvc0_copy_init;
219 pcopy->base.fini = nvc0_copy_fini;
220 pcopy->base.context_new = nvc0_copy_context_new;
221 pcopy->base.context_del = nvc0_copy_context_del;
222 pcopy->base.object_new = nvc0_copy_object_new;
223
224 if (engine == 0) {
225 pcopy->irq = 5;
226 pcopy->pmc = 0x00000040;
227 pcopy->fuc = 0x104000;
228 pcopy->ctx = 0x0230;
229 nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_0);
230 NVOBJ_ENGINE_ADD(dev, COPY0, &pcopy->base);
231 NVOBJ_CLASS(dev, 0x90b5, COPY0);
232 } else {
233 pcopy->irq = 6;
234 pcopy->pmc = 0x00000080;
235 pcopy->fuc = 0x105000;
236 pcopy->ctx = 0x0240;
237 nouveau_irq_register(dev, pcopy->irq, nvc0_copy_isr_1);
238 NVOBJ_ENGINE_ADD(dev, COPY1, &pcopy->base);
239 NVOBJ_CLASS(dev, 0x90b8, COPY1);
240 }
241
242 return 0;
243}
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h
new file mode 100644
index 000000000000..419903880e9d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h
@@ -0,0 +1,527 @@
1uint32_t nvc0_pcopy_data[] = {
2 0x00000000,
3 0x00000000,
4 0x00000000,
5 0x00000000,
6 0x00000000,
7 0x00000000,
8 0x00000000,
9 0x00000000,
10 0x00000000,
11 0x00000000,
12 0x00000000,
13 0x00000000,
14 0x00000000,
15 0x00000000,
16 0x00000000,
17 0x00000000,
18 0x00000000,
19 0x00000000,
20 0x00000000,
21 0x00000000,
22 0x00000000,
23 0x00000000,
24 0x00000000,
25 0x00000000,
26 0x00000000,
27 0x00000000,
28 0x00000000,
29 0x00000000,
30 0x00000000,
31 0x00000000,
32 0x00000000,
33 0x00000000,
34 0x00000000,
35 0x00000000,
36 0x00000000,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 0x00000000,
54 0x00000000,
55 0x00000000,
56 0x00000000,
57 0x00000000,
58 0x00000000,
59 0x00000000,
60 0x00000000,
61 0x00000000,
62 0x00000000,
63 0x00000000,
64 0x00000000,
65 0x00000000,
66 0x00010000,
67 0x00000000,
68 0x00000000,
69 0x00010040,
70 0x0001019f,
71 0x00000000,
72 0x00010050,
73 0x000101a1,
74 0x00000000,
75 0x00070080,
76 0x0000001c,
77 0xfffff000,
78 0x00000020,
79 0xfff80000,
80 0x00000024,
81 0xffffe000,
82 0x00000028,
83 0xfffff800,
84 0x0000002c,
85 0xfffff000,
86 0x00000030,
87 0xfff80000,
88 0x00000034,
89 0xffffe000,
90 0x00070088,
91 0x00000048,
92 0xfffff000,
93 0x0000004c,
94 0xfff80000,
95 0x00000050,
96 0xffffe000,
97 0x00000054,
98 0xfffff800,
99 0x00000058,
100 0xfffff000,
101 0x0000005c,
102 0xfff80000,
103 0x00000060,
104 0xffffe000,
105 0x000200c0,
106 0x000104b8,
107 0x00000000,
108 0x00010541,
109 0x00000000,
110 0x000e00c3,
111 0x00000010,
112 0xffffff00,
113 0x00000014,
114 0x0000000f,
115 0x0000003c,
116 0xffffff00,
117 0x00000040,
118 0x0000000f,
119 0x00000018,
120 0xfff80000,
121 0x00000044,
122 0xfff80000,
123 0x00000074,
124 0xffff0000,
125 0x00000078,
126 0xffffe000,
127 0x00000068,
128 0xfccc0000,
129 0x0000006c,
130 0x00000000,
131 0x00000070,
132 0x00000000,
133 0x00000004,
134 0xffffff00,
135 0x00000008,
136 0x00000000,
137 0x0000000c,
138 0x00000000,
139 0x00000800,
140};
141
142uint32_t nvc0_pcopy_code[] = {
143 0x04fe04bd,
144 0x3517f000,
145 0xf10010fe,
146 0xf1040017,
147 0xf0fff327,
148 0x22d00023,
149 0x0c25f0c0,
150 0xf40012d0,
151 0x17f11031,
152 0x27f01200,
153 0x0012d003,
154 0xf40031f4,
155 0x0ef40028,
156 0x8001cffd,
157 0xf40812c4,
158 0x21f4060b,
159 0x0412c4ca,
160 0xf5070bf4,
161 0xc4010221,
162 0x01d00c11,
163 0xf101f840,
164 0xfe770047,
165 0x47f1004b,
166 0x44cf2100,
167 0x0144f000,
168 0xb60444b6,
169 0xf7f13040,
170 0xf4b6061c,
171 0x1457f106,
172 0x00f5d101,
173 0xb6043594,
174 0x57fe0250,
175 0x0145fe00,
176 0x010052b7,
177 0x00ff67f1,
178 0x56fd60bd,
179 0x0253f004,
180 0xf80545fa,
181 0x0053f003,
182 0xd100e7f0,
183 0x549800fe,
184 0x0845b600,
185 0xb6015698,
186 0x46fd1864,
187 0x0047fe05,
188 0xf00204b9,
189 0x01f40643,
190 0x0604fa09,
191 0xfa060ef4,
192 0x03f80504,
193 0x27f100f8,
194 0x23cf1400,
195 0x1e3fc800,
196 0xf4170bf4,
197 0x21f40132,
198 0x1e3af053,
199 0xf00023d0,
200 0x24d00147,
201 0xcf00f880,
202 0x3dc84023,
203 0x090bf41e,
204 0xf40131f4,
205 0x37f05321,
206 0x8023d002,
207 0x37f100f8,
208 0x32cf1900,
209 0x0033cf40,
210 0x07ff24e4,
211 0xf11024b6,
212 0xbd010057,
213 0x5874bd64,
214 0x57580056,
215 0x0450b601,
216 0xf40446b8,
217 0x76bb4d08,
218 0x0447b800,
219 0xbb0f08f4,
220 0x74b60276,
221 0x0057bb03,
222 0xbbdf0ef4,
223 0x44b60246,
224 0x0045bb03,
225 0xfd014598,
226 0x54b00453,
227 0x201bf400,
228 0x58004558,
229 0x64b00146,
230 0x091bf400,
231 0xf4005380,
232 0x32f4300e,
233 0xf455f901,
234 0x0ef40c01,
235 0x0225f025,
236 0xf10125f0,
237 0xd0100047,
238 0x43d00042,
239 0x4027f040,
240 0xcf0002d0,
241 0x24f08002,
242 0x0024b040,
243 0xf1f71bf4,
244 0xf01d0027,
245 0x23d00137,
246 0xf800f800,
247 0x0027f100,
248 0xf034bd22,
249 0x23d00233,
250 0xf400f800,
251 0x01b0f030,
252 0x0101b000,
253 0xb00201b0,
254 0x04980301,
255 0x3045c71a,
256 0xc70150b6,
257 0x60b63446,
258 0x3847c701,
259 0xf40170b6,
260 0x84bd0232,
261 0x4ac494bd,
262 0x0445b60f,
263 0xa430b4bd,
264 0x0f18f404,
265 0xbbc0a5ff,
266 0x31f400cb,
267 0x220ef402,
268 0xf00c1bf4,
269 0xcbbb10c7,
270 0x160ef400,
271 0xf406a430,
272 0xc7f00c18,
273 0x00cbbb14,
274 0xf1070ef4,
275 0x380080c7,
276 0x80b601c8,
277 0x01b0b601,
278 0xf404b5b8,
279 0x90b6c308,
280 0x0497b801,
281 0xfdb208f4,
282 0x06800065,
283 0x1d08980e,
284 0xf40068fd,
285 0x64bd0502,
286 0x800075fd,
287 0x78fd1907,
288 0x1057f100,
289 0x0654b608,
290 0xd00056d0,
291 0x50b74057,
292 0x06980800,
293 0x0162b619,
294 0x980864b6,
295 0x72b60e07,
296 0x0567fd01,
297 0xb70056d0,
298 0xb4010050,
299 0x56d00060,
300 0x0160b400,
301 0xb44056d0,
302 0x56d00260,
303 0x0360b480,
304 0xb7c056d0,
305 0x98040050,
306 0x56d01b06,
307 0x1c069800,
308 0xf44056d0,
309 0x00f81030,
310 0xc7075798,
311 0x78c76879,
312 0x0380b664,
313 0xb06077c7,
314 0x1bf40e76,
315 0x0477f009,
316 0xf00f0ef4,
317 0x70b6027c,
318 0x0947fd11,
319 0x980677f0,
320 0x5b980c5a,
321 0x00abfd0e,
322 0xbb01b7f0,
323 0xb2b604b7,
324 0xc4abff01,
325 0x9805a7bb,
326 0xe7f00d5d,
327 0x04e8bb01,
328 0xff01e2b6,
329 0xd8bbb4de,
330 0x01e0b605,
331 0xbb0cef94,
332 0xfefd02eb,
333 0x026cf005,
334 0x020860b7,
335 0xd00864b6,
336 0xb7bb006f,
337 0x00cbbb04,
338 0x98085f98,
339 0xfbfd0e5b,
340 0x01b7f000,
341 0xb604b7bb,
342 0xfbbb01b2,
343 0x05f7bb00,
344 0x5f98f0f9,
345 0x01b7f009,
346 0xb604b8bb,
347 0xfbbb01b2,
348 0x05f8bb00,
349 0x78bbf0f9,
350 0x0282b600,
351 0xbb01b7f0,
352 0xb9bb04b8,
353 0x0b589804,
354 0xbb01e7f0,
355 0xe2b604e9,
356 0xf48eff01,
357 0xbb04f7bb,
358 0x79bb00cf,
359 0x0589bb00,
360 0x90fcf0fc,
361 0xbb00d9fd,
362 0x89fd00ad,
363 0x008ffd00,
364 0xbb00a8bb,
365 0x92b604a7,
366 0x0497bb01,
367 0x988069d0,
368 0x58980557,
369 0x00acbb04,
370 0xb6007abb,
371 0x84b60081,
372 0x058bfd10,
373 0x060062b7,
374 0xb70067d0,
375 0xd0040060,
376 0x00f80068,
377 0xb7026cf0,
378 0xb6020260,
379 0x57980864,
380 0x0067d005,
381 0x040060b7,
382 0xb6045798,
383 0x67d01074,
384 0x0060b700,
385 0x06579804,
386 0xf80067d0,
387 0xf900f900,
388 0x0007f110,
389 0x0604b608,
390 0xf00001cf,
391 0x1bf40114,
392 0xfc10fcfa,
393 0xc800f800,
394 0x1bf40d34,
395 0xd121f570,
396 0x0c47f103,
397 0x0644b608,
398 0xb6020598,
399 0x45d00450,
400 0x4040d000,
401 0xd00c57f0,
402 0x40b78045,
403 0x05980400,
404 0x1054b601,
405 0xb70045d0,
406 0xf1050040,
407 0xf00b0057,
408 0x45d00153,
409 0x4057f100,
410 0x0154b640,
411 0x808053f1,
412 0xf14045d0,
413 0xf1111057,
414 0xd0131253,
415 0x57f18045,
416 0x53f11514,
417 0x45d01716,
418 0x0157f1c0,
419 0x0153f026,
420 0x080047f1,
421 0xd00644b6,
422 0x21f50045,
423 0x47f103d1,
424 0x44b6080c,
425 0x02059806,
426 0xd00045d0,
427 0x57f04040,
428 0x8045d004,
429 0x040040b7,
430 0xb6010598,
431 0x45d01054,
432 0x0040b700,
433 0x0057f105,
434 0x0045d003,
435 0x111057f1,
436 0x131253f1,
437 0x984045d0,
438 0x40b70305,
439 0x45d00500,
440 0x0157f100,
441 0x0153f026,
442 0x080047f1,
443 0xd00644b6,
444 0x00f80045,
445 0x03d121f5,
446 0xf4003fc8,
447 0x21f50e0b,
448 0x47f101af,
449 0x0ef40200,
450 0x1067f11e,
451 0x0664b608,
452 0x800177f0,
453 0x07800e07,
454 0x1d079819,
455 0xd00067d0,
456 0x44bd4067,
457 0xbd0232f4,
458 0x043fc854,
459 0xf50a0bf4,
460 0xf403a821,
461 0x21f50a0e,
462 0x49f0029c,
463 0x0231f407,
464 0xc82c57f0,
465 0x0bf4083f,
466 0xa821f50a,
467 0x0a0ef403,
468 0x029c21f5,
469 0xf10849f0,
470 0xb6080057,
471 0x06980654,
472 0x4056d01e,
473 0xf14167f0,
474 0xfd440063,
475 0x54d00546,
476 0x0c3fc800,
477 0xf5070bf4,
478 0xf803eb21,
479 0x0027f100,
480 0xf034bd22,
481 0x23d00133,
482 0x0000f800,
483 0x00000000,
484 0x00000000,
485 0x00000000,
486 0x00000000,
487 0x00000000,
488 0x00000000,
489 0x00000000,
490 0x00000000,
491 0x00000000,
492 0x00000000,
493 0x00000000,
494 0x00000000,
495 0x00000000,
496 0x00000000,
497 0x00000000,
498 0x00000000,
499 0x00000000,
500 0x00000000,
501 0x00000000,
502 0x00000000,
503 0x00000000,
504 0x00000000,
505 0x00000000,
506 0x00000000,
507 0x00000000,
508 0x00000000,
509 0x00000000,
510 0x00000000,
511 0x00000000,
512 0x00000000,
513 0x00000000,
514 0x00000000,
515 0x00000000,
516 0x00000000,
517 0x00000000,
518 0x00000000,
519 0x00000000,
520 0x00000000,
521 0x00000000,
522 0x00000000,
523 0x00000000,
524 0x00000000,
525 0x00000000,
526 0x00000000,
527};
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index 2886f2726a9e..fb4f5943e01b 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -37,7 +37,7 @@ struct nvc0_fifo_priv {
37}; 37};
38 38
39struct nvc0_fifo_chan { 39struct nvc0_fifo_chan {
40 struct nouveau_bo *user; 40 struct nouveau_gpuobj *user;
41 struct nouveau_gpuobj *ramfc; 41 struct nouveau_gpuobj *ramfc;
42}; 42};
43 43
@@ -106,7 +106,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 106 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
107 struct nvc0_fifo_priv *priv = pfifo->priv; 107 struct nvc0_fifo_priv *priv = pfifo->priv;
108 struct nvc0_fifo_chan *fifoch; 108 struct nvc0_fifo_chan *fifoch;
109 u64 ib_virt, user_vinst; 109 u64 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
110 int ret; 110 int ret;
111 111
112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL); 112 chan->fifo_priv = kzalloc(sizeof(*fifoch), GFP_KERNEL);
@@ -115,28 +115,13 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
115 fifoch = chan->fifo_priv; 115 fifoch = chan->fifo_priv;
116 116
117 /* allocate vram for control regs, map into polling area */ 117 /* allocate vram for control regs, map into polling area */
118 ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM, 118 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 0x1000,
119 0, 0, &fifoch->user); 119 NVOBJ_FLAG_ZERO_ALLOC, &fifoch->user);
120 if (ret) 120 if (ret)
121 goto error; 121 goto error;
122 122
123 ret = nouveau_bo_pin(fifoch->user, TTM_PL_FLAG_VRAM);
124 if (ret) {
125 nouveau_bo_ref(NULL, &fifoch->user);
126 goto error;
127 }
128
129 user_vinst = fifoch->user->bo.mem.start << PAGE_SHIFT;
130
131 ret = nouveau_bo_map(fifoch->user);
132 if (ret) {
133 nouveau_bo_unpin(fifoch->user);
134 nouveau_bo_ref(NULL, &fifoch->user);
135 goto error;
136 }
137
138 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000, 123 nouveau_vm_map_at(&priv->user_vma, chan->id * 0x1000,
139 fifoch->user->bo.mem.mm_node); 124 *(struct nouveau_mem **)fifoch->user->node);
140 125
141 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) + 126 chan->user = ioremap_wc(pci_resource_start(dev->pdev, 1) +
142 priv->user_vma.offset + (chan->id * 0x1000), 127 priv->user_vma.offset + (chan->id * 0x1000),
@@ -146,20 +131,6 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
146 goto error; 131 goto error;
147 } 132 }
148 133
149 ib_virt = chan->pushbuf_base + chan->dma.ib_base * 4;
150
151 /* zero channel regs */
152 nouveau_bo_wr32(fifoch->user, 0x0040/4, 0);
153 nouveau_bo_wr32(fifoch->user, 0x0044/4, 0);
154 nouveau_bo_wr32(fifoch->user, 0x0048/4, 0);
155 nouveau_bo_wr32(fifoch->user, 0x004c/4, 0);
156 nouveau_bo_wr32(fifoch->user, 0x0050/4, 0);
157 nouveau_bo_wr32(fifoch->user, 0x0058/4, 0);
158 nouveau_bo_wr32(fifoch->user, 0x005c/4, 0);
159 nouveau_bo_wr32(fifoch->user, 0x0060/4, 0);
160 nouveau_bo_wr32(fifoch->user, 0x0088/4, 0);
161 nouveau_bo_wr32(fifoch->user, 0x008c/4, 0);
162
163 /* ramfc */ 134 /* ramfc */
164 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst, 135 ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst,
165 chan->ramin->vinst, 0x100, 136 chan->ramin->vinst, 0x100,
@@ -167,8 +138,8 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
167 if (ret) 138 if (ret)
168 goto error; 139 goto error;
169 140
170 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(user_vinst)); 141 nv_wo32(fifoch->ramfc, 0x08, lower_32_bits(fifoch->user->vinst));
171 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(user_vinst)); 142 nv_wo32(fifoch->ramfc, 0x0c, upper_32_bits(fifoch->user->vinst));
172 nv_wo32(fifoch->ramfc, 0x10, 0x0000face); 143 nv_wo32(fifoch->ramfc, 0x10, 0x0000face);
173 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902); 144 nv_wo32(fifoch->ramfc, 0x30, 0xfffff902);
174 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt)); 145 nv_wo32(fifoch->ramfc, 0x48, lower_32_bits(ib_virt));
@@ -223,11 +194,7 @@ nvc0_fifo_destroy_context(struct nouveau_channel *chan)
223 return; 194 return;
224 195
225 nouveau_gpuobj_ref(NULL, &fifoch->ramfc); 196 nouveau_gpuobj_ref(NULL, &fifoch->ramfc);
226 if (fifoch->user) { 197 nouveau_gpuobj_ref(NULL, &fifoch->user);
227 nouveau_bo_unmap(fifoch->user);
228 nouveau_bo_unpin(fifoch->user);
229 nouveau_bo_ref(NULL, &fifoch->user);
230 }
231 kfree(fifoch); 198 kfree(fifoch);
232} 199}
233 200
@@ -240,6 +207,21 @@ nvc0_fifo_load_context(struct nouveau_channel *chan)
240int 207int
241nvc0_fifo_unload_context(struct drm_device *dev) 208nvc0_fifo_unload_context(struct drm_device *dev)
242{ 209{
210 int i;
211
212 for (i = 0; i < 128; i++) {
213 if (!(nv_rd32(dev, 0x003004 + (i * 4)) & 1))
214 continue;
215
216 nv_mask(dev, 0x003004 + (i * 4), 0x00000001, 0x00000000);
217 nv_wr32(dev, 0x002634, i);
218 if (!nv_wait(dev, 0x002634, 0xffffffff, i)) {
219 NV_INFO(dev, "PFIFO: kick ch %d failed: 0x%08x\n",
220 i, nv_rd32(dev, 0x002634));
221 return -EBUSY;
222 }
223 }
224
243 return 0; 225 return 0;
244} 226}
245 227
@@ -309,6 +291,7 @@ nvc0_fifo_init(struct drm_device *dev)
309{ 291{
310 struct drm_nouveau_private *dev_priv = dev->dev_private; 292 struct drm_nouveau_private *dev_priv = dev->dev_private;
311 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; 293 struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
294 struct nouveau_channel *chan;
312 struct nvc0_fifo_priv *priv; 295 struct nvc0_fifo_priv *priv;
313 int ret, i; 296 int ret, i;
314 297
@@ -351,23 +334,74 @@ nvc0_fifo_init(struct drm_device *dev)
351 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ 334 nv_wr32(dev, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */
352 nv_wr32(dev, 0x002100, 0xffffffff); 335 nv_wr32(dev, 0x002100, 0xffffffff);
353 nv_wr32(dev, 0x002140, 0xbfffffff); 336 nv_wr32(dev, 0x002140, 0xbfffffff);
337
338 /* restore PFIFO context table */
339 for (i = 0; i < 128; i++) {
340 chan = dev_priv->channels.ptr[i];
341 if (!chan || !chan->fifo_priv)
342 continue;
343
344 nv_wr32(dev, 0x003000 + (i * 8), 0xc0000000 |
345 (chan->ramin->vinst >> 12));
346 nv_wr32(dev, 0x003004 + (i * 8), 0x001f0001);
347 }
348 nvc0_fifo_playlist_update(dev);
349
354 return 0; 350 return 0;
355} 351}
356 352
357struct nouveau_enum nvc0_fifo_fault_unit[] = { 353struct nouveau_enum nvc0_fifo_fault_unit[] = {
358 { 0, "PGRAPH" }, 354 { 0x00, "PGRAPH" },
359 { 3, "PEEPHOLE" }, 355 { 0x03, "PEEPHOLE" },
360 { 4, "BAR1" }, 356 { 0x04, "BAR1" },
361 { 5, "BAR3" }, 357 { 0x05, "BAR3" },
362 { 7, "PFIFO" }, 358 { 0x07, "PFIFO" },
359 { 0x10, "PBSP" },
360 { 0x11, "PPPP" },
361 { 0x13, "PCOUNTER" },
362 { 0x14, "PVP" },
363 { 0x15, "PCOPY0" },
364 { 0x16, "PCOPY1" },
365 { 0x17, "PDAEMON" },
363 {} 366 {}
364}; 367};
365 368
366struct nouveau_enum nvc0_fifo_fault_reason[] = { 369struct nouveau_enum nvc0_fifo_fault_reason[] = {
367 { 0, "PT_NOT_PRESENT" }, 370 { 0x00, "PT_NOT_PRESENT" },
368 { 1, "PT_TOO_SHORT" }, 371 { 0x01, "PT_TOO_SHORT" },
369 { 2, "PAGE_NOT_PRESENT" }, 372 { 0x02, "PAGE_NOT_PRESENT" },
370 { 3, "VM_LIMIT_EXCEEDED" }, 373 { 0x03, "VM_LIMIT_EXCEEDED" },
374 { 0x04, "NO_CHANNEL" },
375 { 0x05, "PAGE_SYSTEM_ONLY" },
376 { 0x06, "PAGE_READ_ONLY" },
377 { 0x0a, "COMPRESSED_SYSRAM" },
378 { 0x0c, "INVALID_STORAGE_TYPE" },
379 {}
380};
381
382struct nouveau_enum nvc0_fifo_fault_hubclient[] = {
383 { 0x01, "PCOPY0" },
384 { 0x02, "PCOPY1" },
385 { 0x04, "DISPATCH" },
386 { 0x05, "CTXCTL" },
387 { 0x06, "PFIFO" },
388 { 0x07, "BAR_READ" },
389 { 0x08, "BAR_WRITE" },
390 { 0x0b, "PVP" },
391 { 0x0c, "PPPP" },
392 { 0x0d, "PBSP" },
393 { 0x11, "PCOUNTER" },
394 { 0x12, "PDAEMON" },
395 { 0x14, "CCACHE" },
396 { 0x15, "CCACHE_POST" },
397 {}
398};
399
400struct nouveau_enum nvc0_fifo_fault_gpcclient[] = {
401 { 0x01, "TEX" },
402 { 0x0c, "ESETUP" },
403 { 0x0e, "CTXCTL" },
404 { 0x0f, "PROP" },
371 {} 405 {}
372}; 406};
373 407
@@ -385,12 +419,20 @@ nvc0_fifo_isr_vm_fault(struct drm_device *dev, int unit)
385 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10)); 419 u32 valo = nv_rd32(dev, 0x2804 + (unit * 0x10));
386 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10)); 420 u32 vahi = nv_rd32(dev, 0x2808 + (unit * 0x10));
387 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10)); 421 u32 stat = nv_rd32(dev, 0x280c + (unit * 0x10));
422 u32 client = (stat & 0x00001f00) >> 8;
388 423
389 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [", 424 NV_INFO(dev, "PFIFO: %s fault at 0x%010llx [",
390 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); 425 (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo);
391 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); 426 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f);
392 printk("] from "); 427 printk("] from ");
393 nouveau_enum_print(nvc0_fifo_fault_unit, unit); 428 nouveau_enum_print(nvc0_fifo_fault_unit, unit);
429 if (stat & 0x00000040) {
430 printk("/");
431 nouveau_enum_print(nvc0_fifo_fault_hubclient, client);
432 } else {
433 printk("/GPC%d/", (stat & 0x1f000000) >> 24);
434 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client);
435 }
394 printk(" on channel 0x%010llx\n", (u64)inst << 12); 436 printk(" on channel 0x%010llx\n", (u64)inst << 12);
395} 437}
396 438
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
index 3de9b721d8db..ca6db204d644 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -30,27 +30,40 @@
30#include "nouveau_mm.h" 30#include "nouveau_mm.h"
31#include "nvc0_graph.h" 31#include "nvc0_graph.h"
32 32
33static void nvc0_graph_isr(struct drm_device *); 33static int
34static void nvc0_runk140_isr(struct drm_device *); 34nvc0_graph_load_context(struct nouveau_channel *chan)
35static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan);
36
37void
38nvc0_graph_fifo_access(struct drm_device *dev, bool enabled)
39{ 35{
36 struct drm_device *dev = chan->dev;
37
38 nv_wr32(dev, 0x409840, 0x00000030);
39 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
40 nv_wr32(dev, 0x409504, 0x00000003);
41 if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010))
42 NV_ERROR(dev, "PGRAPH: load_ctx timeout\n");
43
44 return 0;
40} 45}
41 46
42struct nouveau_channel * 47static int
43nvc0_graph_channel(struct drm_device *dev) 48nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan)
44{ 49{
45 return NULL; 50 nv_wr32(dev, 0x409840, 0x00000003);
51 nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12);
52 nv_wr32(dev, 0x409504, 0x00000009);
53 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) {
54 NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n");
55 return -EBUSY;
56 }
57
58 return 0;
46} 59}
47 60
48static int 61static int
49nvc0_graph_construct_context(struct nouveau_channel *chan) 62nvc0_graph_construct_context(struct nouveau_channel *chan)
50{ 63{
51 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 64 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
52 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; 65 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
53 struct nvc0_graph_chan *grch = chan->pgraph_ctx; 66 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
54 struct drm_device *dev = chan->dev; 67 struct drm_device *dev = chan->dev;
55 int ret, i; 68 int ret, i;
56 u32 *ctx; 69 u32 *ctx;
@@ -89,9 +102,8 @@ nvc0_graph_construct_context(struct nouveau_channel *chan)
89static int 102static int
90nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) 103nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
91{ 104{
92 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 105 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
93 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; 106 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
94 struct nvc0_graph_chan *grch = chan->pgraph_ctx;
95 struct drm_device *dev = chan->dev; 107 struct drm_device *dev = chan->dev;
96 int i = 0, gpc, tp, ret; 108 int i = 0, gpc, tp, ret;
97 u32 magic; 109 u32 magic;
@@ -158,29 +170,27 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
158 return 0; 170 return 0;
159} 171}
160 172
161int 173static int
162nvc0_graph_create_context(struct nouveau_channel *chan) 174nvc0_graph_context_new(struct nouveau_channel *chan, int engine)
163{ 175{
164 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 176 struct drm_device *dev = chan->dev;
177 struct drm_nouveau_private *dev_priv = dev->dev_private;
165 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; 178 struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
166 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; 179 struct nvc0_graph_priv *priv = nv_engine(dev, engine);
167 struct nvc0_graph_priv *priv = pgraph->priv;
168 struct nvc0_graph_chan *grch; 180 struct nvc0_graph_chan *grch;
169 struct drm_device *dev = chan->dev;
170 struct nouveau_gpuobj *grctx; 181 struct nouveau_gpuobj *grctx;
171 int ret, i; 182 int ret, i;
172 183
173 chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL); 184 grch = kzalloc(sizeof(*grch), GFP_KERNEL);
174 if (!chan->pgraph_ctx) 185 if (!grch)
175 return -ENOMEM; 186 return -ENOMEM;
176 grch = chan->pgraph_ctx; 187 chan->engctx[NVOBJ_ENGINE_GR] = grch;
177 188
178 ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, 189 ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256,
179 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, 190 NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC,
180 &grch->grctx); 191 &grch->grctx);
181 if (ret) 192 if (ret)
182 goto error; 193 goto error;
183 chan->ramin_grctx = grch->grctx;
184 grctx = grch->grctx; 194 grctx = grch->grctx;
185 195
186 ret = nvc0_graph_create_context_mmio_list(chan); 196 ret = nvc0_graph_create_context_mmio_list(chan);
@@ -200,104 +210,49 @@ nvc0_graph_create_context(struct nouveau_channel *chan)
200 for (i = 0; i < priv->grctx_size; i += 4) 210 for (i = 0; i < priv->grctx_size; i += 4)
201 nv_wo32(grctx, i, priv->grctx_vals[i / 4]); 211 nv_wo32(grctx, i, priv->grctx_vals[i / 4]);
202 212
203 nv_wo32(grctx, 0xf4, 0); 213 nv_wo32(grctx, 0xf4, 0);
204 nv_wo32(grctx, 0xf8, 0); 214 nv_wo32(grctx, 0xf8, 0);
205 nv_wo32(grctx, 0x10, grch->mmio_nr); 215 nv_wo32(grctx, 0x10, grch->mmio_nr);
206 nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst)); 216 nv_wo32(grctx, 0x14, lower_32_bits(grch->mmio->vinst));
207 nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst)); 217 nv_wo32(grctx, 0x18, upper_32_bits(grch->mmio->vinst));
208 nv_wo32(grctx, 0x1c, 1); 218 nv_wo32(grctx, 0x1c, 1);
209 nv_wo32(grctx, 0x20, 0); 219 nv_wo32(grctx, 0x20, 0);
210 nv_wo32(grctx, 0x28, 0); 220 nv_wo32(grctx, 0x28, 0);
211 nv_wo32(grctx, 0x2c, 0); 221 nv_wo32(grctx, 0x2c, 0);
212 pinstmem->flush(dev); 222 pinstmem->flush(dev);
213 return 0; 223 return 0;
214 224
215error: 225error:
216 pgraph->destroy_context(chan); 226 priv->base.context_del(chan, engine);
217 return ret; 227 return ret;
218} 228}
219 229
220void 230static void
221nvc0_graph_destroy_context(struct nouveau_channel *chan) 231nvc0_graph_context_del(struct nouveau_channel *chan, int engine)
222{ 232{
223 struct nvc0_graph_chan *grch; 233 struct nvc0_graph_chan *grch = chan->engctx[engine];
224
225 grch = chan->pgraph_ctx;
226 chan->pgraph_ctx = NULL;
227 if (!grch)
228 return;
229 234
230 nouveau_gpuobj_ref(NULL, &grch->mmio); 235 nouveau_gpuobj_ref(NULL, &grch->mmio);
231 nouveau_gpuobj_ref(NULL, &grch->unk418810); 236 nouveau_gpuobj_ref(NULL, &grch->unk418810);
232 nouveau_gpuobj_ref(NULL, &grch->unk40800c); 237 nouveau_gpuobj_ref(NULL, &grch->unk40800c);
233 nouveau_gpuobj_ref(NULL, &grch->unk408004); 238 nouveau_gpuobj_ref(NULL, &grch->unk408004);
234 nouveau_gpuobj_ref(NULL, &grch->grctx); 239 nouveau_gpuobj_ref(NULL, &grch->grctx);
235 chan->ramin_grctx = NULL; 240 chan->engctx[engine] = NULL;
236} 241}
237 242
238int 243static int
239nvc0_graph_load_context(struct nouveau_channel *chan) 244nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
245 u32 handle, u16 class)
240{ 246{
241 struct drm_device *dev = chan->dev;
242
243 nv_wr32(dev, 0x409840, 0x00000030);
244 nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12);
245 nv_wr32(dev, 0x409504, 0x00000003);
246 if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010))
247 NV_ERROR(dev, "PGRAPH: load_ctx timeout\n");
248
249 return 0; 247 return 0;
250} 248}
251 249
252static int 250static int
253nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) 251nvc0_graph_fini(struct drm_device *dev, int engine)
254{ 252{
255 nv_wr32(dev, 0x409840, 0x00000003);
256 nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12);
257 nv_wr32(dev, 0x409504, 0x00000009);
258 if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) {
259 NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n");
260 return -EBUSY;
261 }
262
263 return 0; 253 return 0;
264} 254}
265 255
266int
267nvc0_graph_unload_context(struct drm_device *dev)
268{
269 u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12;
270 return nvc0_graph_unload_context_to(dev, inst);
271}
272
273static void
274nvc0_graph_destroy(struct drm_device *dev)
275{
276 struct drm_nouveau_private *dev_priv = dev->dev_private;
277 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
278 struct nvc0_graph_priv *priv;
279
280 priv = pgraph->priv;
281 if (!priv)
282 return;
283
284 nouveau_irq_unregister(dev, 12);
285 nouveau_irq_unregister(dev, 25);
286
287 nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
288 nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
289
290 if (priv->grctx_vals)
291 kfree(priv->grctx_vals);
292 kfree(priv);
293}
294
295void
296nvc0_graph_takedown(struct drm_device *dev)
297{
298 nvc0_graph_destroy(dev);
299}
300
301static int 256static int
302nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, 257nvc0_graph_mthd_page_flip(struct nouveau_channel *chan,
303 u32 class, u32 mthd, u32 data) 258 u32 class, u32 mthd, u32 data)
@@ -306,119 +261,10 @@ nvc0_graph_mthd_page_flip(struct nouveau_channel *chan,
306 return 0; 261 return 0;
307} 262}
308 263
309static int
310nvc0_graph_create(struct drm_device *dev)
311{
312 struct drm_nouveau_private *dev_priv = dev->dev_private;
313 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
314 struct nvc0_graph_priv *priv;
315 int ret, gpc, i;
316
317 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
318 if (!priv)
319 return -ENOMEM;
320 pgraph->priv = priv;
321
322 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
323 if (ret)
324 goto error;
325
326 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8);
327 if (ret)
328 goto error;
329
330 for (i = 0; i < 0x1000; i += 4) {
331 nv_wo32(priv->unk4188b4, i, 0x00000010);
332 nv_wo32(priv->unk4188b8, i, 0x00000010);
333 }
334
335 priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f;
336 priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16;
337 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
338 priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608));
339 priv->tp_total += priv->tp_nr[gpc];
340 }
341
342 /*XXX: these need figuring out... */
343 switch (dev_priv->chipset) {
344 case 0xc0:
345 if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
346 priv->magic_not_rop_nr = 0x07;
347 /* filled values up to tp_total, the rest 0 */
348 priv->magicgpc980[0] = 0x22111000;
349 priv->magicgpc980[1] = 0x00000233;
350 priv->magicgpc980[2] = 0x00000000;
351 priv->magicgpc980[3] = 0x00000000;
352 priv->magicgpc918 = 0x000ba2e9;
353 } else
354 if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
355 priv->magic_not_rop_nr = 0x05;
356 priv->magicgpc980[0] = 0x11110000;
357 priv->magicgpc980[1] = 0x00233222;
358 priv->magicgpc980[2] = 0x00000000;
359 priv->magicgpc980[3] = 0x00000000;
360 priv->magicgpc918 = 0x00092493;
361 } else
362 if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
363 priv->magic_not_rop_nr = 0x06;
364 priv->magicgpc980[0] = 0x11110000;
365 priv->magicgpc980[1] = 0x03332222;
366 priv->magicgpc980[2] = 0x00000000;
367 priv->magicgpc980[3] = 0x00000000;
368 priv->magicgpc918 = 0x00088889;
369 }
370 break;
371 case 0xc3: /* 450, 4/0/0/0, 2 */
372 priv->magic_not_rop_nr = 0x03;
373 priv->magicgpc980[0] = 0x00003210;
374 priv->magicgpc980[1] = 0x00000000;
375 priv->magicgpc980[2] = 0x00000000;
376 priv->magicgpc980[3] = 0x00000000;
377 priv->magicgpc918 = 0x00200000;
378 break;
379 case 0xc4: /* 460, 3/4/0/0, 4 */
380 priv->magic_not_rop_nr = 0x01;
381 priv->magicgpc980[0] = 0x02321100;
382 priv->magicgpc980[1] = 0x00000000;
383 priv->magicgpc980[2] = 0x00000000;
384 priv->magicgpc980[3] = 0x00000000;
385 priv->magicgpc918 = 0x00124925;
386 break;
387 }
388
389 if (!priv->magic_not_rop_nr) {
390 NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n",
391 priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2],
392 priv->tp_nr[3], priv->rop_nr);
393 /* use 0xc3's values... */
394 priv->magic_not_rop_nr = 0x03;
395 priv->magicgpc980[0] = 0x00003210;
396 priv->magicgpc980[1] = 0x00000000;
397 priv->magicgpc980[2] = 0x00000000;
398 priv->magicgpc980[3] = 0x00000000;
399 priv->magicgpc918 = 0x00200000;
400 }
401
402 nouveau_irq_register(dev, 12, nvc0_graph_isr);
403 nouveau_irq_register(dev, 25, nvc0_runk140_isr);
404 NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
405 NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
406 NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
407 NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
408 NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
409 return 0;
410
411error:
412 nvc0_graph_destroy(dev);
413 return ret;
414}
415
416static void 264static void
417nvc0_graph_init_obj418880(struct drm_device *dev) 265nvc0_graph_init_obj418880(struct drm_device *dev)
418{ 266{
419 struct drm_nouveau_private *dev_priv = dev->dev_private; 267 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
420 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
421 struct nvc0_graph_priv *priv = pgraph->priv;
422 int i; 268 int i;
423 269
424 nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); 270 nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000);
@@ -449,35 +295,42 @@ nvc0_graph_init_regs(struct drm_device *dev)
449static void 295static void
450nvc0_graph_init_gpc_0(struct drm_device *dev) 296nvc0_graph_init_gpc_0(struct drm_device *dev)
451{ 297{
452 struct drm_nouveau_private *dev_priv = dev->dev_private; 298 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
453 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; 299 u32 data[TP_MAX / 8];
454 int gpc; 300 u8 tpnr[GPC_MAX];
455 301 int i, gpc, tpc;
456 // TP ROP UNKVAL(magic_not_rop_nr) 302
457 // 450: 4/0/0/0 2 3 303 /*
458 // 460: 3/4/0/0 4 1 304 * TP ROP UNKVAL(magic_not_rop_nr)
459 // 465: 3/4/4/0 4 7 305 * 450: 4/0/0/0 2 3
460 // 470: 3/3/4/4 5 5 306 * 460: 3/4/0/0 4 1
461 // 480: 3/4/4/4 6 6 307 * 465: 3/4/4/0 4 7
462 308 * 470: 3/3/4/4 5 5
463 // magicgpc918 309 * 480: 3/4/4/4 6 6
464 // 450: 00200000 00000000001000000000000000000000 310 *
465 // 460: 00124925 00000000000100100100100100100101 311 * magicgpc918
466 // 465: 000ba2e9 00000000000010111010001011101001 312 * 450: 00200000 00000000001000000000000000000000
467 // 470: 00092493 00000000000010010010010010010011 313 * 460: 00124925 00000000000100100100100100100101
468 // 480: 00088889 00000000000010001000100010001001 314 * 465: 000ba2e9 00000000000010111010001011101001
469 315 * 470: 00092493 00000000000010010010010010010011
470 /* filled values up to tp_total, remainder 0 */ 316 * 480: 00088889 00000000000010001000100010001001
471 // 450: 00003210 00000000 00000000 00000000 317 */
472 // 460: 02321100 00000000 00000000 00000000 318
473 // 465: 22111000 00000233 00000000 00000000 319 memset(data, 0x00, sizeof(data));
474 // 470: 11110000 00233222 00000000 00000000 320 memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
475 // 480: 11110000 03332222 00000000 00000000 321 for (i = 0, gpc = -1; i < priv->tp_total; i++) {
476 322 do {
477 nv_wr32(dev, GPC_BCAST(0x0980), priv->magicgpc980[0]); 323 gpc = (gpc + 1) % priv->gpc_nr;
478 nv_wr32(dev, GPC_BCAST(0x0984), priv->magicgpc980[1]); 324 } while (!tpnr[gpc]);
479 nv_wr32(dev, GPC_BCAST(0x0988), priv->magicgpc980[2]); 325 tpc = priv->tp_nr[gpc] - tpnr[gpc]--;
480 nv_wr32(dev, GPC_BCAST(0x098c), priv->magicgpc980[3]); 326
327 data[i / 8] |= tpc << ((i % 8) * 4);
328 }
329
330 nv_wr32(dev, GPC_BCAST(0x0980), data[0]);
331 nv_wr32(dev, GPC_BCAST(0x0984), data[1]);
332 nv_wr32(dev, GPC_BCAST(0x0988), data[2]);
333 nv_wr32(dev, GPC_BCAST(0x098c), data[3]);
481 334
482 for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 335 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
483 nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 | 336 nv_wr32(dev, GPC_UNIT(gpc, 0x0914), priv->magic_not_rop_nr << 8 |
@@ -509,8 +362,7 @@ nvc0_graph_init_units(struct drm_device *dev)
509static void 362static void
510nvc0_graph_init_gpc_1(struct drm_device *dev) 363nvc0_graph_init_gpc_1(struct drm_device *dev)
511{ 364{
512 struct drm_nouveau_private *dev_priv = dev->dev_private; 365 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
513 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
514 int gpc, tp; 366 int gpc, tp;
515 367
516 for (gpc = 0; gpc < priv->gpc_nr; gpc++) { 368 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
@@ -535,8 +387,7 @@ nvc0_graph_init_gpc_1(struct drm_device *dev)
535static void 387static void
536nvc0_graph_init_rop(struct drm_device *dev) 388nvc0_graph_init_rop(struct drm_device *dev)
537{ 389{
538 struct drm_nouveau_private *dev_priv = dev->dev_private; 390 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
539 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
540 int rop; 391 int rop;
541 392
542 for (rop = 0; rop < priv->rop_nr; rop++) { 393 for (rop = 0; rop < priv->rop_nr; rop++) {
@@ -547,62 +398,36 @@ nvc0_graph_init_rop(struct drm_device *dev)
547 } 398 }
548} 399}
549 400
550static int 401static void
551nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base, 402nvc0_graph_init_fuc(struct drm_device *dev, u32 fuc_base,
552 const char *code_fw, const char *data_fw) 403 struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data)
553{ 404{
554 const struct firmware *fw; 405 int i;
555 char name[32];
556 int ret, i;
557
558 snprintf(name, sizeof(name), "nouveau/%s", data_fw);
559 ret = request_firmware(&fw, name, &dev->pdev->dev);
560 if (ret) {
561 NV_ERROR(dev, "failed to load %s\n", data_fw);
562 return ret;
563 }
564 406
565 nv_wr32(dev, fuc_base + 0x01c0, 0x01000000); 407 nv_wr32(dev, fuc_base + 0x01c0, 0x01000000);
566 for (i = 0; i < fw->size / 4; i++) 408 for (i = 0; i < data->size / 4; i++)
567 nv_wr32(dev, fuc_base + 0x01c4, ((u32 *)fw->data)[i]); 409 nv_wr32(dev, fuc_base + 0x01c4, data->data[i]);
568 release_firmware(fw);
569
570 snprintf(name, sizeof(name), "nouveau/%s", code_fw);
571 ret = request_firmware(&fw, name, &dev->pdev->dev);
572 if (ret) {
573 NV_ERROR(dev, "failed to load %s\n", code_fw);
574 return ret;
575 }
576 410
577 nv_wr32(dev, fuc_base + 0x0180, 0x01000000); 411 nv_wr32(dev, fuc_base + 0x0180, 0x01000000);
578 for (i = 0; i < fw->size / 4; i++) { 412 for (i = 0; i < code->size / 4; i++) {
579 if ((i & 0x3f) == 0) 413 if ((i & 0x3f) == 0)
580 nv_wr32(dev, fuc_base + 0x0188, i >> 6); 414 nv_wr32(dev, fuc_base + 0x0188, i >> 6);
581 nv_wr32(dev, fuc_base + 0x0184, ((u32 *)fw->data)[i]); 415 nv_wr32(dev, fuc_base + 0x0184, code->data[i]);
582 } 416 }
583 release_firmware(fw);
584
585 return 0;
586} 417}
587 418
588static int 419static int
589nvc0_graph_init_ctxctl(struct drm_device *dev) 420nvc0_graph_init_ctxctl(struct drm_device *dev)
590{ 421{
591 struct drm_nouveau_private *dev_priv = dev->dev_private; 422 struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR);
592 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv;
593 u32 r000260; 423 u32 r000260;
594 int ret;
595 424
596 /* load fuc microcode */ 425 /* load fuc microcode */
597 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000); 426 r000260 = nv_mask(dev, 0x000260, 0x00000001, 0x00000000);
598 ret = nvc0_fuc_load_fw(dev, 0x409000, "fuc409c", "fuc409d"); 427 nvc0_graph_init_fuc(dev, 0x409000, &priv->fuc409c, &priv->fuc409d);
599 if (ret == 0) 428 nvc0_graph_init_fuc(dev, 0x41a000, &priv->fuc41ac, &priv->fuc41ad);
600 ret = nvc0_fuc_load_fw(dev, 0x41a000, "fuc41ac", "fuc41ad");
601 nv_wr32(dev, 0x000260, r000260); 429 nv_wr32(dev, 0x000260, r000260);
602 430
603 if (ret)
604 return ret;
605
606 /* start both of them running */ 431 /* start both of them running */
607 nv_wr32(dev, 0x409840, 0xffffffff); 432 nv_wr32(dev, 0x409840, 0xffffffff);
608 nv_wr32(dev, 0x41a10c, 0x00000000); 433 nv_wr32(dev, 0x41a10c, 0x00000000);
@@ -644,41 +469,19 @@ nvc0_graph_init_ctxctl(struct drm_device *dev)
644 return 0; 469 return 0;
645} 470}
646 471
647int 472static int
648nvc0_graph_init(struct drm_device *dev) 473nvc0_graph_init(struct drm_device *dev, int engine)
649{ 474{
650 struct drm_nouveau_private *dev_priv = dev->dev_private;
651 struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
652 int ret; 475 int ret;
653 476
654 dev_priv->engine.graph.accel_blocked = true;
655
656 switch (dev_priv->chipset) {
657 case 0xc0:
658 case 0xc3:
659 case 0xc4:
660 break;
661 default:
662 NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
663 if (nouveau_noaccel != 0)
664 return 0;
665 break;
666 }
667
668 nv_mask(dev, 0x000200, 0x18001000, 0x00000000); 477 nv_mask(dev, 0x000200, 0x18001000, 0x00000000);
669 nv_mask(dev, 0x000200, 0x18001000, 0x18001000); 478 nv_mask(dev, 0x000200, 0x18001000, 0x18001000);
670 479
671 if (!pgraph->priv) {
672 ret = nvc0_graph_create(dev);
673 if (ret)
674 return ret;
675 }
676
677 nvc0_graph_init_obj418880(dev); 480 nvc0_graph_init_obj418880(dev);
678 nvc0_graph_init_regs(dev); 481 nvc0_graph_init_regs(dev);
679 //nvc0_graph_init_unitplemented_magics(dev); 482 /*nvc0_graph_init_unitplemented_magics(dev);*/
680 nvc0_graph_init_gpc_0(dev); 483 nvc0_graph_init_gpc_0(dev);
681 //nvc0_graph_init_unitplemented_c242(dev); 484 /*nvc0_graph_init_unitplemented_c242(dev);*/
682 485
683 nv_wr32(dev, 0x400500, 0x00010001); 486 nv_wr32(dev, 0x400500, 0x00010001);
684 nv_wr32(dev, 0x400100, 0xffffffff); 487 nv_wr32(dev, 0x400100, 0xffffffff);
@@ -697,12 +500,13 @@ nvc0_graph_init(struct drm_device *dev)
697 nv_wr32(dev, 0x400054, 0x34ce3464); 500 nv_wr32(dev, 0x400054, 0x34ce3464);
698 501
699 ret = nvc0_graph_init_ctxctl(dev); 502 ret = nvc0_graph_init_ctxctl(dev);
700 if (ret == 0) 503 if (ret)
701 dev_priv->engine.graph.accel_blocked = false; 504 return ret;
505
702 return 0; 506 return 0;
703} 507}
704 508
705static int 509int
706nvc0_graph_isr_chid(struct drm_device *dev, u64 inst) 510nvc0_graph_isr_chid(struct drm_device *dev, u64 inst)
707{ 511{
708 struct drm_nouveau_private *dev_priv = dev->dev_private; 512 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -806,3 +610,187 @@ nvc0_runk140_isr(struct drm_device *dev)
806 units &= ~(1 << unit); 610 units &= ~(1 << unit);
807 } 611 }
808} 612}
613
614static int
615nvc0_graph_create_fw(struct drm_device *dev, const char *fwname,
616 struct nvc0_graph_fuc *fuc)
617{
618 struct drm_nouveau_private *dev_priv = dev->dev_private;
619 const struct firmware *fw;
620 char f[32];
621 int ret;
622
623 snprintf(f, sizeof(f), "nouveau/nv%02x_%s", dev_priv->chipset, fwname);
624 ret = request_firmware(&fw, f, &dev->pdev->dev);
625 if (ret) {
626 snprintf(f, sizeof(f), "nouveau/%s", fwname);
627 ret = request_firmware(&fw, f, &dev->pdev->dev);
628 if (ret) {
629 NV_ERROR(dev, "failed to load %s\n", fwname);
630 return ret;
631 }
632 }
633
634 fuc->size = fw->size;
635 fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
636 release_firmware(fw);
637 return (fuc->data != NULL) ? 0 : -ENOMEM;
638}
639
640static void
641nvc0_graph_destroy_fw(struct nvc0_graph_fuc *fuc)
642{
643 if (fuc->data) {
644 kfree(fuc->data);
645 fuc->data = NULL;
646 }
647}
648
649static void
650nvc0_graph_destroy(struct drm_device *dev, int engine)
651{
652 struct nvc0_graph_priv *priv = nv_engine(dev, engine);
653
654 nvc0_graph_destroy_fw(&priv->fuc409c);
655 nvc0_graph_destroy_fw(&priv->fuc409d);
656 nvc0_graph_destroy_fw(&priv->fuc41ac);
657 nvc0_graph_destroy_fw(&priv->fuc41ad);
658
659 nouveau_irq_unregister(dev, 12);
660 nouveau_irq_unregister(dev, 25);
661
662 nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
663 nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
664
665 if (priv->grctx_vals)
666 kfree(priv->grctx_vals);
667
668 NVOBJ_ENGINE_DEL(dev, GR);
669 kfree(priv);
670}
671
672int
673nvc0_graph_create(struct drm_device *dev)
674{
675 struct drm_nouveau_private *dev_priv = dev->dev_private;
676 struct nvc0_graph_priv *priv;
677 int ret, gpc, i;
678
679 switch (dev_priv->chipset) {
680 case 0xc0:
681 case 0xc3:
682 case 0xc4:
683 break;
684 default:
685 NV_ERROR(dev, "PGRAPH: unsupported chipset, please report!\n");
686 return 0;
687 }
688
689 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
690 if (!priv)
691 return -ENOMEM;
692
693 priv->base.destroy = nvc0_graph_destroy;
694 priv->base.init = nvc0_graph_init;
695 priv->base.fini = nvc0_graph_fini;
696 priv->base.context_new = nvc0_graph_context_new;
697 priv->base.context_del = nvc0_graph_context_del;
698 priv->base.object_new = nvc0_graph_object_new;
699
700 NVOBJ_ENGINE_ADD(dev, GR, &priv->base);
701 nouveau_irq_register(dev, 12, nvc0_graph_isr);
702 nouveau_irq_register(dev, 25, nvc0_runk140_isr);
703
704 if (nvc0_graph_create_fw(dev, "fuc409c", &priv->fuc409c) ||
705 nvc0_graph_create_fw(dev, "fuc409d", &priv->fuc409d) ||
706 nvc0_graph_create_fw(dev, "fuc41ac", &priv->fuc41ac) ||
707 nvc0_graph_create_fw(dev, "fuc41ad", &priv->fuc41ad)) {
708 ret = 0;
709 goto error;
710 }
711
712
713 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4);
714 if (ret)
715 goto error;
716
717 ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8);
718 if (ret)
719 goto error;
720
721 for (i = 0; i < 0x1000; i += 4) {
722 nv_wo32(priv->unk4188b4, i, 0x00000010);
723 nv_wo32(priv->unk4188b8, i, 0x00000010);
724 }
725
726 priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f;
727 priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16;
728 for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
729 priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608));
730 priv->tp_total += priv->tp_nr[gpc];
731 }
732
733 /*XXX: these need figuring out... */
734 switch (dev_priv->chipset) {
735 case 0xc0:
736 if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */
737 priv->magic_not_rop_nr = 0x07;
738 /* filled values up to tp_total, the rest 0 */
739 priv->magicgpc918 = 0x000ba2e9;
740 } else
741 if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */
742 priv->magic_not_rop_nr = 0x05;
743 priv->magicgpc918 = 0x00092493;
744 } else
745 if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */
746 priv->magic_not_rop_nr = 0x06;
747 priv->magicgpc918 = 0x00088889;
748 }
749 break;
750 case 0xc3: /* 450, 4/0/0/0, 2 */
751 priv->magic_not_rop_nr = 0x03;
752 priv->magicgpc918 = 0x00200000;
753 break;
754 case 0xc4: /* 460, 3/4/0/0, 4 */
755 priv->magic_not_rop_nr = 0x01;
756 priv->magicgpc918 = 0x00124925;
757 break;
758 }
759
760 if (!priv->magic_not_rop_nr) {
761 NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n",
762 priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2],
763 priv->tp_nr[3], priv->rop_nr);
764 /* use 0xc3's values... */
765 priv->magic_not_rop_nr = 0x03;
766 priv->magicgpc918 = 0x00200000;
767 }
768
769 NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
770 NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
771 NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
772 NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
773 NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
774 return 0;
775
776error:
777 nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR);
778 return ret;
779}
780
781MODULE_FIRMWARE("nouveau/nvc0_fuc409c");
782MODULE_FIRMWARE("nouveau/nvc0_fuc409d");
783MODULE_FIRMWARE("nouveau/nvc0_fuc41ac");
784MODULE_FIRMWARE("nouveau/nvc0_fuc41ad");
785MODULE_FIRMWARE("nouveau/nvc3_fuc409c");
786MODULE_FIRMWARE("nouveau/nvc3_fuc409d");
787MODULE_FIRMWARE("nouveau/nvc3_fuc41ac");
788MODULE_FIRMWARE("nouveau/nvc3_fuc41ad");
789MODULE_FIRMWARE("nouveau/nvc4_fuc409c");
790MODULE_FIRMWARE("nouveau/nvc4_fuc409d");
791MODULE_FIRMWARE("nouveau/nvc4_fuc41ac");
792MODULE_FIRMWARE("nouveau/nvc4_fuc41ad");
793MODULE_FIRMWARE("nouveau/fuc409c");
794MODULE_FIRMWARE("nouveau/fuc409d");
795MODULE_FIRMWARE("nouveau/fuc41ac");
796MODULE_FIRMWARE("nouveau/fuc41ad");
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h
index 40e26f9c56c4..f5d184e0689d 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.h
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.h
@@ -28,13 +28,25 @@
28#define GPC_MAX 4 28#define GPC_MAX 4
29#define TP_MAX 32 29#define TP_MAX 32
30 30
31#define ROP_BCAST(r) (0x408800 + (r)) 31#define ROP_BCAST(r) (0x408800 + (r))
32#define ROP_UNIT(u,r) (0x410000 + (u) * 0x400 + (r)) 32#define ROP_UNIT(u, r) (0x410000 + (u) * 0x400 + (r))
33#define GPC_BCAST(r) (0x418000 + (r)) 33#define GPC_BCAST(r) (0x418000 + (r))
34#define GPC_UNIT(t,r) (0x500000 + (t) * 0x8000 + (r)) 34#define GPC_UNIT(t, r) (0x500000 + (t) * 0x8000 + (r))
35#define TP_UNIT(t,m,r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) 35#define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
36
37struct nvc0_graph_fuc {
38 u32 *data;
39 u32 size;
40};
36 41
37struct nvc0_graph_priv { 42struct nvc0_graph_priv {
43 struct nouveau_exec_engine base;
44
45 struct nvc0_graph_fuc fuc409c;
46 struct nvc0_graph_fuc fuc409d;
47 struct nvc0_graph_fuc fuc41ac;
48 struct nvc0_graph_fuc fuc41ad;
49
38 u8 gpc_nr; 50 u8 gpc_nr;
39 u8 rop_nr; 51 u8 rop_nr;
40 u8 tp_nr[GPC_MAX]; 52 u8 tp_nr[GPC_MAX];
@@ -46,15 +58,14 @@ struct nvc0_graph_priv {
46 struct nouveau_gpuobj *unk4188b8; 58 struct nouveau_gpuobj *unk4188b8;
47 59
48 u8 magic_not_rop_nr; 60 u8 magic_not_rop_nr;
49 u32 magicgpc980[4];
50 u32 magicgpc918; 61 u32 magicgpc918;
51}; 62};
52 63
53struct nvc0_graph_chan { 64struct nvc0_graph_chan {
54 struct nouveau_gpuobj *grctx; 65 struct nouveau_gpuobj *grctx;
55 struct nouveau_gpuobj *unk408004; // 0x418810 too 66 struct nouveau_gpuobj *unk408004; /* 0x418810 too */
56 struct nouveau_gpuobj *unk40800c; // 0x419004 too 67 struct nouveau_gpuobj *unk40800c; /* 0x419004 too */
57 struct nouveau_gpuobj *unk418810; // 0x419848 too 68 struct nouveau_gpuobj *unk418810; /* 0x419848 too */
58 struct nouveau_gpuobj *mmio; 69 struct nouveau_gpuobj *mmio;
59 int mmio_nr; 70 int mmio_nr;
60}; 71};
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
index f880ff776db8..6df066114133 100644
--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c
+++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
@@ -1623,7 +1623,7 @@ nvc0_grctx_generate_rop(struct drm_device *dev)
1623{ 1623{
1624 struct drm_nouveau_private *dev_priv = dev->dev_private; 1624 struct drm_nouveau_private *dev_priv = dev->dev_private;
1625 1625
1626 // ROPC_BROADCAST 1626 /* ROPC_BROADCAST */
1627 nv_wr32(dev, 0x408800, 0x02802a3c); 1627 nv_wr32(dev, 0x408800, 0x02802a3c);
1628 nv_wr32(dev, 0x408804, 0x00000040); 1628 nv_wr32(dev, 0x408804, 0x00000040);
1629 nv_wr32(dev, 0x408808, 0x0003e00d); 1629 nv_wr32(dev, 0x408808, 0x0003e00d);
@@ -1647,7 +1647,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev)
1647{ 1647{
1648 int i; 1648 int i;
1649 1649
1650 // GPC_BROADCAST 1650 /* GPC_BROADCAST */
1651 nv_wr32(dev, 0x418380, 0x00000016); 1651 nv_wr32(dev, 0x418380, 0x00000016);
1652 nv_wr32(dev, 0x418400, 0x38004e00); 1652 nv_wr32(dev, 0x418400, 0x38004e00);
1653 nv_wr32(dev, 0x418404, 0x71e0ffff); 1653 nv_wr32(dev, 0x418404, 0x71e0ffff);
@@ -1728,7 +1728,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
1728{ 1728{
1729 struct drm_nouveau_private *dev_priv = dev->dev_private; 1729 struct drm_nouveau_private *dev_priv = dev->dev_private;
1730 1730
1731 // GPC_BROADCAST.TP_BROADCAST 1731 /* GPC_BROADCAST.TP_BROADCAST */
1732 nv_wr32(dev, 0x419848, 0x00000000); 1732 nv_wr32(dev, 0x419848, 0x00000000);
1733 nv_wr32(dev, 0x419864, 0x0000012a); 1733 nv_wr32(dev, 0x419864, 0x0000012a);
1734 nv_wr32(dev, 0x419888, 0x00000000); 1734 nv_wr32(dev, 0x419888, 0x00000000);
@@ -1741,7 +1741,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev)
1741 nv_wr32(dev, 0x419a1c, 0x00000000); 1741 nv_wr32(dev, 0x419a1c, 0x00000000);
1742 nv_wr32(dev, 0x419a20, 0x00000800); 1742 nv_wr32(dev, 0x419a20, 0x00000800);
1743 if (dev_priv->chipset != 0xc0) 1743 if (dev_priv->chipset != 0xc0)
1744 nv_wr32(dev, 0x00419ac4, 0x0007f440); // 0xc3 1744 nv_wr32(dev, 0x00419ac4, 0x0007f440); /* 0xc3 */
1745 nv_wr32(dev, 0x419b00, 0x0a418820); 1745 nv_wr32(dev, 0x419b00, 0x0a418820);
1746 nv_wr32(dev, 0x419b04, 0x062080e6); 1746 nv_wr32(dev, 0x419b04, 0x062080e6);
1747 nv_wr32(dev, 0x419b08, 0x020398a4); 1747 nv_wr32(dev, 0x419b08, 0x020398a4);
@@ -1797,8 +1797,8 @@ int
1797nvc0_grctx_generate(struct nouveau_channel *chan) 1797nvc0_grctx_generate(struct nouveau_channel *chan)
1798{ 1798{
1799 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 1799 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
1800 struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; 1800 struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
1801 struct nvc0_graph_chan *grch = chan->pgraph_ctx; 1801 struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
1802 struct drm_device *dev = chan->dev; 1802 struct drm_device *dev = chan->dev;
1803 int i, gpc, tp, id; 1803 int i, gpc, tp, id;
1804 u32 r000260, tmp; 1804 u32 r000260, tmp;
@@ -1912,13 +1912,13 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
1912 for (i = 1; i < 7; i++) 1912 for (i = 1; i < 7; i++)
1913 data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5); 1913 data2[1] |= ((1 << (i + 5)) % ntpcv) << ((i - 1) * 5);
1914 1914
1915 // GPC_BROADCAST 1915 /* GPC_BROADCAST */
1916 nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) | 1916 nv_wr32(dev, 0x418bb8, (priv->tp_total << 8) |
1917 priv->magic_not_rop_nr); 1917 priv->magic_not_rop_nr);
1918 for (i = 0; i < 6; i++) 1918 for (i = 0; i < 6; i++)
1919 nv_wr32(dev, 0x418b08 + (i * 4), data[i]); 1919 nv_wr32(dev, 0x418b08 + (i * 4), data[i]);
1920 1920
1921 // GPC_BROADCAST.TP_BROADCAST 1921 /* GPC_BROADCAST.TP_BROADCAST */
1922 nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) | 1922 nv_wr32(dev, 0x419bd0, (priv->tp_total << 8) |
1923 priv->magic_not_rop_nr | 1923 priv->magic_not_rop_nr |
1924 data2[0]); 1924 data2[0]);
@@ -1926,7 +1926,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
1926 for (i = 0; i < 6; i++) 1926 for (i = 0; i < 6; i++)
1927 nv_wr32(dev, 0x419b00 + (i * 4), data[i]); 1927 nv_wr32(dev, 0x419b00 + (i * 4), data[i]);
1928 1928
1929 // UNK78xx 1929 /* UNK78xx */
1930 nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) | 1930 nv_wr32(dev, 0x4078bc, (priv->tp_total << 8) |
1931 priv->magic_not_rop_nr); 1931 priv->magic_not_rop_nr);
1932 for (i = 0; i < 6; i++) 1932 for (i = 0; i < 6; i++)
@@ -1944,7 +1944,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
1944 gpc = -1; 1944 gpc = -1;
1945 for (i = 0, gpc = -1; i < 32; i++) { 1945 for (i = 0, gpc = -1; i < 32; i++) {
1946 int ltp = i * (priv->tp_total - 1) / 32; 1946 int ltp = i * (priv->tp_total - 1) / 32;
1947 1947
1948 do { 1948 do {
1949 gpc = (gpc + 1) % priv->gpc_nr; 1949 gpc = (gpc + 1) % priv->gpc_nr;
1950 } while (!tpnr[gpc]); 1950 } while (!tpnr[gpc]);