root/drivers/leds/leds-lp8788.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lp8788_led_init_device
  2. lp8788_led_enable
  3. lp8788_brightness_set
  4. lp8788_led_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * TI LP8788 MFD - keyled driver
   4  *
   5  * Copyright 2012 Texas Instruments
   6  *
   7  * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/slab.h>
  12 #include <linux/err.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/leds.h>
  15 #include <linux/mutex.h>
  16 #include <linux/mfd/lp8788.h>
  17 #include <linux/mfd/lp8788-isink.h>
  18 
  19 #define MAX_BRIGHTNESS                  LP8788_ISINK_MAX_PWM
  20 #define DEFAULT_LED_NAME                "keyboard-backlight"
  21 
  22 struct lp8788_led {
  23         struct lp8788 *lp;
  24         struct mutex lock;
  25         struct led_classdev led_dev;
  26         enum lp8788_isink_number isink_num;
  27         int on;
  28 };
  29 
  30 struct lp8788_led_config {
  31         enum lp8788_isink_scale scale;
  32         enum lp8788_isink_number num;
  33         int iout;
  34 };
  35 
  36 static struct lp8788_led_config default_led_config = {
  37         .scale = LP8788_ISINK_SCALE_100mA,
  38         .num   = LP8788_ISINK_3,
  39         .iout  = 0,
  40 };
  41 
  42 static int lp8788_led_init_device(struct lp8788_led *led,
  43                                 struct lp8788_led_platform_data *pdata)
  44 {
  45         struct lp8788_led_config *cfg = &default_led_config;
  46         u8 addr, mask, val;
  47         int ret;
  48 
  49         if (pdata) {
  50                 cfg->scale = pdata->scale;
  51                 cfg->num = pdata->num;
  52                 cfg->iout = pdata->iout_code;
  53         }
  54 
  55         led->isink_num = cfg->num;
  56 
  57         /* scale configuration */
  58         addr = LP8788_ISINK_CTRL;
  59         mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
  60         val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET);
  61         ret = lp8788_update_bits(led->lp, addr, mask, val);
  62         if (ret)
  63                 return ret;
  64 
  65         /* current configuration */
  66         addr = lp8788_iout_addr[cfg->num];
  67         mask = lp8788_iout_mask[cfg->num];
  68         val = cfg->iout;
  69 
  70         return lp8788_update_bits(led->lp, addr, mask, val);
  71 }
  72 
  73 static int lp8788_led_enable(struct lp8788_led *led,
  74                         enum lp8788_isink_number num, int on)
  75 {
  76         int ret;
  77 
  78         u8 mask = 1 << num;
  79         u8 val = on << num;
  80 
  81         ret = lp8788_update_bits(led->lp, LP8788_ISINK_CTRL, mask, val);
  82         if (ret == 0)
  83                 led->on = on;
  84 
  85         return ret;
  86 }
  87 
  88 static int lp8788_brightness_set(struct led_classdev *led_cdev,
  89                                 enum led_brightness val)
  90 {
  91         struct lp8788_led *led =
  92                         container_of(led_cdev, struct lp8788_led, led_dev);
  93 
  94         enum lp8788_isink_number num = led->isink_num;
  95         int enable, ret;
  96 
  97         mutex_lock(&led->lock);
  98 
  99         switch (num) {
 100         case LP8788_ISINK_1:
 101         case LP8788_ISINK_2:
 102         case LP8788_ISINK_3:
 103                 ret = lp8788_write_byte(led->lp, lp8788_pwm_addr[num], val);
 104                 if (ret < 0)
 105                         goto unlock;
 106                 break;
 107         default:
 108                 mutex_unlock(&led->lock);
 109                 return -EINVAL;
 110         }
 111 
 112         enable = (val > 0) ? 1 : 0;
 113         if (enable != led->on)
 114                 ret = lp8788_led_enable(led, num, enable);
 115 unlock:
 116         mutex_unlock(&led->lock);
 117         return ret;
 118 }
 119 
 120 static int lp8788_led_probe(struct platform_device *pdev)
 121 {
 122         struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 123         struct lp8788_led_platform_data *led_pdata;
 124         struct lp8788_led *led;
 125         struct device *dev = &pdev->dev;
 126         int ret;
 127 
 128         led = devm_kzalloc(dev, sizeof(struct lp8788_led), GFP_KERNEL);
 129         if (!led)
 130                 return -ENOMEM;
 131 
 132         led->lp = lp;
 133         led->led_dev.max_brightness = MAX_BRIGHTNESS;
 134         led->led_dev.brightness_set_blocking = lp8788_brightness_set;
 135 
 136         led_pdata = lp->pdata ? lp->pdata->led_pdata : NULL;
 137 
 138         if (!led_pdata || !led_pdata->name)
 139                 led->led_dev.name = DEFAULT_LED_NAME;
 140         else
 141                 led->led_dev.name = led_pdata->name;
 142 
 143         mutex_init(&led->lock);
 144 
 145         ret = lp8788_led_init_device(led, led_pdata);
 146         if (ret) {
 147                 dev_err(dev, "led init device err: %d\n", ret);
 148                 return ret;
 149         }
 150 
 151         ret = devm_led_classdev_register(dev, &led->led_dev);
 152         if (ret) {
 153                 dev_err(dev, "led register err: %d\n", ret);
 154                 return ret;
 155         }
 156 
 157         return 0;
 158 }
 159 
 160 static struct platform_driver lp8788_led_driver = {
 161         .probe = lp8788_led_probe,
 162         .driver = {
 163                 .name = LP8788_DEV_KEYLED,
 164         },
 165 };
 166 module_platform_driver(lp8788_led_driver);
 167 
 168 MODULE_DESCRIPTION("Texas Instruments LP8788 Keyboard LED Driver");
 169 MODULE_AUTHOR("Milo Kim");
 170 MODULE_LICENSE("GPL");
 171 MODULE_ALIAS("platform:lp8788-keyled");

/* [<][>][^][v][top][bottom][index][help] */