1 2 /* 3 * drm_sysfs.c - Modifications to drm_sysfs_class.c to support 4 * extra sysfs attribute from DRM. Normal drm_sysfs_class 5 * does not allow adding attributes. 6 * 7 * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com> 8 * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> 9 * Copyright (c) 2003-2004 IBM Corp. 10 * 11 * This file is released under the GPLv2 12 * 13 */ 14 15 #include <linux/device.h> 16 #include <linux/kdev_t.h> 17 #include <linux/gfp.h> 18 #include <linux/err.h> 19 #include <linux/export.h> 20 21 #include <drm/drm_sysfs.h> 22 #include <drm/drm_core.h> 23 #include <drm/drmP.h> 24 #include "drm_internal.h" 25 26 #define to_drm_minor(d) dev_get_drvdata(d) 27 #define to_drm_connector(d) dev_get_drvdata(d) 28 29 static struct device_type drm_sysfs_device_minor = { 30 .name = "drm_minor" 31 }; 32 33 struct class *drm_class; 34 35 /** 36 * __drm_class_suspend - internal DRM class suspend routine 37 * @dev: Linux device to suspend 38 * @state: power state to enter 39 * 40 * Just figures out what the actual struct drm_device associated with 41 * @dev is and calls its suspend hook, if present. 42 */ 43 static int __drm_class_suspend(struct device *dev, pm_message_t state) 44 { 45 if (dev->type == &drm_sysfs_device_minor) { 46 struct drm_minor *drm_minor = to_drm_minor(dev); 47 struct drm_device *drm_dev = drm_minor->dev; 48 49 if (drm_minor->type == DRM_MINOR_LEGACY && 50 !drm_core_check_feature(drm_dev, DRIVER_MODESET) && 51 drm_dev->driver->suspend) 52 return drm_dev->driver->suspend(drm_dev, state); 53 } 54 return 0; 55 } 56 57 /** 58 * drm_class_suspend - internal DRM class suspend hook. Simply calls 59 * __drm_class_suspend() with the correct pm state. 60 * @dev: Linux device to suspend 61 */ 62 static int drm_class_suspend(struct device *dev) 63 { 64 return __drm_class_suspend(dev, PMSG_SUSPEND); 65 } 66 67 /** 68 * drm_class_freeze - internal DRM class freeze hook. Simply calls 69 * __drm_class_suspend() with the correct pm state. 70 * @dev: Linux device to freeze 71 */ 72 static int drm_class_freeze(struct device *dev) 73 { 74 return __drm_class_suspend(dev, PMSG_FREEZE); 75 } 76 77 /** 78 * drm_class_resume - DRM class resume hook 79 * @dev: Linux device to resume 80 * 81 * Just figures out what the actual struct drm_device associated with 82 * @dev is and calls its resume hook, if present. 83 */ 84 static int drm_class_resume(struct device *dev) 85 { 86 if (dev->type == &drm_sysfs_device_minor) { 87 struct drm_minor *drm_minor = to_drm_minor(dev); 88 struct drm_device *drm_dev = drm_minor->dev; 89 90 if (drm_minor->type == DRM_MINOR_LEGACY && 91 !drm_core_check_feature(drm_dev, DRIVER_MODESET) && 92 drm_dev->driver->resume) 93 return drm_dev->driver->resume(drm_dev); 94 } 95 return 0; 96 } 97 98 static const struct dev_pm_ops drm_class_dev_pm_ops = { 99 .suspend = drm_class_suspend, 100 .resume = drm_class_resume, 101 .freeze = drm_class_freeze, 102 }; 103 104 static char *drm_devnode(struct device *dev, umode_t *mode) 105 { 106 return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); 107 } 108 109 static CLASS_ATTR_STRING(version, S_IRUGO, 110 CORE_NAME " " 111 __stringify(CORE_MAJOR) "." 112 __stringify(CORE_MINOR) "." 113 __stringify(CORE_PATCHLEVEL) " " 114 CORE_DATE); 115 116 /** 117 * drm_sysfs_init - initialize sysfs helpers 118 * 119 * This is used to create the DRM class, which is the implicit parent of any 120 * other top-level DRM sysfs objects. 121 * 122 * You must call drm_sysfs_destroy() to release the allocated resources. 123 * 124 * Return: 0 on success, negative error code on failure. 125 */ 126 int drm_sysfs_init(void) 127 { 128 int err; 129 130 drm_class = class_create(THIS_MODULE, "drm"); 131 if (IS_ERR(drm_class)) 132 return PTR_ERR(drm_class); 133 134 drm_class->pm = &drm_class_dev_pm_ops; 135 136 err = class_create_file(drm_class, &class_attr_version.attr); 137 if (err) { 138 class_destroy(drm_class); 139 drm_class = NULL; 140 return err; 141 } 142 143 drm_class->devnode = drm_devnode; 144 return 0; 145 } 146 147 /** 148 * drm_sysfs_destroy - destroys DRM class 149 * 150 * Destroy the DRM device class. 151 */ 152 void drm_sysfs_destroy(void) 153 { 154 if (IS_ERR_OR_NULL(drm_class)) 155 return; 156 class_remove_file(drm_class, &class_attr_version.attr); 157 class_destroy(drm_class); 158 drm_class = NULL; 159 } 160 161 /* 162 * Connector properties 163 */ 164 static ssize_t status_store(struct device *device, 165 struct device_attribute *attr, 166 const char *buf, size_t count) 167 { 168 struct drm_connector *connector = to_drm_connector(device); 169 struct drm_device *dev = connector->dev; 170 enum drm_connector_status old_status; 171 int ret; 172 173 ret = mutex_lock_interruptible(&dev->mode_config.mutex); 174 if (ret) 175 return ret; 176 177 old_status = connector->status; 178 179 if (sysfs_streq(buf, "detect")) { 180 connector->force = 0; 181 connector->status = connector->funcs->detect(connector, true); 182 } else if (sysfs_streq(buf, "on")) { 183 connector->force = DRM_FORCE_ON; 184 } else if (sysfs_streq(buf, "on-digital")) { 185 connector->force = DRM_FORCE_ON_DIGITAL; 186 } else if (sysfs_streq(buf, "off")) { 187 connector->force = DRM_FORCE_OFF; 188 } else 189 ret = -EINVAL; 190 191 if (ret == 0 && connector->force) { 192 if (connector->force == DRM_FORCE_ON || 193 connector->force == DRM_FORCE_ON_DIGITAL) 194 connector->status = connector_status_connected; 195 else 196 connector->status = connector_status_disconnected; 197 if (connector->funcs->force) 198 connector->funcs->force(connector); 199 } 200 201 if (old_status != connector->status) { 202 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", 203 connector->base.id, 204 connector->name, 205 old_status, connector->status); 206 207 dev->mode_config.delayed_event = true; 208 if (dev->mode_config.poll_enabled) 209 schedule_delayed_work(&dev->mode_config.output_poll_work, 210 0); 211 } 212 213 mutex_unlock(&dev->mode_config.mutex); 214 215 return ret ? ret : count; 216 } 217 218 static ssize_t status_show(struct device *device, 219 struct device_attribute *attr, 220 char *buf) 221 { 222 struct drm_connector *connector = to_drm_connector(device); 223 224 return snprintf(buf, PAGE_SIZE, "%s\n", 225 drm_get_connector_status_name(connector->status)); 226 } 227 228 static ssize_t dpms_show(struct device *device, 229 struct device_attribute *attr, 230 char *buf) 231 { 232 struct drm_connector *connector = to_drm_connector(device); 233 int dpms; 234 235 dpms = READ_ONCE(connector->dpms); 236 237 return snprintf(buf, PAGE_SIZE, "%s\n", 238 drm_get_dpms_name(dpms)); 239 } 240 241 static ssize_t enabled_show(struct device *device, 242 struct device_attribute *attr, 243 char *buf) 244 { 245 struct drm_connector *connector = to_drm_connector(device); 246 247 return snprintf(buf, PAGE_SIZE, "%s\n", connector->encoder ? "enabled" : 248 "disabled"); 249 } 250 251 static ssize_t edid_show(struct file *filp, struct kobject *kobj, 252 struct bin_attribute *attr, char *buf, loff_t off, 253 size_t count) 254 { 255 struct device *connector_dev = container_of(kobj, struct device, kobj); 256 struct drm_connector *connector = to_drm_connector(connector_dev); 257 unsigned char *edid; 258 size_t size; 259 260 if (!connector->edid_blob_ptr) 261 return 0; 262 263 edid = connector->edid_blob_ptr->data; 264 size = connector->edid_blob_ptr->length; 265 if (!edid) 266 return 0; 267 268 if (off >= size) 269 return 0; 270 271 if (off + count > size) 272 count = size - off; 273 memcpy(buf, edid + off, count); 274 275 return count; 276 } 277 278 static ssize_t modes_show(struct device *device, 279 struct device_attribute *attr, 280 char *buf) 281 { 282 struct drm_connector *connector = to_drm_connector(device); 283 struct drm_display_mode *mode; 284 int written = 0; 285 286 list_for_each_entry(mode, &connector->modes, head) { 287 written += snprintf(buf + written, PAGE_SIZE - written, "%s\n", 288 mode->name); 289 } 290 291 return written; 292 } 293 294 static ssize_t tv_subconnector_show(struct device *device, 295 struct device_attribute *attr, 296 char *buf) 297 { 298 struct drm_connector *connector = to_drm_connector(device); 299 struct drm_device *dev = connector->dev; 300 struct drm_property *prop; 301 uint64_t subconnector; 302 int ret; 303 304 prop = dev->mode_config.tv_subconnector_property; 305 if (!prop) { 306 DRM_ERROR("Unable to find subconnector property\n"); 307 return 0; 308 } 309 310 ret = drm_object_property_get_value(&connector->base, prop, &subconnector); 311 if (ret) 312 return 0; 313 314 return snprintf(buf, PAGE_SIZE, "%s", 315 drm_get_tv_subconnector_name((int)subconnector)); 316 } 317 318 static ssize_t tv_select_subconnector_show(struct device *device, 319 struct device_attribute *attr, 320 char *buf) 321 { 322 struct drm_connector *connector = to_drm_connector(device); 323 struct drm_device *dev = connector->dev; 324 struct drm_property *prop; 325 uint64_t subconnector; 326 int ret; 327 328 prop = dev->mode_config.tv_select_subconnector_property; 329 if (!prop) { 330 DRM_ERROR("Unable to find select subconnector property\n"); 331 return 0; 332 } 333 334 ret = drm_object_property_get_value(&connector->base, prop, &subconnector); 335 if (ret) 336 return 0; 337 338 return snprintf(buf, PAGE_SIZE, "%s", 339 drm_get_tv_select_name((int)subconnector)); 340 } 341 342 static ssize_t dvii_subconnector_show(struct device *device, 343 struct device_attribute *attr, 344 char *buf) 345 { 346 struct drm_connector *connector = to_drm_connector(device); 347 struct drm_device *dev = connector->dev; 348 struct drm_property *prop; 349 uint64_t subconnector; 350 int ret; 351 352 prop = dev->mode_config.dvi_i_subconnector_property; 353 if (!prop) { 354 DRM_ERROR("Unable to find subconnector property\n"); 355 return 0; 356 } 357 358 ret = drm_object_property_get_value(&connector->base, prop, &subconnector); 359 if (ret) 360 return 0; 361 362 return snprintf(buf, PAGE_SIZE, "%s", 363 drm_get_dvi_i_subconnector_name((int)subconnector)); 364 } 365 366 static ssize_t dvii_select_subconnector_show(struct device *device, 367 struct device_attribute *attr, 368 char *buf) 369 { 370 struct drm_connector *connector = to_drm_connector(device); 371 struct drm_device *dev = connector->dev; 372 struct drm_property *prop; 373 uint64_t subconnector; 374 int ret; 375 376 prop = dev->mode_config.dvi_i_select_subconnector_property; 377 if (!prop) { 378 DRM_ERROR("Unable to find select subconnector property\n"); 379 return 0; 380 } 381 382 ret = drm_object_property_get_value(&connector->base, prop, &subconnector); 383 if (ret) 384 return 0; 385 386 return snprintf(buf, PAGE_SIZE, "%s", 387 drm_get_dvi_i_select_name((int)subconnector)); 388 } 389 390 static DEVICE_ATTR_RW(status); 391 static DEVICE_ATTR_RO(enabled); 392 static DEVICE_ATTR_RO(dpms); 393 static DEVICE_ATTR_RO(modes); 394 395 static struct attribute *connector_dev_attrs[] = { 396 &dev_attr_status.attr, 397 &dev_attr_enabled.attr, 398 &dev_attr_dpms.attr, 399 &dev_attr_modes.attr, 400 NULL 401 }; 402 403 static DEVICE_ATTR_RO(tv_subconnector); 404 static DEVICE_ATTR_RO(tv_select_subconnector); 405 406 static struct attribute *connector_tv_dev_attrs[] = { 407 &dev_attr_tv_subconnector.attr, 408 &dev_attr_tv_select_subconnector.attr, 409 NULL 410 }; 411 412 static DEVICE_ATTR_RO(dvii_subconnector); 413 static DEVICE_ATTR_RO(dvii_select_subconnector); 414 415 static struct attribute *connector_dvii_dev_attrs[] = { 416 &dev_attr_dvii_subconnector.attr, 417 &dev_attr_dvii_select_subconnector.attr, 418 NULL 419 }; 420 421 /* Connector type related helpers */ 422 static int kobj_connector_type(struct kobject *kobj) 423 { 424 struct device *dev = kobj_to_dev(kobj); 425 struct drm_connector *connector = to_drm_connector(dev); 426 427 return connector->connector_type; 428 } 429 430 static umode_t connector_is_dvii(struct kobject *kobj, 431 struct attribute *attr, int idx) 432 { 433 return kobj_connector_type(kobj) == DRM_MODE_CONNECTOR_DVII ? 434 attr->mode : 0; 435 } 436 437 static umode_t connector_is_tv(struct kobject *kobj, 438 struct attribute *attr, int idx) 439 { 440 switch (kobj_connector_type(kobj)) { 441 case DRM_MODE_CONNECTOR_Composite: 442 case DRM_MODE_CONNECTOR_SVIDEO: 443 case DRM_MODE_CONNECTOR_Component: 444 case DRM_MODE_CONNECTOR_TV: 445 return attr->mode; 446 } 447 448 return 0; 449 } 450 451 static struct bin_attribute edid_attr = { 452 .attr.name = "edid", 453 .attr.mode = 0444, 454 .size = 0, 455 .read = edid_show, 456 }; 457 458 static struct bin_attribute *connector_bin_attrs[] = { 459 &edid_attr, 460 NULL 461 }; 462 463 static const struct attribute_group connector_dev_group = { 464 .attrs = connector_dev_attrs, 465 .bin_attrs = connector_bin_attrs, 466 }; 467 468 static const struct attribute_group connector_tv_dev_group = { 469 .attrs = connector_tv_dev_attrs, 470 .is_visible = connector_is_tv, 471 }; 472 473 static const struct attribute_group connector_dvii_dev_group = { 474 .attrs = connector_dvii_dev_attrs, 475 .is_visible = connector_is_dvii, 476 }; 477 478 static const struct attribute_group *connector_dev_groups[] = { 479 &connector_dev_group, 480 &connector_tv_dev_group, 481 &connector_dvii_dev_group, 482 NULL 483 }; 484 485 /** 486 * drm_sysfs_connector_add - add a connector to sysfs 487 * @connector: connector to add 488 * 489 * Create a connector device in sysfs, along with its associated connector 490 * properties (so far, connection status, dpms, mode list & edid) and 491 * generate a hotplug event so userspace knows there's a new connector 492 * available. 493 */ 494 int drm_sysfs_connector_add(struct drm_connector *connector) 495 { 496 struct drm_device *dev = connector->dev; 497 498 if (connector->kdev) 499 return 0; 500 501 connector->kdev = 502 device_create_with_groups(drm_class, dev->primary->kdev, 0, 503 connector, connector_dev_groups, 504 "card%d-%s", dev->primary->index, 505 connector->name); 506 DRM_DEBUG("adding \"%s\" to sysfs\n", 507 connector->name); 508 509 if (IS_ERR(connector->kdev)) { 510 DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); 511 return PTR_ERR(connector->kdev); 512 } 513 514 /* Let userspace know we have a new connector */ 515 drm_sysfs_hotplug_event(dev); 516 517 return 0; 518 } 519 520 /** 521 * drm_sysfs_connector_remove - remove an connector device from sysfs 522 * @connector: connector to remove 523 * 524 * Remove @connector and its associated attributes from sysfs. Note that 525 * the device model core will take care of sending the "remove" uevent 526 * at this time, so we don't need to do it. 527 * 528 * Note: 529 * This routine should only be called if the connector was previously 530 * successfully registered. If @connector hasn't been registered yet, 531 * you'll likely see a panic somewhere deep in sysfs code when called. 532 */ 533 void drm_sysfs_connector_remove(struct drm_connector *connector) 534 { 535 if (!connector->kdev) 536 return; 537 DRM_DEBUG("removing \"%s\" from sysfs\n", 538 connector->name); 539 540 device_unregister(connector->kdev); 541 connector->kdev = NULL; 542 } 543 544 /** 545 * drm_sysfs_hotplug_event - generate a DRM uevent 546 * @dev: DRM device 547 * 548 * Send a uevent for the DRM device specified by @dev. Currently we only 549 * set HOTPLUG=1 in the uevent environment, but this could be expanded to 550 * deal with other types of events. 551 */ 552 void drm_sysfs_hotplug_event(struct drm_device *dev) 553 { 554 char *event_string = "HOTPLUG=1"; 555 char *envp[] = { event_string, NULL }; 556 557 DRM_DEBUG("generating hotplug event\n"); 558 559 kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); 560 } 561 EXPORT_SYMBOL(drm_sysfs_hotplug_event); 562 563 static void drm_sysfs_release(struct device *dev) 564 { 565 kfree(dev); 566 } 567 568 /** 569 * drm_sysfs_minor_alloc() - Allocate sysfs device for given minor 570 * @minor: minor to allocate sysfs device for 571 * 572 * This allocates a new sysfs device for @minor and returns it. The device is 573 * not registered nor linked. The caller has to use device_add() and 574 * device_del() to register and unregister it. 575 * 576 * Note that dev_get_drvdata() on the new device will return the minor. 577 * However, the device does not hold a ref-count to the minor nor to the 578 * underlying drm_device. This is unproblematic as long as you access the 579 * private data only in sysfs callbacks. device_del() disables those 580 * synchronously, so they cannot be called after you cleanup a minor. 581 */ 582 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) 583 { 584 const char *minor_str; 585 struct device *kdev; 586 int r; 587 588 if (minor->type == DRM_MINOR_CONTROL) 589 minor_str = "controlD%d"; 590 else if (minor->type == DRM_MINOR_RENDER) 591 minor_str = "renderD%d"; 592 else 593 minor_str = "card%d"; 594 595 kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); 596 if (!kdev) 597 return ERR_PTR(-ENOMEM); 598 599 device_initialize(kdev); 600 kdev->devt = MKDEV(DRM_MAJOR, minor->index); 601 kdev->class = drm_class; 602 kdev->type = &drm_sysfs_device_minor; 603 kdev->parent = minor->dev->dev; 604 kdev->release = drm_sysfs_release; 605 dev_set_drvdata(kdev, minor); 606 607 r = dev_set_name(kdev, minor_str, minor->index); 608 if (r < 0) 609 goto err_free; 610 611 return kdev; 612 613 err_free: 614 put_device(kdev); 615 return ERR_PTR(r); 616 } 617 618 /** 619 * drm_class_device_register - Register a struct device in the drm class. 620 * 621 * @dev: pointer to struct device to register. 622 * 623 * @dev should have all relevant members pre-filled with the exception 624 * of the class member. In particular, the device_type member must 625 * be set. 626 */ 627 628 int drm_class_device_register(struct device *dev) 629 { 630 if (!drm_class || IS_ERR(drm_class)) 631 return -ENOENT; 632 633 dev->class = drm_class; 634 return device_register(dev); 635 } 636 EXPORT_SYMBOL_GPL(drm_class_device_register); 637 638 void drm_class_device_unregister(struct device *dev) 639 { 640 return device_unregister(dev); 641 } 642 EXPORT_SYMBOL_GPL(drm_class_device_unregister); 643