aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2014-02-17 21:56:11 -0500
committerBen Skeggs <bskeggs@redhat.com>2014-03-26 00:08:24 -0400
commit9c9191aaf844e237c025ef574e13d3e1c174c765 (patch)
tree2ad1f6317680d4a9fa4db13c145b78b99d5ad7cd
parent61679fe153b2b9ea5b5e2ab93305419e85e99a9d (diff)
drm/nvd7/therm: handle another kind of PWM fans
This should fix fan management on many nvd7+ chipsets. Signed-off-by: Martin Peres <martin.peres@labri.fr> Tested-by: Timothée Ravier <tim@siosm.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/therm.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c40
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h2
6 files changed, 35 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
index 69891d4a3fe7..d4a68179e586 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h
@@ -31,7 +31,7 @@ struct nouveau_therm {
31 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool); 31 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
32 int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *); 32 int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *);
33 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 33 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
34 int (*pwm_clock)(struct nouveau_therm *); 34 int (*pwm_clock)(struct nouveau_therm *, int line);
35 35
36 int (*fan_get)(struct nouveau_therm *); 36 int (*fan_get)(struct nouveau_therm *);
37 int (*fan_set)(struct nouveau_therm *, int); 37 int (*fan_set)(struct nouveau_therm *, int);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 29d4c417a5b3..ceb85281cbe9 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -242,7 +242,8 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm)
242 /* attempt to locate a drivable fan, and determine control method */ 242 /* attempt to locate a drivable fan, and determine control method */
243 ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); 243 ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func);
244 if (ret == 0) { 244 if (ret == 0) {
245 if (func.log[0] & DCB_GPIO_LOG_DIR_IN) { 245 /* FIXME: is this really the place to perform such checks ? */
246 if (func.line != 16 && func.log[0] & DCB_GPIO_LOG_DIR_IN) {
246 nv_debug(therm, "GPIO_FAN is in input mode\n"); 247 nv_debug(therm, "GPIO_FAN is in input mode\n");
247 ret = -EINVAL; 248 ret = -EINVAL;
248 } else { 249 } else {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
index 5f71db8e8992..9a5c07340263 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
@@ -67,7 +67,7 @@ nouveau_fanpwm_set(struct nouveau_therm *therm, int percent)
67 if (priv->base.bios.pwm_freq) { 67 if (priv->base.bios.pwm_freq) {
68 divs = 1; 68 divs = 1;
69 if (therm->pwm_clock) 69 if (therm->pwm_clock)
70 divs = therm->pwm_clock(therm); 70 divs = therm->pwm_clock(therm, priv->func.line);
71 divs /= priv->base.bios.pwm_freq; 71 divs /= priv->base.bios.pwm_freq;
72 } 72 }
73 73
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index 8cf7597a2182..321db927d638 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -93,7 +93,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
93} 93}
94 94
95int 95int
96nv50_fan_pwm_clock(struct nouveau_therm *therm) 96nv50_fan_pwm_clock(struct nouveau_therm *therm, int line)
97{ 97{
98 int chipset = nv_device(therm)->chipset; 98 int chipset = nv_device(therm)->chipset;
99 int crystal = nv_device(therm)->crystal; 99 int crystal = nv_device(therm)->crystal;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index 4dd4f81ae873..43fec17ea540 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -32,10 +32,12 @@ static int
32pwm_info(struct nouveau_therm *therm, int line) 32pwm_info(struct nouveau_therm *therm, int line)
33{ 33{
34 u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); 34 u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
35
35 switch (gpio & 0x000000c0) { 36 switch (gpio & 0x000000c0) {
36 case 0x00000000: /* normal mode, possibly pwm forced off by us */ 37 case 0x00000000: /* normal mode, possibly pwm forced off by us */
37 case 0x00000040: /* nvio special */ 38 case 0x00000040: /* nvio special */
38 switch (gpio & 0x0000001f) { 39 switch (gpio & 0x0000001f) {
40 case 0x00: return 2;
39 case 0x19: return 1; 41 case 0x19: return 1;
40 case 0x1c: return 0; 42 case 0x1c: return 0;
41 default: 43 default:
@@ -56,8 +58,9 @@ nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
56 int indx = pwm_info(therm, line); 58 int indx = pwm_info(therm, line);
57 if (indx < 0) 59 if (indx < 0)
58 return indx; 60 return indx;
59 61 else if (indx < 2)
60 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); 62 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
63 /* nothing to do for indx == 2, it seems hardwired to PTHERM */
61 return 0; 64 return 0;
62} 65}
63 66
@@ -67,10 +70,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
67 int indx = pwm_info(therm, line); 70 int indx = pwm_info(therm, line);
68 if (indx < 0) 71 if (indx < 0)
69 return indx; 72 return indx;
70 73 else if (indx < 2) {
71 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { 74 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
72 *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); 75 *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
73 *duty = nv_rd32(therm, 0x00e118 + (indx * 8)); 76 *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
77 return 0;
78 }
79 } else if (indx == 2) {
80 *divs = nv_rd32(therm, 0x0200d8) & 0x1fff;
81 *duty = nv_rd32(therm, 0x0200dc) & 0x1fff;
74 return 0; 82 return 0;
75 } 83 }
76 84
@@ -83,16 +91,26 @@ nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
83 int indx = pwm_info(therm, line); 91 int indx = pwm_info(therm, line);
84 if (indx < 0) 92 if (indx < 0)
85 return indx; 93 return indx;
86 94 else if (indx < 2) {
87 nv_wr32(therm, 0x00e114 + (indx * 8), divs); 95 nv_wr32(therm, 0x00e114 + (indx * 8), divs);
88 nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); 96 nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000);
97 } else if (indx == 2) {
98 nv_mask(therm, 0x0200d8, 0x1fff, divs); /* keep the high bits */
99 nv_wr32(therm, 0x0200dc, duty | 0x40000000);
100 }
89 return 0; 101 return 0;
90} 102}
91 103
92static int 104static int
93nvd0_fan_pwm_clock(struct nouveau_therm *therm) 105nvd0_fan_pwm_clock(struct nouveau_therm *therm, int line)
94{ 106{
95 return (nv_device(therm)->crystal * 1000) / 20; 107 int indx = pwm_info(therm, line);
108 if (indx < 0)
109 return 0;
110 else if (indx < 2)
111 return (nv_device(therm)->crystal * 1000) / 20;
112 else
113 return nv_device(therm)->crystal * 1000 / 10;
96} 114}
97 115
98static int 116static int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index 96f8f95693ce..916fca5c7816 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -143,7 +143,7 @@ void nv40_therm_intr(struct nouveau_subdev *);
143int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool); 143int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool);
144int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *); 144int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *);
145int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32); 145int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32);
146int nv50_fan_pwm_clock(struct nouveau_therm *); 146int nv50_fan_pwm_clock(struct nouveau_therm *, int);
147int nv84_temp_get(struct nouveau_therm *therm); 147int nv84_temp_get(struct nouveau_therm *therm);
148int nv84_therm_fini(struct nouveau_object *object, bool suspend); 148int nv84_therm_fini(struct nouveau_object *object, bool suspend);
149 149