Commit 959f3bda authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB: ov7670: add enum/try/s_mbus_fmt support

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent d7709fff
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-i2c-drv.h> #include <media/v4l2-i2c-drv.h>
...@@ -572,11 +573,13 @@ static int ov7670_detect(struct v4l2_subdev *sd) ...@@ -572,11 +573,13 @@ static int ov7670_detect(struct v4l2_subdev *sd)
/* /*
* Store information about the video data format. The color matrix * Store information about the video data format. The color matrix
* is deeply tied into the format, so keep the relevant values here. * is deeply tied into the format, so keep the relevant values here.
* The magic matrix nubmers come from OmniVision. * The magic matrix numbers come from OmniVision.
*/ */
static struct ov7670_format_struct { static struct ov7670_format_struct {
__u8 *desc; __u8 *desc;
__u32 pixelformat; __u32 pixelformat;
enum v4l2_mbus_pixelcode mbus_code;
enum v4l2_colorspace colorspace;
struct regval_list *regs; struct regval_list *regs;
int cmatrix[CMATRIX_LEN]; int cmatrix[CMATRIX_LEN];
int bpp; /* Bytes per pixel */ int bpp; /* Bytes per pixel */
...@@ -584,6 +587,8 @@ static struct ov7670_format_struct { ...@@ -584,6 +587,8 @@ static struct ov7670_format_struct {
{ {
.desc = "YUYV 4:2:2", .desc = "YUYV 4:2:2",
.pixelformat = V4L2_PIX_FMT_YUYV, .pixelformat = V4L2_PIX_FMT_YUYV,
.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.regs = ov7670_fmt_yuv422, .regs = ov7670_fmt_yuv422,
.cmatrix = { 128, -128, 0, -34, -94, 128 }, .cmatrix = { 128, -128, 0, -34, -94, 128 },
.bpp = 2, .bpp = 2,
...@@ -591,6 +596,8 @@ static struct ov7670_format_struct { ...@@ -591,6 +596,8 @@ static struct ov7670_format_struct {
{ {
.desc = "RGB 444", .desc = "RGB 444",
.pixelformat = V4L2_PIX_FMT_RGB444, .pixelformat = V4L2_PIX_FMT_RGB444,
.mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_rgb444, .regs = ov7670_fmt_rgb444,
.cmatrix = { 179, -179, 0, -61, -176, 228 }, .cmatrix = { 179, -179, 0, -61, -176, 228 },
.bpp = 2, .bpp = 2,
...@@ -598,6 +605,8 @@ static struct ov7670_format_struct { ...@@ -598,6 +605,8 @@ static struct ov7670_format_struct {
{ {
.desc = "RGB 565", .desc = "RGB 565",
.pixelformat = V4L2_PIX_FMT_RGB565, .pixelformat = V4L2_PIX_FMT_RGB565,
.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_rgb565, .regs = ov7670_fmt_rgb565,
.cmatrix = { 179, -179, 0, -61, -176, 228 }, .cmatrix = { 179, -179, 0, -61, -176, 228 },
.bpp = 2, .bpp = 2,
...@@ -605,6 +614,8 @@ static struct ov7670_format_struct { ...@@ -605,6 +614,8 @@ static struct ov7670_format_struct {
{ {
.desc = "Raw RGB Bayer", .desc = "Raw RGB Bayer",
.pixelformat = V4L2_PIX_FMT_SBGGR8, .pixelformat = V4L2_PIX_FMT_SBGGR8,
.mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_raw, .regs = ov7670_fmt_raw,
.cmatrix = { 0, 0, 0, 0, 0, 0 }, .cmatrix = { 0, 0, 0, 0, 0, 0 },
.bpp = 1 .bpp = 1
...@@ -748,37 +759,45 @@ static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt) ...@@ -748,37 +759,45 @@ static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
return 0; return 0;
} }
static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
enum v4l2_mbus_pixelcode *code)
{
if (index >= N_OV7670_FMTS)
return -EINVAL;
*code = ov7670_formats[index].mbus_code;
return 0;
}
static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
struct v4l2_format *fmt, struct v4l2_mbus_framefmt *fmt,
struct ov7670_format_struct **ret_fmt, struct ov7670_format_struct **ret_fmt,
struct ov7670_win_size **ret_wsize) struct ov7670_win_size **ret_wsize)
{ {
int index; int index;
struct ov7670_win_size *wsize; struct ov7670_win_size *wsize;
struct v4l2_pix_format *pix = &fmt->fmt.pix;
for (index = 0; index < N_OV7670_FMTS; index++) for (index = 0; index < N_OV7670_FMTS; index++)
if (ov7670_formats[index].pixelformat == pix->pixelformat) if (ov7670_formats[index].mbus_code == fmt->code)
break; break;
if (index >= N_OV7670_FMTS) { if (index >= N_OV7670_FMTS) {
/* default to first format */ /* default to first format */
index = 0; index = 0;
pix->pixelformat = ov7670_formats[0].pixelformat; fmt->code = ov7670_formats[0].mbus_code;
} }
if (ret_fmt != NULL) if (ret_fmt != NULL)
*ret_fmt = ov7670_formats + index; *ret_fmt = ov7670_formats + index;
/* /*
* Fields: the OV devices claim to be progressive. * Fields: the OV devices claim to be progressive.
*/ */
pix->field = V4L2_FIELD_NONE; fmt->field = V4L2_FIELD_NONE;
/* /*
* Round requested image size down to the nearest * Round requested image size down to the nearest
* we support, but not below the smallest. * we support, but not below the smallest.
*/ */
for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES; for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
wsize++) wsize++)
if (pix->width >= wsize->width && pix->height >= wsize->height) if (fmt->width >= wsize->width && fmt->height >= wsize->height)
break; break;
if (wsize >= ov7670_win_sizes + N_WIN_SIZES) if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
wsize--; /* Take the smallest one */ wsize--; /* Take the smallest one */
...@@ -787,30 +806,54 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd, ...@@ -787,30 +806,54 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
/* /*
* Note the size we'll actually handle. * Note the size we'll actually handle.
*/ */
pix->width = wsize->width; fmt->width = wsize->width;
pix->height = wsize->height; fmt->height = wsize->height;
pix->bytesperline = pix->width*ov7670_formats[index].bpp; fmt->colorspace = ov7670_formats[index].colorspace;
pix->sizeimage = pix->height*pix->bytesperline;
return 0; return 0;
} }
static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt)
{ {
return ov7670_try_fmt_internal(sd, fmt, NULL, NULL); return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
} }
static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
struct v4l2_mbus_framefmt mbus_fmt;
struct v4l2_pix_format *pix = &fmt->fmt.pix;
unsigned index;
int ret;
for (index = 0; index < N_OV7670_FMTS; index++)
if (ov7670_formats[index].pixelformat == pix->pixelformat)
break;
if (index >= N_OV7670_FMTS) {
index = 0;
pix->pixelformat = ov7670_formats[index].pixelformat;
}
v4l2_fill_mbus_format(&mbus_fmt, pix, ov7670_formats[index].mbus_code);
ret = ov7670_try_fmt_internal(sd, &mbus_fmt, NULL, NULL);
v4l2_fill_pix_format(pix, &mbus_fmt);
pix->bytesperline = pix->width * ov7670_formats[index].bpp;
pix->sizeimage = pix->height * pix->bytesperline;
return ret;
}
/* /*
* Set a format. * Set a format.
*/ */
static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *fmt)
{ {
int ret;
struct ov7670_format_struct *ovfmt; struct ov7670_format_struct *ovfmt;
struct ov7670_win_size *wsize; struct ov7670_win_size *wsize;
struct ov7670_info *info = to_state(sd); struct ov7670_info *info = to_state(sd);
unsigned char com7; unsigned char com7;
int ret;
ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
if (ret) if (ret)
return ret; return ret;
/* /*
...@@ -845,6 +888,26 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) ...@@ -845,6 +888,26 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
*/ */
if (ret == 0) if (ret == 0)
ret = ov7670_write(sd, REG_CLKRC, info->clkrc); ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
return 0;
}
static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
struct v4l2_mbus_framefmt mbus_fmt;
struct v4l2_pix_format *pix = &fmt->fmt.pix;
unsigned index;
int ret;
for (index = 0; index < N_OV7670_FMTS; index++)
if (ov7670_formats[index].pixelformat == pix->pixelformat)
break;
if (index >= N_OV7670_FMTS) {
index = 0;
pix->pixelformat = ov7670_formats[index].pixelformat;
}
v4l2_fill_mbus_format(&mbus_fmt, pix, ov7670_formats[index].mbus_code);
ret = ov7670_s_mbus_fmt(sd, &mbus_fmt);
v4l2_fill_pix_format(pix, &mbus_fmt);
return ret; return ret;
} }
...@@ -1445,6 +1508,9 @@ static const struct v4l2_subdev_video_ops ov7670_video_ops = { ...@@ -1445,6 +1508,9 @@ static const struct v4l2_subdev_video_ops ov7670_video_ops = {
.enum_fmt = ov7670_enum_fmt, .enum_fmt = ov7670_enum_fmt,
.try_fmt = ov7670_try_fmt, .try_fmt = ov7670_try_fmt,
.s_fmt = ov7670_s_fmt, .s_fmt = ov7670_s_fmt,
.enum_mbus_fmt = ov7670_enum_mbus_fmt,
.try_mbus_fmt = ov7670_try_mbus_fmt,
.s_mbus_fmt = ov7670_s_mbus_fmt,
.s_parm = ov7670_s_parm, .s_parm = ov7670_s_parm,
.g_parm = ov7670_g_parm, .g_parm = ov7670_g_parm,
}; };
......
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