From patchwork Thu Mar 13 10:28:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Jeong X-Patchwork-Id: 3824751 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 07F9F9F1CD for ; Thu, 13 Mar 2014 10:30:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6F825201FB for ; Thu, 13 Mar 2014 10:30:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C7AF5201E9 for ; Thu, 13 Mar 2014 10:30:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753381AbaCMKam (ORCPT ); Thu, 13 Mar 2014 06:30:42 -0400 Received: from mail-pa0-f50.google.com ([209.85.220.50]:35941 "EHLO mail-pa0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752682AbaCMKal (ORCPT ); Thu, 13 Mar 2014 06:30:41 -0400 Received: by mail-pa0-f50.google.com with SMTP id kq14so918741pab.37 for ; Thu, 13 Mar 2014 03:30:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=fv8irPs8cploBAr8LE3h7nVXBtgOev+NXTq35uwjJJE=; b=OYYAm/AqoHhmV6M4dUmqxvzr3FKz1e02YGsgbq2JMSrHEN99kRRiJXI6Yeu3qff1pt frhYl5G4rYNQ7IZYMFGmcBKCfRK2Cj37PiJB0iNtqSAM8tvGqU2UUQiYlzORXWK8GTVb mNoFvIuvv2RrXsBFGGtYoB3F1spBSrzRNZFd86TC6dSF9i4sL1VPCQAExoTXuSOG/M6K +yfVnIf17IXx01fOkgouNHiB3PH10UTSYRQRnSxJC8Aspk8wjwvDiwqcePgiX3TRM+cj Sg8pIX3NTe+KUi4pN8I+xXd2bbX3ymMiFV5rDmNB1TmvsGY3JDr9ufWkmCEG/AiD/9XW R1zQ== X-Received: by 10.66.27.67 with SMTP id r3mr1407875pag.62.1394706641038; Thu, 13 Mar 2014 03:30:41 -0700 (PDT) Received: from localhost.localdomain ([211.36.158.189]) by mx.google.com with ESMTPSA id af1sm7764160pad.12.2014.03.13.03.30.37 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 13 Mar 2014 03:30:40 -0700 (PDT) From: Daniel Jeong To: Jingoo Han Cc: Daniel Jeong , , , Jean-Christophe Plagniol-Villard , Tomi Valkeinen , Bryan Wu , Lee Jones Subject: [PATCH v3] backlight: add new LP8860 backlight driver Date: Thu, 13 Mar 2014 19:28:18 +0900 Message-Id: <1394706498-12923-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, T_DKIM_INVALID, T_RP_MATCHES_RCVD, 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 provides the way to control brightness and current of each channel and provides the way to change values in the eeprom. Signed-off-by: Daniel Jeong --- To support dt structure, another patch file will be sent. changes since v2 - removed some magic number. - fixed the possibility to refer null when backlight is removed. --- drivers/video/backlight/Kconfig | 7 + drivers/video/backlight/Makefile | 1 + drivers/video/backlight/lp8860_bl.c | 526 +++++++++++++++++++++++++++++++ include/linux/platform_data/lp8860_bl.h | 54 ++++ 4 files changed, 588 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..e17e94f --- /dev/null +++ b/drivers/video/backlight/lp8860_bl.c @@ -0,0 +1,526 @@ +/* +* 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 for chip interanl dealy to access the eeprom + * 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; + + for (icnt = LP8860_LED0; icnt < LP8860_LED_MAX; icnt++) { + if (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] = + devm_backlight_device_register(pchip->dev, + 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; + } + /* to control current */ + 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; + } + } + /* to 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] = LP8860_LED0_BR_MAX; + for (icnt = LP8860_LED1; icnt < LP8860_LED_MAX; icnt++) + pdata->max_brt[icnt] = LP8860_LED1_BR_MAX; + } + pchip->pdata = pdata; + + i2c_set_clientdata(client, pchip); + ret = lp8860_backlight_registers(pchip); + return ret; +} + +static int lp8860_remove(struct i2c_client *client) +{ + struct lp8860_chip *pchip = i2c_get_clientdata(client); + + device_remove_file(&(pchip->bled[LP8860_LED0]->dev), &dev_attr_eeprom); + 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..9edd7cf --- /dev/null +++ b/include/linux/platform_data/lp8860_bl.h @@ -0,0 +1,54 @@ +/* + * Simple driver for Texas Instruments LP8860 Backlight 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 __LP8860_H +#define __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 /* __LP8860_H */