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

Commit 3f8e11e4 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nv50/pm: mostly nailed down fan pwm frequency selection



Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 11b7d895
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -524,6 +524,7 @@ struct nouveau_pm_memtimings {
struct nouveau_pm_fan {
	u32 min_duty;
	u32 max_duty;
	u32 pwm_freq;
};

struct nouveau_pm_engine {
+2 −3
Original line number Diff line number Diff line
@@ -206,13 +206,12 @@ nouveau_perf_init(struct drm_device *dev)
		if (version < 0x40) {
			recordlen = perf[3] + (perf[4] * perf[5]);
			entries   = perf[2];

			pm->pwm_divisor = ROM16(perf[6]);
		} else {
			recordlen = perf[2] + (perf[3] * perf[4]);
			entries   = perf[5];
		}

		if (version < 0x30)
			pm->pwm_divisor = ROM16(perf[6]);
	} else {
		if (bios->data[bios->offset + 6] < 0x25) {
			legacy_perf_init(dev);
+3 −0
Original line number Diff line number Diff line
@@ -164,6 +164,9 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp)
			pm->fan.min_duty = value & 0xff;
			pm->fan.max_duty = (value & 0xff00) >> 8;
			break;
		case 0x26:
			pm->fan.pwm_freq = value;
			break;
		}
		temp += recordlen;
	}
+11 −1
Original line number Diff line number Diff line
@@ -201,6 +201,8 @@ nv50_pm_fanspeed_get(struct drm_device *dev)
int
nv50_pm_fanspeed_set(struct drm_device *dev, int percent)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
	struct pwm_info pwm;
	u32 divs, duty;
	int ret;
@@ -209,12 +211,20 @@ nv50_pm_fanspeed_set(struct drm_device *dev, int percent)
	if (ret)
		return ret;

	divs = nv_rd32(dev, 0x00e114 + (pwm.id * 8));
	divs = pm->pwm_divisor;
	if (pm->fan.pwm_freq) {
		/*XXX: PNVIO clock more than likely... */
		divs = 1350000 / pm->fan.pwm_freq;
		if (dev_priv->chipset < 0xa3)
			divs /= 4;
	}

	duty = ((divs * percent) + 99) / 100;
	if (pwm.invert)
		duty = divs - duty;

	nv_mask(dev, pwm.ctrl, 0x00010001 << pwm.line, 0x00000001 << pwm.line);
	nv_wr32(dev, 0x00e114 + (pwm.id * 8), divs);
	nv_wr32(dev, 0x00e118 + (pwm.id * 8), 0x80000000 | duty);
	return 0;
}