Signed-off-by: Karol Herbst <nouv...@karolherbst.de> --- drm/nouveau/nouveau_debugfs.c | 144 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-)
diff --git a/drm/nouveau/nouveau_debugfs.c b/drm/nouveau/nouveau_debugfs.c index 53d2233..d024ffa 100644 --- a/drm/nouveau/nouveau_debugfs.c +++ b/drm/nouveau/nouveau_debugfs.c @@ -45,6 +45,145 @@ nouveau_debugfs_vbios_image(struct seq_file *m, void *data) return 0; } +static int +nouveau_debugfs_pstate_get(struct seq_file *m, void *data) +{ + struct nouveau_debugfs *debugfs = nouveau_debugfs(m->private); + struct nvif_object *ctrl; + struct nvif_control_pstate_info_v0 info = {}; + int ret, i; + + if (!debugfs) + return -ENODEV; + + ctrl = &debugfs->ctrl; + + ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_INFO, + &info, sizeof(info)); + if (ret) + return ret; + + for (i = 0; i < info.count + 1; i++) { + const s32 state = i < info.count ? i : + NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT; + struct nvif_control_pstate_attr_v0 attr = { + .state = state, + .index = 0, + }; + + ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_ATTR, + &attr, sizeof(attr)); + if (ret) + return ret; + + if (i < info.count) + seq_printf(m, "%02x:", attr.state); + else + seq_printf(m, "%s:", info.pwrsrc == 0 ? "DC" : + info.pwrsrc == 1 ? "AC" : + "--"); + + attr.index = 0; + do { + attr.state = state; + ret = nvif_mthd(ctrl, + NVIF_CONTROL_PSTATE_ATTR, + &attr, sizeof(attr)); + if (ret) + return ret; + + seq_printf(m, " %s %d", attr.name, attr.min); + if (attr.min != attr.max) + seq_printf(m, "-%d", attr.max); + seq_printf(m, " %s", attr.unit); + } while (attr.index); + + if (state >= 0) { + if (info.ustate_ac == state) + seq_printf(m, " AC"); + if (info.ustate_dc == state) + seq_printf(m, " DC"); + if (info.pstate == state) + seq_printf(m, " *"); + } else { + if (info.ustate_ac < -1) + seq_printf(m, " AC"); + if (info.ustate_dc < -1) + seq_printf(m, " DC"); + } + + seq_printf(m, "\n"); + } + + return 0; +} + +static ssize_t +nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct nouveau_debugfs *debugfs = nouveau_debugfs(m->private); + struct nvif_object *ctrl; + struct nvif_control_pstate_user_v0 args = { .pwrsrc = -EINVAL }; + char buf[32] = {}, *tmp, *cur = buf; + long value, ret; + + if (!debugfs) + return -ENODEV; + + ctrl = &debugfs->ctrl; + + if (len >= sizeof(buf)) + return -EINVAL; + + if (copy_from_user(buf, ubuf, len)) + return -EFAULT; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (!strncasecmp(cur, "dc:", 3)) { + args.pwrsrc = 0; + cur += 3; + } else + if (!strncasecmp(cur, "ac:", 3)) { + args.pwrsrc = 1; + cur += 3; + } + + if (!strcasecmp(cur, "none")) + args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN; + else + if (!strcasecmp(cur, "auto")) + args.ustate = NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON; + else { + ret = kstrtol(cur, 16, &value); + if (ret) + return ret; + args.ustate = value; + } + + ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, + &args, sizeof(args)); + if (ret < 0) + return ret; + + return len; +} + +static int +nouveau_debugfs_pstate_open(struct inode *inode, struct file *file) +{ + return single_open(file, nouveau_debugfs_pstate_get, inode->i_private); +} + +static const struct file_operations nouveau_pstate_fops = { + .owner = THIS_MODULE, + .open = nouveau_debugfs_pstate_open, + .read = seq_read, + .write = nouveau_debugfs_pstate_set, +}; + static struct drm_info_list nouveau_debugfs_list[] = { { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, }; @@ -53,8 +192,9 @@ static struct drm_info_list nouveau_debugfs_list[] = { static const struct nouveau_debugfs_files { const char *name; const struct file_operations *fops; -} nouveau_debugfs_files[] = {}; - +} nouveau_debugfs_files[] = { + {"pstate", &nouveau_pstate_fops}, +}; static int nouveau_debugfs_create_file(struct drm_minor *minor, -- 2.6.1 _______________________________________________ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau