diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-10-05 21:51:45 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 04:01:15 -0500 |
commit | 549cd872b0777bd72a66daa56558af28ec20d8a5 (patch) | |
tree | 24e3855e21d373634da7e679cb83c821bf1a4749 /drivers/gpu | |
parent | b2337f2333c0bdefc9b230da17ed7188e4eb7f6c (diff) |
drm/nv50/crtc: disable flip overlay around scaling mode changes
Prevents EVO getting all angry at us.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 882080e0b4f5..8eb108b28eb1 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -38,6 +38,39 @@ | |||
38 | #include "nouveau_connector.h" | 38 | #include "nouveau_connector.h" |
39 | #include "nv50_display.h" | 39 | #include "nv50_display.h" |
40 | 40 | ||
41 | static int | ||
42 | nv50_crtc_wait_complete(struct drm_crtc *crtc) | ||
43 | { | ||
44 | struct drm_device *dev = crtc->dev; | ||
45 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
46 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
47 | struct nv50_display *disp = nv50_display(dev); | ||
48 | struct nouveau_channel *evo = disp->master; | ||
49 | u64 start; | ||
50 | int ret; | ||
51 | |||
52 | ret = RING_SPACE(evo, 6); | ||
53 | if (ret) | ||
54 | return ret; | ||
55 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
56 | OUT_RING (evo, 0x80000000); | ||
57 | BEGIN_RING(evo, 0, 0x0080, 1); | ||
58 | OUT_RING (evo, 0); | ||
59 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
60 | OUT_RING (evo, 0x00000000); | ||
61 | |||
62 | nv_wo32(disp->ntfy, 0x000, 0x00000000); | ||
63 | FIRE_RING (evo); | ||
64 | |||
65 | start = ptimer->read(dev); | ||
66 | do { | ||
67 | if (nv_ro32(disp->ntfy, 0x000)) | ||
68 | return 0; | ||
69 | } while (ptimer->read(dev) - start < 2000000000ULL); | ||
70 | |||
71 | return -EBUSY; | ||
72 | } | ||
73 | |||
41 | static void | 74 | static void |
42 | nv50_crtc_lut_load(struct drm_crtc *crtc) | 75 | nv50_crtc_lut_load(struct drm_crtc *crtc) |
43 | { | 76 | { |
@@ -184,10 +217,11 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
184 | { | 217 | { |
185 | struct nouveau_connector *nv_connector = | 218 | struct nouveau_connector *nv_connector = |
186 | nouveau_crtc_connector_get(nv_crtc); | 219 | nouveau_crtc_connector_get(nv_crtc); |
187 | struct drm_device *dev = nv_crtc->base.dev; | 220 | struct drm_crtc *crtc = &nv_crtc->base; |
221 | struct drm_device *dev = crtc->dev; | ||
188 | struct nouveau_channel *evo = nv50_display(dev)->master; | 222 | struct nouveau_channel *evo = nv50_display(dev)->master; |
189 | struct drm_display_mode *native_mode = NULL; | 223 | struct drm_display_mode *native_mode = NULL; |
190 | struct drm_display_mode *mode = &nv_crtc->base.mode; | 224 | struct drm_display_mode *mode = &crtc->mode; |
191 | uint32_t outX, outY, horiz, vert; | 225 | uint32_t outX, outY, horiz, vert; |
192 | int ret; | 226 | int ret; |
193 | 227 | ||
@@ -231,7 +265,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
231 | break; | 265 | break; |
232 | } | 266 | } |
233 | 267 | ||
234 | ret = RING_SPACE(evo, update ? 7 : 5); | 268 | ret = RING_SPACE(evo, 5); |
235 | if (ret) | 269 | if (ret) |
236 | return ret; | 270 | return ret; |
237 | 271 | ||
@@ -251,9 +285,9 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
251 | OUT_RING(evo, outY << 16 | outX); | 285 | OUT_RING(evo, outY << 16 | outX); |
252 | 286 | ||
253 | if (update) { | 287 | if (update) { |
254 | BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); | 288 | nv50_display_flip_stop(crtc); |
255 | OUT_RING(evo, 0); | 289 | nv50_crtc_wait_complete(crtc); |
256 | FIRE_RING(evo); | 290 | nv50_display_flip_next(crtc, crtc->fb, NULL); |
257 | } | 291 | } |
258 | 292 | ||
259 | return 0; | 293 | return 0; |
@@ -441,39 +475,6 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
441 | { | 475 | { |
442 | } | 476 | } |
443 | 477 | ||
444 | static int | ||
445 | nv50_crtc_wait_complete(struct drm_crtc *crtc) | ||
446 | { | ||
447 | struct drm_device *dev = crtc->dev; | ||
448 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
449 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
450 | struct nv50_display *disp = nv50_display(dev); | ||
451 | struct nouveau_channel *evo = disp->master; | ||
452 | u64 start; | ||
453 | int ret; | ||
454 | |||
455 | ret = RING_SPACE(evo, 6); | ||
456 | if (ret) | ||
457 | return ret; | ||
458 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
459 | OUT_RING (evo, 0x80000000); | ||
460 | BEGIN_RING(evo, 0, 0x0080, 1); | ||
461 | OUT_RING (evo, 0); | ||
462 | BEGIN_RING(evo, 0, 0x0084, 1); | ||
463 | OUT_RING (evo, 0x00000000); | ||
464 | |||
465 | nv_wo32(disp->ntfy, 0x000, 0x00000000); | ||
466 | FIRE_RING (evo); | ||
467 | |||
468 | start = ptimer->read(dev); | ||
469 | do { | ||
470 | if (nv_ro32(disp->ntfy, 0x000)) | ||
471 | return 0; | ||
472 | } while (ptimer->read(dev) - start < 2000000000ULL); | ||
473 | |||
474 | return -EBUSY; | ||
475 | } | ||
476 | |||
477 | static void | 478 | static void |
478 | nv50_crtc_prepare(struct drm_crtc *crtc) | 479 | nv50_crtc_prepare(struct drm_crtc *crtc) |
479 | { | 480 | { |