mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
9cbcd3374a
commit
68197b4ba0
|
@ -96,6 +96,8 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent)
|
||||||
duty = divs - duty;
|
duty = divs - duty;
|
||||||
|
|
||||||
ret = priv->fan.pwm_set(therm, func.line, divs, duty);
|
ret = priv->fan.pwm_set(therm, func.line, divs, duty);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = priv->fan.pwm_ctrl(therm, func.line, true);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,19 @@ nv40_temp_get(struct nouveau_therm *therm)
|
||||||
return core_temp;
|
return core_temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
|
||||||
|
{
|
||||||
|
u32 mask = enable ? 0x80000000 : 0x0000000;
|
||||||
|
if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask);
|
||||||
|
else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask);
|
||||||
|
else {
|
||||||
|
nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
|
nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
|
||||||
{
|
{
|
||||||
|
@ -109,11 +122,11 @@ int
|
||||||
nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
||||||
{
|
{
|
||||||
if (line == 2) {
|
if (line == 2) {
|
||||||
nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs);
|
nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs);
|
||||||
} else
|
} else
|
||||||
if (line == 9) {
|
if (line == 9) {
|
||||||
nv_wr32(therm, 0x0015f8, divs);
|
nv_wr32(therm, 0x0015f8, divs);
|
||||||
nv_wr32(therm, 0x0015f4, duty | 0x80000000);
|
nv_mask(therm, 0x0015f4, 0x7fffffff, duty);
|
||||||
} else {
|
} else {
|
||||||
nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
|
nv_error(therm, "unknown pwm ctrl for gpio %d\n", line);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -136,6 +149,7 @@ nv40_therm_ctor(struct nouveau_object *parent,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
priv->base.fan.pwm_ctrl = nv40_fan_pwm_ctrl;
|
||||||
priv->base.fan.pwm_get = nv40_fan_pwm_get;
|
priv->base.fan.pwm_get = nv40_fan_pwm_get;
|
||||||
priv->base.fan.pwm_set = nv40_fan_pwm_set;
|
priv->base.fan.pwm_set = nv40_fan_pwm_set;
|
||||||
priv->base.base.temp_get = nv40_temp_get;
|
priv->base.base.temp_get = nv40_temp_get;
|
||||||
|
|
|
@ -54,6 +54,16 @@ pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
|
||||||
|
{
|
||||||
|
u32 data = enable ? 0x00000001 : 0x00000000;
|
||||||
|
int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id);
|
||||||
|
if (ret == 0)
|
||||||
|
nv_mask(therm, ctrl, 0x00010001 << line, data << line);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
|
nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +87,6 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line);
|
|
||||||
nv_wr32(therm, 0x00e114 + (id * 8), divs);
|
nv_wr32(therm, 0x00e114 + (id * 8), divs);
|
||||||
nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
|
nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -129,6 +138,7 @@ nv50_therm_ctor(struct nouveau_object *parent,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
priv->base.fan.pwm_ctrl = nv50_fan_pwm_ctrl;
|
||||||
priv->base.fan.pwm_get = nv50_fan_pwm_get;
|
priv->base.fan.pwm_get = nv50_fan_pwm_get;
|
||||||
priv->base.fan.pwm_set = nv50_fan_pwm_set;
|
priv->base.fan.pwm_set = nv50_fan_pwm_set;
|
||||||
priv->base.fan.pwm_clock = nv50_fan_pwm_clock;
|
priv->base.fan.pwm_clock = nv50_fan_pwm_clock;
|
||||||
|
|
|
@ -32,17 +32,33 @@ static int
|
||||||
pwm_info(struct nouveau_therm *therm, int line)
|
pwm_info(struct nouveau_therm *therm, int line)
|
||||||
{
|
{
|
||||||
u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
|
u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04));
|
||||||
if (gpio & 0x00000040) {
|
switch (gpio & 0x000000c0) {
|
||||||
|
case 0x00000000: /* normal mode, possibly pwm forced off by us */
|
||||||
|
case 0x00000040: /* nvio special */
|
||||||
switch (gpio & 0x0000001f) {
|
switch (gpio & 0x0000001f) {
|
||||||
case 0x19: return 1;
|
case 0x19: return 1;
|
||||||
case 0x1c: return 0;
|
case 0x1c: return 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
|
nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio);
|
||||||
return -EINVAL;
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable)
|
||||||
|
{
|
||||||
|
u32 data = enable ? 0x00000040 : 0x00000000;
|
||||||
|
int indx = pwm_info(therm, line);
|
||||||
|
if (indx < 0)
|
||||||
|
return indx;
|
||||||
|
|
||||||
|
nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -52,11 +68,15 @@ nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty)
|
||||||
if (indx < 0)
|
if (indx < 0)
|
||||||
return indx;
|
return indx;
|
||||||
|
|
||||||
|
if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) {
|
||||||
*divs = nv_rd32(therm, 0x00e114 + (indx * 8));
|
*divs = nv_rd32(therm, 0x00e114 + (indx * 8));
|
||||||
*duty = nv_rd32(therm, 0x00e118 + (indx * 8));
|
*duty = nv_rd32(therm, 0x00e118 + (indx * 8));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
||||||
{
|
{
|
||||||
|
@ -111,6 +131,7 @@ nvd0_therm_ctor(struct nouveau_object *parent,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
priv->base.fan.pwm_ctrl = nvd0_fan_pwm_ctrl;
|
||||||
priv->base.fan.pwm_get = nvd0_fan_pwm_get;
|
priv->base.fan.pwm_get = nvd0_fan_pwm_get;
|
||||||
priv->base.fan.pwm_set = nvd0_fan_pwm_set;
|
priv->base.fan.pwm_set = nvd0_fan_pwm_set;
|
||||||
priv->base.fan.pwm_clock = nvd0_fan_pwm_clock;
|
priv->base.fan.pwm_clock = nvd0_fan_pwm_clock;
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct nouveau_therm_priv {
|
||||||
|
|
||||||
struct dcb_gpio_func tach;
|
struct dcb_gpio_func tach;
|
||||||
|
|
||||||
|
int (*pwm_ctrl)(struct nouveau_therm *, int line, bool);
|
||||||
int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
|
int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
|
||||||
int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
|
int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
|
||||||
int (*pwm_clock)(struct nouveau_therm *);
|
int (*pwm_clock)(struct nouveau_therm *);
|
||||||
|
|
Loading…
Reference in New Issue