drm_sysfs.c 15 KB

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