drm_sysfs.c 13 KB

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