aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-06-13 14:17:09 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-08-10 05:11:08 +1000
commit7238eca4cf18a5bba8679afc8c71a274e264f82e (patch)
tree96014d6d02c4c8c6db819e36a70bbf4d8d986f78
parent7e1ee6333c32a4b83aad430a4bcb8a7057f36194 (diff)
downloadlinux-docs-7238eca4cf18a5bba8679afc8c71a274e264f82e.tar.gz
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>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/device/ctrl.c25
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/class.h7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sysfs.c38
3 files changed, 52 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
index 754fc1da6a0b9e..fb546f3a1af04e 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/ctrl.c
@@ -40,15 +40,16 @@ nouveau_control_mthd_pstate_info(struct nouveau_object *object, u32 mthd,
return -EINVAL;
if (clk) {
- args->count = clk->state_nr;
- if (clk->pwrsrc)
- args->ustate = clk->ustate_ac;
- else
- args->ustate = clk->ustate_dc;
+ args->count = clk->state_nr;
+ 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->count = 0;
+ 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
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index e0c812bc884f90..d6fd2cbe43334e 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -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
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
index 75dda2b0717614..ab5afc50460a4b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c
@@ -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))
- snappendf(buf, cnt, " *");
+ 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));