xref: /linux/drivers/gpu/drm/drm_sysfs.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
5  *               extra sysfs attribute from DRM. Normal drm_sysfs_class
6  *               does not allow adding attributes.
7  *
8  * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
9  * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
10  * Copyright (c) 2003-2004 IBM Corp.
11  */
12 
13 #include <linux/acpi.h>
14 #include <linux/component.h>
15 #include <linux/device.h>
16 #include <linux/err.h>
17 #include <linux/export.h>
18 #include <linux/gfp.h>
19 #include <linux/i2c.h>
20 #include <linux/kdev_t.h>
21 #include <linux/pci.h>
22 #include <linux/property.h>
23 #include <linux/slab.h>
24 
25 #include <drm/drm_accel.h>
26 #include <drm/drm_connector.h>
27 #include <drm/drm_device.h>
28 #include <drm/drm_file.h>
29 #include <drm/drm_modes.h>
30 #include <drm/drm_print.h>
31 #include <drm/drm_property.h>
32 #include <drm/drm_sysfs.h>
33 
34 #include <asm/video.h>
35 
36 #include "drm_internal.h"
37 #include "drm_crtc_internal.h"
38 
39 #define to_drm_minor(d) dev_get_drvdata(d)
40 #define to_drm_connector(d) dev_get_drvdata(d)
41 
42 /**
43  * DOC: overview
44  *
45  * DRM provides very little additional support to drivers for sysfs
46  * interactions, beyond just all the standard stuff. Drivers who want to expose
47  * additional sysfs properties and property groups can attach them at either
48  * &drm_device.dev or &drm_connector.kdev.
49  *
50  * Registration is automatically handled when calling drm_dev_register(), or
51  * drm_connector_register() in case of hot-plugged connectors. Unregistration is
52  * also automatically handled by drm_dev_unregister() and
53  * drm_connector_unregister().
54  */
55 
56 static struct device_type drm_sysfs_device_minor = {
57 	.name = "drm_minor"
58 };
59 
60 static struct device_type drm_sysfs_device_connector = {
61 	.name = "drm_connector",
62 };
63 
64 struct class *drm_class;
65 
66 #ifdef CONFIG_ACPI
67 static bool drm_connector_acpi_bus_match(struct device *dev)
68 {
69 	return dev->type == &drm_sysfs_device_connector;
70 }
71 
72 static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev)
73 {
74 	struct drm_connector *connector = to_drm_connector(dev);
75 
76 	return to_acpi_device_node(connector->fwnode);
77 }
78 
79 static struct acpi_bus_type drm_connector_acpi_bus = {
80 	.name = "drm_connector",
81 	.match = drm_connector_acpi_bus_match,
82 	.find_companion = drm_connector_acpi_find_companion,
83 };
84 
85 static void drm_sysfs_acpi_register(void)
86 {
87 	register_acpi_bus_type(&drm_connector_acpi_bus);
88 }
89 
90 static void drm_sysfs_acpi_unregister(void)
91 {
92 	unregister_acpi_bus_type(&drm_connector_acpi_bus);
93 }
94 #else
95 static void drm_sysfs_acpi_register(void) { }
96 static void drm_sysfs_acpi_unregister(void) { }
97 #endif
98 
99 static char *drm_devnode(const struct device *dev, umode_t *mode)
100 {
101 	return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
102 }
103 
104 static int typec_connector_bind(struct device *dev,
105 				struct device *typec_connector, void *data)
106 {
107 	int ret;
108 
109 	ret = sysfs_create_link(&dev->kobj, &typec_connector->kobj, "typec_connector");
110 	if (ret)
111 		return ret;
112 
113 	ret = sysfs_create_link(&typec_connector->kobj, &dev->kobj, "drm_connector");
114 	if (ret)
115 		sysfs_remove_link(&dev->kobj, "typec_connector");
116 
117 	return ret;
118 }
119 
120 static void typec_connector_unbind(struct device *dev,
121 				   struct device *typec_connector, void *data)
122 {
123 	sysfs_remove_link(&typec_connector->kobj, "drm_connector");
124 	sysfs_remove_link(&dev->kobj, "typec_connector");
125 }
126 
127 static const struct component_ops typec_connector_ops = {
128 	.bind = typec_connector_bind,
129 	.unbind = typec_connector_unbind,
130 };
131 
132 static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");
133 
134 /**
135  * drm_sysfs_init - initialize sysfs helpers
136  *
137  * This is used to create the DRM class, which is the implicit parent of any
138  * other top-level DRM sysfs objects.
139  *
140  * You must call drm_sysfs_destroy() to release the allocated resources.
141  *
142  * Return: 0 on success, negative error code on failure.
143  */
144 int drm_sysfs_init(void)
145 {
146 	int err;
147 
148 	drm_class = class_create("drm");
149 	if (IS_ERR(drm_class))
150 		return PTR_ERR(drm_class);
151 
152 	err = class_create_file(drm_class, &class_attr_version.attr);
153 	if (err) {
154 		class_destroy(drm_class);
155 		drm_class = NULL;
156 		return err;
157 	}
158 
159 	drm_class->devnode = drm_devnode;
160 
161 	drm_sysfs_acpi_register();
162 	return 0;
163 }
164 
165 /**
166  * drm_sysfs_destroy - destroys DRM class
167  *
168  * Destroy the DRM device class.
169  */
170 void drm_sysfs_destroy(void)
171 {
172 	if (IS_ERR_OR_NULL(drm_class))
173 		return;
174 	drm_sysfs_acpi_unregister();
175 	class_remove_file(drm_class, &class_attr_version.attr);
176 	class_destroy(drm_class);
177 	drm_class = NULL;
178 }
179 
180 static void drm_sysfs_release(struct device *dev)
181 {
182 	kfree(dev);
183 }
184 
185 /*
186  * Connector properties
187  */
188 static ssize_t status_store(struct device *device,
189 			   struct device_attribute *attr,
190 			   const char *buf, size_t count)
191 {
192 	struct drm_connector *connector = to_drm_connector(device);
193 	struct drm_device *dev = connector->dev;
194 	enum drm_connector_force old_force;
195 	int ret;
196 
197 	ret = mutex_lock_interruptible(&dev->mode_config.mutex);
198 	if (ret)
199 		return ret;
200 
201 	old_force = connector->force;
202 
203 	if (sysfs_streq(buf, "detect"))
204 		connector->force = 0;
205 	else if (sysfs_streq(buf, "on"))
206 		connector->force = DRM_FORCE_ON;
207 	else if (sysfs_streq(buf, "on-digital"))
208 		connector->force = DRM_FORCE_ON_DIGITAL;
209 	else if (sysfs_streq(buf, "off"))
210 		connector->force = DRM_FORCE_OFF;
211 	else
212 		ret = -EINVAL;
213 
214 	if (old_force != connector->force || !connector->force) {
215 		drm_dbg_kms(dev, "[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n",
216 			    connector->base.id, connector->name,
217 			    old_force, connector->force);
218 
219 		connector->funcs->fill_modes(connector,
220 					     dev->mode_config.max_width,
221 					     dev->mode_config.max_height);
222 	}
223 
224 	mutex_unlock(&dev->mode_config.mutex);
225 
226 	return ret ? ret : count;
227 }
228 
229 static ssize_t status_show(struct device *device,
230 			   struct device_attribute *attr,
231 			   char *buf)
232 {
233 	struct drm_connector *connector = to_drm_connector(device);
234 	enum drm_connector_status status;
235 
236 	status = READ_ONCE(connector->status);
237 
238 	return sysfs_emit(buf, "%s\n",
239 			  drm_get_connector_status_name(status));
240 }
241 
242 static ssize_t dpms_show(struct device *device,
243 			   struct device_attribute *attr,
244 			   char *buf)
245 {
246 	struct drm_connector *connector = to_drm_connector(device);
247 	int dpms;
248 
249 	dpms = READ_ONCE(connector->dpms);
250 
251 	return sysfs_emit(buf, "%s\n", drm_get_dpms_name(dpms));
252 }
253 
254 static ssize_t enabled_show(struct device *device,
255 			    struct device_attribute *attr,
256 			   char *buf)
257 {
258 	struct drm_connector *connector = to_drm_connector(device);
259 	bool enabled;
260 
261 	enabled = READ_ONCE(connector->encoder);
262 
263 	return sysfs_emit(buf, enabled ? "enabled\n" : "disabled\n");
264 }
265 
266 static ssize_t edid_show(struct file *filp, struct kobject *kobj,
267 			 const struct bin_attribute *attr, char *buf, loff_t off,
268 			 size_t count)
269 {
270 	struct device *connector_dev = kobj_to_dev(kobj);
271 	struct drm_connector *connector = to_drm_connector(connector_dev);
272 	ssize_t ret;
273 
274 	ret = drm_edid_connector_property_show(connector, buf, off, count);
275 
276 	return ret;
277 }
278 
279 static ssize_t modes_show(struct device *device,
280 			   struct device_attribute *attr,
281 			   char *buf)
282 {
283 	struct drm_connector *connector = to_drm_connector(device);
284 	struct drm_display_mode *mode;
285 	int written = 0;
286 
287 	mutex_lock(&connector->dev->mode_config.mutex);
288 	list_for_each_entry(mode, &connector->modes, head) {
289 		written += scnprintf(buf + written, PAGE_SIZE - written, "%s\n",
290 				    mode->name);
291 	}
292 	mutex_unlock(&connector->dev->mode_config.mutex);
293 
294 	return written;
295 }
296 
297 static ssize_t connector_id_show(struct device *device,
298 				 struct device_attribute *attr,
299 				 char *buf)
300 {
301 	struct drm_connector *connector = to_drm_connector(device);
302 
303 	return sysfs_emit(buf, "%d\n", connector->base.id);
304 }
305 
306 static DEVICE_ATTR_RW(status);
307 static DEVICE_ATTR_RO(enabled);
308 static DEVICE_ATTR_RO(dpms);
309 static DEVICE_ATTR_RO(modes);
310 static DEVICE_ATTR_RO(connector_id);
311 
312 static struct attribute *connector_dev_attrs[] = {
313 	&dev_attr_status.attr,
314 	&dev_attr_enabled.attr,
315 	&dev_attr_dpms.attr,
316 	&dev_attr_modes.attr,
317 	&dev_attr_connector_id.attr,
318 	NULL
319 };
320 
321 static const struct bin_attribute edid_attr = {
322 	.attr.name = "edid",
323 	.attr.mode = 0444,
324 	.size = 0,
325 	.read = edid_show,
326 };
327 
328 static const struct bin_attribute *const connector_bin_attrs[] = {
329 	&edid_attr,
330 	NULL
331 };
332 
333 static const struct attribute_group connector_dev_group = {
334 	.attrs = connector_dev_attrs,
335 	.bin_attrs = connector_bin_attrs,
336 };
337 
338 static const struct attribute_group *connector_dev_groups[] = {
339 	&connector_dev_group,
340 	NULL
341 };
342 
343 int drm_sysfs_connector_add(struct drm_connector *connector)
344 {
345 	struct drm_device *dev = connector->dev;
346 	struct device *kdev;
347 	int r;
348 
349 	if (connector->kdev)
350 		return 0;
351 
352 	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
353 	if (!kdev)
354 		return -ENOMEM;
355 
356 	device_initialize(kdev);
357 	kdev->class = drm_class;
358 	kdev->type = &drm_sysfs_device_connector;
359 	kdev->parent = dev->primary->kdev;
360 	kdev->groups = connector_dev_groups;
361 	kdev->release = drm_sysfs_release;
362 	dev_set_drvdata(kdev, connector);
363 
364 	r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name);
365 	if (r)
366 		goto err_free;
367 
368 	drm_dbg_kms(dev, "[CONNECTOR:%d:%s] adding connector to sysfs\n",
369 		    connector->base.id, connector->name);
370 
371 	r = device_add(kdev);
372 	if (r) {
373 		drm_err(dev, "failed to register connector device: %d\n", r);
374 		goto err_free;
375 	}
376 
377 	connector->kdev = kdev;
378 
379 	if (dev_fwnode(kdev)) {
380 		r = component_add(kdev, &typec_connector_ops);
381 		if (r)
382 			drm_err(dev, "failed to add component to create link to typec connector\n");
383 	}
384 
385 	return 0;
386 
387 err_free:
388 	put_device(kdev);
389 	return r;
390 }
391 
392 int drm_sysfs_connector_add_late(struct drm_connector *connector)
393 {
394 	if (connector->ddc)
395 		return sysfs_create_link(&connector->kdev->kobj,
396 					 &connector->ddc->dev.kobj, "ddc");
397 
398 	return 0;
399 }
400 
401 void drm_sysfs_connector_remove_early(struct drm_connector *connector)
402 {
403 	if (connector->ddc)
404 		sysfs_remove_link(&connector->kdev->kobj, "ddc");
405 }
406 
407 void drm_sysfs_connector_remove(struct drm_connector *connector)
408 {
409 	if (!connector->kdev)
410 		return;
411 
412 	if (dev_fwnode(connector->kdev))
413 		component_del(connector->kdev, &typec_connector_ops);
414 
415 	drm_dbg_kms(connector->dev,
416 		    "[CONNECTOR:%d:%s] removing connector from sysfs\n",
417 		    connector->base.id, connector->name);
418 
419 	device_unregister(connector->kdev);
420 	connector->kdev = NULL;
421 }
422 
423 void drm_sysfs_lease_event(struct drm_device *dev)
424 {
425 	char *event_string = "LEASE=1";
426 	char *envp[] = { event_string, NULL };
427 
428 	drm_dbg_lease(dev, "generating lease event\n");
429 
430 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
431 }
432 
433 /**
434  * drm_sysfs_hotplug_event - generate a DRM uevent
435  * @dev: DRM device
436  *
437  * Send a uevent for the DRM device specified by @dev.  Currently we only
438  * set HOTPLUG=1 in the uevent environment, but this could be expanded to
439  * deal with other types of events.
440  *
441  * Any new uapi should be using the drm_sysfs_connector_status_event()
442  * for uevents on connector status change.
443  */
444 void drm_sysfs_hotplug_event(struct drm_device *dev)
445 {
446 	char *event_string = "HOTPLUG=1";
447 	char *envp[] = { event_string, NULL };
448 
449 	drm_dbg_kms(dev, "generating hotplug event\n");
450 
451 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
452 }
453 EXPORT_SYMBOL(drm_sysfs_hotplug_event);
454 
455 /**
456  * drm_sysfs_connector_hotplug_event - generate a DRM uevent for any connector
457  * change
458  * @connector: connector which has changed
459  *
460  * Send a uevent for the DRM connector specified by @connector. This will send
461  * a uevent with the properties HOTPLUG=1 and CONNECTOR.
462  */
463 void drm_sysfs_connector_hotplug_event(struct drm_connector *connector)
464 {
465 	struct drm_device *dev = connector->dev;
466 	char hotplug_str[] = "HOTPLUG=1", conn_id[21];
467 	char *envp[] = { hotplug_str, conn_id, NULL };
468 
469 	snprintf(conn_id, sizeof(conn_id),
470 		 "CONNECTOR=%u", connector->base.id);
471 
472 	drm_dbg_kms(connector->dev,
473 		    "[CONNECTOR:%d:%s] generating connector hotplug event\n",
474 		    connector->base.id, connector->name);
475 
476 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
477 }
478 EXPORT_SYMBOL(drm_sysfs_connector_hotplug_event);
479 
480 /**
481  * drm_sysfs_connector_property_event - generate a DRM uevent for connector
482  * property change
483  * @connector: connector on which property changed
484  * @property: connector property which has changed.
485  *
486  * Send a uevent for the specified DRM connector and property.  Currently we
487  * set HOTPLUG=1 and connector id along with the attached property id
488  * related to the change.
489  */
490 void drm_sysfs_connector_property_event(struct drm_connector *connector,
491 					struct drm_property *property)
492 {
493 	struct drm_device *dev = connector->dev;
494 	char hotplug_str[] = "HOTPLUG=1", conn_id[21], prop_id[21];
495 	char *envp[4] = { hotplug_str, conn_id, prop_id, NULL };
496 
497 	WARN_ON(!drm_mode_obj_find_prop_id(&connector->base,
498 					   property->base.id));
499 
500 	snprintf(conn_id, ARRAY_SIZE(conn_id),
501 		 "CONNECTOR=%u", connector->base.id);
502 	snprintf(prop_id, ARRAY_SIZE(prop_id),
503 		 "PROPERTY=%u", property->base.id);
504 
505 	drm_dbg_kms(connector->dev,
506 		    "[CONNECTOR:%d:%s] generating connector property event for [PROP:%d:%s]\n",
507 		    connector->base.id, connector->name,
508 		    property->base.id, property->name);
509 
510 	kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
511 }
512 EXPORT_SYMBOL(drm_sysfs_connector_property_event);
513 
514 static ssize_t boot_display_show(struct device *dev, struct device_attribute *attr,
515 				 char *buf)
516 {
517 	return sysfs_emit(buf, "1\n");
518 }
519 static DEVICE_ATTR_RO(boot_display);
520 
521 static struct attribute *display_attrs[] = {
522 	&dev_attr_boot_display.attr,
523 	NULL
524 };
525 
526 static umode_t boot_display_visible(struct kobject *kobj,
527 				    struct attribute *a, int n)
528 {
529 	struct device *dev = kobj_to_dev(kobj)->parent;
530 
531 	if (dev_is_pci(dev)) {
532 		struct pci_dev *pdev = to_pci_dev(dev);
533 
534 		if (video_is_primary_device(&pdev->dev))
535 			return a->mode;
536 	}
537 
538 	return 0;
539 }
540 
541 static const struct attribute_group display_attr_group = {
542 	.attrs = display_attrs,
543 	.is_visible = boot_display_visible,
544 };
545 
546 static const struct attribute_group *card_dev_groups[] = {
547 	&display_attr_group,
548 	NULL
549 };
550 
551 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
552 {
553 	const char *minor_str;
554 	struct device *kdev;
555 	int r;
556 
557 	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
558 	if (!kdev)
559 		return ERR_PTR(-ENOMEM);
560 
561 	device_initialize(kdev);
562 
563 	if (minor->type == DRM_MINOR_ACCEL) {
564 		minor_str = "accel%d";
565 		accel_set_device_instance_params(kdev, minor->index);
566 	} else {
567 		if (minor->type == DRM_MINOR_RENDER)
568 			minor_str = "renderD%d";
569 		else
570 			minor_str = "card%d";
571 
572 		kdev->devt = MKDEV(DRM_MAJOR, minor->index);
573 		kdev->class = drm_class;
574 		kdev->groups = card_dev_groups;
575 		kdev->type = &drm_sysfs_device_minor;
576 	}
577 
578 	kdev->parent = minor->dev->dev;
579 	kdev->release = drm_sysfs_release;
580 	dev_set_drvdata(kdev, minor);
581 
582 	r = dev_set_name(kdev, minor_str, minor->index);
583 	if (r < 0)
584 		goto err_free;
585 
586 	return kdev;
587 
588 err_free:
589 	put_device(kdev);
590 	return ERR_PTR(r);
591 }
592 
593 /**
594  * drm_class_device_register - register new device with the DRM sysfs class
595  * @dev: device to register
596  *
597  * Registers a new &struct device within the DRM sysfs class. Essentially only
598  * used by ttm to have a place for its global settings. Drivers should never use
599  * this.
600  */
601 int drm_class_device_register(struct device *dev)
602 {
603 	if (!drm_class || IS_ERR(drm_class))
604 		return -ENOENT;
605 
606 	dev->class = drm_class;
607 	return device_register(dev);
608 }
609 EXPORT_SYMBOL_GPL(drm_class_device_register);
610 
611 /**
612  * drm_class_device_unregister - unregister device with the DRM sysfs class
613  * @dev: device to unregister
614  *
615  * Unregisters a &struct device from the DRM sysfs class. Essentially only used
616  * by ttm to have a place for its global settings. Drivers should never use
617  * this.
618  */
619 void drm_class_device_unregister(struct device *dev)
620 {
621 	return device_unregister(dev);
622 }
623 EXPORT_SYMBOL_GPL(drm_class_device_unregister);
624