Hi Sakari, Thank you for the patch. On Tue, Apr 16, 2024 at 10:32:54PM +0300, Sakari Ailus wrote: > Switch from s_stream() video op to enable_streams() and disable_streams() > pad operations. They are preferred and required for streams support. > > Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > --- > drivers/media/i2c/ccs/ccs-core.c | 83 ++++++++++++++------------------ > 1 file changed, 36 insertions(+), 47 deletions(-) > > diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c > index d14e90f8568a..aaa6bf8495e1 100644 > --- a/drivers/media/i2c/ccs/ccs-core.c > +++ b/drivers/media/i2c/ccs/ccs-core.c > @@ -1715,7 +1715,7 @@ static int ccs_power_off(struct device *dev) > } > > /* ----------------------------------------------------------------------------- > - * Video stream management > + * V4L2 subdev video operations > */ > > static int ccs_pm_get_init(struct ccs_sensor *sensor) > @@ -1739,11 +1739,11 @@ static int ccs_pm_get_init(struct ccs_sensor *sensor) > sensor->handler_setup_needed = false; > > /* Restore V4L2 controls to the previously suspended device */ > - rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler); > + rval = __v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler); > if (rval) > goto error; > > - rval = v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); > + rval = __v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler); > if (rval) > goto error; > > @@ -1755,13 +1755,21 @@ static int ccs_pm_get_init(struct ccs_sensor *sensor) > return rval; > } > > -static int ccs_start_streaming(struct ccs_sensor *sensor) > +static int ccs_enable_streams(struct v4l2_subdev *subdev, > + struct v4l2_subdev_state *state, u32 pad, > + u64 streams_mask) > { > + struct ccs_sensor *sensor = to_ccs_sensor(subdev); > struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); > unsigned int binning_mode; > int rval; > > - mutex_lock(&sensor->mutex); > + if (pad != CCS_PAD_SRC) > + return -EINVAL; > + > + rval = ccs_pm_get_init(sensor); > + if (rval) > + return rval; > > rval = ccs_write(sensor, CSI_DATA_FORMAT, > (sensor->csi_format->width << 8) | > @@ -1880,64 +1888,41 @@ static int ccs_start_streaming(struct ccs_sensor *sensor) > > rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_STREAMING); > > -err_pm_put: > - mutex_unlock(&sensor->mutex); > - > - return rval; > -} > - > -static int ccs_stop_streaming(struct ccs_sensor *sensor) > -{ > - struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); > - int rval; > + sensor->streaming = true; > > - mutex_lock(&sensor->mutex); > - rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_SOFTWARE_STANDBY); > - if (rval) > - goto out; > + return 0; > > - rval = ccs_call_quirk(sensor, post_streamoff); > - if (rval) > - dev_err(&client->dev, "post_streamoff quirks failed\n"); > +err_pm_put: > + pm_runtime_mark_last_busy(&client->dev); > + pm_runtime_put_autosuspend(&client->dev); > > -out: > - mutex_unlock(&sensor->mutex); > return rval; > } > > -/* ----------------------------------------------------------------------------- > - * V4L2 subdev video operations > - */ > - > -static int ccs_set_stream(struct v4l2_subdev *subdev, int enable) > +static int ccs_disable_streams(struct v4l2_subdev *subdev, > + struct v4l2_subdev_state *state, u32 pad, > + u64 streams_mask) > { > struct ccs_sensor *sensor = to_ccs_sensor(subdev); > struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd); > int rval; > > - if (!enable) { > - ccs_stop_streaming(sensor); > - sensor->streaming = false; > - pm_runtime_mark_last_busy(&client->dev); > - pm_runtime_put_autosuspend(&client->dev); > - > - return 0; > - } > + if (pad != CCS_PAD_SRC) > + return -EINVAL; > > - rval = ccs_pm_get_init(sensor); > + rval = ccs_write(sensor, MODE_SELECT, CCS_MODE_SELECT_SOFTWARE_STANDBY); > if (rval) > return rval; > > - sensor->streaming = true; > + rval = ccs_call_quirk(sensor, post_streamoff); > + if (rval) > + dev_err(&client->dev, "post_streamoff quirks failed\n"); > > - rval = ccs_start_streaming(sensor); > - if (rval < 0) { > - sensor->streaming = false; > - pm_runtime_mark_last_busy(&client->dev); > - pm_runtime_put_autosuspend(&client->dev); > - } > + sensor->streaming = false; > + pm_runtime_mark_last_busy(&client->dev); > + pm_runtime_put_autosuspend(&client->dev); > > - return rval; > + return 0; > } > > static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags) > @@ -1963,7 +1948,9 @@ static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags) > } > } > > + mutex_lock(&sensor->mutex); > rval = ccs_pm_get_init(sensor); > + mutex_unlock(&sensor->mutex); > if (rval) > return rval; > > @@ -3047,7 +3034,7 @@ static int ccs_init_state(struct v4l2_subdev *sd, > } > > static const struct v4l2_subdev_video_ops ccs_video_ops = { > - .s_stream = ccs_set_stream, > + .s_stream = v4l2_subdev_s_stream_helper, > .pre_streamon = ccs_pre_streamon, > .post_streamoff = ccs_post_streamoff, > }; > @@ -3058,6 +3045,8 @@ static const struct v4l2_subdev_pad_ops ccs_pad_ops = { > .set_fmt = ccs_set_format, > .get_selection = ccs_get_selection, > .set_selection = ccs_set_selection, > + .enable_streams = ccs_enable_streams, > + .disable_streams = ccs_disable_streams, > }; > > static const struct v4l2_subdev_sensor_ops ccs_sensor_ops = { -- Regards, Laurent Pinchart