summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielle Sun <dsun@nvidia.com>2011-05-26 16:17:44 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:47:22 -0800
commitee95306a08528e24f4303bf2cc5bd6993940a452 (patch)
treea00c59991e04e955214e282530ebc5ea1e56bb01
parent6158523a1472cb2a60c41f720c1c766d77c1a7a4 (diff)
media: video: tegra: TPS61050 flash driver
Kernel driver for TPS61050 flash/torch camera device. Bug 794431 Original-Change-Id: I760bd086c283076dc7136bd8ccd6b75e6e823ea8 Reviewed-on: http://git-master/r/34208 Tested-by: Erik M Lilliebjerg <elilliebjerg@nvidia.com> Reviewed-by: Michael Stewart <mstewart@nvidia.com> Reviewed-by: John Sasinowski <jsasinowski@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com> Rebase-Id: Radb862760f165e40b764b3bb104787427d024c7e
-rw-r--r--drivers/media/video/tegra/Kconfig6
-rw-r--r--drivers/media/video/tegra/Makefile1
-rw-r--r--drivers/media/video/tegra/tps61050.c610
-rw-r--r--include/media/tps61050.h97
4 files changed, 714 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/Kconfig b/drivers/media/video/tegra/Kconfig
index afcbec6b25ab..606e5250dd83 100644
--- a/drivers/media/video/tegra/Kconfig
+++ b/drivers/media/video/tegra/Kconfig
@@ -37,6 +37,12 @@ config TORCH_SSL3250A
---help---
This is a driver for the SSL3250A flash/torch camera device
+config TORCH_TPS61050
+ tristate "TPS61050 flash/torch support"
+ depends on I2C && ARCH_TEGRA
+ ---help---
+ This is a driver for the TPS61050 flash/torch camera device
+
config VIDEO_SH532U
tristate "SH532U focuser support"
depends on I2C && ARCH_TEGRA
diff --git a/drivers/media/video/tegra/Makefile b/drivers/media/video/tegra/Makefile
index 872a3ce0d30a..a416ef0a4f5a 100644
--- a/drivers/media/video/tegra/Makefile
+++ b/drivers/media/video/tegra/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_OV5650) += ov5650.o
obj-$(CONFIG_VIDEO_OV2710) += ov2710.o
obj-$(CONFIG_VIDEO_SOC380) += soc380.o
obj-$(CONFIG_TORCH_SSL3250A) += ssl3250a.o
+obj-$(CONFIG_TORCH_TPS61050) += tps61050.o
obj-$(CONFIG_VIDEO_SH532U) += sh532u.o
obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
diff --git a/drivers/media/video/tegra/tps61050.c b/drivers/media/video/tegra/tps61050.c
new file mode 100644
index 000000000000..45ae5e51fd01
--- /dev/null
+++ b/drivers/media/video/tegra/tps61050.c
@@ -0,0 +1,610 @@
+/*
+ * tps61050.c - tps61050 flash/torch kernel driver
+ *
+ * Copyright (C) 2011 NVIDIA Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <media/tps61050.h>
+
+#define TPS61050_REG0 0x00
+#define TPS61050_REG1 0x01
+#define TPS61050_REG2 0x02
+#define TPS61050_REG3 0x03
+
+
+enum {
+ TPS61050_GPIO_ENVM,
+ TPS61050_GPIO_SYNC,
+};
+
+static struct tps61050_flash_capabilities flash_capabilities = {
+ NUM_FLASH_LEVELS - 1, /*entry 0 doesn't count*/
+ {
+ { 0, 0xFFFFFFFF, 0 },
+ { 150, 558, 2 },
+ { 200, 558, 2 },
+ { 300, 558, 2 },
+ { 400, 558, 2 },
+ { 500, 558, 2 },
+ { 700, 558, 2 },
+ { 900, 558, 2 },
+ { 1200, 558, 2 }
+ }
+};
+
+static struct tps61050_torch_capabilities torch_capabilities = {
+ NUM_TORCH_LEVELS - 1, /*entry 0 doesn't count*/
+ {
+ 0,
+ 50,
+ 75,
+ 100,
+ 150,
+ 200,
+ 250,
+ 250
+ }
+};
+
+struct tps61050_info {
+ int api_pwr;
+ char dname[11];
+ struct i2c_client *i2c_client;
+ struct tps61050_platform_data *pdata;
+ struct miscdevice miscdev;
+ struct list_head list;
+};
+
+static struct tps61050_pin_state dummy_tps61050_pinstate = {
+ .mask = 0x0000,
+ .values = 0x0000,
+};
+
+static struct tps61050_platform_data dummy_tps61050_data = {
+ .cfg = 0,
+ .num = 1,
+ .max_amp_torch = 7,
+ .max_amp_flash = 7,
+ .pinstate = &dummy_tps61050_pinstate,
+ .init = NULL,
+ .exit = NULL,
+ .pm = NULL,
+ .gpio_envm = NULL,
+ .gpio_sync = NULL,
+};
+
+static LIST_HEAD(info_list);
+static DEFINE_SPINLOCK(driver_lock);
+
+static int tps61050_reg_rd(struct tps61050_info *info, u8 reg, u8 *val)
+{
+ struct i2c_msg msg[2];
+ u8 data[2];
+
+ msg[0].addr = info->i2c_client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = data;
+ data[0] = reg;
+ msg[1].addr = info->i2c_client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 1;
+ msg[1].buf = data + 1;
+ *val = 0;
+ if (i2c_transfer(info->i2c_client->adapter, msg, 2) == 2) {
+ *val = data[1];
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+static int tps61050_reg_wr(struct tps61050_info *info, u8 reg, u8 val)
+{
+ struct i2c_msg msg;
+ u8 data[2];
+
+ data[0] = reg;
+ data[1] = val;
+ msg.addr = info->i2c_client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ msg.buf = data;
+ if (i2c_transfer(info->i2c_client->adapter, &msg, 1) == 1)
+ return 0;
+ else
+ return -1;
+}
+
+static int tps61050_gpio(struct tps61050_info *info, int gpio, int val)
+{
+ int prev_val;
+
+ if (val)
+ val = 1;
+ switch (gpio) {
+ case TPS61050_GPIO_ENVM:
+ if (info->pdata->gpio_envm) {
+ prev_val = info->pdata->gpio_envm(val);
+ if (val && (prev_val ^ val))
+ mdelay(1); /* delay for device ready */
+ return 0;
+ }
+ return -1;
+
+ case TPS61050_GPIO_SYNC:
+ if (info->pdata->gpio_sync) {
+ info->pdata->gpio_sync(val);
+ return 0;
+ }
+ return -1;
+
+ default:
+ return -1;
+ }
+}
+
+static int tps61050_pm_brd_wr(struct tps61050_info *info, int pwr)
+{
+ int ret = 0;
+
+ if (info->pdata->pm)
+ ret = info->pdata->pm(pwr);
+ return ret;
+}
+
+static int tps61050_pm_wr(struct tps61050_info *info, int pwr)
+{
+ int ret = -1;
+ u8 reg;
+
+ switch (pwr) {
+ case TPS61050_PWR_OFF:
+ tps61050_gpio(info, TPS61050_GPIO_SYNC, 0);
+ ret = tps61050_pm_brd_wr(info, TPS61050_PWR_COMM);
+ ret |= tps61050_reg_wr(info, TPS61050_REG0, 0x00);
+ ret |= tps61050_reg_wr(info, TPS61050_REG1, 0x00);
+ ret |= tps61050_pm_brd_wr(info, TPS61050_PWR_OFF);
+ break;
+
+ case TPS61050_PWR_STDBY:
+ ret = tps61050_pm_brd_wr(info, TPS61050_PWR_COMM);
+ ret |= tps61050_reg_rd(info, TPS61050_REG0, &reg);
+ reg = reg & 0x3F; /* 7:6 = mode */
+ ret |= tps61050_reg_wr(info, TPS61050_REG0, reg);
+ ret |= tps61050_pm_brd_wr(info, TPS61050_PWR_STDBY);
+ break;
+
+ case TPS61050_PWR_COMM:
+ ret = tps61050_pm_brd_wr(info, TPS61050_PWR_COMM);
+ break;
+
+ case TPS61050_PWR_ON:
+ ret = tps61050_pm_brd_wr(info, TPS61050_PWR_ON);
+ break;
+
+ default:
+ break;
+ }
+
+ if (ret)
+ pr_err("%s: error = %d!\n", __func__, ret);
+ return ret;
+}
+
+static int tps61050_pm_api_wr(struct tps61050_info *info, int pwr)
+{
+ int ret;
+
+ ret = tps61050_pm_wr(info, pwr);
+ if (!ret)
+ info->api_pwr = pwr;
+ else
+ info->api_pwr = TPS61050_PWR_ERR;
+ return ret;
+}
+
+static int tps61050_pm_dev_wr(struct tps61050_info *info, int pwr)
+{
+ int ret = 0;
+
+ if (pwr > info->api_pwr)
+ ret = tps61050_pm_wr(info, pwr);
+ return ret;
+}
+
+static int tps61050_sts_rd(struct tps61050_info *info, u8 *status)
+{
+ int ret;
+
+ *status = 0;
+ tps61050_pm_dev_wr(info, TPS61050_PWR_COMM);
+ ret = tps61050_reg_rd(info, TPS61050_REG2, status);
+ tps61050_pm_dev_wr(info, TPS61050_PWR_OFF);
+ return ret;
+}
+
+static int tps61050_param_rd(struct tps61050_info *info, long arg)
+{
+ struct tps61050_param param_data;
+ int ret;
+ u8 reg;
+
+ if (copy_from_user(&param_data,
+ (const void __user *)arg,
+ sizeof(struct tps61050_param))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ switch (param_data.param) {
+ case TPS61050_FLASH_CAPS:
+ if (param_data.sizeofvalue <
+ sizeof(struct tps61050_flash_capabilities)) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (copy_to_user((void __user *)param_data.p_value,
+ &flash_capabilities,
+ sizeof(struct tps61050_flash_capabilities))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+
+ case TPS61050_FLASH_LEVEL:
+ if (param_data.sizeofvalue <
+ sizeof(flash_capabilities.levels[0].guidenum)) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (info->api_pwr != TPS61050_PWR_ON)
+ tps61050_pm_dev_wr(info, TPS61050_PWR_COMM);
+ ret = tps61050_reg_rd(info, TPS61050_REG1, &reg);
+ /* no need to check return vlaue below */
+ tps61050_pm_dev_wr(info, TPS61050_PWR_OFF);
+ if (reg & 0x80) { /* 7:7 flash on/off */
+ reg &= 0x07; /* 2:0 flash setting */
+ reg++; /* flash setting +1 if flash on */
+ } else {
+ reg = 0; /* flash is off */
+ }
+ if (copy_to_user((void __user *)param_data.p_value,
+ &flash_capabilities.levels[reg].guidenum,
+ sizeof
+ (flash_capabilities.levels[reg].guidenum))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return ret;
+
+ case TPS61050_TORCH_CAPS:
+ if (param_data.sizeofvalue <
+ sizeof(struct tps61050_torch_capabilities)) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (copy_to_user((void __user *)param_data.p_value,
+ &torch_capabilities,
+ sizeof
+ (struct tps61050_torch_capabilities))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+
+ case TPS61050_TORCH_LEVEL:
+ if (param_data.sizeofvalue <
+ sizeof(torch_capabilities.guidenum[0])) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (info->api_pwr != TPS61050_PWR_ON)
+ tps61050_pm_dev_wr(info, TPS61050_PWR_COMM);
+ ret = tps61050_reg_rd(info, TPS61050_REG0, &reg);
+ /* no need to check return vlaue below */
+ tps61050_pm_dev_wr(info, TPS61050_PWR_OFF);
+ reg &= 0x07;
+ if (copy_to_user((void __user *)param_data.p_value,
+ &torch_capabilities.guidenum[reg],
+ sizeof(torch_capabilities.guidenum[reg]))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return ret;
+
+ case TPS61050_FLASH_PIN_STATE:
+ if (param_data.sizeofvalue !=
+ sizeof(struct tps61050_pin_state)) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (copy_to_user((void __user *)param_data.p_value,
+ info->pdata->pinstate,
+ sizeof(struct tps61050_pin_state))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+
+ default:
+ pr_err("%s: unsurported parameter read\n", __func__);
+ return -1;
+ }
+}
+
+static int tps61050_param_wr(struct tps61050_info *info, long arg)
+{
+ struct tps61050_param param_data;
+ u8 reg;
+ u8 val;
+ int ret = 0;
+
+ if (copy_from_user(&param_data,
+ (const void __user *)arg,
+ sizeof(struct tps61050_param))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -1;
+ }
+
+ /*
+ 7:6 flash/torch mode
+ 0 0 = off (power save)
+ 0 1 = torch only (torch power is 2:0 REG0 where 0 = off)
+ 1 0 = flash and torch (flash power is 2:0 REG1 (0 is a power level))
+ 1 1 = N/A
+ Note that 7:6 of REG0 and REG1 are shadowed with each other.
+ In the code below we want to turn on/off one
+ without affecting the other.
+ */
+ val = *(u8 *)param_data.p_value;
+ switch (param_data.param) {
+ case TPS61050_FLASH_LEVEL:
+ if (info->api_pwr != TPS61050_PWR_ON)
+ tps61050_pm_dev_wr(info, TPS61050_PWR_ON);
+ if (val) {
+ val--;
+ if (val > info->pdata->max_amp_flash)
+ val = info->pdata->max_amp_flash;
+ val |= 0x80; /* 7:7=flash mode */
+ } else {
+ ret = tps61050_reg_rd(info, TPS61050_REG0, &reg);
+ if (reg & 0x07) /* 2:0=torch setting */
+ val = 0x40; /* 6:6 enable just torch */
+ }
+ ret |= tps61050_reg_wr(info, TPS61050_REG1, val);
+ val &= 0xC0; /* 7:6=flash/torch mode */
+ if (!val && (info->api_pwr != TPS61050_PWR_ON))
+ tps61050_pm_wr(info, TPS61050_PWR_OFF);
+ return ret;
+
+ case TPS61050_TORCH_LEVEL:
+ if (info->api_pwr != TPS61050_PWR_ON)
+ tps61050_pm_dev_wr(info, TPS61050_PWR_ON);
+ ret = tps61050_reg_rd(info, TPS61050_REG1, &reg);
+ reg &= 0x80; /* 7:7=flash */
+ if (val) {
+ if (val > info->pdata->max_amp_torch)
+ val = info->pdata->max_amp_torch;
+
+ if (!reg) /* test if flash/torch off */
+ val |= (0x40); /* 6:6=torch only mode */
+ } else {
+ val |= reg;
+ }
+ /* odm will check error and decide what to do */
+ ret |= tps61050_reg_wr(info, TPS61050_REG0, val);
+ val &= 0xC0; /* 7:6=mode */
+ if (!val && (info->api_pwr != TPS61050_PWR_ON))
+ tps61050_pm_wr(info, TPS61050_PWR_OFF);
+ return ret;
+
+ case TPS61050_FLASH_PIN_STATE:
+ if (info->pdata->gpio_sync) {
+ return tps61050_gpio(info,
+ TPS61050_GPIO_SYNC,
+ (int)val);
+ } else {
+ if (val)
+ val = 0x08; /* 3:3=soft trigger */
+ ret = tps61050_reg_rd(info, TPS61050_REG1, &reg);
+ val |= reg;
+ /* odm will check error and decide what to do */
+ ret |= tps61050_reg_wr(info, TPS61050_REG1, val);
+ return ret;
+ }
+
+ default:
+ pr_err("%s: unsurported parameter write\n", __func__);
+ return -1;
+ }
+}
+
+static long tps61050_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int pwr;
+ struct tps61050_info *info = file->private_data;
+
+ switch (cmd) {
+ case TPS61050_IOCTL_PWR:
+ pwr = (int)arg * 2;
+ return tps61050_pm_api_wr(info, pwr);
+
+ case TPS61050_IOCTL_PARAM_RD:
+ return tps61050_param_rd(info, arg);
+
+ case TPS61050_IOCTL_PARAM_WR:
+ return tps61050_param_wr(info, arg);
+
+ default:
+ pr_err("%s: unsupported ioctl\n", __func__);
+ return -1;
+ }
+}
+
+
+static int tps61050_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ u8 reg;
+ struct tps61050_info *info = NULL, *pos = NULL;
+
+ pr_debug("%s\n", __func__);
+ rcu_read_lock();
+ list_for_each_entry_rcu(pos, &info_list, list) {
+ if (pos->miscdev.minor == iminor(inode)) {
+ info = pos;
+ break;
+ }
+ }
+ rcu_read_unlock();
+ if (!info)
+ return -ENODEV;
+
+ file->private_data = info;
+ if (info->pdata->init) {
+ ret = info->pdata->init();
+ if (ret) {
+ pr_err("%s: board init failed\n", __func__);
+ return -1;
+ }
+ }
+
+ ret = tps61050_sts_rd(info, &reg);
+ if ((reg & 0xC0) || ret) /* status error bits */
+ pr_err("%s: Device init failed\n", __func__);
+ return ret;
+}
+
+static int tps61050_release(struct inode *inode, struct file *file)
+{
+ struct tps61050_info *info = file->private_data;
+
+ pr_info("%s\n", __func__);
+ tps61050_pm_api_wr(info, TPS61050_PWR_OFF);
+ if (info->pdata->exit)
+ info->pdata->exit();
+ file->private_data = NULL;
+ return 0;
+}
+
+static const struct file_operations tps61050_fileops = {
+ .owner = THIS_MODULE,
+ .open = tps61050_open,
+ .unlocked_ioctl = tps61050_ioctl,
+ .release = tps61050_release,
+};
+
+static int tps61050_remove(struct i2c_client *client)
+{
+ struct tps61050_info *info = i2c_get_clientdata(client);
+
+ pr_debug("%s\n", __func__);
+ tps61050_pm_api_wr(info, TPS61050_PWR_OFF);
+ spin_lock(&driver_lock);
+ list_del_rcu(&info->list);
+ spin_unlock(&driver_lock);
+ synchronize_rcu();
+ misc_deregister(&info->miscdev);
+ kfree(info);
+ return 0;
+}
+
+static int tps61050_probe(
+ struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tps61050_info *info = NULL;
+ u8 reg;
+
+ pr_info("%s\n", __func__);
+ info = kzalloc(sizeof(struct tps61050_info), GFP_KERNEL);
+ if (info == NULL) {
+ pr_err("tps61050: unable to allocate memory!\n");
+ return -ENOMEM;
+ }
+
+ info->i2c_client = client;
+ if (client->dev.platform_data)
+ info->pdata = client->dev.platform_data;
+ else
+ info->pdata = &dummy_tps61050_data;
+ i2c_set_clientdata(client, info);
+ INIT_LIST_HEAD(&info->list);
+ snprintf(info->dname, sizeof(info->dname), "tps61050-%c",
+ ('0' + info->pdata->num));
+ info->miscdev.name = info->dname;
+ info->miscdev.fops = &tps61050_fileops;
+ info->miscdev.minor = MISC_DYNAMIC_MINOR;
+ if (misc_register(&info->miscdev)) {
+ pr_err("tps61050: unable to register misc device!\n");
+ kfree(info);
+ return -ENODEV;
+ }
+
+ spin_lock(&driver_lock);
+ list_add_rcu(&info->list, &info_list);
+ spin_unlock(&driver_lock);
+ if ((tps61050_sts_rd(info, &reg) < 0) &&
+ (info->pdata->cfg & (TPS61050_CFG_NOSENSOR))) {
+ tps61050_remove(client);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id tps61050_id[] = {
+ { "tps61050", 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, tps61050_id);
+
+static struct i2c_driver tps61050_i2c_driver = {
+ .driver = {
+ .name = "tps61050",
+ .owner = THIS_MODULE,
+ },
+ .id_table = tps61050_id,
+ .probe = tps61050_probe,
+ .remove = tps61050_remove,
+};
+
+static int __init tps61050_init(void)
+{
+ pr_info("%s\n", __func__);
+ return i2c_add_driver(&tps61050_i2c_driver);
+}
+
+static void __exit tps61050_exit(void)
+{
+ pr_info("%s\n", __func__);
+ i2c_del_driver(&tps61050_i2c_driver);
+}
+
+module_init(tps61050_init);
+module_exit(tps61050_exit);
diff --git a/include/media/tps61050.h b/include/media/tps61050.h
new file mode 100644
index 000000000000..ac7a328a4b2d
--- /dev/null
+++ b/include/media/tps61050.h
@@ -0,0 +1,97 @@
+/*
+ * tps61050.h - tps61050 flash/torch kernel driver
+ *
+ * Copyright (C) 2011 NVIDIA Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __TPS61050_H__
+#define __TPS61050_H__
+
+#include <linux/ioctl.h> /* For IOCTL macros */
+
+#define NUM_TORCH_LEVELS 8
+#define NUM_FLASH_LEVELS 9
+
+/* Expected higher level power calls are:
+ * 1 = OFF
+ * 2 = STANDBY
+ * 3 = ON
+ * These will be multiplied by 2 before given to the driver PM code
+ * that uses the _PWR_ defines. This allows us to insert defines
+ * (most notably _PWR_COMM) allowing more versatile PM.
+ * The PM actions:
+ * _PWR_OFF = board support for regulators, clocks, etc so no
+ * power to device.
+ * _PWR_STDBY = board support to put device in reset. Device is
+ * useless but powered. No communication possible.
+ * _PWR_COMM = Device is powered but in SW standby. Communication
+ * is possible and device retains programming.
+ * _PWR_ON = Full power with active output.
+ */
+
+#define TPS61050_PWR_ERR 0
+#define TPS61050_PWR_OFF 2
+#define TPS61050_PWR_STDBY 4
+#define TPS61050_PWR_COMM 5
+#define TPS61050_PWR_ON 6
+
+#define TPS61050_CFG_NOSENSOR (1 << 0)
+
+#define TPS61050_IOCTL_CAP _IOWR('o', 1, struct tps61050_param)
+#define TPS61050_IOCTL_PWR _IOW('o', 2, __u8)
+#define TPS61050_IOCTL_PARAM_RD _IOWR('o', 3, struct tps61050_param)
+#define TPS61050_IOCTL_PARAM_WR _IOW('o', 4, struct tps61050_param)
+
+#define TPS61050_FLASH_CAPS 6
+#define TPS61050_FLASH_LEVEL 7
+#define TPS61050_FLASH_PIN_STATE 8
+#define TPS61050_TORCH_CAPS 9
+#define TPS61050_TORCH_LEVEL 10
+
+struct tps61050_param {
+ int param;
+ __s32 sizeofvalue;
+ void *p_value;
+};
+
+struct tps61050_level_info {
+ __s32 guidenum;
+ __u32 sustaintime;
+ __s32 rechargefactor;
+};
+
+struct tps61050_pin_state {
+ __u16 mask;
+ __u16 values;
+};
+
+struct tps61050_flash_capabilities {
+ __u32 numberoflevels;
+ struct tps61050_level_info levels[NUM_FLASH_LEVELS];
+};
+
+struct tps61050_torch_capabilities {
+ __u32 numberoflevels;
+ __s32 guidenum[NUM_TORCH_LEVELS];
+};
+
+#ifdef __KERNEL__
+struct tps61050_platform_data {
+ int cfg;
+ int num;
+ int max_amp_torch;
+ int max_amp_flash;
+ void (*pinstate);
+ int (*init)(void);
+ void (*exit)(void);
+ int (*pm)(int);
+ int (*gpio_envm)(int);
+ int (*gpio_sync)(int);
+};
+#endif /* __KERNEL__ */
+
+#endif /* __TPS61050_H__ */