aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeungJun Kim <riverful.kim@samsung.com>2011-12-12 06:04:03 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-12-30 11:33:09 -0500
commit575d6252a715c599964ec6ec06428e6362c0633e (patch)
tree1cd45c589f0e7b5824fc92748cda4e3abb141a63
parent69eb18032017082bb1c54236290c7e3578e0a3d3 (diff)
[media] m5mols: Extend the busy wait helper
Make m5mols_busy_wait function jiffies based rather than relying on some fixed number of I2C read iterations while busy waiting for the device to execute a request. With fixed number of iterations we may be getting different wait times, depending on the I2C speed. In some conditions we have to wait even if the I2C communications fails, in those cases M5MOLS_I2C_RDY_WAIT_MASK should be passed as the mask argument to m5mols_busy_wait(). Signed-off-by: HeungJun Kim <riverful.kim@samsung.com> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/m5mols/m5mols.h10
-rw-r--r--drivers/media/video/m5mols/m5mols_core.c47
2 files changed, 42 insertions, 15 deletions
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h
index 42c494c1e583..f33171672c31 100644
--- a/drivers/media/video/m5mols/m5mols.h
+++ b/drivers/media/video/m5mols/m5mols.h
@@ -257,7 +257,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
257int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); 257int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
258int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); 258int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
259int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); 259int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
260int m5mols_busy(struct v4l2_subdev *sd, u32 reg, u8 value); 260
261int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
262 int timeout);
263
264/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
265#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16)
266/* ISP state transition timeout, in ms */
267#define M5MOLS_MODE_CHANGE_TIMEOUT 200
268#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250
261 269
262/* 270/*
263 * Mode operation of the M-5MOLS 271 * Mode operation of the M-5MOLS
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c
index 10170b89ab59..5005127bb11c 100644
--- a/drivers/media/video/m5mols/m5mols_core.c
+++ b/drivers/media/video/m5mols/m5mols_core.c
@@ -272,19 +272,35 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
272 return 0; 272 return 0;
273} 273}
274 274
275int m5mols_busy(struct v4l2_subdev *sd, u32 reg, u8 mask) 275/**
276 * m5mols_busy_wait - Busy waiting with I2C register polling
277 * @reg: the I2C_REG() address of an 8-bit status register to check
278 * @value: expected status register value
279 * @mask: bit mask for the read status register value
280 * @timeout: timeout in miliseconds, or -1 for default timeout
281 *
282 * The @reg register value is ORed with @mask before comparing with @value.
283 *
284 * Return: 0 if the requested condition became true within less than
285 * @timeout ms, or else negative errno.
286 */
287int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
288 int timeout)
276{ 289{
277 u8 busy; 290 int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
278 int i; 291 unsigned long end = jiffies + msecs_to_jiffies(ms);
279 int ret; 292 u8 status;
280 293
281 for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { 294 do {
282 ret = m5mols_read_u8(sd, reg, &busy); 295 int ret = m5mols_read_u8(sd, reg, &status);
283 if (ret < 0) 296
297 if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
284 return ret; 298 return ret;
285 if ((busy & mask) == mask) 299 if (!ret && (status & mask & 0xff) == (value & 0xff))
286 return 0; 300 return 0;
287 } 301 usleep_range(100, 250);
302 } while (ms > 0 && time_is_after_jiffies(end));
303
288 return -EBUSY; 304 return -EBUSY;
289} 305}
290 306
@@ -316,8 +332,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
316static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) 332static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
317{ 333{
318 int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); 334 int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
319 335 if (ret < 0)
320 return ret ? ret : m5mols_busy(sd, mode, SYSTEM_SYSMODE); 336 return ret;
337 return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
338 M5MOLS_MODE_CHANGE_TIMEOUT);
321} 339}
322 340
323/** 341/**
@@ -829,9 +847,10 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
829 if (!ret) 847 if (!ret)
830 ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); 848 ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
831 if (!ret) 849 if (!ret)
832 ret = m5mols_busy(sd, SYSTEM_STATUS, REG_AF_IDLE); 850 ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
833 if (!ret) 851 0xff, -1);
834 v4l2_info(sd, "Success soft-landing lens\n"); 852 if (ret < 0)
853 v4l2_warn(sd, "Soft landing lens failed\n");
835 } 854 }
836 855
837 ret = m5mols_sensor_power(info, false); 856 ret = m5mols_sensor_power(info, false);