Commit f1403802 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

media: i2c: max9286: Support 12-bit raw bayer formats

Add support for 12-bit raw bayer formats to the driver, configuring the
GMSL format accordingly.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: default avatarJacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent b904512b
...@@ -136,6 +136,11 @@ ...@@ -136,6 +136,11 @@
#define MAX9286_N_PADS 5 #define MAX9286_N_PADS 5
#define MAX9286_SRC_PAD 4 #define MAX9286_SRC_PAD 4
struct max9286_format_info {
u32 code;
u8 datatype;
};
struct max9286_source { struct max9286_source {
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
...@@ -218,6 +223,34 @@ static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd) ...@@ -218,6 +223,34 @@ static inline struct max9286_priv *sd_to_max9286(struct v4l2_subdev *sd)
return container_of(sd, struct max9286_priv, sd); return container_of(sd, struct max9286_priv, sd);
} }
static const struct max9286_format_info max9286_formats[] = {
{
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.datatype = MAX9286_DATATYPE_YUV422_8BIT,
}, {
.code = MEDIA_BUS_FMT_VYUY8_1X16,
.datatype = MAX9286_DATATYPE_YUV422_8BIT,
}, {
.code = MEDIA_BUS_FMT_YUYV8_1X16,
.datatype = MAX9286_DATATYPE_YUV422_8BIT,
}, {
.code = MEDIA_BUS_FMT_YVYU8_1X16,
.datatype = MAX9286_DATATYPE_YUV422_8BIT,
}, {
.code = MEDIA_BUS_FMT_SBGGR12_1X12,
.datatype = MAX9286_DATATYPE_RAW12,
}, {
.code = MEDIA_BUS_FMT_SGBRG12_1X12,
.datatype = MAX9286_DATATYPE_RAW12,
}, {
.code = MEDIA_BUS_FMT_SGRBG12_1X12,
.datatype = MAX9286_DATATYPE_RAW12,
}, {
.code = MEDIA_BUS_FMT_SRGGB12_1X12,
.datatype = MAX9286_DATATYPE_RAW12,
},
};
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* I2C IO * I2C IO
*/ */
...@@ -479,6 +512,38 @@ static int max9286_check_config_link(struct max9286_priv *priv, ...@@ -479,6 +512,38 @@ static int max9286_check_config_link(struct max9286_priv *priv,
return 0; return 0;
} }
static void max9286_set_video_format(struct max9286_priv *priv,
const struct v4l2_mbus_framefmt *format)
{
const struct max9286_format_info *info = NULL;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(max9286_formats); ++i) {
if (max9286_formats[i].code == format->code) {
info = &max9286_formats[i];
break;
}
}
if (WARN_ON(!info))
return;
/*
* Video format setup:
* Disable CSI output, VC is set according to Link number.
*/
max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV);
/* Enable CSI-2 Lane D0-D3 only, DBL mode. */
max9286_write(priv, 0x12, MAX9286_CSIDBL | MAX9286_DBL |
MAX9286_CSILANECNT(priv->csi2_data_lanes) |
info->datatype);
/* Enable HS/VS encoding, use D14/15 for HS/VS, invert VS. */
max9286_write(priv, 0x0c, MAX9286_HVEN | MAX9286_INVVS |
MAX9286_HVSRC_D14);
}
static void max9286_set_fsync_period(struct max9286_priv *priv) static void max9286_set_fsync_period(struct max9286_priv *priv)
{ {
u32 fsync; u32 fsync;
...@@ -697,6 +762,15 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable) ...@@ -697,6 +762,15 @@ static int max9286_s_stream(struct v4l2_subdev *sd, int enable)
int ret; int ret;
if (enable) { if (enable) {
const struct v4l2_mbus_framefmt *format;
/*
* Get the format from the first used sink pad, as all sink
* formats must be identical.
*/
format = &priv->fmt[__ffs(priv->bound_sources)];
max9286_set_video_format(priv, format);
max9286_set_fsync_period(priv); max9286_set_fsync_period(priv);
/* /*
...@@ -817,22 +891,20 @@ static int max9286_set_fmt(struct v4l2_subdev *sd, ...@@ -817,22 +891,20 @@ static int max9286_set_fmt(struct v4l2_subdev *sd,
{ {
struct max9286_priv *priv = sd_to_max9286(sd); struct max9286_priv *priv = sd_to_max9286(sd);
struct v4l2_mbus_framefmt *cfg_fmt; struct v4l2_mbus_framefmt *cfg_fmt;
unsigned int i;
if (format->pad == MAX9286_SRC_PAD) if (format->pad == MAX9286_SRC_PAD)
return -EINVAL; return -EINVAL;
/* Refuse non YUV422 formats as we hardcode DT to 8 bit YUV422 */ /* Validate the format. */
switch (format->format.code) { for (i = 0; i < ARRAY_SIZE(max9286_formats); ++i) {
case MEDIA_BUS_FMT_UYVY8_1X16: if (max9286_formats[i].code == format->format.code)
case MEDIA_BUS_FMT_VYUY8_1X16: break;
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YVYU8_1X16:
break;
default:
format->format.code = MEDIA_BUS_FMT_UYVY8_1X16;
break;
} }
if (i == ARRAY_SIZE(max9286_formats))
format->format.code = max9286_formats[0].code;
cfg_fmt = max9286_get_pad_format(priv, sd_state, format->pad, cfg_fmt = max9286_get_pad_format(priv, sd_state, format->pad,
format->which); format->which);
if (!cfg_fmt) if (!cfg_fmt)
...@@ -890,16 +962,20 @@ static const struct v4l2_subdev_ops max9286_subdev_ops = { ...@@ -890,16 +962,20 @@ static const struct v4l2_subdev_ops max9286_subdev_ops = {
.pad = &max9286_pad_ops, .pad = &max9286_pad_ops,
}; };
static const struct v4l2_mbus_framefmt max9286_default_format = {
.width = 1280,
.height = 800,
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.colorspace = V4L2_COLORSPACE_SRGB,
.field = V4L2_FIELD_NONE,
.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT,
.quantization = V4L2_QUANTIZATION_DEFAULT,
.xfer_func = V4L2_XFER_FUNC_DEFAULT,
};
static void max9286_init_format(struct v4l2_mbus_framefmt *fmt) static void max9286_init_format(struct v4l2_mbus_framefmt *fmt)
{ {
fmt->width = 1280; *fmt = max9286_default_format;
fmt->height = 800;
fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->field = V4L2_FIELD_NONE;
fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
} }
static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) static int max9286_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
...@@ -1063,23 +1139,9 @@ static int max9286_setup(struct max9286_priv *priv) ...@@ -1063,23 +1139,9 @@ static int max9286_setup(struct max9286_priv *priv)
max9286_write(priv, 0x0b, link_order[priv->route_mask]); max9286_write(priv, 0x0b, link_order[priv->route_mask]);
max9286_write(priv, 0x69, (0xf & ~priv->route_mask)); max9286_write(priv, 0x69, (0xf & ~priv->route_mask));
/* max9286_set_video_format(priv, &max9286_default_format);
* Video format setup:
* Disable CSI output, VC is set according to Link number.
*/
max9286_write(priv, 0x15, MAX9286_VCTYPE | MAX9286_0X15_RESV);
/* Enable CSI-2 Lane D0-D3 only, DBL mode, YUV422 8-bit. */
max9286_write(priv, 0x12, MAX9286_CSIDBL | MAX9286_DBL |
MAX9286_CSILANECNT(priv->csi2_data_lanes) |
MAX9286_DATATYPE_YUV422_8BIT);
max9286_set_fsync_period(priv); max9286_set_fsync_period(priv);
/* Enable HS/VS encoding, use D14/15 for HS/VS, invert VS. */
max9286_write(priv, 0x0c, MAX9286_HVEN | MAX9286_INVVS |
MAX9286_HVSRC_D14);
/* /*
* The overlap window seems to provide additional validation by tracking * The overlap window seems to provide additional validation by tracking
* the delay between vsync and frame sync, generating an error if the * the delay between vsync and frame sync, generating an error if the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment