aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wood <thomas.wood@intel.com>2014-06-18 12:52:32 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-19 02:56:01 -0400
commit30f6570798f6c897df4f1f2c676d803728bfec27 (patch)
tree2ff3e99b8286b75b0cac0a2c07cee9da9c6634bf
parent34ea3d386347cd6de4c2fa2491dd85c9e753e7e4 (diff)
drm/debugfs: add a "force" file per connector
Add a file to debugfs for each connector to enable modification of the "force" connector attribute. This allows connectors to be enabled or disabled for testing and debugging purposes. v2: Add stricter value checking and clean up debugfs_entry if file creation fails in drm_debugfs_connector_add. (David Herrmann) Signed-off-by: Thomas Wood <thomas.wood@intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/drm_crtc.c17
-rw-r--r--drivers/gpu/drm/drm_debugfs.c114
-rw-r--r--include/drm/drmP.h11
-rw-r--r--include/drm/drm_crtc.h2
4 files changed, 143 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index c50c827cefb6..c304e5650bc8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -881,6 +881,8 @@ int drm_connector_init(struct drm_device *dev,
881 drm_object_attach_property(&connector->base, 881 drm_object_attach_property(&connector->base,
882 dev->mode_config.dpms_property, 0); 882 dev->mode_config.dpms_property, 0);
883 883
884 connector->debugfs_entry = NULL;
885
884out_put: 886out_put:
885 if (ret) 887 if (ret)
886 drm_mode_object_put(dev, &connector->base); 888 drm_mode_object_put(dev, &connector->base);
@@ -931,7 +933,19 @@ EXPORT_SYMBOL(drm_connector_cleanup);
931 */ 933 */
932int drm_connector_register(struct drm_connector *connector) 934int drm_connector_register(struct drm_connector *connector)
933{ 935{
934 return drm_sysfs_connector_add(connector); 936 int ret;
937
938 ret = drm_sysfs_connector_add(connector);
939 if (ret)
940 return ret;
941
942 ret = drm_debugfs_connector_add(connector);
943 if (ret) {
944 drm_sysfs_connector_remove(connector);
945 return ret;
946 }
947
948 return 0;
935} 949}
936EXPORT_SYMBOL(drm_connector_register); 950EXPORT_SYMBOL(drm_connector_register);
937 951
@@ -944,6 +958,7 @@ EXPORT_SYMBOL(drm_connector_register);
944void drm_connector_unregister(struct drm_connector *connector) 958void drm_connector_unregister(struct drm_connector *connector)
945{ 959{
946 drm_sysfs_connector_remove(connector); 960 drm_sysfs_connector_remove(connector);
961 drm_debugfs_connector_remove(connector);
947} 962}
948EXPORT_SYMBOL(drm_connector_unregister); 963EXPORT_SYMBOL(drm_connector_unregister);
949 964
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index b4b51d46f339..8ab3f3e38643 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -237,5 +237,119 @@ int drm_debugfs_cleanup(struct drm_minor *minor)
237 return 0; 237 return 0;
238} 238}
239 239
240static int connector_show(struct seq_file *m, void *data)
241{
242 struct drm_connector *connector = m->private;
243 const char *status;
244
245 switch (connector->force) {
246 case DRM_FORCE_ON:
247 status = "on\n";
248 break;
249
250 case DRM_FORCE_ON_DIGITAL:
251 status = "digital\n";
252 break;
253
254 case DRM_FORCE_OFF:
255 status = "off\n";
256 break;
257
258 case DRM_FORCE_UNSPECIFIED:
259 status = "unspecified\n";
260 break;
261
262 default:
263 return 0;
264 }
265
266 seq_puts(m, status);
267
268 return 0;
269}
270
271static int connector_open(struct inode *inode, struct file *file)
272{
273 struct drm_connector *dev = inode->i_private;
274
275 return single_open(file, connector_show, dev);
276}
277
278static ssize_t connector_write(struct file *file, const char __user *ubuf,
279 size_t len, loff_t *offp)
280{
281 struct seq_file *m = file->private_data;
282 struct drm_connector *connector = m->private;
283 char buf[12];
284
285 if (len > sizeof(buf) - 1)
286 return -EINVAL;
287
288 if (copy_from_user(buf, ubuf, len))
289 return -EFAULT;
290
291 buf[len] = '\0';
292
293 if (!strcmp(buf, "on"))
294 connector->force = DRM_FORCE_ON;
295 else if (!strcmp(buf, "digital"))
296 connector->force = DRM_FORCE_ON_DIGITAL;
297 else if (!strcmp(buf, "off"))
298 connector->force = DRM_FORCE_OFF;
299 else if (!strcmp(buf, "unspecified"))
300 connector->force = DRM_FORCE_UNSPECIFIED;
301 else
302 return -EINVAL;
303
304 return len;
305}
306
307static const struct file_operations drm_connector_fops = {
308 .owner = THIS_MODULE,
309 .open = connector_open,
310 .read = seq_read,
311 .llseek = seq_lseek,
312 .release = single_release,
313 .write = connector_write
314};
315
316int drm_debugfs_connector_add(struct drm_connector *connector)
317{
318 struct drm_minor *minor = connector->dev->primary;
319 struct dentry *root, *ent;
320
321 if (!minor->debugfs_root)
322 return -1;
323
324 root = debugfs_create_dir(connector->name, minor->debugfs_root);
325 if (!root)
326 return -ENOMEM;
327
328 connector->debugfs_entry = root;
329
330 /* force */
331 ent = debugfs_create_file("force", S_IRUGO | S_IWUSR, root, connector,
332 &drm_connector_fops);
333 if (!ent)
334 goto error;
335
336 return 0;
337
338error:
339 debugfs_remove_recursive(connector->debugfs_entry);
340 connector->debugfs_entry = NULL;
341 return -ENOMEM;
342}
343
344void drm_debugfs_connector_remove(struct drm_connector *connector)
345{
346 if (!connector->debugfs_entry)
347 return;
348
349 debugfs_remove_recursive(connector->debugfs_entry);
350
351 connector->debugfs_entry = NULL;
352}
353
240#endif /* CONFIG_DEBUG_FS */ 354#endif /* CONFIG_DEBUG_FS */
241 355
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 8af71a8e2c00..57ecc421b19c 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1419,6 +1419,8 @@ extern int drm_debugfs_create_files(const struct drm_info_list *files,
1419extern int drm_debugfs_remove_files(const struct drm_info_list *files, 1419extern int drm_debugfs_remove_files(const struct drm_info_list *files,
1420 int count, struct drm_minor *minor); 1420 int count, struct drm_minor *minor);
1421extern int drm_debugfs_cleanup(struct drm_minor *minor); 1421extern int drm_debugfs_cleanup(struct drm_minor *minor);
1422extern int drm_debugfs_connector_add(struct drm_connector *connector);
1423extern void drm_debugfs_connector_remove(struct drm_connector *connector);
1422#else 1424#else
1423static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, 1425static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id,
1424 struct dentry *root) 1426 struct dentry *root)
@@ -1443,6 +1445,15 @@ static inline int drm_debugfs_cleanup(struct drm_minor *minor)
1443{ 1445{
1444 return 0; 1446 return 0;
1445} 1447}
1448
1449static inline int drm_debugfs_connector_add(struct drm_connector *connector)
1450{
1451 return 0;
1452}
1453static inline void drm_debugfs_connector_remove(struct drm_connector *connector)
1454{
1455}
1456
1446#endif 1457#endif
1447 1458
1448 /* Info file support */ 1459 /* Info file support */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5512c9968d77..d4b0a6a4ad9b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -545,6 +545,8 @@ struct drm_connector {
545 int audio_latency[2]; 545 int audio_latency[2];
546 int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ 546 int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
547 unsigned bad_edid_counter; 547 unsigned bad_edid_counter;
548
549 struct dentry *debugfs_entry;
548}; 550};
549 551
550/** 552/**