Commit 575d6252 authored by HeungJun Kim's avatar HeungJun Kim Committed by Mauro Carvalho Chehab

[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: default avatarHeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 69eb1803
...@@ -257,7 +257,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val); ...@@ -257,7 +257,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
int m5mols_busy(struct v4l2_subdev *sd, u32 reg, u8 value);
int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
int timeout);
/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
#define M5MOLS_I2C_RDY_WAIT_FL (1 << 16)
/* ISP state transition timeout, in ms */
#define M5MOLS_MODE_CHANGE_TIMEOUT 200
#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250
/* /*
* Mode operation of the M-5MOLS * Mode operation of the M-5MOLS
......
...@@ -272,19 +272,35 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) ...@@ -272,19 +272,35 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
return 0; return 0;
} }
int m5mols_busy(struct v4l2_subdev *sd, u32 reg, u8 mask) /**
* m5mols_busy_wait - Busy waiting with I2C register polling
* @reg: the I2C_REG() address of an 8-bit status register to check
* @value: expected status register value
* @mask: bit mask for the read status register value
* @timeout: timeout in miliseconds, or -1 for default timeout
*
* The @reg register value is ORed with @mask before comparing with @value.
*
* Return: 0 if the requested condition became true within less than
* @timeout ms, or else negative errno.
*/
int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
int timeout)
{ {
u8 busy; int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
int i; unsigned long end = jiffies + msecs_to_jiffies(ms);
int ret; u8 status;
for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { do {
ret = m5mols_read_u8(sd, reg, &busy); int ret = m5mols_read_u8(sd, reg, &status);
if (ret < 0)
if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
return ret; return ret;
if ((busy & mask) == mask) if (!ret && (status & mask & 0xff) == (value & 0xff))
return 0; return 0;
} usleep_range(100, 250);
} while (ms > 0 && time_is_after_jiffies(end));
return -EBUSY; return -EBUSY;
} }
...@@ -316,8 +332,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) ...@@ -316,8 +332,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
{ {
int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
if (ret < 0)
return ret ? ret : m5mols_busy(sd, mode, SYSTEM_SYSMODE); return ret;
return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
M5MOLS_MODE_CHANGE_TIMEOUT);
} }
/** /**
...@@ -829,9 +847,10 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) ...@@ -829,9 +847,10 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
if (!ret) if (!ret)
ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
if (!ret) if (!ret)
ret = m5mols_busy(sd, SYSTEM_STATUS, REG_AF_IDLE); ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
if (!ret) 0xff, -1);
v4l2_info(sd, "Success soft-landing lens\n"); if (ret < 0)
v4l2_warn(sd, "Soft landing lens failed\n");
} }
ret = m5mols_sensor_power(info, false); ret = m5mols_sensor_power(info, false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment