aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-12-04 23:56:37 -0500
committerBen Skeggs <bskeggs@redhat.com>2013-02-20 01:00:18 -0500
commit68197b4ba0a3c90190795b97248b840a3e506545 (patch)
treee9e5b0afea8c893950603d147481d5a2a48fc24f /drivers/gpu/drm
parent9cbcd3374a1db6a2faeb660bb49feb9af25c84ec (diff)
drm/nouveau/therm: add interfaces to allow forcing off pwm fan control
Mostly to allow for the possibility of testing 'toggle' fan control easily. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Martin Peres <martin.peres@labri.fr>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c18
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c12
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c31
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h1
5 files changed, 56 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
index 4822733ca885..b4d14490d09e 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
@@ -96,6 +96,8 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent)
96 duty = divs - duty; 96 duty = divs - duty;
97 97
98 ret = priv->fan.pwm_set(therm, func.line, divs, duty); 98 ret = priv->fan.pwm_set(therm, func.line, divs, duty);
99 if (ret == 0)
100 ret = priv->fan.pwm_ctrl(therm, func.line, true);
99 return ret; 101 return ret;
100 } 102 }
101 103
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
index f2092af62ce3..47a15ecbe008 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
@@ -80,6 +80,19 @@ nv40_temp_get(struct nouveau_therm *therm)
80} 80}
81 81
82int 82int
83nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
84{
85 u32 mask = enable ? 0x80000000 : 0x0000000;
86 if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask);
87 else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask);
88 else {
89 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
90 return -ENODEV;
91 }
92 return 0;
93}
94
95int
83nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 96nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
84{ 97{
85 if (line == 2) { 98 if (line == 2) {
@@ -109,11 +122,11 @@ int
109nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) 122nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
110{ 123{
111 if (line == 2) { 124 if (line == 2) {
112 nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); 125 nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
113 } else 126 } else
114 if (line == 9) { 127 if (line == 9) {
115 nv_wr32(therm, 0x0015f8, divs); 128 nv_wr32(therm, 0x0015f8, divs);
116 nv_wr32(therm, 0x0015f4, duty | 0x80000000); 129 nv_mask(therm, 0x0015f4, 0x7fffffff, duty);
117 } else { 130 } else {
118 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); 131 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
119 return -ENODEV; 132 return -ENODEV;
@@ -136,6 +149,7 @@ nv40_therm_ctor(struct nouveau_object *parent,
136 if (ret) 149 if (ret)
137 return ret; 150 return ret;
138 151
152 priv->base.fan.pwm_ctrl = nv40_fan_pwm_ctrl;
139 priv->base.fan.pwm_get = nv40_fan_pwm_get; 153 priv->base.fan.pwm_get = nv40_fan_pwm_get;
140 priv->base.fan.pwm_set = nv40_fan_pwm_set; 154 priv->base.fan.pwm_set = nv40_fan_pwm_set;
141 priv->base.base.temp_get = nv40_temp_get; 155 priv->base.base.temp_get = nv40_temp_get;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
index b7e1ecf93409..6ebad82e4feb 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
@@ -55,6 +55,16 @@ pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx)
55} 55}
56 56
57int 57int
58nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
59{
60 u32 data = enable ? 0x00000001 : 0x00000000;
61 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
62 if (ret == 0)
63 nv_mask(therm, ctrl, 0x00010001 << line, data << line);
64 return ret;
65}
66
67int
58nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 68nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
59{ 69{
60 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); 70 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
@@ -77,7 +87,6 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
77 if (ret) 87 if (ret)
78 return ret; 88 return ret;
79 89
80 nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line);
81 nv_wr32(therm, 0x00e114 + (id * 8), divs); 90 nv_wr32(therm, 0x00e114 + (id * 8), divs);
82 nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); 91 nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
83 return 0; 92 return 0;
@@ -129,6 +138,7 @@ nv50_therm_ctor(struct nouveau_object *parent,
129 if (ret) 138 if (ret)
130 return ret; 139 return ret;
131 140
141 priv->base.fan.pwm_ctrl = nv50_fan_pwm_ctrl;
132 priv->base.fan.pwm_get = nv50_fan_pwm_get; 142 priv->base.fan.pwm_get = nv50_fan_pwm_get;
133 priv->base.fan.pwm_set = nv50_fan_pwm_set; 143 priv->base.fan.pwm_set = nv50_fan_pwm_set;
134 priv->base.fan.pwm_clock = nv50_fan_pwm_clock; 144 priv->base.fan.pwm_clock = nv50_fan_pwm_clock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
index f0336a09cf9e..ec06e895b617 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
@@ -32,32 +32,52 @@ 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 if (gpio & 0x00000040) { 35 switch (gpio & 0x000000c0) {
36 case 0x00000000: /* normal mode, possibly pwm forced off by us */
37 case 0x00000040: /* nvio special */
36 switch (gpio & 0x0000001f) { 38 switch (gpio & 0x0000001f) {
37 case 0x19: return 1; 39 case 0x19: return 1;
38 case 0x1c: return 0; 40 case 0x1c: return 0;
39 default: 41 default:
40 break; 42 break;
41 } 43 }
44 default:
45 break;
42 } 46 }
43 47
44 nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio); 48 nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
45 return -EINVAL; 49 return -ENODEV;
46} 50}
47 51
48static int 52static int
49nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 53nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
50{ 54{
55 u32 data = enable ? 0x00000040 : 0x00000000;
51 int indx = pwm_info(therm, line); 56 int indx = pwm_info(therm, line);
52 if (indx < 0) 57 if (indx < 0)
53 return indx; 58 return indx;
54 59
55 *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); 60 nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
56 *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
57 return 0; 61 return 0;
58} 62}
59 63
60static int 64static int
65nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
66{
67 int indx = pwm_info(therm, line);
68 if (indx < 0)
69 return indx;
70
71 if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
72 *divs = nv_rd32(therm, 0x00e114 + (indx * 8));
73 *duty = nv_rd32(therm, 0x00e118 + (indx * 8));
74 return 0;
75 }
76
77 return -EINVAL;
78}
79
80static int
61nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) 81nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
62{ 82{
63 int indx = pwm_info(therm, line); 83 int indx = pwm_info(therm, line);
@@ -111,6 +131,7 @@ nvd0_therm_ctor(struct nouveau_object *parent,
111 if (ret) 131 if (ret)
112 return ret; 132 return ret;
113 133
134 priv->base.fan.pwm_ctrl = nvd0_fan_pwm_ctrl;
114 priv->base.fan.pwm_get = nvd0_fan_pwm_get; 135 priv->base.fan.pwm_get = nvd0_fan_pwm_get;
115 priv->base.fan.pwm_set = nvd0_fan_pwm_set; 136 priv->base.fan.pwm_set = nvd0_fan_pwm_set;
116 priv->base.fan.pwm_clock = nvd0_fan_pwm_clock; 137 priv->base.fan.pwm_clock = nvd0_fan_pwm_clock;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
index bb940e9d4e8f..a08ca85e43ff 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
@@ -47,6 +47,7 @@ struct nouveau_therm_priv {
47 47
48 struct dcb_gpio_func tach; 48 struct dcb_gpio_func tach;
49 49
50 int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
50 int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); 51 int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
51 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 52 int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
52 int (*pwm_clock)(struct nouveau_therm *); 53 int (*pwm_clock)(struct nouveau_therm *);