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