drm/nv50/disp: more accurate function to determine active crtcs
authorBen Skeggs <bskeggs@redhat.com>
Mon, 23 Jan 2012 03:22:58 +0000 (13:22 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 13 Mar 2012 07:08:29 +0000 (17:08 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Martin Peres <martin.peres@labri.fr>
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.h
drivers/gpu/drm/nouveau/nv50_pm.c

index 7ba28e08ee3198de2094c12e1c2376f53c7934f4..ce440e2e58ca8e2a8ed698d2dd5c3f5968ac16a4 100644 (file)
@@ -50,6 +50,29 @@ nv50_sor_nr(struct drm_device *dev)
        return 4;
 }
 
+u32
+nv50_display_active_crtcs(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       u32 mask = 0;
+       int i;
+
+       if (dev_priv->chipset  < 0x90 ||
+           dev_priv->chipset == 0x92 ||
+           dev_priv->chipset == 0xa0) {
+               for (i = 0; i < 2; i++)
+                       mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i));
+       } else {
+               for (i = 0; i < 4; i++)
+                       mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i));
+       }
+
+       for (i = 0; i < 3; i++)
+               mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i));
+
+       return mask & 3;
+}
+
 static int
 evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data)
 {
index 95874f7c043cf3aad9e80de35712cc9d1aad72f6..5d3dd14d2837c99023e96e8eb950a56031800678 100644 (file)
@@ -74,6 +74,8 @@ void nv50_display_destroy(struct drm_device *dev);
 int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
 int nv50_crtc_set_clock(struct drm_device *, int head, int pclk);
 
+u32  nv50_display_active_crtcs(struct drm_device *);
+
 int  nv50_display_sync(struct drm_device *);
 int  nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
                            struct nouveau_channel *chan);
index 17eb3277b1a02a2508687148860a31971820fe52..109e473fd5f873e946b3753b4dcf5fbc928501ff 100644 (file)
@@ -28,6 +28,7 @@
 #include "nouveau_hw.h"
 #include "nouveau_pm.h"
 #include "nouveau_hwsq.h"
+#include "nv50_display.h"
 
 enum clk_src {
        clk_src_crystal,
@@ -535,6 +536,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
          struct nv50_pm_state *info)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       u32 crtc_mask = nv50_display_active_crtcs(dev);
        struct nouveau_mem_exec_func exec = {
                .dev = dev,
                .precharge = mclk_precharge,
@@ -550,9 +552,8 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
        };
        struct hwsq_ucode *hwsq = &info->mclk_hwsq;
        struct pll_lims pll;
-       u32 crtc_mask = 0;
        int N, M, P;
-       int ret, i;
+       int ret;
 
        /* use pcie refclock if possible, otherwise use mpll */
        info->mctrl  = nv_rd32(dev, 0x004008);
@@ -569,12 +570,6 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
                info->mcoef  = (N << 8) | M;
        }
 
-       /* determine active crtcs */
-       for (i = 0; i < 2; i++) {
-               if (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(i, CLOCK)))
-                       crtc_mask |= (1 << i);
-       }
-
        /* build the ucode which will reclock the memory for us */
        hwsq_init(hwsq);
        if (crtc_mask) {