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