Commit 96e3a6b9 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: smiapp: Avoid maintaining power state information

Instead of keeping track of the power state ourselves, let runtime PM
handle it.

This also splits handling controls between side effect management and
writing the new configuration to the sensor's registers.
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent dd12ed17
...@@ -413,21 +413,14 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) ...@@ -413,21 +413,14 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
struct smiapp_sensor *sensor = struct smiapp_sensor *sensor =
container_of(ctrl->handler, struct smiapp_subdev, ctrl_handler) container_of(ctrl->handler, struct smiapp_subdev, ctrl_handler)
->sensor; ->sensor;
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
int pm_status;
u32 orient = 0; u32 orient = 0;
unsigned int i;
int exposure; int exposure;
int rval; int rval;
switch (ctrl->id) { switch (ctrl->id) {
case V4L2_CID_ANALOGUE_GAIN:
return smiapp_write(
sensor,
SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL, ctrl->val);
case V4L2_CID_EXPOSURE:
return smiapp_write(
sensor,
SMIAPP_REG_U16_COARSE_INTEGRATION_TIME, ctrl->val);
case V4L2_CID_HFLIP: case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
if (sensor->streaming) if (sensor->streaming)
...@@ -440,15 +433,10 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) ...@@ -440,15 +433,10 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
orient |= SMIAPP_IMAGE_ORIENTATION_VFLIP; orient |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
orient ^= sensor->hvflip_inv_mask; orient ^= sensor->hvflip_inv_mask;
rval = smiapp_write(sensor, SMIAPP_REG_U8_IMAGE_ORIENTATION,
orient);
if (rval < 0)
return rval;
smiapp_update_mbus_formats(sensor); smiapp_update_mbus_formats(sensor);
return 0; break;
case V4L2_CID_VBLANK: case V4L2_CID_VBLANK:
exposure = sensor->exposure->val; exposure = sensor->exposure->val;
...@@ -461,59 +449,105 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl) ...@@ -461,59 +449,105 @@ static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
return rval; return rval;
} }
return smiapp_write( break;
sensor, SMIAPP_REG_U16_FRAME_LENGTH_LINES,
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
+ ctrl->val);
case V4L2_CID_HBLANK:
return smiapp_write(
sensor, SMIAPP_REG_U16_LINE_LENGTH_PCK,
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
+ ctrl->val);
case V4L2_CID_LINK_FREQ: case V4L2_CID_LINK_FREQ:
if (sensor->streaming) if (sensor->streaming)
return -EBUSY; return -EBUSY;
return smiapp_pll_update(sensor); rval = smiapp_pll_update(sensor);
if (rval)
case V4L2_CID_TEST_PATTERN: { return rval;
unsigned int i;
return 0;
case V4L2_CID_TEST_PATTERN:
for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
v4l2_ctrl_activate( v4l2_ctrl_activate(
sensor->test_data[i], sensor->test_data[i],
ctrl->val == ctrl->val ==
V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR); V4L2_SMIAPP_TEST_PATTERN_MODE_SOLID_COLOUR);
return smiapp_write( break;
sensor, SMIAPP_REG_U16_TEST_PATTERN_MODE, ctrl->val);
} }
pm_runtime_get_noresume(&client->dev);
pm_status = pm_runtime_get_if_in_use(&client->dev);
pm_runtime_put_noidle(&client->dev);
if (!pm_status)
return 0;
switch (ctrl->id) {
case V4L2_CID_ANALOGUE_GAIN:
rval = smiapp_write(
sensor,
SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL, ctrl->val);
break;
case V4L2_CID_EXPOSURE:
rval = smiapp_write(
sensor,
SMIAPP_REG_U16_COARSE_INTEGRATION_TIME, ctrl->val);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
rval = smiapp_write(sensor, SMIAPP_REG_U8_IMAGE_ORIENTATION,
orient);
break;
case V4L2_CID_VBLANK:
rval = smiapp_write(
sensor, SMIAPP_REG_U16_FRAME_LENGTH_LINES,
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
+ ctrl->val);
break;
case V4L2_CID_HBLANK:
rval = smiapp_write(
sensor, SMIAPP_REG_U16_LINE_LENGTH_PCK,
sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
+ ctrl->val);
break;
case V4L2_CID_TEST_PATTERN:
rval = smiapp_write(
sensor, SMIAPP_REG_U16_TEST_PATTERN_MODE, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN_RED: case V4L2_CID_TEST_PATTERN_RED:
return smiapp_write( rval = smiapp_write(
sensor, SMIAPP_REG_U16_TEST_DATA_RED, ctrl->val); sensor, SMIAPP_REG_U16_TEST_DATA_RED, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN_GREENR: case V4L2_CID_TEST_PATTERN_GREENR:
return smiapp_write( rval = smiapp_write(
sensor, SMIAPP_REG_U16_TEST_DATA_GREENR, ctrl->val); sensor, SMIAPP_REG_U16_TEST_DATA_GREENR, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN_BLUE: case V4L2_CID_TEST_PATTERN_BLUE:
return smiapp_write( rval = smiapp_write(
sensor, SMIAPP_REG_U16_TEST_DATA_BLUE, ctrl->val); sensor, SMIAPP_REG_U16_TEST_DATA_BLUE, ctrl->val);
break;
case V4L2_CID_TEST_PATTERN_GREENB: case V4L2_CID_TEST_PATTERN_GREENB:
return smiapp_write( rval = smiapp_write(
sensor, SMIAPP_REG_U16_TEST_DATA_GREENB, ctrl->val); sensor, SMIAPP_REG_U16_TEST_DATA_GREENB, ctrl->val);
break;
case V4L2_CID_PIXEL_RATE: case V4L2_CID_PIXEL_RATE:
/* For v4l2_ctrl_s_ctrl_int64() used internally. */ /* For v4l2_ctrl_s_ctrl_int64() used internally. */
return 0; rval = 0;
break;
default: default:
return -EINVAL; rval = -EINVAL;
} }
if (pm_status > 0) {
pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
}
return rval;
} }
static const struct v4l2_ctrl_ops smiapp_ctrl_ops = { static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
...@@ -1184,10 +1218,6 @@ static int smiapp_power_on(struct device *dev) ...@@ -1184,10 +1218,6 @@ static int smiapp_power_on(struct device *dev)
sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk); sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk);
usleep_range(sleep, sleep); usleep_range(sleep, sleep);
mutex_lock(&sensor->mutex);
sensor->active = true;
/* /*
* Failures to respond to the address change command have been noticed. * Failures to respond to the address change command have been noticed.
* Those failures seem to be caused by the sensor requiring a longer * Those failures seem to be caused by the sensor requiring a longer
...@@ -1270,24 +1300,9 @@ static int smiapp_power_on(struct device *dev) ...@@ -1270,24 +1300,9 @@ static int smiapp_power_on(struct device *dev)
goto out_cci_addr_fail; goto out_cci_addr_fail;
} }
/* Are we still initialising...? If not, proceed with control setup. */
if (sensor->pixel_array) {
rval = __v4l2_ctrl_handler_setup(
&sensor->pixel_array->ctrl_handler);
if (rval)
goto out_cci_addr_fail;
rval = __v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
if (rval)
goto out_cci_addr_fail;
}
mutex_unlock(&sensor->mutex);
return 0; return 0;
out_cci_addr_fail: out_cci_addr_fail:
mutex_unlock(&sensor->mutex);
gpiod_set_value(sensor->xshutdown, 0); gpiod_set_value(sensor->xshutdown, 0);
clk_disable_unprepare(sensor->ext_clk); clk_disable_unprepare(sensor->ext_clk);
...@@ -1305,8 +1320,6 @@ static int smiapp_power_off(struct device *dev) ...@@ -1305,8 +1320,6 @@ static int smiapp_power_off(struct device *dev)
struct smiapp_sensor *sensor = struct smiapp_sensor *sensor =
container_of(ssd, struct smiapp_sensor, ssds[0]); container_of(ssd, struct smiapp_sensor, ssds[0]);
mutex_lock(&sensor->mutex);
/* /*
* Currently power/clock to lens are enable/disabled separately * Currently power/clock to lens are enable/disabled separately
* but they are essentially the same signals. So if the sensor is * but they are essentially the same signals. So if the sensor is
...@@ -1319,10 +1332,6 @@ static int smiapp_power_off(struct device *dev) ...@@ -1319,10 +1332,6 @@ static int smiapp_power_off(struct device *dev)
SMIAPP_REG_U8_SOFTWARE_RESET, SMIAPP_REG_U8_SOFTWARE_RESET,
SMIAPP_SOFTWARE_RESET); SMIAPP_SOFTWARE_RESET);
sensor->active = false;
mutex_unlock(&sensor->mutex);
gpiod_set_value(sensor->xshutdown, 0); gpiod_set_value(sensor->xshutdown, 0);
clk_disable_unprepare(sensor->ext_clk); clk_disable_unprepare(sensor->ext_clk);
usleep_range(5000, 5000); usleep_range(5000, 5000);
...@@ -1507,6 +1516,30 @@ static int smiapp_stop_streaming(struct smiapp_sensor *sensor) ...@@ -1507,6 +1516,30 @@ static int smiapp_stop_streaming(struct smiapp_sensor *sensor)
* V4L2 subdev video operations * V4L2 subdev video operations
*/ */
static int smiapp_pm_get_init(struct smiapp_sensor *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
int rval;
rval = pm_runtime_get_sync(&client->dev);
if (rval < 0) {
if (rval != -EBUSY && rval != -EAGAIN)
pm_runtime_set_active(&client->dev);
pm_runtime_put_noidle(&client->dev);
return rval;
} else if (!rval) {
rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->
ctrl_handler);
if (rval)
return rval;
return v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
}
return 0;
}
static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable) static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
{ {
struct smiapp_sensor *sensor = to_smiapp_sensor(subdev); struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
...@@ -1516,27 +1549,25 @@ static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable) ...@@ -1516,27 +1549,25 @@ static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
if (sensor->streaming == enable) if (sensor->streaming == enable)
return 0; return 0;
if (enable) { if (!enable) {
rval = pm_runtime_get_sync(&client->dev); smiapp_stop_streaming(sensor);
if (rval < 0) {
if (rval != -EBUSY && rval != -EAGAIN)
pm_runtime_set_active(&client->dev);
pm_runtime_put(&client->dev);
return rval;
}
sensor->streaming = true;
rval = smiapp_start_streaming(sensor);
if (rval < 0)
sensor->streaming = false;
} else {
rval = smiapp_stop_streaming(sensor);
sensor->streaming = false; sensor->streaming = false;
pm_runtime_mark_last_busy(&client->dev); pm_runtime_mark_last_busy(&client->dev);
pm_runtime_put_autosuspend(&client->dev); pm_runtime_put_autosuspend(&client->dev);
return 0;
} }
rval = smiapp_pm_get_init(sensor);
if (rval)
return rval;
sensor->streaming = true;
rval = smiapp_start_streaming(sensor);
if (rval < 0)
sensor->streaming = false;
return rval; return rval;
} }
...@@ -2291,13 +2322,9 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr, ...@@ -2291,13 +2322,9 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
if (!sensor->dev_init_done) if (!sensor->dev_init_done)
return -EBUSY; return -EBUSY;
rval = pm_runtime_get_sync(&client->dev); rval = smiapp_pm_get_init(sensor);
if (rval < 0) { if (rval < 0)
if (rval != -EBUSY && rval != -EAGAIN)
pm_runtime_set_active(&client->dev);
pm_runtime_put_noidle(&client->dev);
return -ENODEV; return -ENODEV;
}
rval = smiapp_read_nvm(sensor, buf, PAGE_SIZE); rval = smiapp_read_nvm(sensor, buf, PAGE_SIZE);
if (rval < 0) { if (rval < 0) {
......
...@@ -223,9 +223,6 @@ int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val) ...@@ -223,9 +223,6 @@ int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val)
len != SMIAPP_REG_32BIT) || flags) len != SMIAPP_REG_32BIT) || flags)
return -EINVAL; return -EINVAL;
if (!sensor->active)
return 0;
msg.addr = client->addr; msg.addr = client->addr;
msg.flags = 0; /* Write */ msg.flags = 0; /* Write */
msg.len = 2 + len; msg.len = 2 + len;
......
...@@ -198,7 +198,6 @@ struct smiapp_sensor { ...@@ -198,7 +198,6 @@ struct smiapp_sensor {
u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */ u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
u8 frame_skip; u8 frame_skip;
bool active; /* is the sensor powered on? */
u16 embedded_start; /* embedded data start line */ u16 embedded_start; /* embedded data start line */
u16 embedded_end; u16 embedded_end;
u16 image_start; /* image data start line */ u16 image_start; /* image data start line */
......
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