summaryrefslogtreecommitdiff
path: root/drivers/media/video
diff options
context:
space:
mode:
authorMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-12 15:28:39 +0100
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2012-11-12 15:28:39 +0100
commitf987e832a9e79d2ce8009a5ea9c7b677624b3b30 (patch)
tree0dd09a5e6b4c60ee0a9916907dfc2cda83f3e496 /drivers/media/video
parentf737b7f46a72c099cf8ac88baff02fbf61b1a47c (diff)
parentfc993d9bc48f772133d8cd156c67c296477db070 (diff)
Merge branch 'l4t/l4t-r16-r2' into colibri
Conflicts: arch/arm/mach-tegra/tegra3_usb_phy.c arch/arm/mach-tegra/usb_phy.c drivers/usb/gadget/tegra_udc.c drivers/usb/otg/Makefile drivers/video/tegra/fb.c sound/soc/tegra/tegra_pcm.c
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/tegra/ad5816.c135
-rw-r--r--drivers/media/video/tegra/ar0832_main.c25
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c149
-rw-r--r--drivers/media/video/tegra/ov5650.c5
-rw-r--r--drivers/media/video/tegra/ov9726.c57
-rw-r--r--drivers/media/video/tegra/sh532u.c8
-rw-r--r--drivers/media/video/tegra/tegra_camera.c24
7 files changed, 338 insertions, 65 deletions
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c
index 9e31acc33cc3..6fdb9f184614 100644
--- a/drivers/media/video/tegra/ad5816.c
+++ b/drivers/media/video/tegra/ad5816.c
@@ -96,12 +96,14 @@
#define AD5816_ID 0x04
#define AD5816_FOCAL_LENGTH (4.570f)
#define AD5816_FNUMBER (2.8f)
-#define AD5816_ACTUATOR_RANGE 680
-#define AD5816_SETTLETIME 110
+#define AD5816_SLEW_RATE 1
+#define AD5816_ACTUATOR_RANGE 1023
+#define AD5816_SETTLETIME 50
#define AD5816_FOCUS_MACRO 810
#define AD5816_FOCUS_INFINITY 50 /* Exact value needs to be decided */
-#define AD5816_POS_LOW_DEFAULT 220
-#define AD5816_POS_HIGH_DEFAULT 900
+#define AD5816_POS_LOW_DEFAULT 0
+#define AD5816_POS_HIGH_DEFAULT 1023
+#define AD5816_POS_CLAMP 0x03ff
/* Need to decide exact value of VCM_THRESHOLD and its use */
/* define AD5816_VCM_THRESHOLD 20 */
@@ -140,6 +142,7 @@ struct ad5816_info {
struct ad5816_info *s_info;
struct nvc_focus_nvc nvc;
struct nvc_focus_cap cap;
+ struct nv_focuser_config nv_config;
struct ad5816_pdata_info config;
};
@@ -154,10 +157,12 @@ static struct ad5816_pdata_info ad5816_default_info = {
static struct nvc_focus_cap ad5816_default_cap = {
.version = NVC_FOCUS_CAP_VER2,
+ .slew_rate = AD5816_SLEW_RATE,
.actuator_range = AD5816_ACTUATOR_RANGE,
.settle_time = AD5816_SETTLETIME,
.focus_macro = AD5816_FOCUS_MACRO,
.focus_infinity = AD5816_FOCUS_INFINITY,
+ .focus_hyper = AD5816_FOCUS_INFINITY,
};
static struct nvc_focus_nvc ad5816_default_nvc = {
@@ -637,28 +642,76 @@ static int ad5816_position_rd(struct ad5816_info *info, unsigned *position)
int err = 0;
err = ad5816_i2c_rd8(info, 0, VCM_CODE_MSB, &t1);
- pos = t1 & 0x03;
+ pos = t1;
err = ad5816_i2c_rd8(info, 0, VCM_CODE_LSB, &t1);
pos = (pos << 8) | t1;
- if(pos)
- *position = pos - info->config.pos_low;
- else
- *position = info->config.pos_low;
- return 0;
+ if (pos < info->config.pos_low)
+ pos = info->config.pos_low;
+ else if (pos > info->config.pos_high)
+ pos = info->config.pos_high;
+
+ *position = pos;
+
+ return err;
}
-static int ad5816_position_wr(struct ad5816_info *info, unsigned position)
+static int ad5816_position_wr(struct ad5816_info *info, s32 position)
{
- u16 data;
+ s16 data;
- position = position + info->config.pos_low;
- if(position > info->config.pos_high)
- position = info->config.pos_high;
+ ad5816_set_arc_mode(info);
- data = position & 0x03ff;
+ if (position > info->config.pos_high)
+ return -EINVAL;
+ data = position & AD5816_POS_CLAMP;
return ad5816_i2c_wr16(info, VCM_CODE_MSB, data);
+
+}
+
+static void ad5816_get_focuser_capabilities(struct ad5816_info *info)
+{
+ memset(&info->nv_config, 0, sizeof(info->nv_config));
+
+ info->nv_config.focal_length = info->nvc.focal_length;
+ info->nv_config.fnumber = info->nvc.fnumber;
+ info->nv_config.max_aperture = info->nvc.fnumber;
+ info->nv_config.range_ends_reversed = 0;
+ info->nv_config.settle_time = info->cap.settle_time;
+
+ info->nv_config.pos_working_low = AF_POS_INVALID_VALUE;
+ info->nv_config.pos_working_high = AF_POS_INVALID_VALUE;
+
+ info->nv_config.pos_actual_low = info->config.pos_low;
+ info->nv_config.pos_actual_high = info->config.pos_high;
+
+ info->nv_config.slew_rate = info->cap.slew_rate;
+ info->nv_config.circle_of_confusion = -1;
+ info->nv_config.num_focuser_sets = 1;
+ info->nv_config.focuser_set[0].macro = info->cap.focus_macro;
+ info->nv_config.focuser_set[0].hyper = info->cap.focus_hyper;
+ info->nv_config.focuser_set[0].inf = info->cap.focus_infinity;
+ info->nv_config.focuser_set[0].settle_time = info->cap.settle_time;
+}
+
+static int ad5816_set_focuser_capabilities(struct ad5816_info *info,
+ struct nvc_param *params)
+{
+ if (copy_from_user(&info->nv_config, (const void __user *)params->p_value,
+ sizeof(struct nv_focuser_config))) {
+ dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n",
+ __func__, sizeof(struct nv_focuser_config));
+ return -EFAULT;
+ }
+
+ /* set pre-set value, as currently ODM sets incorrect value */
+ info->cap.settle_time = AD5816_SETTLETIME;
+
+ dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d info->cap.settle_time %d\n",
+ __func__, sizeof(struct nv_focuser_config), info->cap.settle_time);
+
+ return 0;
}
static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
@@ -706,13 +759,10 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
__func__, info->nvc.fnumber);
break;
case NVC_PARAM_CAPS:
- data_ptr = &info->cap;
- /* there are different sizes depending on the version */
/* send back just what's requested or our max size */
- if (params.sizeofvalue < sizeof(info->cap))
- data_size = params.sizeofvalue;
- else
- data_size = sizeof(info->cap);
+ ad5816_get_focuser_capabilities(info);
+ data_ptr = &info->nv_config;
+ data_size = sizeof(info->nv_config);
dev_err(&info->i2c_client->dev, "%s CAPS\n", __func__);
break;
case NVC_PARAM_STS:
@@ -745,16 +795,16 @@ static int ad5816_param_rd(struct ad5816_info *info, unsigned long arg)
}
static int ad5816_param_wr_s(struct ad5816_info *info,
- struct nvc_param *params, u32 u32val)
+ struct nvc_param *params, s32 s32val)
{
int err = 0;
switch (params->param) {
case NVC_PARAM_LOCUS:
- dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n", __func__, u32val);
- err = ad5816_position_wr(info, u32val);
+ dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n", __func__, s32val);
+ err = ad5816_position_wr(info, s32val);
return err;
case NVC_PARAM_RESET:
- err = ad5816_reset(info, u32val);
+ err = ad5816_reset(info, s32val);
dev_dbg(&info->i2c_client->dev, "%s RESET: %d\n", __func__, err);
return err;
case NVC_PARAM_SELF_TEST:
@@ -773,7 +823,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
{
struct nvc_param params;
u8 u8val;
- u32 u32val;
+ s32 s32val;
int err = 0;
if (copy_from_user(&params, (const void __user *)arg,
sizeof(struct nvc_param))) {
@@ -781,11 +831,11 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
__func__, __LINE__);
return -EFAULT;
}
- if (copy_from_user(&u32val, (const void __user *)params.p_value, sizeof(u32val))) {
+ if (copy_from_user(&s32val, (const void __user *)params.p_value, sizeof(s32val))) {
dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n", __func__, __LINE__);
return -EFAULT;
}
- u8val = (u8)u32val;
+ u8val = (u8)s32val;
/* parameters independent of sync mode */
switch (params.param) {
case NVC_PARAM_STEREO:
@@ -833,7 +883,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
/* sync power */
info->s_info->pwr_api = info->pwr_api;
/* move slave lens to master position */
- err = ad5816_position_wr(info->s_info, info->pos);
+ err = ad5816_position_wr(info->s_info, (s32)info->pos);
if (!err) {
info->s_mode = u8val;
info->s_info->s_mode = u8val;
@@ -854,20 +904,29 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
if (info->pdata->cfg & NVC_CFG_NOERR)
return 0;
return err;
+
+ case NVC_PARAM_CAPS:
+ if (ad5816_set_focuser_capabilities(info, &params)) {
+ dev_err(&info->i2c_client->dev, "%s: Error: copy_from_user bytes %d\n",
+ __func__, params.sizeofvalue);
+ return -EFAULT;
+ }
+ return 0;
+
default:
/* parameters dependent on sync mode */
switch (info->s_mode) {
case NVC_SYNC_OFF:
case NVC_SYNC_MASTER:
- return ad5816_param_wr_s(info, &params, u32val);
+ return ad5816_param_wr_s(info, &params, s32val);
case NVC_SYNC_SLAVE:
- return ad5816_param_wr_s(info->s_info, &params, u32val);
+ return ad5816_param_wr_s(info->s_info, &params, s32val);
case NVC_SYNC_STEREO:
- err = ad5816_param_wr_s(info, &params, u32val);
+ err = ad5816_param_wr_s(info, &params, s32val);
if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX))
err |= ad5816_param_wr_s(info->s_info,
&params,
- u32val);
+ s32val);
return err;
default:
dev_err(&info->i2c_client->dev, "%s %d internal err\n",
@@ -886,10 +945,14 @@ static long ad5816_ioctl(struct file *file,
int err = 0;
switch (cmd) {
case NVC_IOCTL_PARAM_WR:
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
err = ad5816_param_wr(info, arg);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
return err;
case NVC_IOCTL_PARAM_RD:
+ ad5816_pm_dev_wr(info, NVC_PWR_ON);
err = ad5816_param_rd(info, arg);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
return err;
case NVC_IOCTL_PWR_WR:
/* This is a Guaranteed Level of Service (GLOS) call */
@@ -1032,8 +1095,8 @@ static int ad5816_open(struct inode *inode, struct file *file)
}
file->private_data = info;
ad5816_pm_dev_wr(info, NVC_PWR_ON);
- /* set ARC Mode to ensure faster focus */
- ad5816_set_arc_mode(info);
+ ad5816_position_wr(info, info->cap.focus_infinity);
+ ad5816_pm_dev_wr(info, NVC_PWR_OFF);
dev_dbg(&info->i2c_client->dev, "%s\n", __func__);
return 0;
diff --git a/drivers/media/video/tegra/ar0832_main.c b/drivers/media/video/tegra/ar0832_main.c
index 4da9f7e833b9..b1f43da22ec8 100644
--- a/drivers/media/video/tegra/ar0832_main.c
+++ b/drivers/media/video/tegra/ar0832_main.c
@@ -23,10 +23,12 @@
#include <linux/regulator/consumer.h>
#include <media/ar0832_main.h>
+
#define POS_ACTUAL_LOW 0
#define POS_ACTUAL_HIGH 255
#define SETTLE_TIME 100
-#define SLEW_RATE_DEFAULT 1
+#define AR0832_SLEW_RATE_DISABLED 0
+#define AR0832_SLEW_RATE_SLOWEST 7
struct ar0832_sensor_info {
@@ -1930,13 +1932,26 @@ static int ar0832_focuser_set_config(struct ar0832_dev *dev)
struct i2c_client *i2c_client = dev->i2c_client;
struct ar0832_reg reg_vcm_ctrl, reg_vcm_step_time;
int ret = 0;
- u8 vcm_slew = 1;
+ u8 vcm_slew;
+ u16 vcm_control_data;
+ u16 vcm_step_time = 1024;
+
+ /* slew_rate of disabled (0) or default value (1) will disable */
+ /* the slew rate in this case. Any value of 2 onwards will enable */
+ /* the slew rate to a different degree */
+ if (dev->focuser_info->config.slew_rate == SLEW_RATE_DISABLED ||
+ dev->focuser_info->config.slew_rate == SLEW_RATE_DEFAULT)
+ vcm_slew = AR0832_SLEW_RATE_DISABLED;
+ else
+ vcm_slew = dev->focuser_info->config.slew_rate - 1;
+
+ if (vcm_slew > AR0832_SLEW_RATE_SLOWEST)
+ vcm_slew = AR0832_SLEW_RATE_SLOWEST;
/* bit15(0x80) means that VCM driver enable bit. */
/* bit3(0x08) means that keep VCM(AF position) */
/* while sensor is in soft standby mode during mode transitions. */
- u16 vcm_control_data = (0x80 << 8 | (0x08 | (vcm_slew & 0x07)));
- u16 vcm_step_time = 1024;
+ vcm_control_data = (0x80 << 8 | (0x08 | (vcm_slew & 0x07)));
ar0832_get_focuser_vcm_control_regs(&reg_vcm_ctrl, vcm_control_data);
ret = ar0832_write_reg16(dev->i2c_client, reg_vcm_ctrl.addr,
@@ -2422,7 +2437,7 @@ static void ar0832_create_debugfs(struct ar0832_dev *dev)
goto remove_debugfs;
ret = debugfs_create_file("test_pattern",
- S_IWUGO | S_IRUGO,
+ S_IWUSR | S_IRUGO,
dev->debugdir, dev,
&ar0832_debugfs_fops);
if (!ret)
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index 9a54f8e3d025..4501abb9a735 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -1,7 +1,7 @@
/*
* drivers/media/video/tegra/nvavp/nvavp_dev.c
*
- * Copyright (C) 2011-2012 NVIDIA Corp.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* 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
@@ -101,6 +101,10 @@ struct nvavp_info {
struct clk *bsev_clk;
struct clk *vde_clk;
struct clk *cop_clk;
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ struct clk *bsea_clk;
+ struct clk *vcp_clk;
+#endif
/* used for dvfs */
struct clk *sclk;
@@ -115,6 +119,7 @@ struct nvavp_info {
int video_initialized;
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
int audio_initialized;
+ struct work_struct app_notify_work;
#endif
struct work_struct clock_disable_work;
@@ -263,14 +268,26 @@ static void nvavp_clks_disable(struct nvavp_info *nvavp)
}
}
-static u32 nvavp_check_idle(struct nvavp_info *nvavp)
+static u32 nvavp_check_idle(struct nvavp_info *nvavp, int channel_id)
{
- struct nvavp_channel *channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
+ struct nvavp_channel *channel_info = nvavp_get_channel_info(nvavp, channel_id);
struct nv_e276_control *control = channel_info->os_control;
return (control->put == control->get) ? 1 : 0;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static void app_notify_handler(struct work_struct *work)
+{
+ struct nvavp_info *nvavp;
+
+ nvavp = container_of(work, struct nvavp_info,
+ app_notify_work);
+
+ kobject_uevent(&nvavp->nvhost_dev->dev.kobj, KOBJ_CHANGE);
+}
+#endif
+
static void clock_disable_handler(struct work_struct *work)
{
struct nvavp_info *nvavp;
@@ -282,7 +299,7 @@ static void clock_disable_handler(struct work_struct *work)
mutex_lock(&channel_info->pushbuffer_lock);
mutex_lock(&nvavp->open_lock);
- if (nvavp_check_idle(nvavp) && nvavp->pending) {
+ if (nvavp_check_idle(nvavp, NVAVP_VIDEO_CHANNEL) && nvavp->pending) {
nvavp->pending = false;
nvavp_clks_disable(nvavp);
}
@@ -328,6 +345,13 @@ static int nvavp_service(struct nvavp_info *nvavp)
dev_err(&nvavp->nvhost_dev->dev, "AVP timeout\n");
writel(inbox & NVAVP_INBOX_VALID, NVAVP_OS_INBOX);
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (inbox & NVE276_OS_INTERRUPT_APP_NOTIFY) {
+ pr_debug("nvavp_service NVE276_OS_INTERRUPT_APP_NOTIFY\n");
+ schedule_work(&nvavp->app_notify_work);
+ }
+#endif
+
return 0;
}
@@ -970,18 +994,14 @@ static void nvavp_uninit(struct nvavp_info *nvavp)
if (video_initialized) {
pr_debug("nvavp_uninit nvavp->video_initialized\n");
cancel_work_sync(&nvavp->clock_disable_work);
-
nvavp_halt_vde(nvavp);
-
- clk_disable(nvavp->sclk);
- clk_disable(nvavp->emc_clk);
-
nvavp_set_video_init_status(nvavp, 0);
video_initialized = 0;
}
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
if (audio_initialized) {
+ cancel_work_sync(&nvavp->app_notify_work);
nvavp_set_audio_init_status(nvavp, 0);
audio_initialized = 0;
}
@@ -990,6 +1010,9 @@ static void nvavp_uninit(struct nvavp_info *nvavp)
/* Video and Audio both becomes uninitialized */
if (video_initialized == audio_initialized) {
pr_debug("nvavp_uninit both channels unitialized\n");
+
+ clk_disable(nvavp->sclk);
+ clk_disable(nvavp->emc_clk);
disable_irq(nvavp->mbox_from_avp_pend_irq);
nvavp_pushbuffer_deinit(nvavp);
nvavp_halt_avp(nvavp);
@@ -1250,6 +1273,62 @@ static int nvavp_force_clock_stay_on_ioctl(struct file *filp, unsigned int cmd,
return 0;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+static int nvavp_enable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct nvavp_clientctx *clientctx = filp->private_data;
+ struct nvavp_info *nvavp = clientctx->nvavp;
+ struct nvavp_clock_args config;
+
+ if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
+ return -EFAULT;
+
+ dev_dbg(&nvavp->nvhost_dev->dev, "%s: clk_id=%d\n",
+ __func__, config.id);
+
+ if (config.id == NVAVP_MODULE_ID_VCP)
+ clk_enable(nvavp->vcp_clk);
+ else if (config.id == NVAVP_MODULE_ID_BSEA)
+ clk_enable(nvavp->bsea_clk);
+
+ return 0;
+}
+
+static int nvavp_disable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct nvavp_clientctx *clientctx = filp->private_data;
+ struct nvavp_info *nvavp = clientctx->nvavp;
+ struct nvavp_clock_args config;
+
+ if (copy_from_user(&config, (void __user *)arg, sizeof(struct nvavp_clock_args)))
+ return -EFAULT;
+
+ dev_dbg(&nvavp->nvhost_dev->dev, "%s: clk_id=%d\n",
+ __func__, config.id);
+
+ if (config.id == NVAVP_MODULE_ID_VCP)
+ clk_disable(nvavp->vcp_clk);
+ else if (config.id == NVAVP_MODULE_ID_BSEA)
+ clk_disable(nvavp->bsea_clk);
+
+ return 0;
+}
+#else
+static int nvavp_enable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+
+static int nvavp_disable_audio_clocks(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ return 0;
+}
+#endif
+
static int tegra_nvavp_open(struct inode *inode, struct file *filp, int channel_id)
{
struct miscdevice *miscdev = filp->private_data;
@@ -1367,6 +1446,12 @@ static long tegra_nvavp_ioctl(struct file *filp, unsigned int cmd,
case NVAVP_IOCTL_FORCE_CLOCK_STAY_ON:
ret = nvavp_force_clock_stay_on_ioctl(filp, cmd, arg);
break;
+ case NVAVP_IOCTL_ENABLE_AUDIO_CLOCKS:
+ ret = nvavp_enable_audio_clocks(filp, cmd, arg);
+ break;
+ case NVAVP_IOCTL_DISABLE_AUDIO_CLOCKS:
+ ret = nvavp_disable_audio_clocks(filp, cmd, arg);
+ break;
default:
ret = -EINVAL;
break;
@@ -1540,6 +1625,22 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
goto err_get_emc_clk;
}
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ nvavp->bsea_clk = clk_get(&ndev->dev, "bsea");
+ if (IS_ERR(nvavp->bsea_clk)) {
+ dev_err(&ndev->dev, "cannot get bsea clock\n");
+ ret = -ENOENT;
+ goto err_get_bsea_clk;
+ }
+
+ nvavp->vcp_clk = clk_get(&ndev->dev, "vcp");
+ if (IS_ERR(nvavp->vcp_clk)) {
+ dev_err(&ndev->dev, "cannot get vcp clock\n");
+ ret = -ENOENT;
+ goto err_get_vcp_clk;
+ }
+#endif
+
nvavp->clk_enabled = 0;
nvavp_halt_avp(nvavp);
@@ -1558,6 +1659,7 @@ static int tegra_nvavp_probe(struct nvhost_device *ndev,
}
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ INIT_WORK(&nvavp->app_notify_work, app_notify_handler);
nvavp->audio_misc_dev.minor = MISC_DYNAMIC_MINOR;
nvavp->audio_misc_dev.name = "tegra_audio_avpchannel";
nvavp->audio_misc_dev.fops = &tegra_audio_nvavp_fops;
@@ -1591,6 +1693,12 @@ err_audio_misc_reg:
#endif
misc_deregister(&nvavp->video_misc_dev);
err_misc_reg:
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ clk_put(nvavp->vcp_clk);
+err_get_vcp_clk:
+ clk_put(nvavp->bsea_clk);
+err_get_bsea_clk:
+#endif
clk_put(nvavp->emc_clk);
err_get_emc_clk:
clk_put(nvavp->sclk);
@@ -1639,6 +1747,8 @@ static int tegra_nvavp_remove(struct nvhost_device *ndev)
#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
misc_deregister(&nvavp->audio_misc_dev);
+ clk_put(nvavp->vcp_clk);
+ clk_put(nvavp->bsea_clk);
#endif
clk_put(nvavp->bsev_clk);
clk_put(nvavp->vde_clk);
@@ -1662,14 +1772,22 @@ static int tegra_nvavp_suspend(struct nvhost_device *ndev, pm_message_t state)
mutex_lock(&nvavp->open_lock);
if (nvavp->refcount) {
- if (!nvavp->clk_enabled)
+ if (!nvavp->clk_enabled) {
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ if (nvavp_check_idle(nvavp, NVAVP_AUDIO_CHANNEL))
+ nvavp_uninit(nvavp);
+ else
+ ret = -EBUSY;
+#else
nvavp_uninit(nvavp);
- else
+#endif
+ }
+ else {
ret = -EBUSY;
+ }
}
mutex_unlock(&nvavp->open_lock);
-
return ret;
}
@@ -1679,9 +1797,12 @@ static int tegra_nvavp_resume(struct nvhost_device *ndev)
mutex_lock(&nvavp->open_lock);
- if (nvavp->refcount)
+ if (nvavp->refcount) {
nvavp_init(nvavp, NVAVP_VIDEO_CHANNEL);
-
+#if defined(CONFIG_TEGRA_NVAVP_AUDIO)
+ nvavp_init(nvavp, NVAVP_AUDIO_CHANNEL);
+#endif
+ }
mutex_unlock(&nvavp->open_lock);
return 0;
diff --git a/drivers/media/video/tegra/ov5650.c b/drivers/media/video/tegra/ov5650.c
index bac1d00c3bd0..7fae83c21fe2 100644
--- a/drivers/media/video/tegra/ov5650.c
+++ b/drivers/media/video/tegra/ov5650.c
@@ -639,6 +639,11 @@ static struct ov5650_reg mode_320x240[] = {
{0x380f, 0x38},
+ {0x3500, 0x00},
+ {0x3501, 0x13},
+ {0x3502, 0x80},
+ {0x350b, 0x7f},
+
{0x3815, 0x81},
{0x3824, 0x23},
{0x3825, 0x20},
diff --git a/drivers/media/video/tegra/ov9726.c b/drivers/media/video/tegra/ov9726.c
index 378d46fabedf..45d6c85f0925 100644
--- a/drivers/media/video/tegra/ov9726.c
+++ b/drivers/media/video/tegra/ov9726.c
@@ -38,6 +38,7 @@ struct ov9726_devinfo {
struct ov9726_power_rail power_rail;
atomic_t in_use;
__u32 mode;
+ struct ov9726_reg grphold_temp[10];
};
static struct ov9726_reg mode_1280x720[] = {
@@ -603,6 +604,46 @@ static int ov9726_set_gain(struct i2c_client *i2c_client, u16 gain)
return ret;
}
+static int ov9726_set_group_hold(struct ov9726_devinfo *dev,
+ struct ov9726_ae *ae)
+{
+#define OV9726_REG_PUSH8(p, a, v) \
+ do { \
+ (p)->addr = (a); \
+ (p)->val = (v); \
+ (p)++; \
+ } while (0)
+
+#define OV9726_REG_PUSH16(ptr, addr, val) do { \
+ OV9726_REG_PUSH8(ptr, (addr), (val) >> 8); \
+ OV9726_REG_PUSH8(ptr, (addr) + 1, (val) & 0xff); \
+ } while (0)
+
+ struct ov9726_reg *gptr = &dev->grphold_temp[0];
+
+ if (!ae->gain_enable &&
+ !ae->coarse_time_enable &&
+ !ae->frame_length_enable)
+ return 0;
+
+ OV9726_REG_PUSH8(gptr, 0x0104, 0x01);
+ if (ae->gain_enable)
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_GAIN_HI, ae->gain);
+ if (ae->coarse_time_enable)
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_COARSE_TIME_HI, ae->coarse_time);
+ if (ae->frame_length_enable) {
+ OV9726_REG_PUSH16(gptr,
+ OV9726_REG_FRAME_LENGTH_HI, ae->frame_length);
+ }
+ OV9726_REG_PUSH8(gptr, 0x0104, 0x00);
+ OV9726_REG_PUSH8(gptr, OV9726_TABLE_END, 0x00);
+
+ return ov9726_write_table(dev->i2c_client,
+ dev->grphold_temp, NULL, 0);
+}
+
static int ov9726_get_status(struct i2c_client *i2c_client, u8 *status)
{
int err;
@@ -681,19 +722,26 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
}
-
case OV9726_IOCTL_SET_FRAME_LENGTH:
err = ov9726_set_frame_length(i2c_client, (u32)arg);
break;
-
case OV9726_IOCTL_SET_COARSE_TIME:
err = ov9726_set_coarse_time(i2c_client, (u32)arg);
break;
-
case OV9726_IOCTL_SET_GAIN:
err = ov9726_set_gain(i2c_client, (u16)arg);
break;
-
+ case OV9726_IOCTL_SET_GROUP_HOLD:
+ {
+ struct ov9726_ae ae;
+ if (copy_from_user(&ae,
+ (const void __user *)arg, sizeof(struct ov9726_ae))) {
+ pr_info("%s %d\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ err = ov9726_set_group_hold(dev, &ae);
+ break;
+ }
case OV9726_IOCTL_GET_STATUS:
{
u8 status;
@@ -706,7 +754,6 @@ ov9726_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
}
-
default:
err = -EINVAL;
break;
diff --git a/drivers/media/video/tegra/sh532u.c b/drivers/media/video/tegra/sh532u.c
index 84692d992154..e41dd1f4afb1 100644
--- a/drivers/media/video/tegra/sh532u.c
+++ b/drivers/media/video/tegra/sh532u.c
@@ -1406,9 +1406,9 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info,
struct nvc_param *params)
{
if (copy_from_user(&info->config, (const void __user *)params->p_value,
- params->sizeofvalue)) {
+ sizeof(struct nv_focuser_config))) {
dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n",
- __func__, params->sizeofvalue);
+ __func__, sizeof(struct nv_focuser_config));
return -EFAULT;
}
@@ -1420,7 +1420,7 @@ static int sh532u_set_focuser_capabilities(struct sh532u_info *info,
info->config.slew_rate = info->config.slew_rate;
dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d\n",
- __func__, params->sizeofvalue);
+ __func__, sizeof(struct nv_focuser_config));
return 0;
}
@@ -1491,7 +1491,7 @@ static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg)
sh532u_get_focuser_capabilities(info);
data_ptr = &info->config;
- data_size = params.sizeofvalue;
+ data_size = sizeof(info->config);
break;
case NVC_PARAM_STS:
diff --git a/drivers/media/video/tegra/tegra_camera.c b/drivers/media/video/tegra/tegra_camera.c
index 03eecf464c48..2b0cd005096c 100644
--- a/drivers/media/video/tegra/tegra_camera.c
+++ b/drivers/media/video/tegra/tegra_camera.c
@@ -2,7 +2,7 @@
* drivers/media/video/tegra/tegra_camera.c
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2012 Nvidia Corp
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -58,6 +58,25 @@ struct tegra_camera_block {
bool is_enabled;
};
+/*
+ * Declare and define two static variables to provide hint to
+ * gr3d module
+ */
+static int tegra_camera_on;
+static struct tegra_camera_platform_data *pdata;
+
+int is_tegra_camera_on(void)
+{
+ if (pdata) {
+ if (pdata->limit_3d_emc_clk)
+ return tegra_camera_on;
+ else
+ return 0;
+ } else {
+ return 0;
+ }
+}
+
static int tegra_camera_enable_clk(struct tegra_camera_dev *dev)
{
clk_enable(dev->vi_clk);
@@ -227,6 +246,7 @@ static int tegra_camera_power_on(struct tegra_camera_dev *dev)
__func__);
#endif
dev->power_on = 1;
+ tegra_camera_on = dev->power_on;
return ret;
}
@@ -255,6 +275,7 @@ static int tegra_camera_power_off(struct tegra_camera_dev *dev)
}
}
dev->power_on = 0;
+ tegra_camera_on = dev->power_on;
return ret;
}
@@ -425,6 +446,7 @@ static int tegra_camera_probe(struct platform_device *pdev)
mutex_unlock(&dev->tegra_camera_lock);
dev->dev = &pdev->dev;
+ pdata = pdev->dev.platform_data;
/* Get regulator pointer */
#ifdef CONFIG_ARCH_TEGRA_2x_SOC