Skip to content

Commit

Permalink
media: i2c: max9286: Use get_mbus_config for vsync config
Browse files Browse the repository at this point in the history
Instead of hard-coding the vsync inversion setting, get_mbus_config()
allows to set it based on connected sources. This patch inverts
the vsync polarity if all are active low. If polarities are different
between sources, it's an error.

Signed-off-by: Hyun Kwon <hyun.kwon@xilinx.com>
  • Loading branch information
xlnx-hyunkwon committed Mar 26, 2020
1 parent 3f31f1f commit a1d812c
Showing 1 changed file with 62 additions and 4 deletions.
66 changes: 62 additions & 4 deletions drivers/media/i2c/max9286.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit a1d812c

Please sign in to comment.