Commit e3ee691d authored by Hugues Fruchet's avatar Hugues Fruchet Committed by Mauro Carvalho Chehab

media: ov5640: add support of RGB565 and YUYV formats

Add RGB565 (LE & BE) and YUV422 YUYV format in addition
to existing YUV422 UYVY format.
Signed-off-by: default avatarHugues Fruchet <hugues.fruchet@st.com>
Signed-off-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent f22996db
...@@ -76,9 +76,11 @@ ...@@ -76,9 +76,11 @@
#define OV5640_REG_HZ5060_CTRL01 0x3c01 #define OV5640_REG_HZ5060_CTRL01 0x3c01
#define OV5640_REG_SIGMADELTA_CTRL0C 0x3c0c #define OV5640_REG_SIGMADELTA_CTRL0C 0x3c0c
#define OV5640_REG_FRAME_CTRL01 0x4202 #define OV5640_REG_FRAME_CTRL01 0x4202
#define OV5640_REG_FORMAT_CONTROL00 0x4300
#define OV5640_REG_POLARITY_CTRL00 0x4740 #define OV5640_REG_POLARITY_CTRL00 0x4740
#define OV5640_REG_MIPI_CTRL00 0x4800 #define OV5640_REG_MIPI_CTRL00 0x4800
#define OV5640_REG_DEBUG_MODE 0x4814 #define OV5640_REG_DEBUG_MODE 0x4814
#define OV5640_REG_ISP_FORMAT_MUX_CTRL 0x501f
#define OV5640_REG_PRE_ISP_TEST_SET1 0x503d #define OV5640_REG_PRE_ISP_TEST_SET1 0x503d
#define OV5640_REG_SDE_CTRL0 0x5580 #define OV5640_REG_SDE_CTRL0 0x5580
#define OV5640_REG_SDE_CTRL1 0x5581 #define OV5640_REG_SDE_CTRL1 0x5581
...@@ -106,6 +108,18 @@ enum ov5640_frame_rate { ...@@ -106,6 +108,18 @@ enum ov5640_frame_rate {
OV5640_NUM_FRAMERATES, OV5640_NUM_FRAMERATES,
}; };
struct ov5640_pixfmt {
u32 code;
u32 colorspace;
};
static const struct ov5640_pixfmt ov5640_formats[] = {
{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
};
/* /*
* FIXME: remove this when a subdev API becomes available * FIXME: remove this when a subdev API becomes available
* to set the MIPI CSI-2 virtual channel. * to set the MIPI CSI-2 virtual channel.
...@@ -1837,17 +1851,23 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd, ...@@ -1837,17 +1851,23 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
{ {
struct ov5640_dev *sensor = to_ov5640_dev(sd); struct ov5640_dev *sensor = to_ov5640_dev(sd);
const struct ov5640_mode_info *mode; const struct ov5640_mode_info *mode;
int i;
mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true); mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
if (!mode) if (!mode)
return -EINVAL; return -EINVAL;
fmt->width = mode->width; fmt->width = mode->width;
fmt->height = mode->height; fmt->height = mode->height;
fmt->code = sensor->fmt.code;
if (new_mode) if (new_mode)
*new_mode = mode; *new_mode = mode;
for (i = 0; i < ARRAY_SIZE(ov5640_formats); i++)
if (ov5640_formats[i].code == fmt->code)
break;
if (i >= ARRAY_SIZE(ov5640_formats))
fmt->code = ov5640_formats[0].code;
return 0; return 0;
} }
...@@ -1890,6 +1910,45 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd, ...@@ -1890,6 +1910,45 @@ static int ov5640_set_fmt(struct v4l2_subdev *sd,
return ret; return ret;
} }
static int ov5640_set_framefmt(struct ov5640_dev *sensor,
struct v4l2_mbus_framefmt *format)
{
int ret = 0;
bool is_rgb = false;
u8 val;
switch (format->code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
/* YUV422, UYVY */
val = 0x3f;
break;
case MEDIA_BUS_FMT_YUYV8_2X8:
/* YUV422, YUYV */
val = 0x30;
break;
case MEDIA_BUS_FMT_RGB565_2X8_LE:
/* RGB565 {g[2:0],b[4:0]},{r[4:0],g[5:3]} */
val = 0x6F;
is_rgb = true;
break;
case MEDIA_BUS_FMT_RGB565_2X8_BE:
/* RGB565 {r[4:0],g[5:3]},{g[2:0],b[4:0]} */
val = 0x61;
is_rgb = true;
break;
default:
return -EINVAL;
}
/* FORMAT CONTROL00: YUV and RGB formatting */
ret = ov5640_write_reg(sensor, OV5640_REG_FORMAT_CONTROL00, val);
if (ret)
return ret;
/* FORMAT MUX CONTROL: ISP YUV or RGB */
return ov5640_write_reg(sensor, OV5640_REG_ISP_FORMAT_MUX_CTRL,
is_rgb ? 0x01 : 0x00);
}
/* /*
* Sensor Controls. * Sensor Controls.
...@@ -2275,15 +2334,12 @@ static int ov5640_enum_mbus_code(struct v4l2_subdev *sd, ...@@ -2275,15 +2334,12 @@ static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_mbus_code_enum *code) struct v4l2_subdev_mbus_code_enum *code)
{ {
struct ov5640_dev *sensor = to_ov5640_dev(sd);
if (code->pad != 0) if (code->pad != 0)
return -EINVAL; return -EINVAL;
if (code->index != 0) if (code->index >= ARRAY_SIZE(ov5640_formats))
return -EINVAL; return -EINVAL;
code->code = sensor->fmt.code; code->code = ov5640_formats[code->index].code;
return 0; return 0;
} }
...@@ -2299,6 +2355,10 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable) ...@@ -2299,6 +2355,10 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
ret = ov5640_set_mode(sensor, sensor->current_mode); ret = ov5640_set_mode(sensor, sensor->current_mode);
if (ret) if (ret)
goto out; goto out;
ret = ov5640_set_framefmt(sensor, &sensor->fmt);
if (ret)
goto out;
} }
if (sensor->ep.bus_type == V4L2_MBUS_CSI2) if (sensor->ep.bus_type == V4L2_MBUS_CSI2)
......
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