drm_panel.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*
  2. * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the
  12. * next paragraph) shall be included in all copies or substantial portions
  13. * of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include <linux/backlight.h>
  24. #include <linux/err.h>
  25. #include <linux/export.h>
  26. #include <linux/module.h>
  27. #include <linux/of.h>
  28. #include <drm/drm_crtc.h>
  29. #include <drm/drm_panel.h>
  30. #include <drm/drm_print.h>
  31. static DEFINE_MUTEX(panel_lock);
  32. static LIST_HEAD(panel_list);
  33. /**
  34. * DOC: drm panel
  35. *
  36. * The DRM panel helpers allow drivers to register panel objects with a
  37. * central registry and provide functions to retrieve those panels in display
  38. * drivers.
  39. *
  40. * For easy integration into drivers using the &drm_bridge infrastructure please
  41. * take look at drm_panel_bridge_add() and devm_drm_panel_bridge_add().
  42. */
  43. /**
  44. * drm_panel_init - initialize a panel
  45. * @panel: DRM panel
  46. * @dev: parent device of the panel
  47. * @funcs: panel operations
  48. * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
  49. * the panel interface (must NOT be DRM_MODE_CONNECTOR_Unknown)
  50. *
  51. * Initialize the panel structure for subsequent registration with
  52. * drm_panel_add().
  53. */
  54. void drm_panel_init(struct drm_panel *panel, struct device *dev,
  55. const struct drm_panel_funcs *funcs, int connector_type)
  56. {
  57. if (connector_type == DRM_MODE_CONNECTOR_Unknown)
  58. DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev));
  59. INIT_LIST_HEAD(&panel->list);
  60. INIT_LIST_HEAD(&panel->followers);
  61. mutex_init(&panel->follower_lock);
  62. panel->dev = dev;
  63. panel->funcs = funcs;
  64. panel->connector_type = connector_type;
  65. }
  66. EXPORT_SYMBOL(drm_panel_init);
  67. /**
  68. * drm_panel_add - add a panel to the global registry
  69. * @panel: panel to add
  70. *
  71. * Add a panel to the global registry so that it can be looked
  72. * up by display drivers. The panel to be added must have been
  73. * allocated by devm_drm_panel_alloc().
  74. */
  75. void drm_panel_add(struct drm_panel *panel)
  76. {
  77. mutex_lock(&panel_lock);
  78. list_add_tail(&panel->list, &panel_list);
  79. mutex_unlock(&panel_lock);
  80. }
  81. EXPORT_SYMBOL(drm_panel_add);
  82. /**
  83. * drm_panel_remove - remove a panel from the global registry
  84. * @panel: DRM panel
  85. *
  86. * Removes a panel from the global registry.
  87. */
  88. void drm_panel_remove(struct drm_panel *panel)
  89. {
  90. mutex_lock(&panel_lock);
  91. list_del_init(&panel->list);
  92. mutex_unlock(&panel_lock);
  93. }
  94. EXPORT_SYMBOL(drm_panel_remove);
  95. /**
  96. * drm_panel_prepare - power on a panel
  97. * @panel: DRM panel
  98. *
  99. * Calling this function will enable power and deassert any reset signals to
  100. * the panel. After this has completed it is possible to communicate with any
  101. * integrated circuitry via a command bus. This function cannot fail (as it is
  102. * called from the pre_enable call chain). There will always be a call to
  103. * drm_panel_disable() afterwards.
  104. */
  105. void drm_panel_prepare(struct drm_panel *panel)
  106. {
  107. struct drm_panel_follower *follower;
  108. int ret;
  109. if (!panel)
  110. return;
  111. if (panel->prepared) {
  112. dev_warn(panel->dev, "Skipping prepare of already prepared panel\n");
  113. return;
  114. }
  115. mutex_lock(&panel->follower_lock);
  116. if (panel->funcs && panel->funcs->prepare) {
  117. ret = panel->funcs->prepare(panel);
  118. if (ret < 0)
  119. goto exit;
  120. }
  121. panel->prepared = true;
  122. list_for_each_entry(follower, &panel->followers, list) {
  123. if (!follower->funcs->panel_prepared)
  124. continue;
  125. ret = follower->funcs->panel_prepared(follower);
  126. if (ret < 0)
  127. dev_info(panel->dev, "%ps failed: %d\n",
  128. follower->funcs->panel_prepared, ret);
  129. }
  130. exit:
  131. mutex_unlock(&panel->follower_lock);
  132. }
  133. EXPORT_SYMBOL(drm_panel_prepare);
  134. /**
  135. * drm_panel_unprepare - power off a panel
  136. * @panel: DRM panel
  137. *
  138. * Calling this function will completely power off a panel (assert the panel's
  139. * reset, turn off power supplies, ...). After this function has completed, it
  140. * is usually no longer possible to communicate with the panel until another
  141. * call to drm_panel_prepare().
  142. */
  143. void drm_panel_unprepare(struct drm_panel *panel)
  144. {
  145. struct drm_panel_follower *follower;
  146. int ret;
  147. if (!panel)
  148. return;
  149. /*
  150. * If you are seeing the warning below it likely means one of two things:
  151. * - Your panel driver incorrectly calls drm_panel_unprepare() in its
  152. * shutdown routine. You should delete this.
  153. * - You are using panel-edp or panel-simple and your DRM modeset
  154. * driver's shutdown() callback happened after the panel's shutdown().
  155. * In this case the warning is harmless though ideally you should
  156. * figure out how to reverse the order of the shutdown() callbacks.
  157. */
  158. if (!panel->prepared) {
  159. dev_warn(panel->dev, "Skipping unprepare of already unprepared panel\n");
  160. return;
  161. }
  162. mutex_lock(&panel->follower_lock);
  163. list_for_each_entry(follower, &panel->followers, list) {
  164. if (!follower->funcs->panel_unpreparing)
  165. continue;
  166. ret = follower->funcs->panel_unpreparing(follower);
  167. if (ret < 0)
  168. dev_info(panel->dev, "%ps failed: %d\n",
  169. follower->funcs->panel_unpreparing, ret);
  170. }
  171. if (panel->funcs && panel->funcs->unprepare) {
  172. ret = panel->funcs->unprepare(panel);
  173. if (ret < 0)
  174. goto exit;
  175. }
  176. panel->prepared = false;
  177. exit:
  178. mutex_unlock(&panel->follower_lock);
  179. }
  180. EXPORT_SYMBOL(drm_panel_unprepare);
  181. /**
  182. * drm_panel_enable - enable a panel
  183. * @panel: DRM panel
  184. *
  185. * Calling this function will cause the panel display drivers to be turned on
  186. * and the backlight to be enabled. Content will be visible on screen after
  187. * this call completes. This function cannot fail (as it is called from the
  188. * enable call chain). There will always be a call to drm_panel_disable()
  189. * afterwards.
  190. */
  191. void drm_panel_enable(struct drm_panel *panel)
  192. {
  193. struct drm_panel_follower *follower;
  194. int ret;
  195. if (!panel)
  196. return;
  197. if (panel->enabled) {
  198. dev_warn(panel->dev, "Skipping enable of already enabled panel\n");
  199. return;
  200. }
  201. mutex_lock(&panel->follower_lock);
  202. if (panel->funcs && panel->funcs->enable) {
  203. ret = panel->funcs->enable(panel);
  204. if (ret < 0)
  205. goto exit;
  206. }
  207. panel->enabled = true;
  208. ret = backlight_enable(panel->backlight);
  209. if (ret < 0)
  210. DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n",
  211. ret);
  212. list_for_each_entry(follower, &panel->followers, list) {
  213. if (!follower->funcs->panel_enabled)
  214. continue;
  215. ret = follower->funcs->panel_enabled(follower);
  216. if (ret < 0)
  217. dev_info(panel->dev, "%ps failed: %d\n",
  218. follower->funcs->panel_enabled, ret);
  219. }
  220. exit:
  221. mutex_unlock(&panel->follower_lock);
  222. }
  223. EXPORT_SYMBOL(drm_panel_enable);
  224. /**
  225. * drm_panel_disable - disable a panel
  226. * @panel: DRM panel
  227. *
  228. * This will typically turn off the panel's backlight or disable the display
  229. * drivers. For smart panels it should still be possible to communicate with
  230. * the integrated circuitry via any command bus after this call.
  231. */
  232. void drm_panel_disable(struct drm_panel *panel)
  233. {
  234. struct drm_panel_follower *follower;
  235. int ret;
  236. if (!panel)
  237. return;
  238. /*
  239. * If you are seeing the warning below it likely means one of two things:
  240. * - Your panel driver incorrectly calls drm_panel_disable() in its
  241. * shutdown routine. You should delete this.
  242. * - You are using panel-edp or panel-simple and your DRM modeset
  243. * driver's shutdown() callback happened after the panel's shutdown().
  244. * In this case the warning is harmless though ideally you should
  245. * figure out how to reverse the order of the shutdown() callbacks.
  246. */
  247. if (!panel->enabled) {
  248. dev_warn(panel->dev, "Skipping disable of already disabled panel\n");
  249. return;
  250. }
  251. mutex_lock(&panel->follower_lock);
  252. list_for_each_entry(follower, &panel->followers, list) {
  253. if (!follower->funcs->panel_disabling)
  254. continue;
  255. ret = follower->funcs->panel_disabling(follower);
  256. if (ret < 0)
  257. dev_info(panel->dev, "%ps failed: %d\n",
  258. follower->funcs->panel_disabling, ret);
  259. }
  260. ret = backlight_disable(panel->backlight);
  261. if (ret < 0)
  262. DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n",
  263. ret);
  264. if (panel->funcs && panel->funcs->disable) {
  265. ret = panel->funcs->disable(panel);
  266. if (ret < 0)
  267. goto exit;
  268. }
  269. panel->enabled = false;
  270. exit:
  271. mutex_unlock(&panel->follower_lock);
  272. }
  273. EXPORT_SYMBOL(drm_panel_disable);
  274. /**
  275. * drm_panel_get_modes - probe the available display modes of a panel
  276. * @panel: DRM panel
  277. * @connector: DRM connector
  278. *
  279. * The modes probed from the panel are automatically added to the connector
  280. * that the panel is attached to.
  281. *
  282. * Return: The number of modes available from the panel on success, or 0 on
  283. * failure (no modes).
  284. */
  285. int drm_panel_get_modes(struct drm_panel *panel,
  286. struct drm_connector *connector)
  287. {
  288. if (!panel)
  289. return 0;
  290. if (panel->funcs && panel->funcs->get_modes) {
  291. int num;
  292. num = panel->funcs->get_modes(panel, connector);
  293. if (num > 0)
  294. return num;
  295. }
  296. return 0;
  297. }
  298. EXPORT_SYMBOL(drm_panel_get_modes);
  299. static void __drm_panel_free(struct kref *kref)
  300. {
  301. struct drm_panel *panel = container_of(kref, struct drm_panel, refcount);
  302. kfree(panel->container);
  303. }
  304. /**
  305. * drm_panel_get - Acquire a panel reference
  306. * @panel: DRM panel
  307. *
  308. * This function increments the panel's refcount.
  309. * Returns:
  310. * Pointer to @panel
  311. */
  312. struct drm_panel *drm_panel_get(struct drm_panel *panel)
  313. {
  314. if (!panel)
  315. return panel;
  316. kref_get(&panel->refcount);
  317. return panel;
  318. }
  319. EXPORT_SYMBOL(drm_panel_get);
  320. /**
  321. * drm_panel_put - Release a panel reference
  322. * @panel: DRM panel
  323. *
  324. * This function decrements the panel's reference count and frees the
  325. * object if the reference count drops to zero.
  326. */
  327. void drm_panel_put(struct drm_panel *panel)
  328. {
  329. if (panel)
  330. kref_put(&panel->refcount, __drm_panel_free);
  331. }
  332. EXPORT_SYMBOL(drm_panel_put);
  333. /**
  334. * drm_panel_put_void - wrapper to drm_panel_put() taking a void pointer
  335. *
  336. * @data: pointer to @struct drm_panel, cast to a void pointer
  337. *
  338. * Wrapper of drm_panel_put() to be used when a function taking a void
  339. * pointer is needed, for example as a devm action.
  340. */
  341. static void drm_panel_put_void(void *data)
  342. {
  343. struct drm_panel *panel = (struct drm_panel *)data;
  344. drm_panel_put(panel);
  345. }
  346. void *__devm_drm_panel_alloc(struct device *dev, size_t size, size_t offset,
  347. const struct drm_panel_funcs *funcs,
  348. int connector_type)
  349. {
  350. void *container;
  351. struct drm_panel *panel;
  352. int err;
  353. if (!funcs) {
  354. dev_warn(dev, "Missing funcs pointer\n");
  355. return ERR_PTR(-EINVAL);
  356. }
  357. container = kzalloc(size, GFP_KERNEL);
  358. if (!container)
  359. return ERR_PTR(-ENOMEM);
  360. panel = container + offset;
  361. panel->container = container;
  362. panel->funcs = funcs;
  363. kref_init(&panel->refcount);
  364. err = devm_add_action_or_reset(dev, drm_panel_put_void, panel);
  365. if (err)
  366. return ERR_PTR(err);
  367. drm_panel_init(panel, dev, funcs, connector_type);
  368. return container;
  369. }
  370. EXPORT_SYMBOL(__devm_drm_panel_alloc);
  371. #ifdef CONFIG_OF
  372. /**
  373. * of_drm_find_panel - look up a panel using a device tree node
  374. * @np: device tree node of the panel
  375. *
  376. * Searches the set of registered panels for one that matches the given device
  377. * tree node. If a matching panel is found, return a pointer to it.
  378. *
  379. * Return: A pointer to the panel registered for the specified device tree
  380. * node or an ERR_PTR() if no panel matching the device tree node can be found.
  381. *
  382. * Possible error codes returned by this function:
  383. *
  384. * - EPROBE_DEFER: the panel device has not been probed yet, and the caller
  385. * should retry later
  386. * - ENODEV: the device is not available (status != "okay" or "ok")
  387. */
  388. struct drm_panel *of_drm_find_panel(const struct device_node *np)
  389. {
  390. struct drm_panel *panel;
  391. if (!of_device_is_available(np))
  392. return ERR_PTR(-ENODEV);
  393. mutex_lock(&panel_lock);
  394. list_for_each_entry(panel, &panel_list, list) {
  395. if (panel->dev->of_node == np) {
  396. mutex_unlock(&panel_lock);
  397. return panel;
  398. }
  399. }
  400. mutex_unlock(&panel_lock);
  401. return ERR_PTR(-EPROBE_DEFER);
  402. }
  403. EXPORT_SYMBOL(of_drm_find_panel);
  404. /**
  405. * of_drm_get_panel_orientation - look up the orientation of the panel through
  406. * the "rotation" binding from a device tree node
  407. * @np: device tree node of the panel
  408. * @orientation: orientation enum to be filled in
  409. *
  410. * Looks up the rotation of a panel in the device tree. The orientation of the
  411. * panel is expressed as a property name "rotation" in the device tree. The
  412. * rotation in the device tree is counter clockwise.
  413. *
  414. * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the
  415. * rotation property doesn't exist. Return a negative error code on failure.
  416. */
  417. int of_drm_get_panel_orientation(const struct device_node *np,
  418. enum drm_panel_orientation *orientation)
  419. {
  420. int rotation, ret;
  421. ret = of_property_read_u32(np, "rotation", &rotation);
  422. if (ret == -EINVAL) {
  423. /* Don't return an error if there's no rotation property. */
  424. *orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
  425. return 0;
  426. }
  427. if (ret < 0)
  428. return ret;
  429. if (rotation == 0)
  430. *orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
  431. else if (rotation == 90)
  432. *orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
  433. else if (rotation == 180)
  434. *orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
  435. else if (rotation == 270)
  436. *orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
  437. else
  438. return -EINVAL;
  439. return 0;
  440. }
  441. EXPORT_SYMBOL(of_drm_get_panel_orientation);
  442. #endif
  443. /* Find panel by fwnode. This should be identical to of_drm_find_panel(). */
  444. static struct drm_panel *find_panel_by_fwnode(const struct fwnode_handle *fwnode)
  445. {
  446. struct drm_panel *panel;
  447. if (!fwnode_device_is_available(fwnode))
  448. return ERR_PTR(-ENODEV);
  449. mutex_lock(&panel_lock);
  450. list_for_each_entry(panel, &panel_list, list) {
  451. if (dev_fwnode(panel->dev) == fwnode) {
  452. mutex_unlock(&panel_lock);
  453. return panel;
  454. }
  455. }
  456. mutex_unlock(&panel_lock);
  457. return ERR_PTR(-EPROBE_DEFER);
  458. }
  459. /* Find panel by follower device */
  460. static struct drm_panel *find_panel_by_dev(struct device *follower_dev)
  461. {
  462. struct fwnode_handle *fwnode;
  463. struct drm_panel *panel;
  464. fwnode = fwnode_find_reference(dev_fwnode(follower_dev), "panel", 0);
  465. if (IS_ERR(fwnode))
  466. return ERR_PTR(-ENODEV);
  467. panel = find_panel_by_fwnode(fwnode);
  468. fwnode_handle_put(fwnode);
  469. return panel;
  470. }
  471. /**
  472. * drm_is_panel_follower() - Check if the device is a panel follower
  473. * @dev: The 'struct device' to check
  474. *
  475. * This checks to see if a device needs to be power sequenced together with
  476. * a panel using the panel follower API.
  477. *
  478. * The "panel" property of the follower points to the panel to be followed.
  479. *
  480. * Return: true if we should be power sequenced with a panel; false otherwise.
  481. */
  482. bool drm_is_panel_follower(struct device *dev)
  483. {
  484. /*
  485. * The "panel" property is actually a phandle, but for simplicity we
  486. * don't bother trying to parse it here. We just need to know if the
  487. * property is there.
  488. */
  489. return device_property_present(dev, "panel");
  490. }
  491. EXPORT_SYMBOL(drm_is_panel_follower);
  492. /**
  493. * drm_panel_add_follower() - Register something to follow panel state.
  494. * @follower_dev: The 'struct device' for the follower.
  495. * @follower: The panel follower descriptor for the follower.
  496. *
  497. * A panel follower is called right after preparing/enabling the panel and right
  498. * before unpreparing/disabling the panel. It's primary intention is to power on
  499. * an associated touchscreen, though it could be used for any similar devices.
  500. * Multiple devices are allowed the follow the same panel.
  501. *
  502. * If a follower is added to a panel that's already been prepared/enabled, the
  503. * follower's prepared/enabled callback is called right away.
  504. *
  505. * The "panel" property of the follower points to the panel to be followed.
  506. *
  507. * Return: 0 or an error code. Note that -ENODEV means that we detected that
  508. * follower_dev is not actually following a panel. The caller may
  509. * choose to ignore this return value if following a panel is optional.
  510. */
  511. int drm_panel_add_follower(struct device *follower_dev,
  512. struct drm_panel_follower *follower)
  513. {
  514. struct drm_panel *panel;
  515. int ret;
  516. panel = find_panel_by_dev(follower_dev);
  517. if (IS_ERR(panel))
  518. return PTR_ERR(panel);
  519. get_device(panel->dev);
  520. follower->panel = panel;
  521. mutex_lock(&panel->follower_lock);
  522. list_add_tail(&follower->list, &panel->followers);
  523. if (panel->prepared && follower->funcs->panel_prepared) {
  524. ret = follower->funcs->panel_prepared(follower);
  525. if (ret < 0)
  526. dev_info(panel->dev, "%ps failed: %d\n",
  527. follower->funcs->panel_prepared, ret);
  528. }
  529. if (panel->enabled && follower->funcs->panel_enabled) {
  530. ret = follower->funcs->panel_enabled(follower);
  531. if (ret < 0)
  532. dev_info(panel->dev, "%ps failed: %d\n",
  533. follower->funcs->panel_enabled, ret);
  534. }
  535. mutex_unlock(&panel->follower_lock);
  536. return 0;
  537. }
  538. EXPORT_SYMBOL(drm_panel_add_follower);
  539. /**
  540. * drm_panel_remove_follower() - Reverse drm_panel_add_follower().
  541. * @follower: The panel follower descriptor for the follower.
  542. *
  543. * Undo drm_panel_add_follower(). This includes calling the follower's
  544. * unpreparing/disabling function if we're removed from a panel that's currently
  545. * prepared/enabled.
  546. *
  547. * Return: 0 or an error code.
  548. */
  549. void drm_panel_remove_follower(struct drm_panel_follower *follower)
  550. {
  551. struct drm_panel *panel = follower->panel;
  552. int ret;
  553. mutex_lock(&panel->follower_lock);
  554. if (panel->enabled && follower->funcs->panel_disabling) {
  555. ret = follower->funcs->panel_disabling(follower);
  556. if (ret < 0)
  557. dev_info(panel->dev, "%ps failed: %d\n",
  558. follower->funcs->panel_disabling, ret);
  559. }
  560. if (panel->prepared && follower->funcs->panel_unpreparing) {
  561. ret = follower->funcs->panel_unpreparing(follower);
  562. if (ret < 0)
  563. dev_info(panel->dev, "%ps failed: %d\n",
  564. follower->funcs->panel_unpreparing, ret);
  565. }
  566. list_del_init(&follower->list);
  567. mutex_unlock(&panel->follower_lock);
  568. put_device(panel->dev);
  569. }
  570. EXPORT_SYMBOL(drm_panel_remove_follower);
  571. static void drm_panel_remove_follower_void(void *follower)
  572. {
  573. drm_panel_remove_follower(follower);
  574. }
  575. /**
  576. * devm_drm_panel_add_follower() - devm version of drm_panel_add_follower()
  577. * @follower_dev: The 'struct device' for the follower.
  578. * @follower: The panel follower descriptor for the follower.
  579. *
  580. * Handles calling drm_panel_remove_follower() using devm on the follower_dev.
  581. *
  582. * Return: 0 or an error code.
  583. */
  584. int devm_drm_panel_add_follower(struct device *follower_dev,
  585. struct drm_panel_follower *follower)
  586. {
  587. int ret;
  588. ret = drm_panel_add_follower(follower_dev, follower);
  589. if (ret)
  590. return ret;
  591. return devm_add_action_or_reset(follower_dev,
  592. drm_panel_remove_follower_void, follower);
  593. }
  594. EXPORT_SYMBOL(devm_drm_panel_add_follower);
  595. #if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
  596. /**
  597. * drm_panel_of_backlight - use backlight device node for backlight
  598. * @panel: DRM panel
  599. *
  600. * Use this function to enable backlight handling if your panel
  601. * uses device tree and has a backlight phandle.
  602. *
  603. * When the panel is enabled backlight will be enabled after a
  604. * successful call to &drm_panel_funcs.enable()
  605. *
  606. * When the panel is disabled backlight will be disabled before the
  607. * call to &drm_panel_funcs.disable().
  608. *
  609. * A typical implementation for a panel driver supporting device tree
  610. * will call this function at probe time. Backlight will then be handled
  611. * transparently without requiring any intervention from the driver.
  612. * drm_panel_of_backlight() must be called after the call to drm_panel_init().
  613. *
  614. * Return: 0 on success or a negative error code on failure.
  615. */
  616. int drm_panel_of_backlight(struct drm_panel *panel)
  617. {
  618. struct backlight_device *backlight;
  619. if (!panel || !panel->dev)
  620. return -EINVAL;
  621. backlight = devm_of_find_backlight(panel->dev);
  622. if (IS_ERR(backlight))
  623. return PTR_ERR(backlight);
  624. panel->backlight = backlight;
  625. return 0;
  626. }
  627. EXPORT_SYMBOL(drm_panel_of_backlight);
  628. #endif
  629. MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
  630. MODULE_DESCRIPTION("DRM panel infrastructure");
  631. MODULE_LICENSE("GPL and additional rights");