drm/nv50/pm: mostly nailed down fan pwm frequency selection
authorBen Skeggs <bskeggs@redhat.com>
Mon, 15 Aug 2011 06:13:34 +0000 (16:13 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 21 Dec 2011 09:01:11 +0000 (19:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_temp.c
drivers/gpu/drm/nouveau/nv50_pm.c

index 432be65..251eaf8 100644 (file)
@@ -524,6 +524,7 @@ struct nouveau_pm_memtimings {
 struct nouveau_pm_fan {
        u32 min_duty;
        u32 max_duty;
+       u32 pwm_freq;
 };
 
 struct nouveau_pm_engine {
index 3d20dca..6ea57c9 100644 (file)
@@ -206,13 +206,12 @@ nouveau_perf_init(struct drm_device *dev)
                if (version < 0x40) {
                        recordlen = perf[3] + (perf[4] * perf[5]);
                        entries   = perf[2];
+
+                       pm->pwm_divisor = ROM16(perf[6]);
                } else {
                        recordlen = perf[2] + (perf[3] * perf[4]);
                        entries   = perf[5];
                }
-
-               if (version < 0x30)
-                       pm->pwm_divisor = ROM16(perf[6]);
        } else {
                if (bios->data[bios->offset + 6] < 0x25) {
                        legacy_perf_init(dev);
index 97c172c..6364e4c 100644 (file)
@@ -164,6 +164,9 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
                        pm->fan.min_duty = value & 0xff;
                        pm->fan.max_duty = (value & 0xff00) >> 8;
                        break;
+               case 0x26:
+                       pm->fan.pwm_freq = value;
+                       break;
                }
                temp += recordlen;
        }
index 713c718..0cbf538 100644 (file)
@@ -201,6 +201,8 @@ nv50_pm_fanspeed_get(struct drm_device *dev)
 int
 nv50_pm_fanspeed_set(struct drm_device *dev, int percent)
 {
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
        struct pwm_info pwm;
        u32 divs, duty;
        int ret;
@@ -209,12 +211,20 @@ nv50_pm_fanspeed_set(struct drm_device *dev, int percent)
        if (ret)
                return ret;
 
-       divs = nv_rd32(dev, 0x00e114 + (pwm.id * 8));
+       divs = pm->pwm_divisor;
+       if (pm->fan.pwm_freq) {
+               /*XXX: PNVIO clock more than likely... */
+               divs = 1350000 / pm->fan.pwm_freq;
+               if (dev_priv->chipset < 0xa3)
+                       divs /= 4;
+       }
+
        duty = ((divs * percent) + 99) / 100;
        if (pwm.invert)
                duty = divs - duty;
 
        nv_mask(dev, pwm.ctrl, 0x00010001 << pwm.line, 0x00000001 << pwm.line);
+       nv_wr32(dev, 0x00e114 + (pwm.id * 8), divs);
        nv_wr32(dev, 0x00e118 + (pwm.id * 8), 0x80000000 | duty);
        return 0;
 }