From patchwork Mon Mar 3 09:14:36 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Jeong X-Patchwork-Id: 3752201 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7E42B9F35F for ; Mon, 3 Mar 2014 09:15:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DEC3E20165 for ; Mon, 3 Mar 2014 09:15:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1AF992039E for ; Mon, 3 Mar 2014 09:15:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754066AbaCCJPP (ORCPT ); Mon, 3 Mar 2014 04:15:15 -0500 Received: from mail-pb0-f52.google.com ([209.85.160.52]:39013 "EHLO mail-pb0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754019AbaCCJPL (ORCPT ); Mon, 3 Mar 2014 04:15:11 -0500 Received: by mail-pb0-f52.google.com with SMTP id rr13so3546535pbb.11 for ; Mon, 03 Mar 2014 01:15:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=cOa9letYuv/x9dOJD5//6b8wx1rAgxtr2DlIgBa8l28=; b=veAH7nCfqOthHb9duJAgvulM8VSRP7mz3SPoc8us6Faz1bMUEGx/FR3u9hHWxdOLVU EHez9ZtlpZBO7h2Gz4itpCzFAzAuOALIcawLdM1tJZUYMk9YCqmT7c2El6x2tBvskeOw MFqYp8Vr7fuktrjDZzykzgjOma6ff9TFXaTawXiKbAKdP22Ale63LBaFN6g5+QCEMUw+ EIAdGCjKj/fur2PwKchaAYNE5W/SWoQFK9LTi4h2ihEU+JVeJ98cJghSlsQFaUDRnZq0 P6LrnNlw0g21mp0a6P81QMxxzZEON76NXbt3ubjFKBgcX+tqc9cmQ7E4k7WNpujcioRF IIDg== X-Received: by 10.66.192.162 with SMTP id hh2mr2075538pac.150.1393838111043; Mon, 03 Mar 2014 01:15:11 -0800 (PST) Received: from localhost.localdomain ([117.111.1.107]) by mx.google.com with ESMTPSA id os1sm79972681pac.20.2014.03.03.01.15.07 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 03 Mar 2014 01:15:10 -0800 (PST) From: Daniel Jeong To: Jingoo Han Cc: Daniel Jeong , , , Jean-Christophe Plagniol-Villard , Tomi Valkeinen Subject: [PATCH] backlight: add new LP8860 backlight driver Date: Mon, 3 Mar 2014 18:14:36 +0900 Message-Id: <1393838076-4559-1-git-send-email-gshark.jeong@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds LP8860 backlight device driver. LP8860 is a low EMI and High performance 4 channel LED Driver of TI. This device driver provide the way to control brightness and currnet of each channel and provide the way to write eeprom. To support dt structure, another patch file will be sent. Signed-off-by: Daniel Jeong Signed-off-by: Daniel Jeong --- drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/lp8860_bl.c | 528 +++++++++++++++++++++++++++++++ include/linux/platform_data/lp8860_bl.h | 54 ++++ 4 files changed, 590 insertions(+) create mode 100644 drivers/video/backlight/lp8860_bl.c create mode 100644 include/linux/platform_data/lp8860_bl.h diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 5a3eb2e..908048f 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -397,6 +397,13 @@ config BACKLIGHT_LP8788 help This supports TI LP8788 backlight driver. +config BACKLIGHT_LP8860 + tristate "Backlight Driver for LP8860" + depends on BACKLIGHT_CLASS_DEVICE && I2C + select REGMAP_I2C + help + This supports TI LP8860 Backlight Driver + config BACKLIGHT_OT200 tristate "Backlight driver for ot200 visualisation device" depends on BACKLIGHT_CLASS_DEVICE && CS5535_MFGPT && GPIO_CS5535 diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index bb82002..cbc5ac3 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o obj-$(CONFIG_BACKLIGHT_LP8788) += lp8788_bl.o +obj-$(CONFIG_BACKLIGHT_LP8860) += lp8860_bl.o obj-$(CONFIG_BACKLIGHT_LV5207LP) += lv5207lp.o obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o diff --git a/drivers/video/backlight/lp8860_bl.c b/drivers/video/backlight/lp8860_bl.c new file mode 100644 index 0000000..4712e84 --- /dev/null +++ b/drivers/video/backlight/lp8860_bl.c @@ -0,0 +1,528 @@ +/* +* Simple driver for Texas Instruments lp8860 Backlight driver chip +* +* Copyright (C) 2014 Texas Instruments +* Author: Daniel Jeong +* Ldd Mlp +* +* 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 +#include +#include + +#define REG_CL0_BRT_H 0x00 +#define REG_CL0_BRT_L 0x01 +#define REG_CL0_I_H 0x02 +#define REG_CL0_I_L 0x03 + +#define REG_CL1_BRT_H 0x04 +#define REG_CL1_BRT_L 0x05 +#define REG_CL1_I 0x06 + +#define REG_CL2_BRT_H 0x07 +#define REG_CL2_BRT_L 0x08 +#define REG_CL2_I 0x09 + +#define REG_CL3_BRT_H 0x0a +#define REG_CL3_BRT_L 0x0b +#define REG_CL3_I 0x0c + +#define REG_CONF 0x0d +#define REG_STATUS 0x0e +#define REG_ID 0x12 + +#define REG_ROM_CTRL 0x19 +#define REG_ROM_UNLOCK 0x1a +#define REG_ROM_START 0x60 +#define REG_ROM_END 0x78 + +#define REG_EEPROM_START 0x60 +#define REG_EEPROM_END 0x78 +#define REG_MAX 0xFF + +struct lp8860_chip { + struct device *dev; + struct lp8860_platform_data *pdata; + struct backlight_device *bled[LP8860_LED_MAX]; + struct regmap *regmap; +}; + +/* brightness control */ +static int lp8860_bled_update_status(struct backlight_device *bl, + enum lp8860_leds nsr) +{ + int ret = -EINVAL; + struct lp8860_chip *pchip = bl_get_data(bl); + + if (pchip->pdata->mode) + return 0; + + if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) + bl->props.brightness = 0; + + switch (nsr) { + case LP8860_LED0: + ret = regmap_write(pchip->regmap, + REG_CL0_BRT_H, bl->props.brightness >> 8); + ret |= regmap_write(pchip->regmap, + REG_CL0_BRT_L, bl->props.brightness & 0xff); + break; + case LP8860_LED1: + ret = regmap_write(pchip->regmap, + REG_CL1_BRT_H, + (bl->props.brightness >> 8) & 0x1f); + ret |= + regmap_write(pchip->regmap, REG_CL1_BRT_L, + bl->props.brightness & 0xff); + break; + case LP8860_LED2: + ret = regmap_write(pchip->regmap, + REG_CL2_BRT_H, + (bl->props.brightness >> 8) & 0x1f); + ret |= + regmap_write(pchip->regmap, REG_CL2_BRT_L, + bl->props.brightness & 0xff); + break; + case LP8860_LED3: + ret = regmap_write(pchip->regmap, + REG_CL3_BRT_H, + (bl->props.brightness >> 8) & 0x1f); + ret |= + regmap_write(pchip->regmap, REG_CL3_BRT_L, + bl->props.brightness & 0xff); + break; + default: + BUG(); + } + if (ret < 0) + dev_err(pchip->dev, "fail : i2c access to register.\n"); + else + ret = bl->props.brightness; + + return ret; +} + +static int lp8860_bled_get_brightness(struct backlight_device *bl, + enum lp8860_leds nsr) +{ + struct lp8860_chip *pchip = bl_get_data(bl); + unsigned int rval_h, rval_l; + int ret = -EINVAL; + + switch (nsr) { + case LP8860_LED0: + ret = regmap_read(pchip->regmap, REG_CL0_BRT_H, &rval_h); + ret |= regmap_read(pchip->regmap, REG_CL0_BRT_L, &rval_l); + break; + case LP8860_LED1: + ret = regmap_read(pchip->regmap, REG_CL1_BRT_H, &rval_h); + ret |= regmap_read(pchip->regmap, REG_CL1_BRT_L, &rval_l); + break; + case LP8860_LED2: + ret = regmap_read(pchip->regmap, REG_CL2_BRT_H, &rval_h); + ret |= regmap_read(pchip->regmap, REG_CL2_BRT_L, &rval_l); + break; + case LP8860_LED3: + ret = regmap_read(pchip->regmap, REG_CL3_BRT_H, &rval_h); + ret |= regmap_read(pchip->regmap, REG_CL3_BRT_L, &rval_l); + break; + default: + BUG(); + } + if (ret < 0) { + dev_err(pchip->dev, "fail : i2c access to register.\n"); + return ret; + } + bl->props.brightness = (rval_h << 8) | rval_l; + return bl->props.brightness; +} + +static int lp8860_update_status_bled0(struct backlight_device *bl) +{ + return lp8860_bled_update_status(bl, LP8860_LED0); +} + +static int lp8860_get_brightness_bled0(struct backlight_device *bl) +{ + return lp8860_bled_get_brightness(bl, LP8860_LED0); +} + +static int lp8860_update_status_bled1(struct backlight_device *bl) +{ + return lp8860_bled_update_status(bl, LP8860_LED1); +} + +static int lp8860_get_brightness_bled1(struct backlight_device *bl) +{ + return lp8860_bled_get_brightness(bl, LP8860_LED1); +} + +static int lp8860_update_status_bled2(struct backlight_device *bl) +{ + return lp8860_bled_update_status(bl, LP8860_LED2); +} + +static int lp8860_get_brightness_bled2(struct backlight_device *bl) +{ + return lp8860_bled_get_brightness(bl, LP8860_LED2); +} + +static int lp8860_update_status_bled3(struct backlight_device *bl) +{ + return lp8860_bled_update_status(bl, LP8860_LED3); +} + +static int lp8860_get_brightness_bled3(struct backlight_device *bl) +{ + return lp8860_bled_get_brightness(bl, LP8860_LED3); +} + +#define lp8860_bled_ops(_id)\ +{\ + .options = BL_CORE_SUSPENDRESUME,\ + .update_status = lp8860_update_status_bled##_id,\ + .get_brightness = lp8860_get_brightness_bled##_id,\ +} + +static const struct backlight_ops lp8860_bled_ops[LP8860_LED_MAX] = { + [LP8860_LED0] = lp8860_bled_ops(0), + [LP8860_LED1] = lp8860_bled_ops(1), + [LP8860_LED2] = lp8860_bled_ops(2), + [LP8860_LED3] = lp8860_bled_ops(3), +}; + +/* current control */ +static int lp8860_set_current(struct device *dev, + const char *buf, enum lp8860_leds nsr) +{ + struct lp8860_chip *pchip = dev_get_drvdata(dev); + unsigned int ival; + ssize_t ret; + + ret = kstrtouint(buf, 10, &ival); + if (ret) + return ret; + + switch (nsr) { + case LP8860_LED0: + ival = min_t(unsigned int, ival, LP8860_LED0_BR_MAX); + ret = regmap_write(pchip->regmap, REG_CL0_I_H, ival >> 8); + ret |= regmap_write(pchip->regmap, REG_CL0_I_L, ival & 0xff); + break; + case LP8860_LED1: + ival = min_t(unsigned int, ival, LP8860_LED1_BR_MAX); + ret = regmap_write(pchip->regmap, REG_CL1_I, ival & 0xff); + break; + case LP8860_LED2: + ival = min_t(unsigned int, ival, LP8860_LED2_BR_MAX); + ret = regmap_write(pchip->regmap, REG_CL2_I, ival & 0xff); + break; + case LP8860_LED3: + ival = min_t(unsigned int, ival, LP8860_LED3_BR_MAX); + ret = regmap_write(pchip->regmap, REG_CL3_I, ival & 0xff); + break; + default: + BUG(); + } + if (ret < 0) + dev_err(pchip->dev, "fail : i2c access error.\n"); + + return ret; +} + +static ssize_t lp8860_current_store_bled0(struct device *dev, + struct device_attribute *devAttr, + const char *buf, size_t size) +{ + int ret; + + ret = lp8860_set_current(dev, buf, LP8860_LED0); + if (ret < 0) + return ret; + return size; +} + +static ssize_t lp8860_current_store_bled1(struct device *dev, + struct device_attribute *devAttr, + const char *buf, size_t size) +{ + int ret; + + ret = lp8860_set_current(dev, buf, LP8860_LED1); + if (ret < 0) + return ret; + return size; +} + +static ssize_t lp8860_current_store_bled2(struct device *dev, + struct device_attribute *devAttr, + const char *buf, size_t size) +{ + int ret; + + ret = lp8860_set_current(dev, buf, LP8860_LED2); + if (ret < 0) + return ret; + return size; +} + +static ssize_t lp8860_current_store_bled3(struct device *dev, + struct device_attribute *devAttr, + const char *buf, size_t size) +{ + int ret; + + ret = lp8860_set_current(dev, buf, LP8860_LED3); + if (ret < 0) + return ret; + return size; +} + +#define lp8860_attr(_name, _show, _store)\ +{\ + .attr = {\ + .name = _name,\ + .mode = S_IWUSR,\ + },\ + .show = _show,\ + .store = _store,\ +} + +static struct device_attribute lp8860_dev_attr[LP8860_LED_MAX] = { + [LP8860_LED0] = lp8860_attr("current", NULL, + lp8860_current_store_bled0), + [LP8860_LED1] = lp8860_attr("current", NULL, + lp8860_current_store_bled1), + [LP8860_LED2] = lp8860_attr("current", NULL, + lp8860_current_store_bled2), + [LP8860_LED3] = lp8860_attr("current", NULL, + lp8860_current_store_bled3), +}; + +/* + * eeprom write and readback to check. + * eeprom register range is from 60h to 78h + * buffer value to write data [reg] [data] + * e.g) to change the register 0x60 value to 0xff + * buffer value should be 60 ff + */ +static ssize_t lp8860_eeprom_store(struct device *dev, + struct device_attribute *devAttr, + const char *buf, size_t size) +{ + struct lp8860_chip *pchip = dev_get_drvdata(dev); + unsigned int reg, data, rval; + char *tok; + int ret; + + /* register no. */ + tok = strsep((char **)&buf, " ,\n"); + if (tok == NULL) + goto err_input; + ret = kstrtouint(tok, 16, ®); + if (ret) + goto err_input; + + /* register value */ + tok = strsep((char **)&buf, " ,\n"); + if (tok == NULL) + goto err_input; + ret = kstrtouint(tok, 16, &data); + if (ret) + goto err_input; + /* + * EEPROM Programming sequence + * (program data permanently from registers to NVM) + * 1. Unlock EEPROM by writing + * the unlock codes to register 1Ah(08, BA, EF) + * 2. Write data to EEPROM registers (address 60h...78h) + * 3. Write EE_PROG to 1 in address 19h. (02h to address 19h) + * 4. Wait 100ms + * 5. Write EE_PROG to 0 in address 19h. (00h to address 19h) + */ + if (reg < REG_EEPROM_START || reg > REG_EEPROM_END || data > 0xff) + goto err_input; + ret = regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0x08); + ret |= regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0xba); + ret |= regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0xef); + ret |= regmap_write(pchip->regmap, reg, data); + ret |= regmap_write(pchip->regmap, REG_ROM_CTRL, 0x02); + msleep(100); + ret |= regmap_write(pchip->regmap, REG_ROM_CTRL, 0x00); + if (ret < 0) + goto err_i2c; + + /* read back */ + ret = regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0x08); + ret |= regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0xba); + ret |= regmap_write(pchip->regmap, REG_ROM_UNLOCK, 0xef); + ret |= regmap_write(pchip->regmap, REG_ROM_CTRL, 0x01); + msleep(100); + ret |= regmap_write(pchip->regmap, REG_ROM_CTRL, 0x00); + ret |= regmap_read(pchip->regmap, reg, &rval); + if (ret < 0) + goto err_i2c; + if (rval != data) + dev_err(pchip->dev, "fail : eeprom did not change.\n"); + + return size; + +err_i2c: + dev_err(pchip->dev, "fail : i2c access error.\n"); + return ret; + +err_input: + dev_err(pchip->dev, "fail : input fail.\n"); + return -EINVAL; +} + +static DEVICE_ATTR(eeprom, S_IWUSR, NULL, lp8860_eeprom_store); + +/* backlight register and remove */ +static char *lp8860_bled_name[LP8860_LED_MAX] = { + [LP8860_LED0] = "bled0", + [LP8860_LED1] = "bled1", + [LP8860_LED2] = "bled2", + [LP8860_LED3] = "bled3", +}; + +static int lp8860_backlight_remove(struct lp8860_chip *pchip) +{ + int icnt; + + device_remove_file(&(pchip->bled[0]->dev), &dev_attr_eeprom); + for (icnt = LP8860_LED0; icnt < LP8860_LED_MAX; icnt++) { + if (pchip->bled[icnt]) { + backlight_device_unregister(pchip->bled[icnt]); + device_remove_file(&(pchip->bled[icnt]->dev), + &lp8860_dev_attr[icnt]); + } + } + return 0; +} + +static int lp8860_backlight_registers(struct lp8860_chip *pchip) +{ + struct backlight_properties props; + struct lp8860_platform_data *pdata = pchip->pdata; + int icnt, ret; + + props.type = BACKLIGHT_RAW; + for (icnt = LP8860_LED0; icnt < LP8860_LED_MAX; icnt++) { + props.max_brightness = pdata->max_brt[icnt]; + pchip->bled[icnt] = + backlight_device_register(lp8860_bled_name[icnt], + pchip->dev, pchip, + &lp8860_bled_ops[icnt], &props); + if (IS_ERR(pchip->bled[icnt])) { + dev_err(pchip->dev, "fail : backlight register.\n"); + ret = PTR_ERR(pchip->bled[icnt]); + goto err_out; + } + + ret = device_create_file(&(pchip->bled[icnt]->dev), + &lp8860_dev_attr[icnt]); + if (ret < 0) { + dev_err(pchip->dev, "fail : to add sysfs entries.\n"); + goto err_out; + } + } + /* access eeprom */ + ret = device_create_file(&(pchip->bled[LP8860_LED0]->dev), + &dev_attr_eeprom); + if (ret < 0) { + dev_err(pchip->dev, "fail : to add sysfs entries.\n"); + goto err_out; + } + return 0; + +err_out: + lp8860_backlight_remove(pchip); + return ret; +} + +static const struct regmap_config lp8860_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, +}; + +static int lp8860_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lp8860_chip *pchip; + struct lp8860_platform_data *pdata = dev_get_platdata(&client->dev); + int ret, icnt; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "fail : i2c functionality check.\n"); + return -EOPNOTSUPP; + } + + pchip = devm_kzalloc(&client->dev, + sizeof(struct lp8860_chip), GFP_KERNEL); + if (!pchip) + return -ENOMEM; + pchip->dev = &client->dev; + + pchip->regmap = devm_regmap_init_i2c(client, &lp8860_regmap); + if (IS_ERR(pchip->regmap)) { + ret = PTR_ERR(pchip->regmap); + dev_err(pchip->dev, "fail : allocate i2c register map.\n"); + return ret; + } + + if (pdata == NULL) { + pdata = devm_kzalloc(pchip->dev, + sizeof(struct lp8860_platform_data), + GFP_KERNEL); + if (pdata == NULL) + return -ENOMEM; + pdata->max_brt[LP8860_LED0] = 65535; + for (icnt = LP8860_LED1; icnt < LP8860_LED_MAX; icnt++) + pdata->max_brt[icnt] = 8191; + pchip->pdata = pdata; + } else { + pchip->pdata = pdata; + } + i2c_set_clientdata(client, pchip); + ret = lp8860_backlight_registers(pchip); + return ret; +} + +static int lp8860_remove(struct i2c_client *client) +{ + return lp8860_backlight_remove(i2c_get_clientdata(client)); +} + +static const struct i2c_device_id lp8860_id[] = { + {LP8860_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lp8860_id); +static struct i2c_driver lp8860_i2c_driver = { + .driver = { + .name = LP8860_NAME, + }, + .probe = lp8860_probe, + .remove = lp8860_remove, + .id_table = lp8860_id, +}; + +module_i2c_driver(lp8860_i2c_driver); + +MODULE_DESCRIPTION("Texas Instruments LP8860 Backlight Driver"); +MODULE_AUTHOR("Daniel Jeong "); +MODULE_AUTHOR("Ldd Mlp "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/lp8860_bl.h b/include/linux/platform_data/lp8860_bl.h new file mode 100644 index 0000000..61bd0f5 --- /dev/null +++ b/include/linux/platform_data/lp8860_bl.h @@ -0,0 +1,54 @@ +/* + * Simple driver for Texas Instruments LM3642 LED Flash driver chip + * Copyright (C) 2014 Texas Instruments + * + * 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. + * + */ + +#ifndef __LINUX_LP8860_H +#define __LINUX_LP8860_H + +#define LP8860_NAME "lp8860" +#define LP8860_ADDR 0x2d + +#define LP8860_LED0_BR_MAX 65535 +#define LP8860_LED1_BR_MAX 8191 +#define LP8860_LED2_BR_MAX 8191 +#define LP8860_LED3_BR_MAX 8191 + +#define LP8860_LED0_I_MAX 4095 +#define LP8860_LED1_I_MAX 255 +#define LP8860_LED2_I_MAX 255 +#define LP8860_LED3_I_MAX 255 + +enum lp8860_leds { + LP8860_LED0 = 0, + LP8860_LED1, + LP8860_LED2, + LP8860_LED3, + LP8860_LED_MAX +}; + +enum lp8860_ctrl_mode { + LP8860_CTRL_I2C = 0, + LP8860_CTRL_I2C_PWM, +}; + +/* struct lp8860 platform data + * @mode : control mode + * @max_brt : maximum brightness. + * LED0 0 ~ 65535 + * LED1 0 ~ 8191 + * LED2 0 ~ 8191 + * LED3 0 ~ 8191 + */ +struct lp8860_platform_data { + + enum lp8860_ctrl_mode mode; + int max_brt[LP8860_LED_MAX]; +}; + +#endif /* __LINUX_LP8860_H */