drm/nouveau/therm: calculate the pwm divisor on nv50+
v2: Martin Peres <martin.peres@labri.fr> - fixed unintentional use of floating point Signed-off-by: Martin Peres <martin.peres@labri.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
bf6546b421
commit
cfc732bbc5
|
@ -81,10 +81,10 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent)
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
divs = priv->bios_perf_fan.pwm_divisor;
|
divs = priv->bios_perf_fan.pwm_divisor;
|
||||||
if (priv->bios_fan.pwm_freq) {
|
if (priv->bios_fan.pwm_freq) {
|
||||||
/*XXX: PNVIO clock more than likely... */
|
divs = 1;
|
||||||
divs = 135000 /priv->bios_fan.pwm_freq;
|
if (priv->fan.pwm_clock)
|
||||||
if (nv_device(therm)->chipset < 0xa3)
|
divs = priv->fan.pwm_clock(therm);
|
||||||
divs /= 4;
|
divs /= priv->bios_fan.pwm_freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
duty = ((divs * percent) + 99) / 100;
|
duty = ((divs * percent) + 99) / 100;
|
||||||
|
@ -163,6 +163,11 @@ nouveau_therm_fan_safety_checks(struct nouveau_therm *therm)
|
||||||
priv->bios_fan.min_duty = priv->bios_fan.max_duty;
|
priv->bios_fan.min_duty = priv->bios_fan.max_duty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nouveau_therm_fan_ctor(struct nouveau_therm *therm)
|
nouveau_therm_fan_ctor(struct nouveau_therm *therm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,6 +79,32 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nv50_fan_pwm_clock(struct nouveau_therm *therm)
|
||||||
|
{
|
||||||
|
int chipset = nv_device(therm)->chipset;
|
||||||
|
int crystal = nv_device(therm)->crystal;
|
||||||
|
int pwm_clock;
|
||||||
|
|
||||||
|
/* determine the PWM source clock */
|
||||||
|
if (chipset > 0x50 && chipset < 0x94) {
|
||||||
|
u8 pwm_div = nv_rd32(therm, 0x410c);
|
||||||
|
if (nv_rd32(therm, 0xc040) & 0x800000) {
|
||||||
|
/* Use the HOST clock (100 MHz)
|
||||||
|
* Where does this constant(2.4) comes from? */
|
||||||
|
pwm_clock = (100000000 >> pwm_div) / 10 / 24;
|
||||||
|
} else {
|
||||||
|
/* Where does this constant(20) comes from? */
|
||||||
|
pwm_clock = (crystal * 1000) >> pwm_div;
|
||||||
|
pwm_clock /= 20;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pwm_clock = (crystal * 1000) / 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pwm_clock;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nv50_temp_get(struct nouveau_therm *therm)
|
nv50_temp_get(struct nouveau_therm *therm)
|
||||||
{
|
{
|
||||||
|
@ -107,6 +133,7 @@ nv50_therm_ctor(struct nouveau_object *parent,
|
||||||
|
|
||||||
priv->fan.pwm_get = nv50_fan_pwm_get;
|
priv->fan.pwm_get = nv50_fan_pwm_get;
|
||||||
priv->fan.pwm_set = nv50_fan_pwm_set;
|
priv->fan.pwm_set = nv50_fan_pwm_set;
|
||||||
|
priv->fan.pwm_clock = nv50_fan_pwm_clock;
|
||||||
|
|
||||||
therm->temp_get = nv50_temp_get;
|
therm->temp_get = nv50_temp_get;
|
||||||
therm->fan_get = nouveau_therm_fan_get;
|
therm->fan_get = nouveau_therm_fan_get;
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct nouveau_therm_priv {
|
||||||
|
|
||||||
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 *);
|
||||||
} fan;
|
} fan;
|
||||||
|
|
||||||
/* ic */
|
/* ic */
|
||||||
|
|
Loading…
Reference in New Issue