summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/tegra/ad5816.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/drivers/media/video/tegra/ad5816.c b/drivers/media/video/tegra/ad5816.c
index 9f1c060e1718..4741e1f2aaa4 100644
--- a/drivers/media/video/tegra/ad5816.c
+++ b/drivers/media/video/tegra/ad5816.c
@@ -1,22 +1,20 @@
-/* Copyright (C) 2011-2012 NVIDIA Corporation.
+/* ad5816.c - focuser device driver for AD5816
*
- * 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.
+ * Copyright (c) 2012-2013, NVIDIA Corporation. All Rights Reserved.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
-/* This is a NVC kernel driver for a focuser device called
- * ad5816.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
/* Implementation
* --------------
* The board level details about the device need to be provided in the board
@@ -131,6 +129,7 @@ struct ad5816_info {
struct nvc_focus_cap cap;
struct nv_focuser_config nv_config;
struct ad5816_pdata_info config;
+ unsigned long ltv_ms;
};
/**
@@ -451,14 +450,33 @@ static int ad5816_position_rd(struct ad5816_info *info, unsigned *position)
static int ad5816_position_wr(struct ad5816_info *info, s32 position)
{
- s16 data;
+ struct timeval tv;
+ unsigned long tvl;
+ unsigned long dly;
+ int err;
if (position < info->config.pos_low || position > info->config.pos_high)
- return -EINVAL;
-
- data = position & AD5816_POS_CLAMP;
- return ad5816_i2c_wr16(info, VCM_CODE_MSB, data);
+ err = -EINVAL;
+ else {
+ do_gettimeofday(&tv);
+ tvl = ((unsigned long)tv.tv_sec * USEC_PER_SEC +
+ tv.tv_usec) / USEC_PER_MSEC;
+ if (tvl - info->ltv_ms < info->cap.settle_time) {
+ dly = (tvl - info->ltv_ms) * USEC_PER_MSEC;
+ dev_dbg(&info->i2c_client->dev,
+ "%s not settled(%lu uS).\n", __func__, dly);
+ usleep_range(dly, dly + 20);
+ }
+ err = ad5816_i2c_wr16(info, VCM_CODE_MSB,
+ position & AD5816_POS_CLAMP);
+ }
+ if (err)
+ dev_err(&info->i2c_client->dev, "%s ERROR: %d\n",
+ __func__, err);
+ else
+ info->ltv_ms = tvl;
+ return err;
}
static void ad5816_get_focuser_capabilities(struct ad5816_info *info)
@@ -660,8 +678,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
if (!err) {
info->s_mode = u8val;
info->s_info->s_mode = u8val;
- }
- else {
+ } else {
if (info->s_mode != NVC_SYNC_STEREO)
ad5816_pm_wr(info->s_info,
NVC_PWR_OFF);
@@ -681,8 +698,7 @@ static int ad5816_param_wr(struct ad5816_info *info, unsigned long arg)
if (!err) {
info->s_mode = u8val;
info->s_info->s_mode = u8val;
- }
- else {
+ } else {
if (info->s_mode != NVC_SYNC_SLAVE)
ad5816_pm_wr(info->s_info,
NVC_PWR_OFF);
@@ -1055,4 +1071,4 @@ static void __exit ad5816_exit(void)
module_init(ad5816_init);
module_exit(ad5816_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");