]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nv04_crtc.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nv04_crtc.c
index 497df8765f28489c0dbaf34f0cdde137de46c80c..40e180741629e056f72445ffab06104760bd70ec 100644 (file)
@@ -33,6 +33,7 @@
 #include "nouveau_fb.h"
 #include "nouveau_hw.h"
 #include "nvreg.h"
+#include "nouveau_fbcon.h"
 
 static int
 nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
@@ -109,7 +110,7 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod
        struct nouveau_pll_vals *pv = &regp->pllvals;
        struct pll_lims pll_lim;
 
-       if (get_pll_limits(dev, nv_crtc->index ? VPLL2 : VPLL1, &pll_lim))
+       if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim))
                return;
 
        /* NM2 == 0 is used to determine single stage mode on two stage plls */
@@ -157,7 +158,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct drm_device *dev = crtc->dev;
-       struct drm_connector *connector;
        unsigned char seq1 = 0, crtc17 = 0;
        unsigned char crtc1A;
 
@@ -212,10 +212,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
        NVVgaSeqReset(dev, nv_crtc->index, false);
 
        NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
-
-       /* Update connector polling modes */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-               nouveau_connector_set_polling(connector);
 }
 
 static bool
@@ -718,6 +714,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
 
        drm_crtc_cleanup(crtc);
 
+       nouveau_bo_unmap(nv_crtc->cursor.nvbo);
        nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
        kfree(nv_crtc);
 }
@@ -768,8 +765,9 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
 }
 
 static int
-nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-                       struct drm_framebuffer *old_fb)
+nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
+                          struct drm_framebuffer *passed_fb,
+                          int x, int y, bool atomic)
 {
        struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
        struct drm_device *dev = crtc->dev;
@@ -780,13 +778,26 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        int arb_burst, arb_lwm;
        int ret;
 
-       ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
-       if (ret)
-               return ret;
+       /* 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.)
+        */
+       if (atomic) {
+               drm_fb = passed_fb;
+               fb = nouveau_framebuffer(passed_fb);
+       }
+       else {
+               /* 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 (old_fb) {
-               struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb);
-               nouveau_bo_unpin(ofb->nvbo);
+               if (passed_fb) {
+                       struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
+                       nouveau_bo_unpin(ofb->nvbo);
+               }
        }
 
        nv_crtc->fb.offset = fb->nvbo->bo.offset;
@@ -815,7 +826,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        /* Update the framebuffer location. */
        regp->fb_start = nv_crtc->fb.offset & ~3;
        regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8);
-       NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start);
+       nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start);
 
        /* Update the arbitration parameters. */
        nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel,
@@ -826,7 +837,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX);
        crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX);
 
-       if (dev_priv->card_type >= NV_30) {
+       if (dev_priv->card_type >= NV_20) {
                regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8;
                crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47);
        }
@@ -834,6 +845,29 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
        return 0;
 }
 
+static int
+nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+                       struct drm_framebuffer *old_fb)
+{
+       return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
+}
+
+static int
+nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
+                              struct drm_framebuffer *fb,
+                              int x, int y, enum mode_set_atomic state)
+{
+       struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+       struct drm_device *dev = dev_priv->dev;
+
+       if (state == ENTER_ATOMIC_MODE_SET)
+               nouveau_fbcon_save_disable_accel(dev);
+       else
+               nouveau_fbcon_restore_accel(dev);
+
+       return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
+}
+
 static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
                               struct nouveau_bo *dst)
 {
@@ -962,6 +996,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
        .mode_fixup = nv_crtc_mode_fixup,
        .mode_set = nv_crtc_mode_set,
        .mode_set_base = nv04_crtc_mode_set_base,
+       .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
        .load_lut = nv_crtc_gamma_load,
 };