From 82e5c40d88f928afffe7bd4027719d3184433908 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 4 Jul 2013 21:13:25 +0200 Subject: backlight: Add Sanyo LV5207LP backlight driver The LV5207LP is a multi-purpose 7 LEDs driver for the mobile market. Only the main LED is supported by this driver. Signed-off-by: Laurent Pinchart Acked-by: Jingoo Han Signed-off-by: Simon Horman --- drivers/video/backlight/lv5207lp.c | 171 +++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 drivers/video/backlight/lv5207lp.c (limited to 'drivers/video/backlight/lv5207lp.c') diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c new file mode 100644 index 000000000000..498fd73d59b9 --- /dev/null +++ b/drivers/video/backlight/lv5207lp.c @@ -0,0 +1,171 @@ +/* + * Sanyo LV5207LP LED Driver + * + * Copyright (C) 2013 Ideas on board SPRL + * + * Contact: Laurent Pinchart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define LV5207LP_CTRL1 0x00 +#define LV5207LP_CPSW (1 << 7) +#define LV5207LP_SCTEN (1 << 6) +#define LV5207LP_C10 (1 << 5) +#define LV5207LP_CKSW (1 << 4) +#define LV5207LP_RSW (1 << 3) +#define LV5207LP_GSW (1 << 2) +#define LV5207LP_BSW (1 << 1) +#define LV5207LP_CTRL2 0x01 +#define LV5207LP_MSW (1 << 7) +#define LV5207LP_MLED4 (1 << 6) +#define LV5207LP_RED 0x02 +#define LV5207LP_GREEN 0x03 +#define LV5207LP_BLUE 0x04 + +#define LV5207LP_MAX_BRIGHTNESS 32 + +struct lv5207lp { + struct i2c_client *client; + struct backlight_device *backlight; + struct lv5207lp_platform_data *pdata; +}; + +static int lv5207lp_write(struct lv5207lp *lv, u8 reg, u8 data) +{ + return i2c_smbus_write_byte_data(lv->client, reg, data); +} + +static int lv5207lp_backlight_update_status(struct backlight_device *backlight) +{ + struct lv5207lp *lv = bl_get_data(backlight); + int brightness = backlight->props.brightness; + + if (backlight->props.power != FB_BLANK_UNBLANK || + backlight->props.fb_blank != FB_BLANK_UNBLANK || + backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + brightness = 0; + + if (brightness) { + lv5207lp_write(lv, LV5207LP_CTRL1, + LV5207LP_CPSW | LV5207LP_C10 | LV5207LP_CKSW); + lv5207lp_write(lv, LV5207LP_CTRL2, + LV5207LP_MSW | LV5207LP_MLED4 | + (brightness - 1)); + } else { + lv5207lp_write(lv, LV5207LP_CTRL1, 0); + lv5207lp_write(lv, LV5207LP_CTRL2, 0); + } + + return 0; +} + +static int lv5207lp_backlight_get_brightness(struct backlight_device *backlight) +{ + return backlight->props.brightness; +} + +static int lv5207lp_backlight_check_fb(struct backlight_device *backlight, + struct fb_info *info) +{ + struct lv5207lp *lv = bl_get_data(backlight); + + return lv->pdata->fbdev == NULL || lv->pdata->fbdev == info->dev; +} + +static const struct backlight_ops lv5207lp_backlight_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lv5207lp_backlight_update_status, + .get_brightness = lv5207lp_backlight_get_brightness, + .check_fb = lv5207lp_backlight_check_fb, +}; + +static int lv5207lp_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lv5207lp_platform_data *pdata = client->dev.platform_data; + struct backlight_device *backlight; + struct backlight_properties props; + struct lv5207lp *lv; + + if (pdata == NULL) { + dev_err(&client->dev, "No platform data supplied\n"); + return -EINVAL; + } + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_warn(&client->dev, + "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n"); + return -EIO; + } + + lv = devm_kzalloc(&client->dev, sizeof(*lv), GFP_KERNEL); + if (!lv) + return -ENOMEM; + + lv->client = client; + lv->pdata = pdata; + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.max_brightness = min_t(unsigned int, pdata->max_value, + LV5207LP_MAX_BRIGHTNESS); + props.brightness = clamp_t(unsigned int, pdata->def_value, 0, + props.max_brightness); + + backlight = backlight_device_register(dev_name(&client->dev), + &lv->client->dev, lv, + &lv5207lp_backlight_ops, &props); + if (IS_ERR(backlight)) { + dev_err(&client->dev, "failed to register backlight\n"); + return PTR_ERR(backlight); + } + + backlight_update_status(backlight); + i2c_set_clientdata(client, backlight); + + return 0; +} + +static int lv5207lp_remove(struct i2c_client *client) +{ + struct backlight_device *backlight = i2c_get_clientdata(client); + + backlight->props.brightness = 0; + backlight_update_status(backlight); + backlight_device_unregister(backlight); + + return 0; +} + +static const struct i2c_device_id lv5207lp_ids[] = { + { "lv5207lp", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lv5207lp_ids); + +static struct i2c_driver lv5207lp_driver = { + .driver = { + .name = "lv5207lp", + }, + .probe = lv5207lp_probe, + .remove = lv5207lp_remove, + .id_table = lv5207lp_ids, +}; + +module_i2c_driver(lv5207lp_driver); + +MODULE_DESCRIPTION("Sanyo LV5207LP Backlight Driver"); +MODULE_AUTHOR("Laurent Pinchart "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From c512794cada491e008eeca822af7e4ad5db72a56 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 12 Nov 2013 15:09:04 -0800 Subject: backlight: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. This is a cosmetic change to make the code simpler and enhance the readability. Signed-off-by: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lv5207lp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video/backlight/lv5207lp.c') diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c index 498fd73d59b9..8091a28b2405 100644 --- a/drivers/video/backlight/lv5207lp.c +++ b/drivers/video/backlight/lv5207lp.c @@ -93,7 +93,7 @@ static const struct backlight_ops lv5207lp_backlight_ops = { static int lv5207lp_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct lv5207lp_platform_data *pdata = client->dev.platform_data; + struct lv5207lp_platform_data *pdata = dev_get_platdata(&client->dev); struct backlight_device *backlight; struct backlight_properties props; struct lv5207lp *lv; -- cgit v1.2.3 From e924c2aadfbd18a38bcc805f32e5ffc1bdad4ad7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 12 Nov 2013 15:09:20 -0800 Subject: backlight: lv5207lp: use devm_backlight_device_register() Use devm_backlight_device_register() to make cleanup paths simpler. Signed-off-by: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lv5207lp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/video/backlight/lv5207lp.c') diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c index 8091a28b2405..1802b2d1357d 100644 --- a/drivers/video/backlight/lv5207lp.c +++ b/drivers/video/backlight/lv5207lp.c @@ -124,9 +124,9 @@ static int lv5207lp_probe(struct i2c_client *client, props.brightness = clamp_t(unsigned int, pdata->def_value, 0, props.max_brightness); - backlight = backlight_device_register(dev_name(&client->dev), - &lv->client->dev, lv, - &lv5207lp_backlight_ops, &props); + backlight = devm_backlight_device_register(&client->dev, + dev_name(&client->dev), &lv->client->dev, + lv, &lv5207lp_backlight_ops, &props); if (IS_ERR(backlight)) { dev_err(&client->dev, "failed to register backlight\n"); return PTR_ERR(backlight); @@ -144,7 +144,6 @@ static int lv5207lp_remove(struct i2c_client *client) backlight->props.brightness = 0; backlight_update_status(backlight); - backlight_device_unregister(backlight); return 0; } -- cgit v1.2.3