aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.h3
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c77
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.h1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_evo.c20
5 files changed, 77 insertions, 26 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index c36f1763feaa..6c9501b3226b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -78,7 +78,8 @@ enum {
78 NvEvoVRAM = 0x01000000, 78 NvEvoVRAM = 0x01000000,
79 NvEvoFB16 = 0x01000001, 79 NvEvoFB16 = 0x01000001,
80 NvEvoFB32 = 0x01000002, 80 NvEvoFB32 = 0x01000002,
81 NvEvoVRAM_LP = 0x01000003 81 NvEvoVRAM_LP = 0x01000003,
82 NvEvoSync = 0xcafe0000
82}; 83};
83 84
84#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039 85#define NV_MEMORY_TO_MEMORY_FORMAT 0x00000039
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index bc5fa36677c1..a94aff57cc06 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -443,6 +443,42 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
443{ 443{
444} 444}
445 445
446static int
447nv50_crtc_wait_complete(struct drm_crtc *crtc)
448{
449 struct drm_device *dev = crtc->dev;
450 struct drm_nouveau_private *dev_priv = dev->dev_private;
451 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
452 struct nv50_display *disp = nv50_display(dev);
453 struct nouveau_channel *evo = disp->master;
454 u64 start;
455 int ret;
456
457 ret = RING_SPACE(evo, 6);
458 if (ret)
459 return ret;
460 BEGIN_RING(evo, 0, 0x0084, 1);
461 OUT_RING (evo, 0x80000000);
462 BEGIN_RING(evo, 0, 0x0080, 1);
463 OUT_RING (evo, 0);
464 BEGIN_RING(evo, 0, 0x0084, 1);
465 OUT_RING (evo, 0x00000000);
466
467 nv_wo32(disp->ntfy, 0x000, 0x00000000);
468 FIRE_RING (evo);
469
470 start = ptimer->read(dev);
471 do {
472 nv_wr32(dev, 0x61002c, 0x370);
473 nv_wr32(dev, 0x000140, 1);
474
475 if (nv_ro32(disp->ntfy, 0x000))
476 return 0;
477 } while (ptimer->read(dev) - start < 2000000000ULL);
478
479 return -EBUSY;
480}
481
446static void 482static void
447nv50_crtc_prepare(struct drm_crtc *crtc) 483nv50_crtc_prepare(struct drm_crtc *crtc)
448{ 484{
@@ -459,23 +495,13 @@ static void
459nv50_crtc_commit(struct drm_crtc *crtc) 495nv50_crtc_commit(struct drm_crtc *crtc)
460{ 496{
461 struct drm_device *dev = crtc->dev; 497 struct drm_device *dev = crtc->dev;
462 struct nouveau_channel *evo = nv50_display(dev)->master;
463 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 498 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
464 int ret;
465 499
466 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); 500 NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
467 501
468 nv50_crtc_blank(nv_crtc, false); 502 nv50_crtc_blank(nv_crtc, false);
469 drm_vblank_post_modeset(dev, nv_crtc->index); 503 drm_vblank_post_modeset(dev, nv_crtc->index);
470 504 nv50_crtc_wait_complete(crtc);
471 ret = RING_SPACE(evo, 2);
472 if (ret) {
473 NV_ERROR(dev, "no space while committing crtc\n");
474 return;
475 }
476 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
477 OUT_RING (evo, 0);
478 FIRE_RING (evo);
479} 505}
480 506
481static bool 507static bool
@@ -488,7 +514,7 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
488static int 514static int
489nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, 515nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
490 struct drm_framebuffer *passed_fb, 516 struct drm_framebuffer *passed_fb,
491 int x, int y, bool update, bool atomic) 517 int x, int y, bool atomic)
492{ 518{
493 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); 519 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
494 struct drm_device *dev = nv_crtc->base.dev; 520 struct drm_device *dev = nv_crtc->base.dev;
@@ -598,15 +624,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
598 nv50_crtc_lut_load(crtc); 624 nv50_crtc_lut_load(crtc);
599 } 625 }
600 626
601 if (update) {
602 ret = RING_SPACE(evo, 2);
603 if (ret)
604 return ret;
605 BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
606 OUT_RING(evo, 0);
607 FIRE_RING(evo);
608 }
609
610 return 0; 627 return 0;
611} 628}
612 629
@@ -696,14 +713,20 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
696 nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); 713 nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
697 nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); 714 nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
698 715
699 return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); 716 return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
700} 717}
701 718
702static int 719static int
703nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 720nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
704 struct drm_framebuffer *old_fb) 721 struct drm_framebuffer *old_fb)
705{ 722{
706 return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); 723 int ret;
724
725 ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
726 if (ret)
727 return ret;
728
729 return nv50_crtc_wait_complete(crtc);
707} 730}
708 731
709static int 732static int
@@ -711,7 +734,13 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
711 struct drm_framebuffer *fb, 734 struct drm_framebuffer *fb,
712 int x, int y, enum mode_set_atomic state) 735 int x, int y, enum mode_set_atomic state)
713{ 736{
714 return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); 737 int ret;
738
739 ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
740 if (ret)
741 return ret;
742
743 return nv50_crtc_wait_complete(crtc);
715} 744}
716 745
717static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { 746static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index e295a17d68f4..09d7994ea099 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -183,7 +183,7 @@ nv50_display_init(struct drm_device *dev)
183 return ret; 183 return ret;
184 BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); 184 BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2);
185 OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); 185 OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED);
186 OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE); 186 OUT_RING(evo, NvEvoSync);
187 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); 187 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1);
188 OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); 188 OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
189 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); 189 BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index ea37f230aee8..a51b8853a924 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -37,6 +37,7 @@
37 37
38struct nv50_display { 38struct nv50_display {
39 struct nouveau_channel *master; 39 struct nouveau_channel *master;
40 struct nouveau_gpuobj *ntfy;
40 41
41 struct tasklet_struct tasklet; 42 struct tasklet_struct tasklet;
42 struct { 43 struct {
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
index 9703f759b717..eea96205fca2 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.c
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -203,6 +203,7 @@ nv50_evo_destroy(struct drm_device *dev)
203{ 203{
204 struct nv50_display *disp = nv50_display(dev); 204 struct nv50_display *disp = nv50_display(dev);
205 205
206 nouveau_gpuobj_ref(NULL, &disp->ntfy);
206 nv50_evo_channel_del(&disp->master); 207 nv50_evo_channel_del(&disp->master);
207} 208}
208 209
@@ -251,6 +252,25 @@ nv50_evo_create(struct drm_device *dev)
251 if (ret) 252 if (ret)
252 goto err; 253 goto err;
253 254
255 /* not sure exactly what this is..
256 *
257 * the first dword of the structure is used by nvidia to wait on
258 * full completion of an EVO "update" command.
259 *
260 * method 0x8c on the master evo channel will fill a lot more of
261 * this structure with some undefined info
262 */
263 ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0,
264 NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy);
265 if (ret)
266 goto err;
267
268 ret = nv50_evo_dmaobj_new(disp->master, 0x3d, NvEvoSync, 0, 0x19,
269 disp->ntfy->vinst, disp->ntfy->vinst +
270 disp->ntfy->size, 0x00010000);
271 if (ret)
272 goto err;
273
254 /* create some default objects for the scanout memtypes we support */ 274 /* create some default objects for the scanout memtypes we support */
255 if (dev_priv->card_type >= NV_C0) { 275 if (dev_priv->card_type >= NV_C0) {
256 ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19, 276 ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,