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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
7e1ee6333c
commit
7238eca4cf
|
@ -41,14 +41,15 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
|
||||||
|
|
||||||
if (clk) {
|
if (clk) {
|
||||||
args->count = clk->state_nr;
|
args->count = clk->state_nr;
|
||||||
if (clk->pwrsrc)
|
args->ustate_ac = clk->ustate_ac;
|
||||||
args->ustate = clk->ustate_ac;
|
args->ustate_dc = clk->ustate_dc;
|
||||||
else
|
args->pwrsrc = clk->pwrsrc;
|
||||||
args->ustate = clk->ustate_dc;
|
|
||||||
args->pstate = clk->pstate;
|
args->pstate = clk->pstate;
|
||||||
} else {
|
} else {
|
||||||
args->count = 0;
|
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;
|
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 nouveau_clock *clk = nouveau_clock(object);
|
||||||
struct nv_control_pstate_user *args = data;
|
struct nv_control_pstate_user *args = data;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (size < sizeof(*args) || !clk)
|
if (size < sizeof(*args) || !clk)
|
||||||
return -EINVAL;
|
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
|
struct nouveau_oclass
|
||||||
|
|
|
@ -148,7 +148,9 @@ struct nv_perfctr_read {
|
||||||
|
|
||||||
struct nv_control_pstate_info {
|
struct nv_control_pstate_info {
|
||||||
u32 count; /* out: number of power states */
|
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 */
|
u32 pstate; /* out: current pstate index */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,7 +168,8 @@ struct nv_control_pstate_attr {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nv_control_pstate_user {
|
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
|
/* DMA FIFO channel classes
|
||||||
|
|
|
@ -68,7 +68,9 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
|
||||||
if (i < info.count)
|
if (i < info.count)
|
||||||
snappendf(buf, cnt, "%02x:", attr.state);
|
snappendf(buf, cnt, "%02x:", attr.state);
|
||||||
else
|
else
|
||||||
snappendf(buf, cnt, "--:");
|
snappendf(buf, cnt, "%s:", info.pwrsrc == 0 ? "DC" :
|
||||||
|
info.pwrsrc == 1 ? "AC" :
|
||||||
|
"--");
|
||||||
|
|
||||||
attr.index = 0;
|
attr.index = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -84,9 +86,20 @@ nouveau_sysfs_pstate_get(struct device *d, struct device_attribute *a, char *b)
|
||||||
snappendf(buf, cnt, " %s", attr.unit);
|
snappendf(buf, cnt, " %s", attr.unit);
|
||||||
} while (attr.index);
|
} while (attr.index);
|
||||||
|
|
||||||
if ((state >= 0 && info.pstate == state) ||
|
if (state >= 0) {
|
||||||
(state < 0 && info.ustate < 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, " *");
|
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");
|
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)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct nouveau_sysfs *sysfs = nouveau_sysfs(drm_device(d));
|
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;
|
long value, ret;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
if ((tmp = strchr(buf, '\n')))
|
if ((tmp = strchr(buf, '\n')))
|
||||||
*tmp = '\0';
|
*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"))
|
if (!strcasecmp(buf, "none"))
|
||||||
args.state = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
|
args.ustate = NV_CONTROL_PSTATE_USER_STATE_UNKNOWN;
|
||||||
else
|
else
|
||||||
if (!strcasecmp(buf, "auto"))
|
if (!strcasecmp(buf, "auto"))
|
||||||
args.state = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
|
args.ustate = NV_CONTROL_PSTATE_USER_STATE_PERFMON;
|
||||||
else {
|
else {
|
||||||
ret = kstrtol(buf, 16, &value);
|
ret = kstrtol(buf, 16, &value);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
args.state = value;
|
args.ustate = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args));
|
ret = nv_exec(sysfs->ctrl, NV_CONTROL_PSTATE_USER, &args, sizeof(args));
|
||||||
|
|
Loading…
Reference in New Issue