root/drivers/video/backlight/pcf50633-backlight.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcf50633_bl_set_brightness_limit
  2. pcf50633_bl_update_status
  3. pcf50633_bl_get_brightness
  4. pcf50633_bl_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
   4  *      PCF50633 backlight device driver
   5  */
   6 
   7 #include <linux/kernel.h>
   8 #include <linux/module.h>
   9 #include <linux/slab.h>
  10 #include <linux/platform_device.h>
  11 
  12 #include <linux/backlight.h>
  13 #include <linux/fb.h>
  14 
  15 #include <linux/mfd/pcf50633/core.h>
  16 #include <linux/mfd/pcf50633/backlight.h>
  17 
  18 struct pcf50633_bl {
  19         struct pcf50633 *pcf;
  20         struct backlight_device *bl;
  21 
  22         unsigned int brightness;
  23         unsigned int brightness_limit;
  24 };
  25 
  26 /*
  27  * pcf50633_bl_set_brightness_limit
  28  *
  29  * Update the brightness limit for the pc50633 backlight. The actual brightness
  30  * will not go above the limit. This is useful to limit power drain for example
  31  * on low battery.
  32  *
  33  * @dev: Pointer to a pcf50633 device
  34  * @limit: The brightness limit. Valid values are 0-63
  35  */
  36 int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit)
  37 {
  38         struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev);
  39 
  40         if (!pcf_bl)
  41                 return -ENODEV;
  42 
  43         pcf_bl->brightness_limit = limit & 0x3f;
  44         backlight_update_status(pcf_bl->bl);
  45 
  46         return 0;
  47 }
  48 
  49 static int pcf50633_bl_update_status(struct backlight_device *bl)
  50 {
  51         struct pcf50633_bl *pcf_bl = bl_get_data(bl);
  52         unsigned int new_brightness;
  53 
  54 
  55         if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) ||
  56                 bl->props.power != FB_BLANK_UNBLANK)
  57                 new_brightness = 0;
  58         else if (bl->props.brightness < pcf_bl->brightness_limit)
  59                 new_brightness = bl->props.brightness;
  60         else
  61                 new_brightness = pcf_bl->brightness_limit;
  62 
  63 
  64         if (pcf_bl->brightness == new_brightness)
  65                 return 0;
  66 
  67         if (new_brightness) {
  68                 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT,
  69                                         new_brightness);
  70                 if (!pcf_bl->brightness)
  71                         pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1);
  72         } else {
  73                 pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0);
  74         }
  75 
  76         pcf_bl->brightness = new_brightness;
  77 
  78         return 0;
  79 }
  80 
  81 static int pcf50633_bl_get_brightness(struct backlight_device *bl)
  82 {
  83         struct pcf50633_bl *pcf_bl = bl_get_data(bl);
  84 
  85         return pcf_bl->brightness;
  86 }
  87 
  88 static const struct backlight_ops pcf50633_bl_ops = {
  89         .get_brightness = pcf50633_bl_get_brightness,
  90         .update_status  = pcf50633_bl_update_status,
  91         .options        = BL_CORE_SUSPENDRESUME,
  92 };
  93 
  94 static int pcf50633_bl_probe(struct platform_device *pdev)
  95 {
  96         struct pcf50633_bl *pcf_bl;
  97         struct device *parent = pdev->dev.parent;
  98         struct pcf50633_platform_data *pcf50633_data = dev_get_platdata(parent);
  99         struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data;
 100         struct backlight_properties bl_props;
 101 
 102         pcf_bl = devm_kzalloc(&pdev->dev, sizeof(*pcf_bl), GFP_KERNEL);
 103         if (!pcf_bl)
 104                 return -ENOMEM;
 105 
 106         memset(&bl_props, 0, sizeof(bl_props));
 107         bl_props.type = BACKLIGHT_RAW;
 108         bl_props.max_brightness = 0x3f;
 109         bl_props.power = FB_BLANK_UNBLANK;
 110 
 111         if (pdata) {
 112                 bl_props.brightness = pdata->default_brightness;
 113                 pcf_bl->brightness_limit = pdata->default_brightness_limit;
 114         } else {
 115                 bl_props.brightness = 0x3f;
 116                 pcf_bl->brightness_limit = 0x3f;
 117         }
 118 
 119         pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent);
 120 
 121         pcf_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name,
 122                                                 &pdev->dev, pcf_bl,
 123                                                 &pcf50633_bl_ops, &bl_props);
 124 
 125         if (IS_ERR(pcf_bl->bl))
 126                 return PTR_ERR(pcf_bl->bl);
 127 
 128         platform_set_drvdata(pdev, pcf_bl);
 129 
 130         pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time);
 131 
 132         /*
 133          * Should be different from bl_props.brightness, so we do not exit
 134          * update_status early the first time it's called
 135          */
 136         pcf_bl->brightness = pcf_bl->bl->props.brightness + 1;
 137 
 138         backlight_update_status(pcf_bl->bl);
 139 
 140         return 0;
 141 }
 142 
 143 static struct platform_driver pcf50633_bl_driver = {
 144         .probe =        pcf50633_bl_probe,
 145         .driver = {
 146                 .name = "pcf50633-backlight",
 147         },
 148 };
 149 
 150 module_platform_driver(pcf50633_bl_driver);
 151 
 152 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 153 MODULE_DESCRIPTION("PCF50633 backlight driver");
 154 MODULE_LICENSE("GPL");
 155 MODULE_ALIAS("platform:pcf50633-backlight");

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