提交 7238eca4 编写于 作者: B Ben Skeggs

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: NBen Skeggs <bskeggs@redhat.com>
上级 7e1ee633
...@@ -40,15 +40,16 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd, ...@@ -40,15 +40,16 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
return -EINVAL; return -EINVAL;
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, ...@@ -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 { ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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, " *"); 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"); snappendf(buf, cnt, "\n");
} }
...@@ -98,23 +111,32 @@ nouveau_sysfs_pstate_set(struct device *d, struct device_attribute *a, ...@@ -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));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册