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

Commit 7238eca4 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: expose pstate selection per-power source in sysfs



echo ac:id >> pstate # select mode when on mains power
echo dc:id >> pstate # select mode when on battery
echo id >> pstate # select mode for both

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7e1ee633
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -41,14 +41,15 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,

	if (clk) {
		args->count = clk->state_nr;
		if (clk->pwrsrc)
			args->ustate = clk->ustate_ac;
		else
			args->ustate = clk->ustate_dc;
		args->ustate_ac = clk->ustate_ac;
		args->ustate_dc = clk->ustate_dc;
		args->pwrsrc = clk->pwrsrc;
		args->pstate = clk->pstate;
	} else {
		args->count = 0;
		args->ustate = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
		args->ustate_ac = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
		args->ustate_dc = NV_CONTROL_PSTATE_INFO_USTATE_DISABLE;
		args->pwrsrc = -ENOSYS;
		args->pstate = NV_CONTROL_PSTATE_INFO_PSTATE_UNKNOWN;
	}

@@ -122,11 +123,19 @@ nouveau_control_mthd_pstate_user(struct nouveau_object *object, u32 mthd,
{
	struct nouveau_clock *clk = nouveau_clock(object);
	struct nv_control_pstate_user *args = data;
	int ret = 0;

	if (size < sizeof(*args) || !clk)
		return -EINVAL;

	return nouveau_clock_ustate(clk, args->state, clk->pwrsrc);
	if (args->pwrsrc >= 0) {
		ret |= nouveau_clock_ustate(clk, args->ustate, args->pwrsrc);
	} else {
		ret |= nouveau_clock_ustate(clk, args->ustate, 0);
		ret |= nouveau_clock_ustate(clk, args->ustate, 1);
	}

	return ret;
}

struct nouveau_oclass
+5 −2
Original line number Diff line number Diff line
@@ -148,7 +148,9 @@ struct nv_perfctr_read {

struct nv_control_pstate_info {
	u32 count; /* out: number of power states */
	s32 ustate; /* out: current target pstate index */
	s32 ustate_ac; /* out: target pstate index */
	s32 ustate_dc; /* out: target pstate index */
	s32 pwrsrc; /* out: current power source */
	u32 pstate; /* out: current pstate index */
};

@@ -166,7 +168,8 @@ struct nv_control_pstate_attr {
};

struct nv_control_pstate_user {
	s32 state; /*  in: pstate identifier */
	s32 ustate; /*  in: pstate identifier */
	s32 pwrsrc; /*  in: target power source */
};

/* DMA FIFO channel classes
+30 −8
Original line number Diff line number Diff line
@@ -68,7 +68,9 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
		if (i < info.count)
			snappendf(buf, cnt, "%02x:", attr.state);
		else
			snappendf(buf, cnt, "--:");
			snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" :
						   info.pwrsrc == 1 ? "AC" :
						   "--");

		attr.index = 0;
		do {
@@ -84,9 +86,20 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
			snappendf(buf, cnt, " %s", attr.unit);
		} while (attr.index);

		if ((state >= 0 && info.pstate == state) ||
		    (state <  0 && info.ustate < 0))
		if (state >= 0) {
			if (info.ustate_ac == state)
				snappendf(buf, cnt, " AC");
			if (info.ustate_dc == state)
				snappendf(buf, cnt, " DC");
			if (info.pstate == state)
				snappendf(buf, cnt, " *");
		} else {
			if (info.ustate_ac < -1)
				snappendf(buf, cnt, " AC");
			if (info.ustate_dc < -1)
				snappendf(buf, cnt, " DC");
		}

		snappendf(buf, cnt, "\n");
	}

@@ -98,23 +111,32 @@ nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a,
			 const char *buf, size_t count)
{
	struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
	struct nv_control_pstate_user args;
	struct nv_control_pstate_user args = { .pwrsrc = -EINVAL };
	long value, ret;
	char *tmp;

	if ((tmp = strchr(buf, '\n')))
		*tmp = '\0';

	if (!strncasecmp(buf, "dc:", 3)) {
		args.pwrsrc = 0;
		buf += 3;
	} else
	if (!strncasecmp(buf, "ac:", 3)) {
		args.pwrsrc = 1;
		buf += 3;
	}

	if (!strcasecmp(buf, "none"))
		args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
		args.ustate = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
	else
	if (!strcasecmp(buf, "auto"))
		args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
		args.ustate = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
	else {
		ret = kstrtol(buf, 16, &value);
		if (ret)
			return ret;
		args.state = value;
		args.ustate = value;
	}

	ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args));