From 7238eca4cf18a5bba8679afc8c71a274e264f82e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 13 Jun 2014 14:17:09 +1000 Subject: [PATCH] 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 --- .../gpu/drm/nouveau/core/engine/device/ctrl.c | 25 ++++++++---- .../gpu/drm/nouveau/core/include/core/class.h | 7 +++- drivers/gpu/drm/nouveau/nouveau_sysfs.c | 38 +++++++++++++++---- 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 754fc1da6a0b..fb546f3a1af0 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 e0c812bc884f..d6fd2cbe4333 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 75dda2b07176..ab5afc50460a 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)); -- 2.20.1