Re: [PULL] soc-camera and mediabus

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All,

>> 3) it would be interesting to patch the other sensor drivers to be compatible
>>    with soc_camera (mt9v011/ov7670);
> 
> Well, this could be done, yes, but does it make sense to do this blindly 
> without any hardware to test? I would rather add such conversions on a 
> one-by-one basis as need arises.
> 
I'm working on the ov7670. I've added the media bus stuff to what I've
previously posted but I haven't tested as yet.  For reference, a quick and dirty
cut of the patch is below.  Some thought is needed on how to deal with the sections
that currently need to be different for the soc-camera and non soc camera uses.
(mainly the registration code in probe).

On another note, does anyone have an objection to making the set_bus_param
function optional?   At the moment we are adding null functions for those
devices that can't actually change anything which seems a little pointless.

Jonathan


diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 0e2184e..e57c3b5 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -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@xxxxxxx>");
@@ -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)
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux