2012-06-17 01:55:52 +00:00
|
|
|
/*
|
2012-07-06 21:27:15 +00:00
|
|
|
* LM3530 backlight device driver
|
|
|
|
*
|
2012-06-17 01:55:52 +00:00
|
|
|
* Copyright (C) 2011-2012, LG Eletronics,Inc. All rights reservced.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/platform_device.h>
|
2012-07-06 21:27:15 +00:00
|
|
|
#include <linux/platform_data/lm35xx_bl.h>
|
2012-06-17 01:55:52 +00:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/backlight.h>
|
|
|
|
#include <linux/fb.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/gpio.h>
|
2012-06-28 02:41:21 +00:00
|
|
|
#include <linux/mutex.h>
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
#define I2C_BL_NAME "lm3530"
|
|
|
|
|
|
|
|
#define BL_ON 1
|
|
|
|
#define BL_OFF 0
|
|
|
|
|
2012-06-28 02:41:21 +00:00
|
|
|
static DEFINE_MUTEX(backlight_mtx);
|
|
|
|
|
2012-06-17 01:55:52 +00:00
|
|
|
static struct i2c_client *lm3530_i2c_client;
|
|
|
|
|
|
|
|
struct lm3530_device {
|
|
|
|
struct i2c_client *client;
|
|
|
|
struct backlight_device *bl_dev;
|
|
|
|
int gpio;
|
|
|
|
int max_current;
|
|
|
|
int min_brightness;
|
|
|
|
int max_brightness;
|
2012-10-02 19:22:07 +00:00
|
|
|
int default_brightness;
|
2012-09-05 02:28:34 +00:00
|
|
|
char *blmap;
|
|
|
|
int blmap_size;
|
2012-06-17 01:55:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct i2c_device_id lm3530_bl_id[] = {
|
|
|
|
{ I2C_BL_NAME, 0 },
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static int lm3530_write_reg(struct i2c_client *client,
|
|
|
|
unsigned char reg, unsigned char val);
|
|
|
|
|
|
|
|
static int cur_main_lcd_level;
|
|
|
|
static int saved_main_lcd_level;
|
|
|
|
static int backlight_status = BL_ON;
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
static void lm3530_hw_reset(struct i2c_client *client)
|
2012-06-17 01:55:52 +00:00
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
|
|
|
int gpio = dev->gpio;
|
|
|
|
|
2012-06-17 01:55:52 +00:00
|
|
|
if (gpio_is_valid(gpio)) {
|
|
|
|
gpio_direction_output(gpio, 1);
|
|
|
|
gpio_set_value_cansleep(gpio, 1);
|
|
|
|
mdelay(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lm3530_write_reg(struct i2c_client *client,
|
|
|
|
unsigned char reg, unsigned char val)
|
|
|
|
{
|
|
|
|
u8 buf[2];
|
|
|
|
struct i2c_msg msg = {
|
|
|
|
client->addr, 0, 2, buf
|
|
|
|
};
|
|
|
|
|
|
|
|
buf[0] = reg;
|
|
|
|
buf[1] = val;
|
|
|
|
|
|
|
|
if (i2c_transfer(client->adapter, &msg, 1) < 0)
|
|
|
|
dev_err(&client->dev, "i2c write error\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lm3530_set_main_current_level(struct i2c_client *client, int level)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
2012-06-17 01:55:52 +00:00
|
|
|
int cal_value = 0;
|
2012-07-06 21:27:15 +00:00
|
|
|
int min_brightness = dev->min_brightness;
|
|
|
|
int max_brightness = dev->max_brightness;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
dev->bl_dev->props.brightness = cur_main_lcd_level = level;
|
|
|
|
|
|
|
|
if (level != 0) {
|
2012-10-02 19:22:07 +00:00
|
|
|
if (level > 0 && level <= min_brightness)
|
2012-06-17 01:55:52 +00:00
|
|
|
cal_value = min_brightness;
|
2012-10-02 19:22:07 +00:00
|
|
|
else if (level > min_brightness && level <= max_brightness)
|
|
|
|
cal_value = level;
|
|
|
|
else if (level > max_brightness)
|
2012-06-17 01:55:52 +00:00
|
|
|
cal_value = max_brightness;
|
|
|
|
|
2012-09-05 02:28:34 +00:00
|
|
|
if (dev->blmap) {
|
|
|
|
if (cal_value < dev->blmap_size)
|
|
|
|
lm3530_write_reg(client, 0xA0,
|
|
|
|
dev->blmap[cal_value]);
|
|
|
|
else
|
|
|
|
dev_warn(&client->dev, "invalid index %d:%d\n",
|
|
|
|
dev->blmap_size,
|
|
|
|
cal_value);
|
|
|
|
} else {
|
|
|
|
lm3530_write_reg(client, 0xA0, cal_value);
|
|
|
|
}
|
2012-06-17 01:55:52 +00:00
|
|
|
} else
|
|
|
|
lm3530_write_reg(client, 0x10, 0x00);
|
|
|
|
|
2012-06-28 02:41:21 +00:00
|
|
|
mdelay(1);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
2012-09-28 01:35:04 +00:00
|
|
|
static bool first_boot = true;
|
2012-07-06 21:27:15 +00:00
|
|
|
static void lm3530_backlight_on(struct i2c_client *client, int level)
|
2012-06-17 01:55:52 +00:00
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
|
|
|
|
2012-06-28 02:41:21 +00:00
|
|
|
mutex_lock(&backlight_mtx);
|
2012-06-17 01:55:52 +00:00
|
|
|
if (backlight_status == BL_OFF) {
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%s, ++ lm3530_backlight_on \n",__func__);
|
|
|
|
lm3530_hw_reset(client);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_write_reg(dev->client, 0xA0, 0x00);
|
|
|
|
lm3530_write_reg(dev->client, 0x10, dev->max_current);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
2012-09-28 01:35:04 +00:00
|
|
|
if (first_boot) {
|
|
|
|
lm3530_write_reg(dev->client, 0x10, dev->max_current);
|
|
|
|
first_boot = false;
|
|
|
|
}
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_set_main_current_level(dev->client, level);
|
2012-06-17 01:55:52 +00:00
|
|
|
backlight_status = BL_ON;
|
2012-06-28 02:41:21 +00:00
|
|
|
mutex_unlock(&backlight_mtx);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
static void lm3530_backlight_off(struct i2c_client *client)
|
2012-06-17 01:55:52 +00:00
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
|
|
|
int gpio = dev->gpio;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%s, on: %d\n", __func__, backlight_status);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-06-28 02:41:21 +00:00
|
|
|
mutex_lock(&backlight_mtx);
|
|
|
|
if (backlight_status == BL_OFF) {
|
|
|
|
mutex_unlock(&backlight_mtx);
|
2012-06-17 01:55:52 +00:00
|
|
|
return;
|
2012-06-28 02:41:21 +00:00
|
|
|
}
|
|
|
|
|
2012-06-17 01:55:52 +00:00
|
|
|
saved_main_lcd_level = cur_main_lcd_level;
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_set_main_current_level(dev->client, 0);
|
2012-06-17 01:55:52 +00:00
|
|
|
backlight_status = BL_OFF;
|
|
|
|
|
|
|
|
gpio_tlmm_config(GPIO_CFG(gpio, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
|
|
|
|
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
|
|
|
|
gpio_direction_output(gpio, 0);
|
|
|
|
msleep(6);
|
2012-06-28 02:41:21 +00:00
|
|
|
mutex_unlock(&backlight_mtx);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void lm3530_lcd_backlight_set_level(int level)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct i2c_client *client = lm3530_i2c_client;
|
2012-10-02 19:22:07 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
2012-07-06 21:27:15 +00:00
|
|
|
|
|
|
|
if (!client) {
|
|
|
|
pr_warn("%s: not yet enabled\n", __func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-02 19:22:07 +00:00
|
|
|
if (level > dev->max_brightness)
|
|
|
|
level = dev->max_brightness;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_debug("%s: level %d\n", __func__, level);
|
|
|
|
if (level)
|
|
|
|
lm3530_backlight_on(client, level);
|
|
|
|
else
|
|
|
|
lm3530_backlight_off(client);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lm3530_lcd_backlight_set_level);
|
|
|
|
|
2012-07-19 22:36:37 +00:00
|
|
|
void lm3530_lcd_backlight_pwm_disable(void)
|
|
|
|
{
|
|
|
|
struct i2c_client *client = lm3530_i2c_client;
|
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
|
|
|
|
|
|
|
if (backlight_status == BL_OFF)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lm3530_write_reg(client, 0x10, dev->max_current & 0x1F);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lm3530_lcd_backlight_pwm_disable);
|
|
|
|
|
2012-07-19 22:55:56 +00:00
|
|
|
int lm3530_lcd_backlight_on_status(void)
|
|
|
|
{
|
|
|
|
return backlight_status;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(lm3530_lcd_backlight_on_status);
|
|
|
|
|
2012-06-17 01:55:52 +00:00
|
|
|
static int bl_set_intensity(struct backlight_device *bd)
|
|
|
|
{
|
2012-10-02 19:22:07 +00:00
|
|
|
struct i2c_client *client = lm3530_i2c_client;
|
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(client);
|
2012-07-26 21:09:57 +00:00
|
|
|
int brightness = bd->props.brightness;
|
|
|
|
|
|
|
|
if ((bd->props.state & BL_CORE_FBBLANK) ||
|
|
|
|
(bd->props.state & BL_CORE_SUSPENDED))
|
|
|
|
brightness = 0;
|
|
|
|
else if (brightness == 0)
|
2012-10-02 19:22:07 +00:00
|
|
|
brightness = dev->default_brightness;
|
2012-07-26 21:09:57 +00:00
|
|
|
|
|
|
|
lm3530_lcd_backlight_set_level(brightness);
|
2012-06-17 01:55:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int bl_get_intensity(struct backlight_device *bd)
|
|
|
|
{
|
|
|
|
return cur_main_lcd_level;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t lcd_backlight_show_level(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
return snprintf(buf, PAGE_SIZE, "LCD Backlight Level is : %d\n",
|
2012-06-17 01:55:52 +00:00
|
|
|
cur_main_lcd_level);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t lcd_backlight_store_level(struct device *dev,
|
|
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
int level;
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
level = simple_strtoul(buf, NULL, 10);
|
|
|
|
lm3530_lcd_backlight_set_level(level);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lm3530_bl_resume(struct i2c_client *client)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_backlight_on(client, saved_main_lcd_level);
|
2012-06-17 01:55:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lm3530_bl_suspend(struct i2c_client *client, pm_message_t state)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%s: new state: %d\n", __func__, state.event);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_backlight_off(client);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t lcd_backlight_show_on_off(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%s received (prev backlight_status: %s)\n", __func__,
|
2012-06-17 01:55:52 +00:00
|
|
|
backlight_status ? "ON" : "OFF");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t lcd_backlight_store_on_off(struct device *dev,
|
|
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
|
|
{
|
|
|
|
int on_off;
|
|
|
|
struct i2c_client *client = to_i2c_client(dev);
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%s received (prev backlight_status: %s)\n", __func__,
|
2012-06-17 01:55:52 +00:00
|
|
|
backlight_status ? "ON" : "OFF");
|
|
|
|
|
|
|
|
on_off = simple_strtoul(buf, NULL, 10);
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
pr_info("%d", on_off);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
if (on_off == 1)
|
|
|
|
lm3530_bl_resume(client);
|
|
|
|
else if (on_off == 0)
|
|
|
|
lm3530_bl_suspend(client, PMSG_SUSPEND);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
|
|
|
}
|
|
|
|
DEVICE_ATTR(lm3530_level, 0644, lcd_backlight_show_level,
|
|
|
|
lcd_backlight_store_level);
|
|
|
|
DEVICE_ATTR(lm3530_backlight_on_off, 0644, lcd_backlight_show_on_off,
|
|
|
|
lcd_backlight_store_on_off);
|
|
|
|
|
|
|
|
static struct backlight_ops lm3530_bl_ops = {
|
|
|
|
.update_status = bl_set_intensity,
|
|
|
|
.get_brightness = bl_get_intensity,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __devinit lm3530_probe(struct i2c_client *i2c_dev,
|
|
|
|
const struct i2c_device_id *id)
|
|
|
|
{
|
|
|
|
struct backlight_platform_data *pdata;
|
|
|
|
struct lm3530_device *dev;
|
|
|
|
struct backlight_device *bl_dev;
|
|
|
|
struct backlight_properties props;
|
2012-07-06 21:27:15 +00:00
|
|
|
int err = 0;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
pdata = i2c_dev->dev.platform_data;
|
2012-07-06 21:27:15 +00:00
|
|
|
if (!pdata)
|
|
|
|
return -ENODEV;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
dev = kzalloc(sizeof(struct lm3530_device), GFP_KERNEL);
|
2012-07-06 21:27:15 +00:00
|
|
|
if (!dev) {
|
|
|
|
dev_err(&i2c_dev->dev, "out of memory\n");
|
|
|
|
return -ENOMEM;
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
memset(&props, 0, sizeof(struct backlight_properties));
|
|
|
|
props.type = BACKLIGHT_RAW;
|
2012-10-02 19:22:07 +00:00
|
|
|
props.max_brightness = pdata->max_brightness;
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
bl_dev = backlight_device_register(I2C_BL_NAME, &i2c_dev->dev, NULL,
|
|
|
|
&lm3530_bl_ops, &props);
|
2012-07-06 21:27:15 +00:00
|
|
|
if (IS_ERR(bl_dev)) {
|
|
|
|
dev_err(&i2c_dev->dev, "failed to register backlight\n");
|
|
|
|
err = PTR_ERR(bl_dev);
|
|
|
|
goto err_backlight_device_register;
|
|
|
|
}
|
2012-10-02 19:22:07 +00:00
|
|
|
bl_dev->props.max_brightness = pdata->max_brightness;
|
|
|
|
bl_dev->props.brightness = pdata->default_brightness;
|
2012-06-17 01:55:52 +00:00
|
|
|
bl_dev->props.power = FB_BLANK_UNBLANK;
|
|
|
|
|
|
|
|
dev->bl_dev = bl_dev;
|
|
|
|
dev->client = i2c_dev;
|
|
|
|
dev->gpio = pdata->gpio;
|
|
|
|
dev->max_current = pdata->max_current;
|
|
|
|
dev->min_brightness = pdata->min_brightness;
|
|
|
|
dev->max_brightness = pdata->max_brightness;
|
2012-10-02 19:22:07 +00:00
|
|
|
dev->default_brightness = pdata->default_brightness;
|
2012-09-05 02:28:34 +00:00
|
|
|
dev->blmap = pdata->blmap;
|
|
|
|
dev->blmap_size = pdata->blmap_size;
|
2012-06-17 01:55:52 +00:00
|
|
|
i2c_set_clientdata(i2c_dev, dev);
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
if (gpio_is_valid(dev->gpio)) {
|
|
|
|
err = gpio_request(dev->gpio, "lm3530 reset");
|
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&i2c_dev->dev, "failed to request gpio\n");
|
|
|
|
goto err_gpio_request;
|
|
|
|
}
|
|
|
|
}
|
2012-06-17 01:55:52 +00:00
|
|
|
|
|
|
|
err = device_create_file(&i2c_dev->dev, &dev_attr_lm3530_level);
|
2012-07-06 21:27:15 +00:00
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&i2c_dev->dev, "failed to create 1st sysfs\n");
|
|
|
|
goto err_device_create_file_1;
|
|
|
|
}
|
2012-06-17 01:55:52 +00:00
|
|
|
err = device_create_file(&i2c_dev->dev,
|
|
|
|
&dev_attr_lm3530_backlight_on_off);
|
2012-07-06 21:27:15 +00:00
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&i2c_dev->dev, "failed to create 2nd sysfs\n");
|
|
|
|
goto err_device_create_file_2;
|
|
|
|
}
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_i2c_client = i2c_dev;
|
|
|
|
|
|
|
|
pr_info("lm3530 probed\n");
|
2012-06-17 01:55:52 +00:00
|
|
|
return 0;
|
2012-07-06 21:27:15 +00:00
|
|
|
|
|
|
|
err_device_create_file_2:
|
|
|
|
device_remove_file(&i2c_dev->dev, &dev_attr_lm3530_level);
|
|
|
|
err_device_create_file_1:
|
|
|
|
if (gpio_is_valid(dev->gpio))
|
|
|
|
gpio_free(dev->gpio);
|
|
|
|
err_gpio_request:
|
|
|
|
backlight_device_unregister(bl_dev);
|
|
|
|
err_backlight_device_register:
|
|
|
|
kfree(dev);
|
|
|
|
|
|
|
|
return err;
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int __devexit lm3530_remove(struct i2c_client *i2c_dev)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
struct lm3530_device *dev = i2c_get_clientdata(i2c_dev);
|
2012-06-17 01:55:52 +00:00
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
lm3530_i2c_client = NULL;
|
2012-06-17 01:55:52 +00:00
|
|
|
device_remove_file(&i2c_dev->dev, &dev_attr_lm3530_level);
|
|
|
|
device_remove_file(&i2c_dev->dev, &dev_attr_lm3530_backlight_on_off);
|
|
|
|
i2c_set_clientdata(i2c_dev, NULL);
|
|
|
|
|
2012-07-06 21:27:15 +00:00
|
|
|
if (gpio_is_valid(dev->gpio))
|
|
|
|
gpio_free(dev->gpio);
|
|
|
|
|
|
|
|
backlight_device_unregister(dev->bl_dev);
|
|
|
|
kfree(dev);
|
|
|
|
|
2012-06-17 01:55:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct i2c_driver main_lm3530_driver = {
|
|
|
|
.probe = lm3530_probe,
|
|
|
|
.remove = lm3530_remove,
|
|
|
|
.id_table = lm3530_bl_id,
|
|
|
|
.driver = {
|
|
|
|
.name = I2C_BL_NAME,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init lcd_backlight_init(void)
|
|
|
|
{
|
2012-07-06 21:27:15 +00:00
|
|
|
return i2c_add_driver(&main_lm3530_driver);
|
2012-06-17 01:55:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module_init(lcd_backlight_init);
|
|
|
|
|
|
|
|
MODULE_DESCRIPTION("LM3530 Backlight Control");
|
|
|
|
MODULE_AUTHOR("Jaeseong Gim <jaeseong.gim@lge.com>");
|
|
|
|
MODULE_LICENSE("GPL");
|