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