summaryrefslogtreecommitdiff
path: root/drivers/media/video
diff options
context:
space:
mode:
authorFrank Chen <frankc@nvidia.com>2013-04-02 10:59:51 -0700
committerJohn Sasinowski <jsasinowski@nvidia.com>2013-04-04 16:26:44 -0700
commitd77044150cb1a43a4b9566c2ca5d417f49d8b685 (patch)
tree5acba9d3a01957c18a80a5f669edef7c0f034a8e /drivers/media/video
parent56e06b6e143045e897ebe0e32b8624395f38a6a8 (diff)
media: video: tegra: Add group hold for ar0833
Add group hold support for ar0833 HDR sensor Bug 1250073 Change-Id: I7b4f294391a261c861a83f10889b91c086a8e593 Signed-off-by: Frank Chen <frankc@nvidia.com> Reviewed-on: http://git-master/r/215640 Reviewed-by: John Sasinowski <jsasinowski@nvidia.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/tegra/ar0833.c189
1 files changed, 145 insertions, 44 deletions
diff --git a/drivers/media/video/tegra/ar0833.c b/drivers/media/video/tegra/ar0833.c
index 0d1e771a876f..fbaf12d92fe0 100644
--- a/drivers/media/video/tegra/ar0833.c
+++ b/drivers/media/video/tegra/ar0833.c
@@ -71,17 +71,6 @@ struct ar0833_info {
#include "ar0833_mode_tbls.c"
-static struct ar0833_reg set_param_grphold_tbl[] = {
- /* Enable Group Hold */
- {0x0104 | AR0833_TABLE_8BIT, 0x0001},
- /* place holders */
- {AR0833_TABLE_NOP, 0x0000},
- {AR0833_TABLE_NOP, 0x0000},
- /* Release Group Hold */
- {0x0104 | AR0833_TABLE_8BIT, 0x0000},
- {AR0833_TABLE_END, 0x0000},
-};
-
struct ar0833_mode_desc {
u16 xres;
u16 yres;
@@ -400,63 +389,164 @@ static int ar0833_write_table(
return 0;
}
-static int ar0833_set_frame_length(struct ar0833_info *info, u32 frame_length)
+static int ar0833_set_frame_length(struct ar0833_info *info, u32 frame_length,
+ bool group_hold)
{
+ struct ar0833_reg reg_list;
int ret;
- dev_dbg(&info->i2c_client->dev, "%s 0x%x\n", __func__, frame_length);
- set_param_grphold_tbl[1].addr = 0x0340;
- set_param_grphold_tbl[1].val = (u16)frame_length;
- ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
- set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+ if (ret)
+ return ret;
+ }
+
+ ar0833_get_frame_length_regs(&reg_list, frame_length);
+ ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+ reg_list.val);
+ if (ret)
+ return ret;
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+ if (ret)
+ return ret;
+ }
return ret;
}
-static int ar0833_set_coarse_time(struct ar0833_info *info, u32 coarse_time)
+static int ar0833_set_coarse_time(struct ar0833_info *info, u32 coarse_time,
+ bool group_hold)
{
int ret;
+ struct ar0833_reg reg_list;
+
+ ar0833_get_coarse_time_regs(&reg_list, coarse_time);
+
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+ if (ret)
+ return ret;
+ }
- dev_dbg(&info->i2c_client->dev, "%s 0x%x\n", __func__, coarse_time);
- set_param_grphold_tbl[1].addr = 0x0202;
- set_param_grphold_tbl[1].val = (u16)coarse_time;
- ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
- set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+ ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+ reg_list.val);
+ if (ret)
+ return ret;
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+ if (ret)
+ return ret;
+ }
return ret;
}
-static int ar0833_set_hdr_coarse_time(
- struct ar0833_info *info, struct ar0833_hdr *values)
+static int ar0833_set_hdr_coarse_time(struct ar0833_info *info,
+ struct ar0833_hdr *values,
+ bool group_hold)
{
int ret;
+ struct ar0833_reg reg_list;
+ struct ar0833_reg reg_list_short;
+
+ ar0833_get_coarse_time_regs(&reg_list, values->coarse_time_long);
+ ar0833_get_coarse_time_short_regs(&reg_list_short,
+ values->coarse_time_short);
+
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+ if (ret)
+ return ret;
+ }
- dev_dbg(&info->i2c_client->dev, "%s 0x%04x 0x%04x\n",
- __func__, values->coarse_time_long, values->coarse_time_short);
- set_param_grphold_tbl[1].addr = 0x0202;
- set_param_grphold_tbl[1].val = values->coarse_time_long;
- set_param_grphold_tbl[2].addr = 0x3088;
- set_param_grphold_tbl[2].val = values->coarse_time_short;
- ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
- set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
- set_param_grphold_tbl[2].addr = AR0833_TABLE_NOP;
+ ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+ reg_list.val);
+ if (ret)
+ return ret;
+ ret = ar0833_write_reg16(info->i2c_client, reg_list_short.addr,
+ reg_list_short.val);
+ if (ret)
+ return ret;
+
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+ if (ret)
+ return ret;
+ }
return ret;
}
-static int ar0833_set_gain(struct ar0833_info *info, u16 gain)
+static int ar0833_set_gain(struct ar0833_info *info, u16 gain,
+ bool group_hold)
{
int ret;
+ struct ar0833_reg reg_list;
+
+ ar0833_get_gain_reg(&reg_list, gain);
- dev_dbg(&info->i2c_client->dev, "%s 0x%04x\n", __func__, gain);
- set_param_grphold_tbl[1].addr = 0x305e;
- set_param_grphold_tbl[1].val = gain;
- ret = ar0833_write_table(info, set_param_grphold_tbl, NULL, 0);
- set_param_grphold_tbl[1].addr = AR0833_TABLE_NOP;
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x1);
+ if (ret)
+ return ret;
+ }
+
+ ret = ar0833_write_reg16(info->i2c_client, reg_list.addr,
+ reg_list.val);
+ if (ret)
+ return ret;
+ if (group_hold) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x0104, 0x0);
+ if (ret)
+ return ret;
+ }
return ret;
}
+static int
+ar0833_set_group_hold(struct ar0833_info *info, struct ar0833_ae *ae)
+{
+ int ret;
+ int count = 0;
+ bool groupHoldEnabled = false;
+ struct ar0833_hdr values;
+
+ values.coarse_time_long = ae->coarse_time;
+ values.coarse_time_short = ae->coarse_time_short;
+
+ if (ae->gain_enable)
+ count++;
+ if (ae->coarse_time_enable)
+ count++;
+ if (ae->frame_length_enable)
+ count++;
+ if (count >= 2)
+ groupHoldEnabled = true;
+
+ if (groupHoldEnabled) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x104, 0x1);
+ if (ret)
+ return ret;
+ }
+
+ if (ae->gain_enable)
+ ar0833_set_gain(info, ae->gain, false);
+ if (ae->coarse_time_enable)
+ ar0833_set_hdr_coarse_time(info, &values, false);
+ if (ae->frame_length_enable)
+ ar0833_set_frame_length(info, ae->frame_length, false);
+
+ if (groupHoldEnabled) {
+ ret = ar0833_write_reg16(info->i2c_client, 0x104, 0x0);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static int ar0833_get_status(struct ar0833_info *info, u8 *status)
{
int err;
@@ -1016,12 +1106,12 @@ static long ar0833_ioctl(struct file *file,
case AR0833_IOCTL_SET_FRAME_LENGTH:
dev_dbg(&info->i2c_client->dev,
"AR0833_IOCTL_SET_FRAME_LENGTH %x\n", (u32)arg);
- err = ar0833_set_frame_length(info, (u32)arg);
+ err = ar0833_set_frame_length(info, (u32)arg, true);
break;
case AR0833_IOCTL_SET_COARSE_TIME:
dev_dbg(&info->i2c_client->dev,
"AR0833_IOCTL_SET_COARSE_TIME %x\n", (u32)arg);
- err = ar0833_set_coarse_time(info, (u32)arg);
+ err = ar0833_set_coarse_time(info, (u32)arg, true);
break;
case AR0833_IOCTL_SET_HDR_COARSE_TIME:
{
@@ -1035,14 +1125,25 @@ static long ar0833_ioctl(struct file *file,
err = -EFAULT;
break;
}
- err = ar0833_set_hdr_coarse_time(info, &values);
+ err = ar0833_set_hdr_coarse_time(info, &values, true);
break;
}
case AR0833_IOCTL_SET_GAIN:
dev_dbg(&info->i2c_client->dev,
"AR0833_IOCTL_SET_GAIN %x\n", (u32)arg);
- err = ar0833_set_gain(info, (u16)arg);
+ err = ar0833_set_gain(info, (u16)arg, true);
break;
+ case AR0833_IOCTL_SET_GROUP_HOLD:
+ {
+ struct ar0833_ae ae;
+ if (copy_from_user(&ae, (const void __user *)arg,
+ sizeof(struct ar0833_ae))) {
+ dev_err(&info->i2c_client->dev,
+ "%s:fail group hold\n", __func__);
+ return -EFAULT;
+ }
+ return ar0833_set_group_hold(info, &ae);
+ }
case AR0833_IOCTL_GET_STATUS:
{
u8 status;