@@ -18,6 +18,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv.h>
+#include <media/soc_camera.h>
MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
@@ -545,7 +546,7 @@ static struct ov7670_format_struct {
.bpp = 1
},
};
-#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats)
+
/*
@@ -668,52 +669,37 @@ static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
return ret;
}
+static enum v4l2_mbus_pixelcode ov7670_codes[] = {
+ V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_RGB565_2X8_LE,
+};
-static int ov7670_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+static int ov7670_enum_fmt(struct v4l2_subdev *sd, int index, enum v4l2_mbus_pixelcode *code)
{
- struct ov7670_format_struct *ofmt;
-
- if (fmt->index >= N_OV7670_FMTS)
+ if (index >= ARRAY_SIZE(ov7670_codes))
return -EINVAL;
- ofmt = ov7670_formats + fmt->index;
- fmt->flags = 0;
- strcpy(fmt->description, ofmt->desc);
- fmt->pixelformat = ofmt->pixelformat;
+ *code = ov7670_codes[index];
return 0;
}
static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
- struct v4l2_format *fmt,
- struct ov7670_format_struct **ret_fmt,
- struct ov7670_win_size **ret_wsize)
+ struct v4l2_mbus_framefmt *mf,
+ struct ov7670_format_struct **ret_fmt,
+ struct ov7670_win_size **ret_wsize)
{
int index;
struct ov7670_win_size *wsize;
- struct v4l2_pix_format *pix = &fmt->fmt.pix;
- for (index = 0; index < N_OV7670_FMTS; index++)
- if (ov7670_formats[index].pixelformat == pix->pixelformat)
- break;
- if (index >= N_OV7670_FMTS) {
- /* default to first format */
- index = 0;
- pix->pixelformat = ov7670_formats[0].pixelformat;
- }
- if (ret_fmt != NULL)
- *ret_fmt = ov7670_formats + index;
- /*
- * Fields: the OV devices claim to be progressive.
- */
- pix->field = V4L2_FIELD_NONE;
+ mf->field = V4L2_FIELD_NONE;
/*
* Round requested image size down to the nearest
* we support, but not below the smallest.
*/
for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
wsize++)
- if (pix->width >= wsize->width && pix->height >= wsize->height)
+ if ( mf->width >= wsize->width && mf->height >= wsize->height)
break;
if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
wsize--; /* Take the smallest one */
@@ -722,22 +708,34 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
/*
* Note the size we'll actually handle.
*/
- pix->width = wsize->width;
- pix->height = wsize->height;
- pix->bytesperline = pix->width*ov7670_formats[index].bpp;
- pix->sizeimage = pix->height*pix->bytesperline;
+ mf->width = wsize->width;
+ mf->height = wsize->height;
+ switch (mf->code) {
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+ if (ret_fmt != NULL)
+ *ret_fmt = ov7670_formats + 2;
+ break;
+ default:
+ mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ mf->colorspace = V4L2_COLORSPACE_JPEG;
+ if (ret_fmt != NULL)
+ *ret_fmt = ov7670_formats;
+ break;
+ }
return 0;
}
-static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int ov7670_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
{
- return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
+ return ov7670_try_fmt_internal(sd, mf, NULL, NULL);
}
/*
* Set a format.
*/
-static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
{
int ret;
struct ov7670_format_struct *ovfmt;
@@ -745,7 +743,11 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
struct ov7670_info *info = to_state(sd);
unsigned char com7, clkrc = 0;
- ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
+ ret = ov7670_init(sd, 0);
+ if (ret)
+ return ret;
+
+ ret = ov7670_try_fmt_internal(sd, mf, &ovfmt, &wsize);
if (ret)
return ret;
/*
@@ -753,7 +755,7 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
* CLKRC. If we're *not*, however, then rewriting clkrc hoses
* the colors.
*/
- if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
+ if (mf->code == V4L2_MBUS_FMT_RGB565_2X8_LE) {
ret = ov7670_read(sd, REG_CLKRC, &clkrc);
if (ret)
return ret;
@@ -778,7 +780,7 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
ret = ov7670_write_array(sd, wsize->regs);
info->fmt = ovfmt;
- if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0)
+ if (mf->code == V4L2_MBUS_FMT_RGB565_2X8_LE && ret == 0)
ret = ov7670_write(sd, REG_CLKRC, clkrc);
return ret;
}
@@ -1226,11 +1228,11 @@ static const struct v4l2_subdev_core_ops ov7670_core_ops = {
};
static const struct v4l2_subdev_video_ops ov7670_video_ops = {
- .enum_fmt = ov7670_enum_fmt,
- .try_fmt = ov7670_try_fmt,
- .s_fmt = ov7670_s_fmt,
.s_parm = ov7670_s_parm,
.g_parm = ov7670_g_parm,
+ .s_mbus_fmt = ov7670_s_fmt,
+ .try_mbus_fmt = ov7670_try_fmt,
+ .enum_mbus_fmt = ov7670_enum_fmt,
};
static const struct v4l2_subdev_ops ov7670_ops = {
@@ -1239,6 +1241,28 @@ static const struct v4l2_subdev_ops ov7670_ops = {
};
/* ----------------------------------------------------------------------- */
+static unsigned long ov7670_soc_query_bus_param(struct soc_camera_device *icd)
+{
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+
+ unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
+ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
+ SOCAM_DATAWIDTH_8 | SOCAM_DATA_ACTIVE_HIGH;
+
+ return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+/* This device only supports one bus option */
+static int ov7670_soc_set_bus_param(struct soc_camera_device *icd,
+ unsigned long flags)
+{
+ return 0;
+}
+
+static struct soc_camera_ops ov7670_soc_ops = {
+ .set_bus_param = ov7670_soc_set_bus_param,
+ .query_bus_param = ov7670_soc_query_bus_param,
+};
static int ov7670_probe(struct i2c_client *client,
const struct i2c_device_id *id)
@@ -1246,6 +1270,12 @@ static int ov7670_probe(struct i2c_client *client,
struct v4l2_subdev *sd;
struct ov7670_info *info;
int ret;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ if (!icd) {
+ dev_err(&client->dev, "OV7670: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+ icd->ops = &ov7670_soc_ops;
info = kzalloc(sizeof(struct ov7670_info), GFP_KERNEL);
if (info == NULL)