diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-12-04 23:56:37 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-02-20 01:00:18 -0500 |
commit | 68197b4ba0a3c90190795b97248b840a3e506545 (patch) | |
tree | e9e5b0afea8c893950603d147481d5a2a48fc24f /drivers/gpu/drm | |
parent | 9cbcd3374a1db6a2faeb660bb49feb9af25c84ec (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.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | 1 |
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 | ||
82 | int | 82 | int |
83 | nv40_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 | |||
95 | int | ||
83 | nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) | 96 | nv40_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 | |||
109 | nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) | 122 | nv40_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 | ||
57 | int | 57 | int |
58 | nv50_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 | |||
67 | int | ||
58 | nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) | 68 | nv50_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 | |||
32 | pwm_info(struct nouveau_therm *therm, int line) | 32 | pwm_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 | ||
48 | static int | 52 | static int |
49 | nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) | 53 | nvd0_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 | ||
60 | static int | 64 | static int |
65 | nvd0_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 | |||
80 | static int | ||
61 | nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) | 81 | nvd0_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 *); |