Re: [PATCH v2 5/7] media: i2c: imx219: Use subdev active state

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

 




Hi Jacopo.

On 7/31/23 1:05 PM, Jacopo Mondi wrote:
Hi Umang

On Mon, Jul 31, 2023 at 02:56:06AM +0530, Umang Jain wrote:
Hi Jacopo ,

On 7/10/23 9:22 PM, Jacopo Mondi wrote:
Port the imx219 sensor driver to use the subdev active state.

Move all the format configuration to the subdevice state and simplify
the format handling, locking and initialization.

Signed-off-by: Jacopo Mondi <jacopo.mondi@xxxxxxxxxxxxxxxx>
Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>
---
   drivers/media/i2c/imx219.c | 179 ++++++++++---------------------------
   1 file changed, 48 insertions(+), 131 deletions(-)

diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
index 6963e24e1bc2..73e06583d651 100644
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -460,8 +460,6 @@ struct imx219 {
   	struct v4l2_subdev sd;
   	struct media_pad pad;
-	struct v4l2_mbus_framefmt fmt;
-
   	struct clk *xclk; /* system clock to IMX219 */
   	u32 xclk_freq;
@@ -481,12 +479,6 @@ struct imx219 {
   	/* Current mode */
   	const struct imx219_mode *mode;
-	/*
-	 * Mutex for serialized access:
-	 * Protect sensor module set pad format and start/stop streaming safely.
-	 */
-	struct mutex mutex;
-
   	/* Streaming on/off */
   	bool streaming;
@@ -576,8 +568,6 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
   {
   	unsigned int i;
-	lockdep_assert_held(&imx219->mutex);
-
   	for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); i++)
   		if (imx219_mbus_formats[i] == code)
   			break;
@@ -591,20 +581,6 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
   	return imx219_mbus_formats[i];
   }
-static void imx219_set_default_format(struct imx219 *imx219)
-{
-	struct v4l2_mbus_framefmt *fmt;
-
-	fmt = &imx219->fmt;
-	fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
-	fmt->colorspace = V4L2_COLORSPACE_RAW;
-	fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-	fmt->width = supported_modes[0].width;
-	fmt->height = supported_modes[0].height;
-	fmt->field = V4L2_FIELD_NONE;
-	fmt->xfer_func = V4L2_XFER_FUNC_NONE;
-}
-
   static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
   {
   	struct imx219 *imx219 =
@@ -701,9 +677,6 @@ static int imx219_init_cfg(struct v4l2_subdev *sd,
   	struct v4l2_mbus_framefmt *format;
   	struct v4l2_rect *crop;
-	/* imx219_get_format_code() wants mutex locked. */
-	mutex_lock(&imx219->mutex);
-
   	/* Initialize try_fmt */
   	format = v4l2_subdev_get_pad_format(sd, state, 0);
   	format->width = supported_modes[0].width;
@@ -723,8 +696,6 @@ static int imx219_init_cfg(struct v4l2_subdev *sd,
   	crop->width = IMX219_PIXEL_ARRAY_WIDTH;
   	crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
-	mutex_unlock(&imx219->mutex);
-
   	return 0;
   }
@@ -737,9 +708,7 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
   	if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
   		return -EINVAL;
-	mutex_lock(&imx219->mutex);
   	code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
-	mutex_unlock(&imx219->mutex);
   	return 0;
   }
@@ -754,9 +723,7 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
   	if (fse->index >= ARRAY_SIZE(supported_modes))
   		return -EINVAL;
-	mutex_lock(&imx219->mutex);
   	code = imx219_get_format_code(imx219, fse->code);
-	mutex_unlock(&imx219->mutex);
   	if (fse->code != code)
   		return -EINVAL;
@@ -785,52 +752,16 @@ static void imx219_update_pad_format(struct imx219 *imx219,
   	imx219_reset_colorspace(&fmt->format);
   }
-static int __imx219_get_pad_format(struct imx219 *imx219,
-				   struct v4l2_subdev_state *sd_state,
-				   struct v4l2_subdev_format *fmt)
-{
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		struct v4l2_mbus_framefmt *try_fmt =
-			v4l2_subdev_get_try_format(&imx219->sd, sd_state,
-						   fmt->pad);
-		/* update the code which could change due to vflip or hflip: */
-		try_fmt->code = imx219_get_format_code(imx219, try_fmt->code);
-		fmt->format = *try_fmt;
-	} else {
-		imx219_update_pad_format(imx219, imx219->mode, fmt);
-		fmt->format.code = imx219_get_format_code(imx219,
-							  imx219->fmt.code);
-	}
-
-	return 0;
-}
-
-static int imx219_get_pad_format(struct v4l2_subdev *sd,
-				 struct v4l2_subdev_state *sd_state,
-				 struct v4l2_subdev_format *fmt)
-{
-	struct imx219 *imx219 = to_imx219(sd);
-	int ret;
-
-	mutex_lock(&imx219->mutex);
-	ret = __imx219_get_pad_format(imx219, sd_state, fmt);
-	mutex_unlock(&imx219->mutex);
-
-	return ret;
-}
-
   static int imx219_set_pad_format(struct v4l2_subdev *sd,
   				 struct v4l2_subdev_state *sd_state,
   				 struct v4l2_subdev_format *fmt)
   {
   	struct imx219 *imx219 = to_imx219(sd);
   	const struct imx219_mode *mode;
-	struct v4l2_mbus_framefmt *framefmt;
   	int exposure_max, exposure_def, hblank;
+	struct v4l2_mbus_framefmt *format;
   	unsigned int i;
-	mutex_lock(&imx219->mutex);
-
   	for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); i++)
   		if (imx219_mbus_formats[i] == fmt->format.code)
   			break;
@@ -844,13 +775,14 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
   				      ARRAY_SIZE(supported_modes),
   				      width, height,
   				      fmt->format.width, fmt->format.height);
+
   	imx219_update_pad_format(imx219, mode, fmt);
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
-		*framefmt = fmt->format;
-	} else if (imx219->mode != mode ||
-		   imx219->fmt.code != fmt->format.code) {
-		imx219->fmt = fmt->format;
+	format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
+
+	if (imx219->mode == mode && format->code == fmt->format.code)
+		return 0;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
   		imx219->mode = mode;
   		/* Update limits and set FPS to default */
   		__v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
@@ -876,14 +808,15 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
   					 hblank);
   	}
-	mutex_unlock(&imx219->mutex);
+	*format = fmt->format;
   	return 0;
   }
-static int imx219_set_framefmt(struct imx219 *imx219)
+static int imx219_set_framefmt(struct imx219 *imx219,
+			       const struct v4l2_mbus_framefmt *format)
   {
-	switch (imx219->fmt.code) {
+	switch (format->code) {
   	case MEDIA_BUS_FMT_SRGGB8_1X8:
   	case MEDIA_BUS_FMT_SGRBG8_1X8:
   	case MEDIA_BUS_FMT_SGBRG8_1X8:
@@ -902,7 +835,8 @@ static int imx219_set_framefmt(struct imx219 *imx219)
   	return -EINVAL;
   }
-static int imx219_set_binning(struct imx219 *imx219)
+static int imx219_set_binning(struct imx219 *imx219,
+			      const struct v4l2_mbus_framefmt *format)
   {
   	if (!imx219->mode->binning) {
   		return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
@@ -910,7 +844,7 @@ static int imx219_set_binning(struct imx219 *imx219)
   					IMX219_BINNING_NONE);
   	}
-	switch (imx219->fmt.code) {
+	switch (format->code) {
   	case MEDIA_BUS_FMT_SRGGB8_1X8:
   	case MEDIA_BUS_FMT_SGRBG8_1X8:
   	case MEDIA_BUS_FMT_SGBRG8_1X8:
@@ -931,34 +865,13 @@ static int imx219_set_binning(struct imx219 *imx219)
   	return -EINVAL;
   }
-static const struct v4l2_rect *
-__imx219_get_pad_crop(struct imx219 *imx219,
-		      struct v4l2_subdev_state *sd_state,
-		      unsigned int pad, enum v4l2_subdev_format_whence which)
-{
-	switch (which) {
-	case V4L2_SUBDEV_FORMAT_TRY:
-		return v4l2_subdev_get_try_crop(&imx219->sd, sd_state, pad);
-	case V4L2_SUBDEV_FORMAT_ACTIVE:
-		return &imx219->mode->crop;
-	}
-
-	return NULL;
-}
-
   static int imx219_get_selection(struct v4l2_subdev *sd,
   				struct v4l2_subdev_state *sd_state,
   				struct v4l2_subdev_selection *sel)
   {
   	switch (sel->target) {
   	case V4L2_SEL_TGT_CROP: {
-		struct imx219 *imx219 = to_imx219(sd);
-
-		mutex_lock(&imx219->mutex);
-		sel->r = *__imx219_get_pad_crop(imx219, sd_state, sel->pad,
-						sel->which);
-		mutex_unlock(&imx219->mutex);
-
+		sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
   		return 0;
   	}
@@ -990,9 +903,11 @@ static int imx219_configure_lanes(struct imx219 *imx219)
   				IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE);
   };
-static int imx219_start_streaming(struct imx219 *imx219)
+static int imx219_start_streaming(struct imx219 *imx219,
+				  struct v4l2_subdev_state *state)
   {
   	struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
+	const struct v4l2_mbus_framefmt *format;
   	const struct imx219_reg_list *reg_list;
   	int ret;
@@ -1022,14 +937,15 @@ static int imx219_start_streaming(struct imx219 *imx219)
   		goto err_rpm_put;
   	}
-	ret = imx219_set_framefmt(imx219);
+	format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
+	ret = imx219_set_framefmt(imx219, format);
   	if (ret) {
   		dev_err(&client->dev, "%s failed to set frame format: %d\n",
   			__func__, ret);
   		goto err_rpm_put;
   	}
-	ret = imx219_set_binning(imx219);
+	ret = imx219_set_binning(imx219, format);
   	if (ret) {
   		dev_err(&client->dev, "%s failed to set binning: %d\n",
   			__func__, ret);
@@ -1078,35 +994,30 @@ static void imx219_stop_streaming(struct imx219 *imx219)
   static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
   {
   	struct imx219 *imx219 = to_imx219(sd);
+	struct v4l2_subdev_state *state;
   	int ret = 0;
-	mutex_lock(&imx219->mutex);
-	if (imx219->streaming == enable) {
-		mutex_unlock(&imx219->mutex);
-		return 0;
-	}
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	if (imx219->streaming == enable)
+		goto unlock;
   	if (enable) {
   		/*
   		 * Apply default & customized values
   		 * and then start streaming.
   		 */
-		ret = imx219_start_streaming(imx219);
+		ret = imx219_start_streaming(imx219, state);
   		if (ret)
-			goto err_unlock;
+			goto unlock;
   	} else {
   		imx219_stop_streaming(imx219);
   	}
   	imx219->streaming = enable;
-	mutex_unlock(&imx219->mutex);
-
-	return ret;
-
-err_unlock:
-	mutex_unlock(&imx219->mutex);
-
+unlock:
+	v4l2_subdev_unlock_state(state);
   	return ret;
   }
@@ -1171,10 +1082,13 @@ static int __maybe_unused imx219_resume(struct device *dev)
   {
   	struct v4l2_subdev *sd = dev_get_drvdata(dev);
   	struct imx219 *imx219 = to_imx219(sd);
+	struct v4l2_subdev_state *state;
   	int ret;
   	if (imx219->streaming) {
-		ret = imx219_start_streaming(imx219);
+		state = v4l2_subdev_lock_and_get_active_state(sd);
+		ret = imx219_start_streaming(imx219, state);
+		v4l2_subdev_unlock_state(state);
   		if (ret)
   			goto error;
   	}
@@ -1237,7 +1151,7 @@ static const struct v4l2_subdev_video_ops imx219_video_ops = {
   static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
   	.init_cfg = imx219_init_cfg,
   	.enum_mbus_code = imx219_enum_mbus_code,
-	.get_fmt = imx219_get_pad_format,
+	.get_fmt = v4l2_subdev_get_fmt,
   	.set_fmt = imx219_set_pad_format,
   	.get_selection = imx219_get_selection,
   	.enum_frame_size = imx219_enum_frame_size,
@@ -1270,9 +1184,6 @@ static int imx219_init_controls(struct imx219 *imx219)
   	if (ret)
   		return ret;
-	mutex_init(&imx219->mutex);
-	ctrl_hdlr->lock = &imx219->mutex;
-
   	/* By default, PIXEL_RATE is read only */
   	imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
   					       V4L2_CID_PIXEL_RATE,
@@ -1369,7 +1280,6 @@ static int imx219_init_controls(struct imx219 *imx219)
   error:
   	v4l2_ctrl_handler_free(ctrl_hdlr);
-	mutex_destroy(&imx219->mutex);
   	return ret;
   }
@@ -1377,7 +1287,6 @@ static int imx219_init_controls(struct imx219 *imx219)
   static void imx219_free_controls(struct imx219 *imx219)
   {
   	v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
-	mutex_destroy(&imx219->mutex);
   }
   static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
@@ -1514,19 +1423,23 @@ static int imx219_probe(struct i2c_client *client)
   	/* Initialize source pad */
   	imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
-	/* Initialize default format */
-	imx219_set_default_format(imx219);
-
   	ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
   	if (ret) {
   		dev_err(dev, "failed to init entity pads: %d\n", ret);
   		goto error_handler_free;
   	}
+	imx219->sd.state_lock = imx219->ctrl_handler.lock;
+	ret = v4l2_subdev_init_finalize(&imx219->sd);
+	if (ret < 0) {
+		dev_err(dev, "subdev init error: %d\n", ret);
maybe dev_err_probe ? other than that,
Is there anything that might cause a deferred probe in the
v4l2_subdev_init_finalize() call path ? I can only see a call to
the init_cfg() operation where one could potentially hit a deferred
probe, but this driver's implementation doesn't (and other shouldn't
anyway).

You are correct!  I don't see any op causing deffered probe too.
Sorry for the noise!
Reviewed-by: Umang Jain <umang.jain@xxxxxxxxxxxxxxxx>

+		goto error_media_entity;
+	}
+
   	ret = v4l2_async_register_subdev_sensor(&imx219->sd);
   	if (ret < 0) {
   		dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
-		goto error_media_entity;
+		goto error_subdev_cleanup;
   	}
   	/* Enable runtime PM and turn off the device */
@@ -1536,6 +1449,9 @@ static int imx219_probe(struct i2c_client *client)
   	return 0;
+error_subdev_cleanup:
+	v4l2_subdev_cleanup(&imx219->sd);
+
   error_media_entity:
   	media_entity_cleanup(&imx219->sd.entity);
@@ -1554,6 +1470,7 @@ static void imx219_remove(struct i2c_client *client)
   	struct imx219 *imx219 = to_imx219(sd);
   	v4l2_async_unregister_subdev(sd);
+	v4l2_subdev_cleanup(sd);
   	media_entity_cleanup(&sd->entity);
   	imx219_free_controls(imx219);




[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