drm_sysfs.c 15 KB

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