at v5.5 708 lines 19 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Backlight Lowlevel Control Abstraction 4 * 5 * Copyright (C) 2003,2004 Hewlett-Packard Company 6 * 7 */ 8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10 11#include <linux/module.h> 12#include <linux/init.h> 13#include <linux/device.h> 14#include <linux/backlight.h> 15#include <linux/notifier.h> 16#include <linux/ctype.h> 17#include <linux/err.h> 18#include <linux/fb.h> 19#include <linux/slab.h> 20 21#ifdef CONFIG_PMAC_BACKLIGHT 22#include <asm/backlight.h> 23#endif 24 25static struct list_head backlight_dev_list; 26static struct mutex backlight_dev_list_mutex; 27static struct blocking_notifier_head backlight_notifier; 28 29static const char *const backlight_types[] = { 30 [BACKLIGHT_RAW] = "raw", 31 [BACKLIGHT_PLATFORM] = "platform", 32 [BACKLIGHT_FIRMWARE] = "firmware", 33}; 34 35static const char *const backlight_scale_types[] = { 36 [BACKLIGHT_SCALE_UNKNOWN] = "unknown", 37 [BACKLIGHT_SCALE_LINEAR] = "linear", 38 [BACKLIGHT_SCALE_NON_LINEAR] = "non-linear", 39}; 40 41#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ 42 defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) 43/* This callback gets called when something important happens inside a 44 * framebuffer driver. We're looking if that important event is blanking, 45 * and if it is and necessary, we're switching backlight power as well ... 46 */ 47static int fb_notifier_callback(struct notifier_block *self, 48 unsigned long event, void *data) 49{ 50 struct backlight_device *bd; 51 struct fb_event *evdata = data; 52 int node = evdata->info->node; 53 int fb_blank = 0; 54 55 /* If we aren't interested in this event, skip it immediately ... */ 56 if (event != FB_EVENT_BLANK) 57 return 0; 58 59 bd = container_of(self, struct backlight_device, fb_notif); 60 mutex_lock(&bd->ops_lock); 61 if (bd->ops) 62 if (!bd->ops->check_fb || 63 bd->ops->check_fb(bd, evdata->info)) { 64 fb_blank = *(int *)evdata->data; 65 if (fb_blank == FB_BLANK_UNBLANK && 66 !bd->fb_bl_on[node]) { 67 bd->fb_bl_on[node] = true; 68 if (!bd->use_count++) { 69 bd->props.state &= ~BL_CORE_FBBLANK; 70 bd->props.fb_blank = FB_BLANK_UNBLANK; 71 backlight_update_status(bd); 72 } 73 } else if (fb_blank != FB_BLANK_UNBLANK && 74 bd->fb_bl_on[node]) { 75 bd->fb_bl_on[node] = false; 76 if (!(--bd->use_count)) { 77 bd->props.state |= BL_CORE_FBBLANK; 78 bd->props.fb_blank = fb_blank; 79 backlight_update_status(bd); 80 } 81 } 82 } 83 mutex_unlock(&bd->ops_lock); 84 return 0; 85} 86 87static int backlight_register_fb(struct backlight_device *bd) 88{ 89 memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); 90 bd->fb_notif.notifier_call = fb_notifier_callback; 91 92 return fb_register_client(&bd->fb_notif); 93} 94 95static void backlight_unregister_fb(struct backlight_device *bd) 96{ 97 fb_unregister_client(&bd->fb_notif); 98} 99#else 100static inline int backlight_register_fb(struct backlight_device *bd) 101{ 102 return 0; 103} 104 105static inline void backlight_unregister_fb(struct backlight_device *bd) 106{ 107} 108#endif /* CONFIG_FB */ 109 110static void backlight_generate_event(struct backlight_device *bd, 111 enum backlight_update_reason reason) 112{ 113 char *envp[2]; 114 115 switch (reason) { 116 case BACKLIGHT_UPDATE_SYSFS: 117 envp[0] = "SOURCE=sysfs"; 118 break; 119 case BACKLIGHT_UPDATE_HOTKEY: 120 envp[0] = "SOURCE=hotkey"; 121 break; 122 default: 123 envp[0] = "SOURCE=unknown"; 124 break; 125 } 126 envp[1] = NULL; 127 kobject_uevent_env(&bd->dev.kobj, KOBJ_CHANGE, envp); 128 sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness"); 129} 130 131static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr, 132 char *buf) 133{ 134 struct backlight_device *bd = to_backlight_device(dev); 135 136 return sprintf(buf, "%d\n", bd->props.power); 137} 138 139static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr, 140 const char *buf, size_t count) 141{ 142 int rc; 143 struct backlight_device *bd = to_backlight_device(dev); 144 unsigned long power, old_power; 145 146 rc = kstrtoul(buf, 0, &power); 147 if (rc) 148 return rc; 149 150 rc = -ENXIO; 151 mutex_lock(&bd->ops_lock); 152 if (bd->ops) { 153 pr_debug("set power to %lu\n", power); 154 if (bd->props.power != power) { 155 old_power = bd->props.power; 156 bd->props.power = power; 157 rc = backlight_update_status(bd); 158 if (rc) 159 bd->props.power = old_power; 160 else 161 rc = count; 162 } else { 163 rc = count; 164 } 165 } 166 mutex_unlock(&bd->ops_lock); 167 168 return rc; 169} 170static DEVICE_ATTR_RW(bl_power); 171 172static ssize_t brightness_show(struct device *dev, 173 struct device_attribute *attr, char *buf) 174{ 175 struct backlight_device *bd = to_backlight_device(dev); 176 177 return sprintf(buf, "%d\n", bd->props.brightness); 178} 179 180int backlight_device_set_brightness(struct backlight_device *bd, 181 unsigned long brightness) 182{ 183 int rc = -ENXIO; 184 185 mutex_lock(&bd->ops_lock); 186 if (bd->ops) { 187 if (brightness > bd->props.max_brightness) 188 rc = -EINVAL; 189 else { 190 pr_debug("set brightness to %lu\n", brightness); 191 bd->props.brightness = brightness; 192 rc = backlight_update_status(bd); 193 } 194 } 195 mutex_unlock(&bd->ops_lock); 196 197 backlight_generate_event(bd, BACKLIGHT_UPDATE_SYSFS); 198 199 return rc; 200} 201EXPORT_SYMBOL(backlight_device_set_brightness); 202 203static ssize_t brightness_store(struct device *dev, 204 struct device_attribute *attr, const char *buf, size_t count) 205{ 206 int rc; 207 struct backlight_device *bd = to_backlight_device(dev); 208 unsigned long brightness; 209 210 rc = kstrtoul(buf, 0, &brightness); 211 if (rc) 212 return rc; 213 214 rc = backlight_device_set_brightness(bd, brightness); 215 216 return rc ? rc : count; 217} 218static DEVICE_ATTR_RW(brightness); 219 220static ssize_t type_show(struct device *dev, struct device_attribute *attr, 221 char *buf) 222{ 223 struct backlight_device *bd = to_backlight_device(dev); 224 225 return sprintf(buf, "%s\n", backlight_types[bd->props.type]); 226} 227static DEVICE_ATTR_RO(type); 228 229static ssize_t max_brightness_show(struct device *dev, 230 struct device_attribute *attr, char *buf) 231{ 232 struct backlight_device *bd = to_backlight_device(dev); 233 234 return sprintf(buf, "%d\n", bd->props.max_brightness); 235} 236static DEVICE_ATTR_RO(max_brightness); 237 238static ssize_t actual_brightness_show(struct device *dev, 239 struct device_attribute *attr, char *buf) 240{ 241 int rc = -ENXIO; 242 struct backlight_device *bd = to_backlight_device(dev); 243 244 mutex_lock(&bd->ops_lock); 245 if (bd->ops && bd->ops->get_brightness) 246 rc = sprintf(buf, "%d\n", bd->ops->get_brightness(bd)); 247 else 248 rc = sprintf(buf, "%d\n", bd->props.brightness); 249 mutex_unlock(&bd->ops_lock); 250 251 return rc; 252} 253static DEVICE_ATTR_RO(actual_brightness); 254 255static ssize_t scale_show(struct device *dev, 256 struct device_attribute *attr, char *buf) 257{ 258 struct backlight_device *bd = to_backlight_device(dev); 259 260 if (WARN_ON(bd->props.scale > BACKLIGHT_SCALE_NON_LINEAR)) 261 return sprintf(buf, "unknown\n"); 262 263 return sprintf(buf, "%s\n", backlight_scale_types[bd->props.scale]); 264} 265static DEVICE_ATTR_RO(scale); 266 267static struct class *backlight_class; 268 269#ifdef CONFIG_PM_SLEEP 270static int backlight_suspend(struct device *dev) 271{ 272 struct backlight_device *bd = to_backlight_device(dev); 273 274 mutex_lock(&bd->ops_lock); 275 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { 276 bd->props.state |= BL_CORE_SUSPENDED; 277 backlight_update_status(bd); 278 } 279 mutex_unlock(&bd->ops_lock); 280 281 return 0; 282} 283 284static int backlight_resume(struct device *dev) 285{ 286 struct backlight_device *bd = to_backlight_device(dev); 287 288 mutex_lock(&bd->ops_lock); 289 if (bd->ops && bd->ops->options & BL_CORE_SUSPENDRESUME) { 290 bd->props.state &= ~BL_CORE_SUSPENDED; 291 backlight_update_status(bd); 292 } 293 mutex_unlock(&bd->ops_lock); 294 295 return 0; 296} 297#endif 298 299static SIMPLE_DEV_PM_OPS(backlight_class_dev_pm_ops, backlight_suspend, 300 backlight_resume); 301 302static void bl_device_release(struct device *dev) 303{ 304 struct backlight_device *bd = to_backlight_device(dev); 305 kfree(bd); 306} 307 308static struct attribute *bl_device_attrs[] = { 309 &dev_attr_bl_power.attr, 310 &dev_attr_brightness.attr, 311 &dev_attr_actual_brightness.attr, 312 &dev_attr_max_brightness.attr, 313 &dev_attr_scale.attr, 314 &dev_attr_type.attr, 315 NULL, 316}; 317ATTRIBUTE_GROUPS(bl_device); 318 319/** 320 * backlight_force_update - tell the backlight subsystem that hardware state 321 * has changed 322 * @bd: the backlight device to update 323 * 324 * Updates the internal state of the backlight in response to a hardware event, 325 * and generate a uevent to notify userspace 326 */ 327void backlight_force_update(struct backlight_device *bd, 328 enum backlight_update_reason reason) 329{ 330 mutex_lock(&bd->ops_lock); 331 if (bd->ops && bd->ops->get_brightness) 332 bd->props.brightness = bd->ops->get_brightness(bd); 333 mutex_unlock(&bd->ops_lock); 334 backlight_generate_event(bd, reason); 335} 336EXPORT_SYMBOL(backlight_force_update); 337 338/** 339 * backlight_device_register - create and register a new object of 340 * backlight_device class. 341 * @name: the name of the new object(must be the same as the name of the 342 * respective framebuffer device). 343 * @parent: a pointer to the parent device 344 * @devdata: an optional pointer to be stored for private driver use. The 345 * methods may retrieve it by using bl_get_data(bd). 346 * @ops: the backlight operations structure. 347 * 348 * Creates and registers new backlight device. Returns either an 349 * ERR_PTR() or a pointer to the newly allocated device. 350 */ 351struct backlight_device *backlight_device_register(const char *name, 352 struct device *parent, void *devdata, const struct backlight_ops *ops, 353 const struct backlight_properties *props) 354{ 355 struct backlight_device *new_bd; 356 int rc; 357 358 pr_debug("backlight_device_register: name=%s\n", name); 359 360 new_bd = kzalloc(sizeof(struct backlight_device), GFP_KERNEL); 361 if (!new_bd) 362 return ERR_PTR(-ENOMEM); 363 364 mutex_init(&new_bd->update_lock); 365 mutex_init(&new_bd->ops_lock); 366 367 new_bd->dev.class = backlight_class; 368 new_bd->dev.parent = parent; 369 new_bd->dev.release = bl_device_release; 370 dev_set_name(&new_bd->dev, "%s", name); 371 dev_set_drvdata(&new_bd->dev, devdata); 372 373 /* Set default properties */ 374 if (props) { 375 memcpy(&new_bd->props, props, 376 sizeof(struct backlight_properties)); 377 if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) { 378 WARN(1, "%s: invalid backlight type", name); 379 new_bd->props.type = BACKLIGHT_RAW; 380 } 381 } else { 382 new_bd->props.type = BACKLIGHT_RAW; 383 } 384 385 rc = device_register(&new_bd->dev); 386 if (rc) { 387 put_device(&new_bd->dev); 388 return ERR_PTR(rc); 389 } 390 391 rc = backlight_register_fb(new_bd); 392 if (rc) { 393 device_unregister(&new_bd->dev); 394 return ERR_PTR(rc); 395 } 396 397 new_bd->ops = ops; 398 399#ifdef CONFIG_PMAC_BACKLIGHT 400 mutex_lock(&pmac_backlight_mutex); 401 if (!pmac_backlight) 402 pmac_backlight = new_bd; 403 mutex_unlock(&pmac_backlight_mutex); 404#endif 405 406 mutex_lock(&backlight_dev_list_mutex); 407 list_add(&new_bd->entry, &backlight_dev_list); 408 mutex_unlock(&backlight_dev_list_mutex); 409 410 blocking_notifier_call_chain(&backlight_notifier, 411 BACKLIGHT_REGISTERED, new_bd); 412 413 return new_bd; 414} 415EXPORT_SYMBOL(backlight_device_register); 416 417struct backlight_device *backlight_device_get_by_type(enum backlight_type type) 418{ 419 bool found = false; 420 struct backlight_device *bd; 421 422 mutex_lock(&backlight_dev_list_mutex); 423 list_for_each_entry(bd, &backlight_dev_list, entry) { 424 if (bd->props.type == type) { 425 found = true; 426 break; 427 } 428 } 429 mutex_unlock(&backlight_dev_list_mutex); 430 431 return found ? bd : NULL; 432} 433EXPORT_SYMBOL(backlight_device_get_by_type); 434 435/** 436 * backlight_device_unregister - unregisters a backlight device object. 437 * @bd: the backlight device object to be unregistered and freed. 438 * 439 * Unregisters a previously registered via backlight_device_register object. 440 */ 441void backlight_device_unregister(struct backlight_device *bd) 442{ 443 if (!bd) 444 return; 445 446 mutex_lock(&backlight_dev_list_mutex); 447 list_del(&bd->entry); 448 mutex_unlock(&backlight_dev_list_mutex); 449 450#ifdef CONFIG_PMAC_BACKLIGHT 451 mutex_lock(&pmac_backlight_mutex); 452 if (pmac_backlight == bd) 453 pmac_backlight = NULL; 454 mutex_unlock(&pmac_backlight_mutex); 455#endif 456 457 blocking_notifier_call_chain(&backlight_notifier, 458 BACKLIGHT_UNREGISTERED, bd); 459 460 mutex_lock(&bd->ops_lock); 461 bd->ops = NULL; 462 mutex_unlock(&bd->ops_lock); 463 464 backlight_unregister_fb(bd); 465 device_unregister(&bd->dev); 466} 467EXPORT_SYMBOL(backlight_device_unregister); 468 469static void devm_backlight_device_release(struct device *dev, void *res) 470{ 471 struct backlight_device *backlight = *(struct backlight_device **)res; 472 473 backlight_device_unregister(backlight); 474} 475 476static int devm_backlight_device_match(struct device *dev, void *res, 477 void *data) 478{ 479 struct backlight_device **r = res; 480 481 return *r == data; 482} 483 484/** 485 * backlight_register_notifier - get notified of backlight (un)registration 486 * @nb: notifier block with the notifier to call on backlight (un)registration 487 * 488 * @return 0 on success, otherwise a negative error code 489 * 490 * Register a notifier to get notified when backlight devices get registered 491 * or unregistered. 492 */ 493int backlight_register_notifier(struct notifier_block *nb) 494{ 495 return blocking_notifier_chain_register(&backlight_notifier, nb); 496} 497EXPORT_SYMBOL(backlight_register_notifier); 498 499/** 500 * backlight_unregister_notifier - unregister a backlight notifier 501 * @nb: notifier block to unregister 502 * 503 * @return 0 on success, otherwise a negative error code 504 * 505 * Register a notifier to get notified when backlight devices get registered 506 * or unregistered. 507 */ 508int backlight_unregister_notifier(struct notifier_block *nb) 509{ 510 return blocking_notifier_chain_unregister(&backlight_notifier, nb); 511} 512EXPORT_SYMBOL(backlight_unregister_notifier); 513 514/** 515 * devm_backlight_device_register - resource managed backlight_device_register() 516 * @dev: the device to register 517 * @name: the name of the device 518 * @parent: a pointer to the parent device 519 * @devdata: an optional pointer to be stored for private driver use 520 * @ops: the backlight operations structure 521 * @props: the backlight properties 522 * 523 * @return a struct backlight on success, or an ERR_PTR on error 524 * 525 * Managed backlight_device_register(). The backlight_device returned 526 * from this function are automatically freed on driver detach. 527 * See backlight_device_register() for more information. 528 */ 529struct backlight_device *devm_backlight_device_register(struct device *dev, 530 const char *name, struct device *parent, void *devdata, 531 const struct backlight_ops *ops, 532 const struct backlight_properties *props) 533{ 534 struct backlight_device **ptr, *backlight; 535 536 ptr = devres_alloc(devm_backlight_device_release, sizeof(*ptr), 537 GFP_KERNEL); 538 if (!ptr) 539 return ERR_PTR(-ENOMEM); 540 541 backlight = backlight_device_register(name, parent, devdata, ops, 542 props); 543 if (!IS_ERR(backlight)) { 544 *ptr = backlight; 545 devres_add(dev, ptr); 546 } else { 547 devres_free(ptr); 548 } 549 550 return backlight; 551} 552EXPORT_SYMBOL(devm_backlight_device_register); 553 554/** 555 * devm_backlight_device_unregister - resource managed backlight_device_unregister() 556 * @dev: the device to unregister 557 * @bd: the backlight device to unregister 558 * 559 * Deallocated a backlight allocated with devm_backlight_device_register(). 560 * Normally this function will not need to be called and the resource management 561 * code will ensure that the resource is freed. 562 */ 563void devm_backlight_device_unregister(struct device *dev, 564 struct backlight_device *bd) 565{ 566 int rc; 567 568 rc = devres_release(dev, devm_backlight_device_release, 569 devm_backlight_device_match, bd); 570 WARN_ON(rc); 571} 572EXPORT_SYMBOL(devm_backlight_device_unregister); 573 574#ifdef CONFIG_OF 575static int of_parent_match(struct device *dev, const void *data) 576{ 577 return dev->parent && dev->parent->of_node == data; 578} 579 580/** 581 * of_find_backlight_by_node() - find backlight device by device-tree node 582 * @node: device-tree node of the backlight device 583 * 584 * Returns a pointer to the backlight device corresponding to the given DT 585 * node or NULL if no such backlight device exists or if the device hasn't 586 * been probed yet. 587 * 588 * This function obtains a reference on the backlight device and it is the 589 * caller's responsibility to drop the reference by calling put_device() on 590 * the backlight device's .dev field. 591 */ 592struct backlight_device *of_find_backlight_by_node(struct device_node *node) 593{ 594 struct device *dev; 595 596 dev = class_find_device(backlight_class, NULL, node, of_parent_match); 597 598 return dev ? to_backlight_device(dev) : NULL; 599} 600EXPORT_SYMBOL(of_find_backlight_by_node); 601#endif 602 603/** 604 * of_find_backlight - Get backlight device 605 * @dev: Device 606 * 607 * This function looks for a property named 'backlight' on the DT node 608 * connected to @dev and looks up the backlight device. 609 * 610 * Call backlight_put() to drop the reference on the backlight device. 611 * 612 * Returns: 613 * A pointer to the backlight device if found. 614 * Error pointer -EPROBE_DEFER if the DT property is set, but no backlight 615 * device is found. 616 * NULL if there's no backlight property. 617 */ 618struct backlight_device *of_find_backlight(struct device *dev) 619{ 620 struct backlight_device *bd = NULL; 621 struct device_node *np; 622 623 if (!dev) 624 return NULL; 625 626 if (IS_ENABLED(CONFIG_OF) && dev->of_node) { 627 np = of_parse_phandle(dev->of_node, "backlight", 0); 628 if (np) { 629 bd = of_find_backlight_by_node(np); 630 of_node_put(np); 631 if (!bd) 632 return ERR_PTR(-EPROBE_DEFER); 633 /* 634 * Note: gpio_backlight uses brightness as 635 * power state during probe 636 */ 637 if (!bd->props.brightness) 638 bd->props.brightness = bd->props.max_brightness; 639 } 640 } 641 642 return bd; 643} 644EXPORT_SYMBOL(of_find_backlight); 645 646static void devm_backlight_release(void *data) 647{ 648 backlight_put(data); 649} 650 651/** 652 * devm_of_find_backlight - Resource-managed of_find_backlight() 653 * @dev: Device 654 * 655 * Device managed version of of_find_backlight(). 656 * The reference on the backlight device is automatically 657 * dropped on driver detach. 658 */ 659struct backlight_device *devm_of_find_backlight(struct device *dev) 660{ 661 struct backlight_device *bd; 662 int ret; 663 664 bd = of_find_backlight(dev); 665 if (IS_ERR_OR_NULL(bd)) 666 return bd; 667 ret = devm_add_action(dev, devm_backlight_release, bd); 668 if (ret) { 669 backlight_put(bd); 670 return ERR_PTR(ret); 671 } 672 return bd; 673} 674EXPORT_SYMBOL(devm_of_find_backlight); 675 676static void __exit backlight_class_exit(void) 677{ 678 class_destroy(backlight_class); 679} 680 681static int __init backlight_class_init(void) 682{ 683 backlight_class = class_create(THIS_MODULE, "backlight"); 684 if (IS_ERR(backlight_class)) { 685 pr_warn("Unable to create backlight class; errno = %ld\n", 686 PTR_ERR(backlight_class)); 687 return PTR_ERR(backlight_class); 688 } 689 690 backlight_class->dev_groups = bl_device_groups; 691 backlight_class->pm = &backlight_class_dev_pm_ops; 692 INIT_LIST_HEAD(&backlight_dev_list); 693 mutex_init(&backlight_dev_list_mutex); 694 BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier); 695 696 return 0; 697} 698 699/* 700 * if this is compiled into the kernel, we need to ensure that the 701 * class is registered before users of the class try to register lcd's 702 */ 703postcore_initcall(backlight_class_init); 704module_exit(backlight_class_exit); 705 706MODULE_LICENSE("GPL"); 707MODULE_AUTHOR("Jamey Hicks <jamey.hicks@hp.com>, Andrew Zabolotny <zap@homelink.ru>"); 708MODULE_DESCRIPTION("Backlight Lowlevel Control Abstraction");