linux/drivers/video/backlight/da9052_bl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Backlight Driver for Dialog DA9052 PMICs
   4 *
   5 * Copyright(c) 2012 Dialog Semiconductor Ltd.
   6 *
   7 * Author: David Dajun Chen <dchen@diasemi.com>
   8 */
   9
  10#include <linux/backlight.h>
  11#include <linux/delay.h>
  12#include <linux/fb.h>
  13#include <linux/module.h>
  14#include <linux/platform_device.h>
  15
  16#include <linux/mfd/da9052/da9052.h>
  17#include <linux/mfd/da9052/reg.h>
  18
  19#define DA9052_MAX_BRIGHTNESS           0xFF
  20
  21enum {
  22        DA9052_WLEDS_OFF,
  23        DA9052_WLEDS_ON,
  24};
  25
  26enum {
  27        DA9052_TYPE_WLED1,
  28        DA9052_TYPE_WLED2,
  29        DA9052_TYPE_WLED3,
  30};
  31
  32static const unsigned char wled_bank[] = {
  33        DA9052_LED1_CONF_REG,
  34        DA9052_LED2_CONF_REG,
  35        DA9052_LED3_CONF_REG,
  36};
  37
  38struct da9052_bl {
  39        struct da9052 *da9052;
  40        uint brightness;
  41        uint state;
  42        uint led_reg;
  43};
  44
  45static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
  46{
  47        unsigned char boost_en;
  48        unsigned char i_sink;
  49        int ret;
  50
  51        boost_en = 0x3F;
  52        i_sink = 0xFF;
  53        if (wleds->state == DA9052_WLEDS_OFF) {
  54                boost_en = 0x00;
  55                i_sink = 0x00;
  56        }
  57
  58        ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en);
  59        if (ret < 0)
  60                return ret;
  61
  62        ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink);
  63        if (ret < 0)
  64                return ret;
  65
  66        ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0);
  67        if (ret < 0)
  68                return ret;
  69
  70        usleep_range(10000, 11000);
  71
  72        if (wleds->brightness) {
  73                ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg],
  74                                       wleds->brightness);
  75                if (ret < 0)
  76                        return ret;
  77        }
  78
  79        return 0;
  80}
  81
  82static int da9052_backlight_update_status(struct backlight_device *bl)
  83{
  84        int brightness = bl->props.brightness;
  85        struct da9052_bl *wleds = bl_get_data(bl);
  86
  87        wleds->brightness = brightness;
  88        wleds->state = DA9052_WLEDS_ON;
  89
  90        return da9052_adjust_wled_brightness(wleds);
  91}
  92
  93static int da9052_backlight_get_brightness(struct backlight_device *bl)
  94{
  95        struct da9052_bl *wleds = bl_get_data(bl);
  96
  97        return wleds->brightness;
  98}
  99
 100static const struct backlight_ops da9052_backlight_ops = {
 101        .update_status = da9052_backlight_update_status,
 102        .get_brightness = da9052_backlight_get_brightness,
 103};
 104
 105static int da9052_backlight_probe(struct platform_device *pdev)
 106{
 107        struct backlight_device *bl;
 108        struct backlight_properties props;
 109        struct da9052_bl *wleds;
 110
 111        wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL);
 112        if (!wleds)
 113                return -ENOMEM;
 114
 115        wleds->da9052 = dev_get_drvdata(pdev->dev.parent);
 116        wleds->brightness = 0;
 117        wleds->led_reg = platform_get_device_id(pdev)->driver_data;
 118        wleds->state = DA9052_WLEDS_OFF;
 119
 120        props.type = BACKLIGHT_RAW;
 121        props.max_brightness = DA9052_MAX_BRIGHTNESS;
 122
 123        bl = devm_backlight_device_register(&pdev->dev, pdev->name,
 124                                        wleds->da9052->dev, wleds,
 125                                        &da9052_backlight_ops, &props);
 126        if (IS_ERR(bl)) {
 127                dev_err(&pdev->dev, "Failed to register backlight\n");
 128                return PTR_ERR(bl);
 129        }
 130
 131        bl->props.max_brightness = DA9052_MAX_BRIGHTNESS;
 132        bl->props.brightness = 0;
 133        platform_set_drvdata(pdev, bl);
 134
 135        return da9052_adjust_wled_brightness(wleds);
 136}
 137
 138static int da9052_backlight_remove(struct platform_device *pdev)
 139{
 140        struct backlight_device *bl = platform_get_drvdata(pdev);
 141        struct da9052_bl *wleds = bl_get_data(bl);
 142
 143        wleds->brightness = 0;
 144        wleds->state = DA9052_WLEDS_OFF;
 145        da9052_adjust_wled_brightness(wleds);
 146
 147        return 0;
 148}
 149
 150static const struct platform_device_id da9052_wled_ids[] = {
 151        {
 152                .name           = "da9052-wled1",
 153                .driver_data    = DA9052_TYPE_WLED1,
 154        },
 155        {
 156                .name           = "da9052-wled2",
 157                .driver_data    = DA9052_TYPE_WLED2,
 158        },
 159        {
 160                .name           = "da9052-wled3",
 161                .driver_data    = DA9052_TYPE_WLED3,
 162        },
 163        { },
 164};
 165MODULE_DEVICE_TABLE(platform, da9052_wled_ids);
 166
 167static struct platform_driver da9052_wled_driver = {
 168        .probe          = da9052_backlight_probe,
 169        .remove         = da9052_backlight_remove,
 170        .id_table       = da9052_wled_ids,
 171        .driver = {
 172                .name   = "da9052-wled",
 173        },
 174};
 175
 176module_platform_driver(da9052_wled_driver);
 177
 178MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
 179MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC");
 180MODULE_LICENSE("GPL");
 181