diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dma.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 77 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_evo.c | 20 |
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 | ||
446 | static int | ||
447 | nv50_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 | |||
446 | static void | 482 | static void |
447 | nv50_crtc_prepare(struct drm_crtc *crtc) | 483 | nv50_crtc_prepare(struct drm_crtc *crtc) |
448 | { | 484 | { |
@@ -459,23 +495,13 @@ static void | |||
459 | nv50_crtc_commit(struct drm_crtc *crtc) | 495 | nv50_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 | ||
481 | static bool | 507 | static bool |
@@ -488,7 +514,7 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
488 | static int | 514 | static int |
489 | nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | 515 | nv50_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 | ||
702 | static int | 719 | static int |
703 | nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 720 | nv50_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 | ||
709 | static int | 732 | static 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 | ||
717 | static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { | 746 | static 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 | ||
38 | struct nv50_display { | 38 | struct 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, |