]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/nouveau/dispnv04/crtc.c
Merge branch 'drm-next-3.12' of git://people.freedesktop.org/~agd5f/linux into drm...
[karo-tx-linux.git] / drivers / gpu / drm / nouveau / dispnv04 / crtc.c
index 6413552df21cd3296a16f78907230dd16d0827b3..d4fbf11360febee34d2774c08233944c6b546fc4 100644 (file)
@@ -607,6 +607,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
        regp->ramdac_a34 = 0x1;
 }
 
+static int
+nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       int ret;
+
+       ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
+       if (ret == 0) {
+               if (disp->image[nv_crtc->index])
+                       nouveau_bo_unpin(disp->image[nv_crtc->index]);
+               nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
+       }
+
+       return ret;
+}
+
 /**
  * Sets up registers for the given mode/adjusted_mode pair.
  *
@@ -623,10 +641,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct drm_device *dev = crtc->dev;
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct nouveau_drm *drm = nouveau_drm(dev);
+       int ret;
 
        NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
        drm_mode_debug_printmodeline(adjusted_mode);
 
+       ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
+
        /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
        nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
 
@@ -723,6 +746,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
 {
+       struct nv04_display *disp = nv04_display(crtc->dev);
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
        if (!nv_crtc)
@@ -730,6 +754,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 
        drm_crtc_cleanup(crtc);
 
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+
        nouveau_bo_unmap(nv_crtc->cursor.nvbo);
        nouveau_bo_unpin(nv_crtc->cursor.nvbo);
        nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
@@ -754,6 +782,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
        nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
 }
 
+static void
+nv_crtc_disable(struct drm_crtc *crtc)
+{
+       struct nv04_display *disp = nv04_display(crtc->dev);
+       struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+       if (disp->image[nv_crtc->index])
+               nouveau_bo_unpin(disp->image[nv_crtc->index]);
+       nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
+}
+
 static void
 nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
                  uint32_t size)
@@ -792,7 +830,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        struct drm_framebuffer *drm_fb;
        struct nouveau_framebuffer *fb;
        int arb_burst, arb_lwm;
-       int ret;
 
        NV_DEBUG(drm, "index %d\n", nv_crtc->index);
 
@@ -802,10 +839,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
                return 0;
        }
 
-
        /* If atomic, we want to switch to the fb we were passed, so
-        * now we update pointers to do that.  (We don't pin; just
-        * assume we're already pinned and update the base address.)
+        * now we update pointers to do that.
         */
        if (atomic) {
                drm_fb = passed_fb;
@@ -813,17 +848,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
        } else {
                drm_fb = crtc->fb;
                fb = nouveau_framebuffer(crtc->fb);
-               /* If not atomic, we can go ahead and pin, and unpin the
-                * old fb we were passed.
-                */
-               ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
-               if (ret)
-                       return ret;
-
-               if (passed_fb) {
-                       struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
-                       nouveau_bo_unpin(ofb->nvbo);
-               }
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -878,6 +902,9 @@ static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
                        struct drm_framebuffer *old_fb)
 {
+       int ret = nv_crtc_swap_fbs(crtc, old_fb);
+       if (ret)
+               return ret;
        return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
@@ -1074,6 +1101,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
        .mode_set_base = nv04_crtc_mode_set_base,
        .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
        .load_lut = nv_crtc_gamma_load,
+       .disable = nv_crtc_disable,
 };
 
 int