[PATCH] adv7604: reports wrong colorspace when source is sending RGB

From: Hans Verkuil
Date: Thu Nov 10 2016 - 08:20:31 EST


If the HDMI source is transmitting RGB (as opposed to YUV), then the
colorspace was set to SMPTE170M or REC709 if the source used CE timings.

But that has nothing to do with the colorspace.

If the source sends RGB, then the colorspace is sRGB, otherwise it is one
of 170M or REC709, depending on the colorimetry setting.

Note that we ignore the extended colorimetry setting, that can be supported
in the future.

Signed-off-by: Hans Verkuil <hans.verkuil@xxxxxxxxx>
---
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index fa7046e..27ef9c4 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -1813,9 +1813,14 @@ static int adv76xx_enum_mbus_code(struct v4l2_subdev *sd,
return 0;
}

-static void adv76xx_fill_format(struct adv76xx_state *state,
+static void adv76xx_fill_format(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *format)
{
+ struct adv76xx_state *state = to_state(sd);
+ bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
+ u8 y = HDMI_COLORSPACE_RGB;
+ u8 c = HDMI_COLORIMETRY_NONE;
+
memset(format, 0, sizeof(*format));

format->width = state->timings.bt.width;
@@ -1823,7 +1828,23 @@ static void adv76xx_fill_format(struct adv76xx_state *state,
format->field = V4L2_FIELD_NONE;
format->colorspace = V4L2_COLORSPACE_SRGB;

- if (state->timings.bt.flags & V4L2_DV_FL_IS_CE_VIDEO)
+ if (hdmi_signal && (io_read(sd, 0x60) & 1)) {
+ y = infoframe_read(sd, 0x01) >> 5;
+ c = infoframe_read(sd, 0x02) >> 6;
+ }
+
+ if (y == HDMI_COLORSPACE_RGB)
+ return;
+
+ /*
+ * Note that this ignores the extended colorimetry settings.
+ * That's something for the future.
+ */
+ if (c == HDMI_COLORIMETRY_ITU_601)
+ format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else if (c == HDMI_COLORIMETRY_ITU_709)
+ format->colorspace = V4L2_COLORSPACE_REC709;
+ else
format->colorspace = (state->timings.bt.height <= 576) ?
V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
}
@@ -1888,7 +1909,7 @@ static int adv76xx_get_format(struct v4l2_subdev *sd,
if (format->pad != state->source_pad)
return -EINVAL;

- adv76xx_fill_format(state, &format->format);
+ adv76xx_fill_format(sd, &format->format);

if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *fmt;
@@ -1936,7 +1957,7 @@ static int adv76xx_set_format(struct v4l2_subdev *sd,
if (info == NULL)
info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);

- adv76xx_fill_format(state, &format->format);
+ adv76xx_fill_format(sd, &format->format);
format->format.code = info->code;

if (format->which == V4L2_SUBDEV_FORMAT_TRY) {