root/drivers/leds/leds-pm8058.c

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

DEFINITIONS

This source file includes following definitions.
  1. pm8058_led_set
  2. pm8058_led_get
  3. pm8058_led_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2010, 2011, 2016 The Linux Foundation. All rights reserved.
   3  */
   4 #include <linux/leds.h>
   5 #include <linux/module.h>
   6 #include <linux/of.h>
   7 #include <linux/of_device.h>
   8 #include <linux/platform_device.h>
   9 #include <linux/pm.h>
  10 #include <linux/regmap.h>
  11 
  12 #define PM8058_LED_TYPE_COMMON  0x00
  13 #define PM8058_LED_TYPE_KEYPAD  0x01
  14 #define PM8058_LED_TYPE_FLASH   0x02
  15 
  16 #define PM8058_LED_TYPE_COMMON_MASK     0xf8
  17 #define PM8058_LED_TYPE_KEYPAD_MASK     0xf0
  18 #define PM8058_LED_TYPE_COMMON_SHIFT    3
  19 #define PM8058_LED_TYPE_KEYPAD_SHIFT    4
  20 
  21 struct pm8058_led {
  22         struct regmap *map;
  23         u32 reg;
  24         u32 ledtype;
  25         struct led_classdev cdev;
  26 };
  27 
  28 static void pm8058_led_set(struct led_classdev *cled,
  29         enum led_brightness value)
  30 {
  31         struct pm8058_led *led;
  32         int ret = 0;
  33         unsigned int mask = 0;
  34         unsigned int val = 0;
  35 
  36         led = container_of(cled, struct pm8058_led, cdev);
  37         switch (led->ledtype) {
  38         case PM8058_LED_TYPE_COMMON:
  39                 mask = PM8058_LED_TYPE_COMMON_MASK;
  40                 val = value << PM8058_LED_TYPE_COMMON_SHIFT;
  41                 break;
  42         case PM8058_LED_TYPE_KEYPAD:
  43         case PM8058_LED_TYPE_FLASH:
  44                 mask = PM8058_LED_TYPE_KEYPAD_MASK;
  45                 val = value << PM8058_LED_TYPE_KEYPAD_SHIFT;
  46                 break;
  47         default:
  48                 break;
  49         }
  50 
  51         ret = regmap_update_bits(led->map, led->reg, mask, val);
  52         if (ret)
  53                 pr_err("Failed to set LED brightness\n");
  54 }
  55 
  56 static enum led_brightness pm8058_led_get(struct led_classdev *cled)
  57 {
  58         struct pm8058_led *led;
  59         int ret;
  60         unsigned int val;
  61 
  62         led = container_of(cled, struct pm8058_led, cdev);
  63 
  64         ret = regmap_read(led->map, led->reg, &val);
  65         if (ret) {
  66                 pr_err("Failed to get LED brightness\n");
  67                 return LED_OFF;
  68         }
  69 
  70         switch (led->ledtype) {
  71         case PM8058_LED_TYPE_COMMON:
  72                 val &= PM8058_LED_TYPE_COMMON_MASK;
  73                 val >>= PM8058_LED_TYPE_COMMON_SHIFT;
  74                 break;
  75         case PM8058_LED_TYPE_KEYPAD:
  76         case PM8058_LED_TYPE_FLASH:
  77                 val &= PM8058_LED_TYPE_KEYPAD_MASK;
  78                 val >>= PM8058_LED_TYPE_KEYPAD_SHIFT;
  79                 break;
  80         default:
  81                 val = LED_OFF;
  82                 break;
  83         }
  84 
  85         return val;
  86 }
  87 
  88 static int pm8058_led_probe(struct platform_device *pdev)
  89 {
  90         struct pm8058_led *led;
  91         struct device_node *np = pdev->dev.of_node;
  92         int ret;
  93         struct regmap *map;
  94         const char *state;
  95         enum led_brightness maxbright;
  96 
  97         led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
  98         if (!led)
  99                 return -ENOMEM;
 100 
 101         led->ledtype = (u32)(unsigned long)of_device_get_match_data(&pdev->dev);
 102 
 103         map = dev_get_regmap(pdev->dev.parent, NULL);
 104         if (!map) {
 105                 dev_err(&pdev->dev, "Parent regmap unavailable.\n");
 106                 return -ENXIO;
 107         }
 108         led->map = map;
 109 
 110         ret = of_property_read_u32(np, "reg", &led->reg);
 111         if (ret) {
 112                 dev_err(&pdev->dev, "no register offset specified\n");
 113                 return -EINVAL;
 114         }
 115 
 116         /* Use label else node name */
 117         led->cdev.name = of_get_property(np, "label", NULL) ? : np->name;
 118         led->cdev.default_trigger =
 119                 of_get_property(np, "linux,default-trigger", NULL);
 120         led->cdev.brightness_set = pm8058_led_set;
 121         led->cdev.brightness_get = pm8058_led_get;
 122         if (led->ledtype == PM8058_LED_TYPE_COMMON)
 123                 maxbright = 31; /* 5 bits */
 124         else
 125                 maxbright = 15; /* 4 bits */
 126         led->cdev.max_brightness = maxbright;
 127 
 128         state = of_get_property(np, "default-state", NULL);
 129         if (state) {
 130                 if (!strcmp(state, "keep")) {
 131                         led->cdev.brightness = pm8058_led_get(&led->cdev);
 132                 } else if (!strcmp(state, "on")) {
 133                         led->cdev.brightness = maxbright;
 134                         pm8058_led_set(&led->cdev, maxbright);
 135                 } else {
 136                         led->cdev.brightness = LED_OFF;
 137                         pm8058_led_set(&led->cdev, LED_OFF);
 138                 }
 139         }
 140 
 141         if (led->ledtype == PM8058_LED_TYPE_KEYPAD ||
 142             led->ledtype == PM8058_LED_TYPE_FLASH)
 143                 led->cdev.flags = LED_CORE_SUSPENDRESUME;
 144 
 145         ret = devm_led_classdev_register(&pdev->dev, &led->cdev);
 146         if (ret) {
 147                 dev_err(&pdev->dev, "unable to register led \"%s\"\n",
 148                         led->cdev.name);
 149                 return ret;
 150         }
 151 
 152         return 0;
 153 }
 154 
 155 static const struct of_device_id pm8058_leds_id_table[] = {
 156         {
 157                 .compatible = "qcom,pm8058-led",
 158                 .data = (void *)PM8058_LED_TYPE_COMMON
 159         },
 160         {
 161                 .compatible = "qcom,pm8058-keypad-led",
 162                 .data = (void *)PM8058_LED_TYPE_KEYPAD
 163         },
 164         {
 165                 .compatible = "qcom,pm8058-flash-led",
 166                 .data = (void *)PM8058_LED_TYPE_FLASH
 167         },
 168         { },
 169 };
 170 MODULE_DEVICE_TABLE(of, pm8058_leds_id_table);
 171 
 172 static struct platform_driver pm8058_led_driver = {
 173         .probe          = pm8058_led_probe,
 174         .driver         = {
 175                 .name   = "pm8058-leds",
 176                 .of_match_table = pm8058_leds_id_table,
 177         },
 178 };
 179 module_platform_driver(pm8058_led_driver);
 180 
 181 MODULE_DESCRIPTION("PM8058 LEDs driver");
 182 MODULE_LICENSE("GPL v2");
 183 MODULE_ALIAS("platform:pm8058-leds");

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