|
@@ -443,6 +443,42 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+nv50_crtc_wait_complete(struct drm_crtc *crtc)
|
|
|
+{
|
|
|
+ struct drm_device *dev = crtc->dev;
|
|
|
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
|
|
|
+ struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
|
|
|
+ struct nv50_display *disp = nv50_display(dev);
|
|
|
+ struct nouveau_channel *evo = disp->master;
|
|
|
+ u64 start;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = RING_SPACE(evo, 6);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ BEGIN_RING(evo, 0, 0x0084, 1);
|
|
|
+ OUT_RING (evo, 0x80000000);
|
|
|
+ BEGIN_RING(evo, 0, 0x0080, 1);
|
|
|
+ OUT_RING (evo, 0);
|
|
|
+ BEGIN_RING(evo, 0, 0x0084, 1);
|
|
|
+ OUT_RING (evo, 0x00000000);
|
|
|
+
|
|
|
+ nv_wo32(disp->ntfy, 0x000, 0x00000000);
|
|
|
+ FIRE_RING (evo);
|
|
|
+
|
|
|
+ start = ptimer->read(dev);
|
|
|
+ do {
|
|
|
+ nv_wr32(dev, 0x61002c, 0x370);
|
|
|
+ nv_wr32(dev, 0x000140, 1);
|
|
|
+
|
|
|
+ if (nv_ro32(disp->ntfy, 0x000))
|
|
|
+ return 0;
|
|
|
+ } while (ptimer->read(dev) - start < 2000000000ULL);
|
|
|
+
|
|
|
+ return -EBUSY;
|
|
|
+}
|
|
|
+
|
|
|
static void
|
|
|
nv50_crtc_prepare(struct drm_crtc *crtc)
|
|
|
{
|
|
@@ -459,23 +495,13 @@ static void
|
|
|
nv50_crtc_commit(struct drm_crtc *crtc)
|
|
|
{
|
|
|
struct drm_device *dev = crtc->dev;
|
|
|
- struct nouveau_channel *evo = nv50_display(dev)->master;
|
|
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
|
|
- int ret;
|
|
|
|
|
|
NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
|
|
|
|
|
|
nv50_crtc_blank(nv_crtc, false);
|
|
|
drm_vblank_post_modeset(dev, nv_crtc->index);
|
|
|
-
|
|
|
- ret = RING_SPACE(evo, 2);
|
|
|
- if (ret) {
|
|
|
- NV_ERROR(dev, "no space while committing crtc\n");
|
|
|
- return;
|
|
|
- }
|
|
|
- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
|
|
|
- OUT_RING (evo, 0);
|
|
|
- FIRE_RING (evo);
|
|
|
+ nv50_crtc_wait_complete(crtc);
|
|
|
}
|
|
|
|
|
|
static bool
|
|
@@ -488,7 +514,7 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|
|
static int
|
|
|
nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|
|
struct drm_framebuffer *passed_fb,
|
|
|
- int x, int y, bool update, bool atomic)
|
|
|
+ int x, int y, bool atomic)
|
|
|
{
|
|
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
|
|
struct drm_device *dev = nv_crtc->base.dev;
|
|
@@ -598,15 +624,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|
|
nv50_crtc_lut_load(crtc);
|
|
|
}
|
|
|
|
|
|
- if (update) {
|
|
|
- ret = RING_SPACE(evo, 2);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
|
|
|
- OUT_RING(evo, 0);
|
|
|
- FIRE_RING(evo);
|
|
|
- }
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -696,14 +713,20 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|
|
nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
|
|
|
nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
|
|
|
|
|
|
- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false);
|
|
|
+ return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
struct drm_framebuffer *old_fb)
|
|
|
{
|
|
|
- return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return nv50_crtc_wait_complete(crtc);
|
|
|
}
|
|
|
|
|
|
static int
|
|
@@ -711,7 +734,13 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
|
|
|
struct drm_framebuffer *fb,
|
|
|
int x, int y, enum mode_set_atomic state)
|
|
|
{
|
|
|
- return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ return nv50_crtc_wait_complete(crtc);
|
|
|
}
|
|
|
|
|
|
static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
|