@@ -188,8 +188,11 @@ struct max9286_priv {
struct v4l2_async_notifier notifier;
};
+#define to_index(priv, source) ((source) - &(priv)->sources[0])
+
static struct max9286_source *next_source(struct max9286_priv *priv,
- struct max9286_source *source)
+ struct max9286_source *source,
+ bool routed)
{
if (!source)
source = &priv->sources[0];
@@ -197,17 +200,27 @@ static struct max9286_source *next_source(struct max9286_priv *priv,
source++;
for (; source < &priv->sources[MAX9286_NUM_GMSL]; source++) {
- if (source->fwnode)
+ unsigned int index = to_index(priv, source);
+
+ if (!source->fwnode)
+ continue;
+
+ /*
+ * Careful here! A very unfortunate call to set_routing() can
+ * change priv->route_mask behind our back!
+ */
+ if (!routed || priv->route_mask & BIT(index))
return source;
}
return NULL;
}
-#define for_each_source(priv, source) \
- for ((source) = NULL; ((source) = next_source((priv), (source))); )
+#define for_each_route(priv, source) \
+ for ((source) = NULL; ((source) = next_source((priv), (source), true)); )
-#define to_index(priv, source) ((source) - &(priv)->sources[0])
+#define for_each_source(priv, source) \
+ for ((source) = NULL; ((source) = next_source((priv), (source), false)); )
static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd)
{
@@ -409,7 +422,7 @@ static int max9286_check_video_links(struct max9286_priv *priv)
if (ret < 0)
return -EIO;
- if ((ret & MAX9286_VIDEO_DETECT_MASK) == priv->source_mask)
+ if ((ret & MAX9286_VIDEO_DETECT_MASK) == priv->route_mask)
break;
usleep_range(350, 500);
@@ -493,9 +506,10 @@ static int max9286_check_config_link(struct max9286_priv *priv,
static int max9286_set_pixelrate(struct max9286_priv *priv)
{
struct max9286_source *source = NULL;
+ unsigned int num_routes = 0;
u64 pixelrate = 0;
- for_each_source(priv, source) {
+ for_each_route(priv, source) {
struct v4l2_ctrl *ctrl;
u64 source_rate = 0;
@@ -516,6 +530,8 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
"Unable to calculate pixel rate\n");
return -EINVAL;
}
+
+ num_routes++;
}
if (!pixelrate) {
@@ -529,7 +545,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
* by the number of available sources.
*/
return v4l2_ctrl_s_ctrl_int64(priv->pixelrate,
- pixelrate * priv->nsources);
+ pixelrate * num_routes);
}
static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
@@ -691,8 +707,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
*/
max9286_i2c_mux_open(priv);
- /* Start all cameras. */
- for_each_source(priv, source) {
+ /* Start cameras. */
+ for_each_route(priv, source) {
ret = v4l2_subdev_call(source->sd, video, s_stream, 1);
if (ret)
return ret;
@@ -733,8 +749,8 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
} else {
max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV);
- /* Stop all cameras. */
- for_each_source(priv, source)
+ /* Stop cameras. */
+ for_each_route(priv, source)
v4l2_subdev_call(source->sd, video, s_stream, 0);
max9286_i2c_mux_close(priv);
@@ -912,6 +928,29 @@ static int max9286_set_routing(struct v4l2_subdev *sd,
v4l2_subdev_lock_state(state);
ret = _max9286_set_routing(sd, state, routing);
+ if (ret)
+ goto out;
+
+ if (which == V4L2_SUBDEV_FORMAT_TRY)
+ goto out;
+
+ /*
+ * Update the active routes mask and the pixel rate according to the
+ * routed sources.
+ */
+ priv->route_mask = 0;
+ for (i = 0; i < routing->num_routes; ++i) {
+ struct v4l2_subdev_route *route = &routing->routes[i];
+
+ if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+ continue;
+
+ priv->route_mask |= BIT(route->sink_pad);
+ }
+
+ max9286_set_pixelrate(priv);
+
+out:
v4l2_subdev_unlock_state(state);
return ret;
Now that the device supports routing, use the enabled routes instead of the connected sources to compute the output pixel rate. To do so, update the route_mask after a set_routing() call with the ACTIVE format, and re-calculate the pixel rate just after. At the same time, start and stop only the enabled routes at s_stream() time. Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org> --- drivers/media/i2c/max9286.c | 63 ++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-)