aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_display.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-02-06 22:29:23 -0500
committerBen Skeggs <bskeggs@redhat.com>2011-02-24 15:45:11 -0500
commitcdccc70eff1eaf3627a716374f9ebc115fc4621c (patch)
tree744a5a9e35c5749326d3bfb85336afceb24c2b4d /drivers/gpu/drm/nouveau/nv50_display.c
parent45c4e0aae96c6354bf5131a282a74fe38d032de3 (diff)
drm/nv50-nvc0: initialise display sync channels
Also imports a couple of helper functions that'll be used to implement page flipping in the following commits.. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c123
1 files changed, 122 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 09d7994ea099..75a376cc342a 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -178,7 +178,7 @@ nv50_display_init(struct drm_device *dev)
178 178
179 nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); 179 nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9);
180 180
181 ret = RING_SPACE(evo, 11); 181 ret = RING_SPACE(evo, 15);
182 if (ret) 182 if (ret)
183 return ret; 183 return ret;
184 BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); 184 BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2);
@@ -192,6 +192,11 @@ nv50_display_init(struct drm_device *dev)
192 OUT_RING(evo, 0); 192 OUT_RING(evo, 0);
193 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); 193 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1);
194 OUT_RING(evo, 0); 194 OUT_RING(evo, 0);
195 /* required to make display sync channels not hate life */
196 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1);
197 OUT_RING (evo, 0x00000311);
198 BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1);
199 OUT_RING (evo, 0x00000311);
195 FIRE_RING(evo); 200 FIRE_RING(evo);
196 if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) 201 if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2))
197 NV_ERROR(dev, "evo pushbuf stalled\n"); 202 NV_ERROR(dev, "evo pushbuf stalled\n");
@@ -366,6 +371,122 @@ nv50_display_destroy(struct drm_device *dev)
366 kfree(disp); 371 kfree(disp);
367} 372}
368 373
374void
375nv50_display_flip_stop(struct drm_crtc *crtc)
376{
377 struct nv50_display *disp = nv50_display(crtc->dev);
378 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
379 struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
380 struct nouveau_channel *evo = dispc->sync;
381 int ret;
382
383 ret = RING_SPACE(evo, 8);
384 if (ret) {
385 WARN_ON(1);
386 return;
387 }
388
389 BEGIN_RING(evo, 0, 0x0084, 1);
390 OUT_RING (evo, 0x00000000);
391 BEGIN_RING(evo, 0, 0x0094, 1);
392 OUT_RING (evo, 0x00000000);
393 BEGIN_RING(evo, 0, 0x00c0, 1);
394 OUT_RING (evo, 0x00000000);
395 BEGIN_RING(evo, 0, 0x0080, 1);
396 OUT_RING (evo, 0x00000000);
397 FIRE_RING (evo);
398}
399
400int
401nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
402 struct nouveau_channel *chan)
403{
404 struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
405 struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
406 struct nv50_display *disp = nv50_display(crtc->dev);
407 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
408 struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
409 struct nouveau_channel *evo = dispc->sync;
410 int ret;
411
412 ret = RING_SPACE(evo, 24);
413 if (unlikely(ret))
414 return ret;
415
416 /* synchronise with the rendering channel, if necessary */
417 if (likely(chan)) {
418 u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
419
420 ret = RING_SPACE(chan, 10);
421 if (ret) {
422 WIND_RING(evo);
423 return ret;
424 }
425
426 if (dev_priv->chipset < 0xc0) {
427 BEGIN_RING(chan, NvSubSw, 0x0060, 2);
428 OUT_RING (chan, NvEvoSema0 + nv_crtc->index);
429 OUT_RING (chan, dispc->sem.offset);
430 BEGIN_RING(chan, NvSubSw, 0x006c, 1);
431 OUT_RING (chan, 0xf00d0000 | dispc->sem.value);
432 BEGIN_RING(chan, NvSubSw, 0x0064, 2);
433 OUT_RING (chan, dispc->sem.offset ^ 0x10);
434 OUT_RING (chan, 0x74b1e000);
435 BEGIN_RING(chan, NvSubSw, 0x0060, 1);
436 if (dev_priv->chipset < 0x84)
437 OUT_RING (chan, NvSema);
438 else
439 OUT_RING (chan, chan->vram_handle);
440 } else {
441 BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
442 OUT_RING (chan, upper_32_bits(offset));
443 OUT_RING (chan, lower_32_bits(offset));
444 OUT_RING (chan, 0xf00d0000 | dispc->sem.value);
445 OUT_RING (chan, 0x1002);
446 BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
447 OUT_RING (chan, upper_32_bits(offset));
448 OUT_RING (chan, lower_32_bits(offset ^ 0x10));
449 OUT_RING (chan, 0x74b1e000);
450 OUT_RING (chan, 0x1001);
451 }
452 FIRE_RING (chan);
453 } else {
454 nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4,
455 0xf00d0000 | dispc->sem.value);
456 }
457
458 /* queue the flip on the crtc's "display sync" channel */
459 BEGIN_RING(evo, 0, 0x0100, 1);
460 OUT_RING (evo, 0xfffe0000);
461 BEGIN_RING(evo, 0, 0x0084, 5);
462 OUT_RING (evo, chan ? 0x00000100 : 0x00000010);
463 OUT_RING (evo, dispc->sem.offset);
464 OUT_RING (evo, 0xf00d0000 | dispc->sem.value);
465 OUT_RING (evo, 0x74b1e000);
466 OUT_RING (evo, NvEvoSync);
467 BEGIN_RING(evo, 0, 0x00a0, 2);
468 OUT_RING (evo, 0x00000000);
469 OUT_RING (evo, 0x00000000);
470 BEGIN_RING(evo, 0, 0x00c0, 1);
471 OUT_RING (evo, nv_fb->r_dma);
472 BEGIN_RING(evo, 0, 0x0110, 2);
473 OUT_RING (evo, 0x00000000);
474 OUT_RING (evo, 0x00000000);
475 BEGIN_RING(evo, 0, 0x0800, 5);
476 OUT_RING (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
477 OUT_RING (evo, 0);
478 OUT_RING (evo, (fb->height << 16) | fb->width);
479 OUT_RING (evo, nv_fb->r_pitch);
480 OUT_RING (evo, nv_fb->r_format);
481 BEGIN_RING(evo, 0, 0x0080, 1);
482 OUT_RING (evo, 0x00000000);
483 FIRE_RING (evo);
484
485 dispc->sem.offset ^= 0x10;
486 dispc->sem.value++;
487 return 0;
488}
489
369static u16 490static u16
370nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, 491nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb,
371 u32 mc, int pxclk) 492 u32 mc, int pxclk)