root/drivers/video/backlight/lm3533_bl.c

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

DEFINITIONS

This source file includes following definitions.
  1. lm3533_bl_get_ctrlbank_id
  2. lm3533_bl_update_status
  3. lm3533_bl_get_brightness
  4. show_id
  5. show_als_channel
  6. show_als_en
  7. store_als_en
  8. show_linear
  9. store_linear
  10. show_pwm
  11. store_pwm
  12. lm3533_bl_attr_is_visible
  13. lm3533_bl_setup
  14. lm3533_bl_probe
  15. lm3533_bl_remove
  16. lm3533_bl_suspend
  17. lm3533_bl_resume
  18. lm3533_bl_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * lm3533-bl.c -- LM3533 Backlight driver
   4  *
   5  * Copyright (C) 2011-2012 Texas Instruments
   6  *
   7  * Author: Johan Hovold <jhovold@gmail.com>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/init.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/backlight.h>
  14 #include <linux/fb.h>
  15 #include <linux/slab.h>
  16 
  17 #include <linux/mfd/lm3533.h>
  18 
  19 
  20 #define LM3533_HVCTRLBANK_COUNT         2
  21 #define LM3533_BL_MAX_BRIGHTNESS        255
  22 
  23 #define LM3533_REG_CTRLBANK_AB_BCONF    0x1a
  24 
  25 
  26 struct lm3533_bl {
  27         struct lm3533 *lm3533;
  28         struct lm3533_ctrlbank cb;
  29         struct backlight_device *bd;
  30         int id;
  31 };
  32 
  33 
  34 static inline int lm3533_bl_get_ctrlbank_id(struct lm3533_bl *bl)
  35 {
  36         return bl->id;
  37 }
  38 
  39 static int lm3533_bl_update_status(struct backlight_device *bd)
  40 {
  41         struct lm3533_bl *bl = bl_get_data(bd);
  42         int brightness = bd->props.brightness;
  43 
  44         if (bd->props.power != FB_BLANK_UNBLANK)
  45                 brightness = 0;
  46         if (bd->props.fb_blank != FB_BLANK_UNBLANK)
  47                 brightness = 0;
  48 
  49         return lm3533_ctrlbank_set_brightness(&bl->cb, (u8)brightness);
  50 }
  51 
  52 static int lm3533_bl_get_brightness(struct backlight_device *bd)
  53 {
  54         struct lm3533_bl *bl = bl_get_data(bd);
  55         u8 val;
  56         int ret;
  57 
  58         ret = lm3533_ctrlbank_get_brightness(&bl->cb, &val);
  59         if (ret)
  60                 return ret;
  61 
  62         return val;
  63 }
  64 
  65 static const struct backlight_ops lm3533_bl_ops = {
  66         .get_brightness = lm3533_bl_get_brightness,
  67         .update_status  = lm3533_bl_update_status,
  68 };
  69 
  70 static ssize_t show_id(struct device *dev,
  71                                 struct device_attribute *attr, char *buf)
  72 {
  73         struct lm3533_bl *bl = dev_get_drvdata(dev);
  74 
  75         return scnprintf(buf, PAGE_SIZE, "%d\n", bl->id);
  76 }
  77 
  78 static ssize_t show_als_channel(struct device *dev,
  79                                 struct device_attribute *attr, char *buf)
  80 {
  81         struct lm3533_bl *bl = dev_get_drvdata(dev);
  82         unsigned channel = lm3533_bl_get_ctrlbank_id(bl);
  83 
  84         return scnprintf(buf, PAGE_SIZE, "%u\n", channel);
  85 }
  86 
  87 static ssize_t show_als_en(struct device *dev,
  88                                 struct device_attribute *attr, char *buf)
  89 {
  90         struct lm3533_bl *bl = dev_get_drvdata(dev);
  91         int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
  92         u8 val;
  93         u8 mask;
  94         bool enable;
  95         int ret;
  96 
  97         ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
  98         if (ret)
  99                 return ret;
 100 
 101         mask = 1 << (2 * ctrlbank);
 102         enable = val & mask;
 103 
 104         return scnprintf(buf, PAGE_SIZE, "%d\n", enable);
 105 }
 106 
 107 static ssize_t store_als_en(struct device *dev,
 108                                         struct device_attribute *attr,
 109                                         const char *buf, size_t len)
 110 {
 111         struct lm3533_bl *bl = dev_get_drvdata(dev);
 112         int ctrlbank = lm3533_bl_get_ctrlbank_id(bl);
 113         int enable;
 114         u8 val;
 115         u8 mask;
 116         int ret;
 117 
 118         if (kstrtoint(buf, 0, &enable))
 119                 return -EINVAL;
 120 
 121         mask = 1 << (2 * ctrlbank);
 122 
 123         if (enable)
 124                 val = mask;
 125         else
 126                 val = 0;
 127 
 128         ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
 129                                                                         mask);
 130         if (ret)
 131                 return ret;
 132 
 133         return len;
 134 }
 135 
 136 static ssize_t show_linear(struct device *dev,
 137                                 struct device_attribute *attr, char *buf)
 138 {
 139         struct lm3533_bl *bl = dev_get_drvdata(dev);
 140         u8 val;
 141         u8 mask;
 142         int linear;
 143         int ret;
 144 
 145         ret = lm3533_read(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, &val);
 146         if (ret)
 147                 return ret;
 148 
 149         mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
 150 
 151         if (val & mask)
 152                 linear = 1;
 153         else
 154                 linear = 0;
 155 
 156         return scnprintf(buf, PAGE_SIZE, "%x\n", linear);
 157 }
 158 
 159 static ssize_t store_linear(struct device *dev,
 160                                         struct device_attribute *attr,
 161                                         const char *buf, size_t len)
 162 {
 163         struct lm3533_bl *bl = dev_get_drvdata(dev);
 164         unsigned long linear;
 165         u8 mask;
 166         u8 val;
 167         int ret;
 168 
 169         if (kstrtoul(buf, 0, &linear))
 170                 return -EINVAL;
 171 
 172         mask = 1 << (2 * lm3533_bl_get_ctrlbank_id(bl) + 1);
 173 
 174         if (linear)
 175                 val = mask;
 176         else
 177                 val = 0;
 178 
 179         ret = lm3533_update(bl->lm3533, LM3533_REG_CTRLBANK_AB_BCONF, val,
 180                                                                         mask);
 181         if (ret)
 182                 return ret;
 183 
 184         return len;
 185 }
 186 
 187 static ssize_t show_pwm(struct device *dev,
 188                                         struct device_attribute *attr,
 189                                         char *buf)
 190 {
 191         struct lm3533_bl *bl = dev_get_drvdata(dev);
 192         u8 val;
 193         int ret;
 194 
 195         ret = lm3533_ctrlbank_get_pwm(&bl->cb, &val);
 196         if (ret)
 197                 return ret;
 198 
 199         return scnprintf(buf, PAGE_SIZE, "%u\n", val);
 200 }
 201 
 202 static ssize_t store_pwm(struct device *dev,
 203                                         struct device_attribute *attr,
 204                                         const char *buf, size_t len)
 205 {
 206         struct lm3533_bl *bl = dev_get_drvdata(dev);
 207         u8 val;
 208         int ret;
 209 
 210         if (kstrtou8(buf, 0, &val))
 211                 return -EINVAL;
 212 
 213         ret = lm3533_ctrlbank_set_pwm(&bl->cb, val);
 214         if (ret)
 215                 return ret;
 216 
 217         return len;
 218 }
 219 
 220 static LM3533_ATTR_RO(als_channel);
 221 static LM3533_ATTR_RW(als_en);
 222 static LM3533_ATTR_RO(id);
 223 static LM3533_ATTR_RW(linear);
 224 static LM3533_ATTR_RW(pwm);
 225 
 226 static struct attribute *lm3533_bl_attributes[] = {
 227         &dev_attr_als_channel.attr,
 228         &dev_attr_als_en.attr,
 229         &dev_attr_id.attr,
 230         &dev_attr_linear.attr,
 231         &dev_attr_pwm.attr,
 232         NULL,
 233 };
 234 
 235 static umode_t lm3533_bl_attr_is_visible(struct kobject *kobj,
 236                                              struct attribute *attr, int n)
 237 {
 238         struct device *dev = container_of(kobj, struct device, kobj);
 239         struct lm3533_bl *bl = dev_get_drvdata(dev);
 240         umode_t mode = attr->mode;
 241 
 242         if (attr == &dev_attr_als_channel.attr ||
 243                                         attr == &dev_attr_als_en.attr) {
 244                 if (!bl->lm3533->have_als)
 245                         mode = 0;
 246         }
 247 
 248         return mode;
 249 };
 250 
 251 static struct attribute_group lm3533_bl_attribute_group = {
 252         .is_visible     = lm3533_bl_attr_is_visible,
 253         .attrs          = lm3533_bl_attributes
 254 };
 255 
 256 static int lm3533_bl_setup(struct lm3533_bl *bl,
 257                                         struct lm3533_bl_platform_data *pdata)
 258 {
 259         int ret;
 260 
 261         ret = lm3533_ctrlbank_set_max_current(&bl->cb, pdata->max_current);
 262         if (ret)
 263                 return ret;
 264 
 265         return lm3533_ctrlbank_set_pwm(&bl->cb, pdata->pwm);
 266 }
 267 
 268 static int lm3533_bl_probe(struct platform_device *pdev)
 269 {
 270         struct lm3533 *lm3533;
 271         struct lm3533_bl_platform_data *pdata;
 272         struct lm3533_bl *bl;
 273         struct backlight_device *bd;
 274         struct backlight_properties props;
 275         int ret;
 276 
 277         dev_dbg(&pdev->dev, "%s\n", __func__);
 278 
 279         lm3533 = dev_get_drvdata(pdev->dev.parent);
 280         if (!lm3533)
 281                 return -EINVAL;
 282 
 283         pdata = dev_get_platdata(&pdev->dev);
 284         if (!pdata) {
 285                 dev_err(&pdev->dev, "no platform data\n");
 286                 return -EINVAL;
 287         }
 288 
 289         if (pdev->id < 0 || pdev->id >= LM3533_HVCTRLBANK_COUNT) {
 290                 dev_err(&pdev->dev, "illegal backlight id %d\n", pdev->id);
 291                 return -EINVAL;
 292         }
 293 
 294         bl = devm_kzalloc(&pdev->dev, sizeof(*bl), GFP_KERNEL);
 295         if (!bl)
 296                 return -ENOMEM;
 297 
 298         bl->lm3533 = lm3533;
 299         bl->id = pdev->id;
 300 
 301         bl->cb.lm3533 = lm3533;
 302         bl->cb.id = lm3533_bl_get_ctrlbank_id(bl);
 303         bl->cb.dev = NULL;                      /* until registered */
 304 
 305         memset(&props, 0, sizeof(props));
 306         props.type = BACKLIGHT_RAW;
 307         props.max_brightness = LM3533_BL_MAX_BRIGHTNESS;
 308         props.brightness = pdata->default_brightness;
 309         bd = devm_backlight_device_register(&pdev->dev, pdata->name,
 310                                         pdev->dev.parent, bl, &lm3533_bl_ops,
 311                                         &props);
 312         if (IS_ERR(bd)) {
 313                 dev_err(&pdev->dev, "failed to register backlight device\n");
 314                 return PTR_ERR(bd);
 315         }
 316 
 317         bl->bd = bd;
 318         bl->cb.dev = &bl->bd->dev;
 319 
 320         platform_set_drvdata(pdev, bl);
 321 
 322         ret = sysfs_create_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
 323         if (ret < 0) {
 324                 dev_err(&pdev->dev, "failed to create sysfs attributes\n");
 325                 return ret;
 326         }
 327 
 328         backlight_update_status(bd);
 329 
 330         ret = lm3533_bl_setup(bl, pdata);
 331         if (ret)
 332                 goto err_sysfs_remove;
 333 
 334         ret = lm3533_ctrlbank_enable(&bl->cb);
 335         if (ret)
 336                 goto err_sysfs_remove;
 337 
 338         return 0;
 339 
 340 err_sysfs_remove:
 341         sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
 342 
 343         return ret;
 344 }
 345 
 346 static int lm3533_bl_remove(struct platform_device *pdev)
 347 {
 348         struct lm3533_bl *bl = platform_get_drvdata(pdev);
 349         struct backlight_device *bd = bl->bd;
 350 
 351         dev_dbg(&bd->dev, "%s\n", __func__);
 352 
 353         bd->props.power = FB_BLANK_POWERDOWN;
 354         bd->props.brightness = 0;
 355 
 356         lm3533_ctrlbank_disable(&bl->cb);
 357         sysfs_remove_group(&bd->dev.kobj, &lm3533_bl_attribute_group);
 358 
 359         return 0;
 360 }
 361 
 362 #ifdef CONFIG_PM_SLEEP
 363 static int lm3533_bl_suspend(struct device *dev)
 364 {
 365         struct lm3533_bl *bl = dev_get_drvdata(dev);
 366 
 367         dev_dbg(dev, "%s\n", __func__);
 368 
 369         return lm3533_ctrlbank_disable(&bl->cb);
 370 }
 371 
 372 static int lm3533_bl_resume(struct device *dev)
 373 {
 374         struct lm3533_bl *bl = dev_get_drvdata(dev);
 375 
 376         dev_dbg(dev, "%s\n", __func__);
 377 
 378         return lm3533_ctrlbank_enable(&bl->cb);
 379 }
 380 #endif
 381 
 382 static SIMPLE_DEV_PM_OPS(lm3533_bl_pm_ops, lm3533_bl_suspend, lm3533_bl_resume);
 383 
 384 static void lm3533_bl_shutdown(struct platform_device *pdev)
 385 {
 386         struct lm3533_bl *bl = platform_get_drvdata(pdev);
 387 
 388         dev_dbg(&pdev->dev, "%s\n", __func__);
 389 
 390         lm3533_ctrlbank_disable(&bl->cb);
 391 }
 392 
 393 static struct platform_driver lm3533_bl_driver = {
 394         .driver = {
 395                 .name   = "lm3533-backlight",
 396                 .pm     = &lm3533_bl_pm_ops,
 397         },
 398         .probe          = lm3533_bl_probe,
 399         .remove         = lm3533_bl_remove,
 400         .shutdown       = lm3533_bl_shutdown,
 401 };
 402 module_platform_driver(lm3533_bl_driver);
 403 
 404 MODULE_AUTHOR("Johan Hovold <jhovold@gmail.com>");
 405 MODULE_DESCRIPTION("LM3533 Backlight driver");
 406 MODULE_LICENSE("GPL");
 407 MODULE_ALIAS("platform:lm3533-backlight");

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