diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-11-12 15:28:39 +0100 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2012-11-12 15:28:39 +0100 |
commit | f987e832a9e79d2ce8009a5ea9c7b677624b3b30 (patch) | |
tree | 0dd09a5e6b4c60ee0a9916907dfc2cda83f3e496 /drivers/media/video | |
parent | f737b7f46a72c099cf8ac88baff02fbf61b1a47c (diff) | |
parent | fc993d9bc48f772133d8cd156c67c296477db070 (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.c | 135 | ||||
-rw-r--r-- | drivers/media/video/tegra/ar0832_main.c | 25 | ||||
-rw-r--r-- | drivers/media/video/tegra/nvavp/nvavp_dev.c | 149 | ||||
-rw-r--r-- | drivers/media/video/tegra/ov5650.c | 5 | ||||
-rw-r--r-- | drivers/media/video/tegra/ov9726.c | 57 | ||||
-rw-r--r-- | drivers/media/video/tegra/sh532u.c | 8 | ||||
-rw-r--r-- | drivers/media/video/tegra/tegra_camera.c | 24 |
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(¶ms, (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, ¶ms)) { + 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, ¶ms, u32val); + return ad5816_param_wr_s(info, ¶ms, s32val); case NVC_SYNC_SLAVE: - return ad5816_param_wr_s(info->s_info, ¶ms, u32val); + return ad5816_param_wr_s(info->s_info, ¶ms, s32val); case NVC_SYNC_STEREO: - err = ad5816_param_wr_s(info, ¶ms, u32val); + err = ad5816_param_wr_s(info, ¶ms, s32val); if (!(info->pdata->cfg & NVC_CFG_SYNC_I2C_MUX)) err |= ad5816_param_wr_s(info->s_info, ¶ms, - 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(®_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 |