[PATCH 1/4] media: i2c: st-vgxy61: Use sub-device active state

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Use sub-device active state. Rely on control handler lock to serialize
access to the active state.

Signed-off-by: Julien Massot <julien.massot@xxxxxxxxxxxxx>
---
 drivers/media/i2c/st-vgxy61.c | 109 ++++++++++++----------------------
 1 file changed, 39 insertions(+), 70 deletions(-)

diff --git a/drivers/media/i2c/st-vgxy61.c b/drivers/media/i2c/st-vgxy61.c
index b9e7c57027b1..733713f909cf 100644
--- a/drivers/media/i2c/st-vgxy61.c
+++ b/drivers/media/i2c/st-vgxy61.c
@@ -397,8 +397,6 @@ struct vgxy61_dev {
 	u16 line_length;
 	u16 rot_term;
 	bool gpios_polarity;
-	/* Lock to protect all members below */
-	struct mutex lock;
 	struct v4l2_ctrl_handler ctrl_handler;
 	struct v4l2_ctrl *pixel_rate_ctrl;
 	struct v4l2_ctrl *expo_ctrl;
@@ -686,27 +684,6 @@ static int vgxy61_enum_mbus_code(struct v4l2_subdev *sd,
 	return 0;
 }
 
-static int vgxy61_get_fmt(struct v4l2_subdev *sd,
-			  struct v4l2_subdev_state *sd_state,
-			  struct v4l2_subdev_format *format)
-{
-	struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
-	struct v4l2_mbus_framefmt *fmt;
-
-	mutex_lock(&sensor->lock);
-
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-		fmt = v4l2_subdev_state_get_format(sd_state, format->pad);
-	else
-		fmt = &sensor->fmt;
-
-	format->format = *fmt;
-
-	mutex_unlock(&sensor->lock);
-
-	return 0;
-}
-
 static u16 vgxy61_get_vblank_min(struct vgxy61_dev *sensor,
 				 enum vgxy61_hdr_mode hdr)
 {
@@ -1167,16 +1144,17 @@ static int vgxy61_stream_disable(struct vgxy61_dev *sensor)
 static int vgxy61_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
+	struct v4l2_subdev_state *sd_state;
 	int ret = 0;
 
-	mutex_lock(&sensor->lock);
+	sd_state = v4l2_subdev_lock_and_get_active_state(&sensor->sd);
 
 	ret = enable ? vgxy61_stream_enable(sensor) :
 	      vgxy61_stream_disable(sensor);
 	if (!ret)
 		sensor->streaming = enable;
 
-	mutex_unlock(&sensor->lock);
+	v4l2_subdev_unlock_state(sd_state);
 
 	return ret;
 }
@@ -1187,51 +1165,39 @@ static int vgxy61_set_fmt(struct v4l2_subdev *sd,
 {
 	struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
 	const struct vgxy61_mode_info *new_mode;
-	struct v4l2_mbus_framefmt *fmt;
 	int ret;
 
-	mutex_lock(&sensor->lock);
-
-	if (sensor->streaming) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if (sensor->streaming)
+		return -EBUSY;
 
 	ret = vgxy61_try_fmt_internal(sd, &format->format, &new_mode);
 	if (ret)
-		goto out;
-
-	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
-		fmt = v4l2_subdev_state_get_format(sd_state, 0);
-		*fmt = format->format;
-	} else if (sensor->current_mode != new_mode ||
-		   sensor->fmt.code != format->format.code) {
-		fmt = &sensor->fmt;
-		*fmt = format->format;
-
-		sensor->current_mode = new_mode;
-
-		/* Reset vblank and framelength to default */
-		ret = vgxy61_update_vblank(sensor,
-					   VGXY61_FRAME_LENGTH_DEF -
-					   new_mode->crop.height,
-					   sensor->hdr);
-
-		/* Update controls to reflect new mode */
-		__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_ctrl,
-					 get_pixel_rate(sensor));
-		__v4l2_ctrl_modify_range(sensor->vblank_ctrl,
-					 sensor->vblank_min,
-					 0xffff - new_mode->crop.height,
-					 1, sensor->vblank);
-		__v4l2_ctrl_s_ctrl(sensor->vblank_ctrl, sensor->vblank);
-		__v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min,
-					 sensor->expo_max, 1,
-					 sensor->expo_long);
-	}
+		return ret;
+
+	*v4l2_subdev_state_get_format(sd_state, format->pad) = format->format;
 
-out:
-	mutex_unlock(&sensor->lock);
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+		return 0;
+
+	sensor->current_mode = new_mode;
+
+	/* Reset vblank and framelength to default */
+	ret = vgxy61_update_vblank(sensor,
+				   VGXY61_FRAME_LENGTH_DEF -
+				   new_mode->crop.height,
+				   sensor->hdr);
+
+	/* Update controls to reflect new mode */
+	__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_ctrl,
+				 get_pixel_rate(sensor));
+	__v4l2_ctrl_modify_range(sensor->vblank_ctrl,
+				 sensor->vblank_min,
+				 0xffff - new_mode->crop.height,
+				 1, sensor->vblank);
+	__v4l2_ctrl_s_ctrl(sensor->vblank_ctrl, sensor->vblank);
+	__v4l2_ctrl_modify_range(sensor->expo_ctrl, sensor->expo_min,
+				 sensor->expo_max, 1,
+				 sensor->expo_long);
 
 	return ret;
 }
@@ -1321,8 +1287,6 @@ static int vgxy61_init_controls(struct vgxy61_dev *sensor)
 	int ret;
 
 	v4l2_ctrl_handler_init(hdl, 16);
-	/* We can use our own mutex for the ctrl lock */
-	hdl->lock = &sensor->lock;
 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN, 0, 0x1c, 1,
 			  sensor->analog_gain);
 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_DIGITAL_GAIN, 0, 0xfff, 1,
@@ -1398,7 +1362,7 @@ static const struct v4l2_subdev_video_ops vgxy61_video_ops = {
 
 static const struct v4l2_subdev_pad_ops vgxy61_pad_ops = {
 	.enum_mbus_code = vgxy61_enum_mbus_code,
-	.get_fmt = vgxy61_get_fmt,
+	.get_fmt = v4l2_subdev_get_fmt,
 	.set_fmt = vgxy61_set_fmt,
 	.get_selection = vgxy61_get_selection,
 	.enum_frame_size = vgxy61_enum_frame_size,
@@ -1801,7 +1765,7 @@ static int vgxy61_probe(struct i2c_client *client)
 	vgxy61_fill_framefmt(sensor, sensor->current_mode, &sensor->fmt,
 			     VGXY61_MEDIA_BUS_FMT_DEF);
 
-	mutex_init(&sensor->lock);
+	sensor->sd.state_lock = sensor->ctrl_handler.lock;
 
 	ret = vgxy61_update_hdr(sensor, sensor->hdr);
 	if (ret)
@@ -1820,6 +1784,10 @@ static int vgxy61_probe(struct i2c_client *client)
 		goto error_handler_free;
 	}
 
+	ret = v4l2_subdev_init_finalize(&sensor->sd);
+	if (ret)
+		goto error_media_entity_cleanup;
+
 	/* Enable runtime PM and turn off the device */
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
@@ -1841,11 +1809,12 @@ static int vgxy61_probe(struct i2c_client *client)
 error_pm_runtime:
 	pm_runtime_disable(&client->dev);
 	pm_runtime_set_suspended(&client->dev);
+	v4l2_subdev_cleanup(&sensor->sd);
+error_media_entity_cleanup:
 	media_entity_cleanup(&sensor->sd.entity);
 error_handler_free:
 	v4l2_ctrl_handler_free(sensor->sd.ctrl_handler);
 error_power_off:
-	mutex_destroy(&sensor->lock);
 	vgxy61_power_off(dev);
 
 	return ret;
@@ -1857,7 +1826,7 @@ static void vgxy61_remove(struct i2c_client *client)
 	struct vgxy61_dev *sensor = to_vgxy61_dev(sd);
 
 	v4l2_async_unregister_subdev(&sensor->sd);
-	mutex_destroy(&sensor->lock);
+	v4l2_subdev_cleanup(&sensor->sd);
 	media_entity_cleanup(&sensor->sd.entity);
 
 	pm_runtime_disable(&client->dev);
-- 
2.44.0





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux