diff --git a/drivers/media/i2c/max9286.c b/drivers/media/i2c/max9286.c index 070992509028a..4501a007908f6 100644 --- a/drivers/media/i2c/max9286.c +++ b/drivers/media/i2c/max9286.c @@ -556,6 +556,64 @@ static void max9286_v4l2_notifier_unregister(struct max9286_priv *priv) v4l2_async_notifier_cleanup(&priv->notifier); } +static int max9286_check_source(struct max9286_priv *priv) +{ + struct max9286_source *source; + unsigned int vsync_active = 0; + u8 val = MAX9286_HVEN | MAX9286_HVSRC_D14; + int ret; + + for_each_source(priv, source) { + struct v4l2_mbus_pad_config mbus_config = { 0 }; + unsigned int index = to_index(priv, source); + + ret = v4l2_subdev_call(source->sd, pad, get_mbus_config, + source->pad, &mbus_config); + if (ret) { + if (ret != -ENOIOCTLCMD) { + dev_err(&priv->client->dev, + "failed to get remote mbus config\n"); + return ret; + } + + dev_info(&priv->client->dev, + "No remote mbus configuration available\n"); + /* Assume it's active high, comaptible to GMSL */ + vsync_active |= BIT(index); + + continue; + } + + if (mbus_config.type != V4L2_MBUS_GMSL) { + dev_err(&priv->client->dev, + "invalid mbus type %u\n", mbus_config.type); + return -EINVAL; + } + + if (mbus_config.gmsl.vsync_active) + vsync_active |= BIT(index); + } + + if (!vsync_active) { + val |= MAX9286_INVVS; + } else if (!(vsync_active == priv->source_mask)) { + dev_err(&priv->client->dev, + "sources have different vsync polarities %4x\n", + vsync_active); + return -EINVAL; + } + + max9286_write(priv, 0x0c, val); + + /* + * Wait for 2ms to allow the link to resynchronize after the + * configuration change. + */ + usleep_range(2000, 5000); + + return 0; +} + static int max9286_s_stream(struct v4l2_subdev *sd, int enable) { struct max9286_priv *priv = sd_to_max9286(sd); @@ -565,6 +623,10 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) int ret; if (enable) { + ret = max9286_check_source(priv); + if (ret) + return ret; + /* * The frame sync between cameras is transmitted across the * reverse channel as GPIO. We must open all channels while @@ -895,10 +957,6 @@ static int max9286_setup(struct max9286_priv *priv) max9286_write(priv, 0x01, MAX9286_FSYNCMODE_INT_HIZ | MAX9286_FSYNCMETH_AUTO); - /* Enable HS/VS encoding, use D14/15 for HS/VS, invert VS. */ - max9286_write(priv, 0x0c, MAX9286_HVEN | MAX9286_INVVS | - MAX9286_HVSRC_D14); - /* * Wait for 2ms to allow the link to resynchronize after the * configuration change.