aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);