Currently a subdevice without streams support (V4L2_SUBDEV_FL_STREAMS), e.g. a sensor subdevice with a single source pad, must use the v4l2_subdev_video_ops.s_stream op, instead of v4l2_subdev_pad_ops.enable/disable_streams. This is because the enable/disable_streams machinery requires a routing table which a subdev cannot have with a single pad. Implement enable/disable_streams support for subdevs without streams support. As they don't support multiple streams, each pad must contain a single stream, with stream ID 0, and rather than tracking enabled streams, we can track enabled pads similarly to the enable/disable_streams_fallback by using the sd->enabled_pads field. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxxxxxxxxx> --- drivers/media/v4l2-core/v4l2-subdev.c | 86 +++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index 91298bb84e6b..d86f930be2c4 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -2158,21 +2158,32 @@ int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, * Verify that the requested streams exist and that they are not * already enabled. */ - for (i = 0; i < state->stream_configs.num_configs; ++i) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; + if (sd->flags & V4L2_SUBDEV_FL_STREAMS) { + for (i = 0; i < state->stream_configs.num_configs; ++i) { + struct v4l2_subdev_stream_config *cfg = + &state->stream_configs.configs[i]; - if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream))) - continue; + if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream))) + continue; - found_streams |= BIT_ULL(cfg->stream); + found_streams |= BIT_ULL(cfg->stream); - if (cfg->enabled) { - dev_dbg(dev, "stream %u already enabled on %s:%u\n", - cfg->stream, sd->entity.name, pad); + if (cfg->enabled) { + dev_dbg(dev, "stream %u already enabled on %s:%u\n", + cfg->stream, sd->entity.name, pad); + ret = -EALREADY; + goto done; + } + } + } else { + if (sd->enabled_pads & BIT_ULL(pad)) { + dev_dbg(dev, "stream 0 already enabled on %s:%u\n", + sd->entity.name, pad); ret = -EALREADY; goto done; } + + found_streams = BIT_ULL(0); } if (found_streams != streams_mask) { @@ -2194,12 +2205,16 @@ int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad, } /* Mark the streams as enabled. */ - for (i = 0; i < state->stream_configs.num_configs; ++i) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; + if (sd->flags & V4L2_SUBDEV_FL_STREAMS) { + for (i = 0; i < state->stream_configs.num_configs; ++i) { + struct v4l2_subdev_stream_config *cfg = + &state->stream_configs.configs[i]; - if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream))) - cfg->enabled = true; + if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream))) + cfg->enabled = true; + } + } else { + sd->enabled_pads |= BIT_ULL(pad); } done: @@ -2281,21 +2296,32 @@ int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad, * Verify that the requested streams exist and that they are not * already disabled. */ - for (i = 0; i < state->stream_configs.num_configs; ++i) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; + if (sd->flags & V4L2_SUBDEV_FL_STREAMS) { + for (i = 0; i < state->stream_configs.num_configs; ++i) { + struct v4l2_subdev_stream_config *cfg = + &state->stream_configs.configs[i]; - if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream))) - continue; + if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream))) + continue; - found_streams |= BIT_ULL(cfg->stream); + found_streams |= BIT_ULL(cfg->stream); - if (!cfg->enabled) { - dev_dbg(dev, "stream %u already disabled on %s:%u\n", - cfg->stream, sd->entity.name, pad); + if (!cfg->enabled) { + dev_dbg(dev, "stream %u already disabled on %s:%u\n", + cfg->stream, sd->entity.name, pad); + ret = -EALREADY; + goto done; + } + } + } else { + if (!(sd->enabled_pads & BIT_ULL(pad))) { + dev_dbg(dev, "stream 0 already disabled on %s:%u\n", + sd->entity.name, pad); ret = -EALREADY; goto done; } + + found_streams = BIT_ULL(0); } if (found_streams != streams_mask) { @@ -2317,12 +2343,16 @@ int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad, } /* Mark the streams as disabled. */ - for (i = 0; i < state->stream_configs.num_configs; ++i) { - struct v4l2_subdev_stream_config *cfg = - &state->stream_configs.configs[i]; + if (sd->flags & V4L2_SUBDEV_FL_STREAMS) { + for (i = 0; i < state->stream_configs.num_configs; ++i) { + struct v4l2_subdev_stream_config *cfg = + &state->stream_configs.configs[i]; - if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream))) - cfg->enabled = false; + if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream))) + cfg->enabled = false; + } + } else { + sd->enabled_pads &= ~BIT_ULL(pad); } done: -- 2.34.1