2 * Copyright (C) 2009 Red Hat <bskeggs@redhat.com>
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Ben Skeggs <bskeggs@redhat.com>
31 #include <linux/debugfs.h>
32 #include <nvif/class.h>
33 #include <nvif/if0001.h>
34 #include "nouveau_debugfs.h"
35 #include "nouveau_drv.h"
38 nouveau_debugfs_vbios_image(struct seq_file
*m
, void *data
)
40 struct drm_info_node
*node
= (struct drm_info_node
*) m
->private;
41 struct nouveau_drm
*drm
= nouveau_drm(node
->minor
->dev
);
44 for (i
= 0; i
< drm
->vbios
.length
; i
++)
45 seq_printf(m
, "%c", drm
->vbios
.data
[i
]);
50 nouveau_debugfs_pstate_get(struct seq_file
*m
, void *data
)
52 struct drm_device
*drm
= m
->private;
53 struct nouveau_debugfs
*debugfs
= nouveau_debugfs(drm
);
54 struct nvif_object
*ctrl
= &debugfs
->ctrl
;
55 struct nvif_control_pstate_info_v0 info
= {};
61 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_INFO
, &info
, sizeof(info
));
65 for (i
= 0; i
< info
.count
+ 1; i
++) {
66 const s32 state
= i
< info
.count
? i
:
67 NVIF_CONTROL_PSTATE_ATTR_V0_STATE_CURRENT
;
68 struct nvif_control_pstate_attr_v0 attr
= {
73 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_ATTR
,
79 seq_printf(m
, "%02x:", attr
.state
);
81 seq_printf(m
, "%s:", info
.pwrsrc
== 0 ? "DC" :
82 info
.pwrsrc
== 1 ? "AC" : "--");
87 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_ATTR
,
92 seq_printf(m
, " %s %d", attr
.name
, attr
.min
);
93 if (attr
.min
!= attr
.max
)
94 seq_printf(m
, "-%d", attr
.max
);
95 seq_printf(m
, " %s", attr
.unit
);
99 if (info
.ustate_ac
== state
)
100 seq_printf(m
, " AC");
101 if (info
.ustate_dc
== state
)
102 seq_printf(m
, " DC");
103 if (info
.pstate
== state
)
106 if (info
.ustate_ac
< -1)
107 seq_printf(m
, " AC");
108 if (info
.ustate_dc
< -1)
109 seq_printf(m
, " DC");
119 nouveau_debugfs_pstate_set(struct file
*file
, const char __user
*ubuf
,
120 size_t len
, loff_t
*offp
)
122 struct seq_file
*m
= file
->private_data
;
123 struct drm_device
*drm
= m
->private;
124 struct nouveau_debugfs
*debugfs
= nouveau_debugfs(drm
);
125 struct nvif_object
*ctrl
= &debugfs
->ctrl
;
126 struct nvif_control_pstate_user_v0 args
= { .pwrsrc
= -EINVAL
};
127 char buf
[32] = {}, *tmp
, *cur
= buf
;
133 if (len
>= sizeof(buf
))
136 if (copy_from_user(buf
, ubuf
, len
))
139 if ((tmp
= strchr(buf
, '\n')))
142 if (!strncasecmp(cur
, "dc:", 3)) {
146 if (!strncasecmp(cur
, "ac:", 3)) {
151 if (!strcasecmp(cur
, "none"))
152 args
.ustate
= NVIF_CONTROL_PSTATE_USER_V0_STATE_UNKNOWN
;
154 if (!strcasecmp(cur
, "auto"))
155 args
.ustate
= NVIF_CONTROL_PSTATE_USER_V0_STATE_PERFMON
;
157 ret
= kstrtol(cur
, 16, &value
);
163 ret
= pm_runtime_get_sync(drm
->dev
);
164 if (IS_ERR_VALUE(ret
) && ret
!= -EACCES
)
166 ret
= nvif_mthd(ctrl
, NVIF_CONTROL_PSTATE_USER
, &args
, sizeof(args
));
167 pm_runtime_put_autosuspend(drm
->dev
);
175 nouveau_debugfs_pstate_open(struct inode
*inode
, struct file
*file
)
177 return single_open(file
, nouveau_debugfs_pstate_get
, inode
->i_private
);
180 static const struct file_operations nouveau_pstate_fops
= {
181 .owner
= THIS_MODULE
,
182 .open
= nouveau_debugfs_pstate_open
,
184 .write
= nouveau_debugfs_pstate_set
,
187 static struct drm_info_list nouveau_debugfs_list
[] = {
188 { "vbios.rom", nouveau_debugfs_vbios_image
, 0, NULL
},
190 #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
192 static const struct nouveau_debugfs_files
{
194 const struct file_operations
*fops
;
195 } nouveau_debugfs_files
[] = {
196 {"pstate", &nouveau_pstate_fops
},
200 nouveau_drm_debugfs_init(struct drm_minor
*minor
)
202 struct dentry
*dentry
;
205 for (i
= 0; i
< ARRAY_SIZE(nouveau_debugfs_files
); i
++) {
206 dentry
= debugfs_create_file(nouveau_debugfs_files
[i
].name
,
208 minor
->debugfs_root
, minor
->dev
,
209 nouveau_debugfs_files
[i
].fops
);
214 return drm_debugfs_create_files(nouveau_debugfs_list
,
215 NOUVEAU_DEBUGFS_ENTRIES
,
216 minor
->debugfs_root
, minor
);
220 nouveau_debugfs_init(struct nouveau_drm
*drm
)
224 drm
->debugfs
= kzalloc(sizeof(*drm
->debugfs
), GFP_KERNEL
);
228 ret
= nvif_object_init(&drm
->client
.device
.object
, 0,
229 NVIF_CLASS_CONTROL
, NULL
, 0,
230 &drm
->debugfs
->ctrl
);
238 nouveau_debugfs_fini(struct nouveau_drm
*drm
)
240 if (drm
->debugfs
&& drm
->debugfs
->ctrl
.priv
)
241 nvif_object_fini(&drm
->debugfs
->ctrl
);