diff options
-rw-r--r-- | drivers/media/video/m5mols/m5mols.h | 10 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_core.c | 47 |
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); | |||
257 | int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); | 257 | int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); |
258 | int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); | 258 | int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); |
259 | int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); | 259 | int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); |
260 | int m5mols_busy(struct v4l2_subdev *sd, u32 reg, u8 value); | 260 | |
261 | int 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 | ||
275 | int 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 | */ | ||
287 | int 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) | |||
316 | static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) | 332 | static 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); |