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