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