Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfc732bb authored by Martin Peres's avatar Martin Peres Committed by Ben Skeggs
Browse files

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: default avatarMartin Peres <martin.peres@labri.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent bf6546b4
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -81,10 +81,10 @@ nouveau_therm_fan_set(struct nouveau_therm *therm, int percent)
	if (ret == 0) {
		divs = priv->bios_perf_fan.pwm_divisor;
		if (priv->bios_fan.pwm_freq) {
			/*XXX: PNVIO clock more than likely... */
			divs = 135000 /priv->bios_fan.pwm_freq;
			if (nv_device(therm)->chipset < 0xa3)
				divs /= 4;
			divs = 1;
			if (priv->fan.pwm_clock)
				divs = priv->fan.pwm_clock(therm);
			divs /= priv->bios_fan.pwm_freq;
		}

		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;
}

int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm)
{
	return 1;
}

int
nouveau_therm_fan_ctor(struct nouveau_therm *therm)
{
+27 −0
Original line number Diff line number Diff line
@@ -79,6 +79,32 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty)
	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
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_set = nv50_fan_pwm_set;
	priv->fan.pwm_clock = nv50_fan_pwm_clock;

	therm->temp_get = nv50_temp_get;
	therm->fan_get = nouveau_therm_fan_get;
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct nouveau_therm_priv {

		int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*);
		int (*pwm_set)(struct nouveau_therm *, int line, u32, u32);
		int (*pwm_clock)(struct nouveau_therm *);
	} fan;

	/* ic */