LCOV - code coverage report
Current view: top level - drivers/video/backlight - backlight.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 194 4.6 %
Date: 2022-12-09 01:23:36 Functions: 1 27 3.7 %

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

Generated by: LCOV version 1.14