commit: http://blackfin.uclinux.org/git/?p=linux-kernel;a=commitdiff;h=412fdfb9a38c1790a9000917448988baae22d5e7
branch: http://blackfin.uclinux.org/git/?p=linux-kernel;a=shortlog;h=refs/heads/trunk

add formats table to store sensor supported formats

Signed-off-by: Scott Jiang <[email protected]>
---
 drivers/media/video/blackfin/bfin_capture.c |  148 ++++++++++++++-------------
 include/media/v4l2-subdev.h                 |    1 +
 2 files changed, 78 insertions(+), 71 deletions(-)

diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c
index 144d38a..d296355 100644
--- a/drivers/media/video/blackfin/bfin_capture.c
+++ b/drivers/media/video/blackfin/bfin_capture.c
@@ -77,6 +77,10 @@ struct bcap_device {
 	struct v4l2_pix_format fmt;
 	/* bits per pixel*/
 	int bpp;
+	/* used to store sensor supported format */
+	struct bcap_format *sensor_formats;
+	/* number of sensor formats array */
+	int num_sensor_formats;
 	/* pointing to current video buffer */
 	struct bcap_buffer *cur_frm;
 	/* pointing to next video buffer */
@@ -141,45 +145,59 @@ static struct bcap_buffer *to_bcap_vb(struct vb2_buffer *vb)
 	return container_of(vb, struct bcap_buffer, vb);
 }
 
+static int bcap_init_sensor_formats(struct bcap_device *bcap_dev)
+{
+	enum v4l2_mbus_pixelcode code;
+	struct bcap_format *sf;
+	unsigned int num_formats = 0;
+	int i, j;
+
+	while (!v4l2_subdev_call(bcap_dev->sd, video,
+				enum_mbus_fmt, num_formats, &code))
+		num_formats++;
+	if (!num_formats)
+		return -ENXIO;
+
+	sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL);
+	if (!sf)
+		return -ENOMEM;
+
+	for (i = 0; i < num_formats; i++) {
+		v4l2_subdev_call(bcap_dev->sd, video,
+				enum_mbus_fmt, i, &code);
+		for (j = 0; j < BCAP_MAX_FMTS; j++)
+			if (code == bcap_formats[j].mbus_code)
+				break;
+		if (j == BCAP_MAX_FMTS) {
+			/* we don't allow this sensor working with our bridge */
+			kfree(sf);
+			return -EINVAL;
+		}
+		sf[i] = bcap_formats[j];
+	}
+	bcap_dev->sensor_formats = sf;
+	bcap_dev->num_sensor_formats = num_formats;
+	return 0;
+}
+
+static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
+{
+	bcap_dev->num_sensor_formats = 0;
+	kfree(bcap_dev->sensor_formats);
+	bcap_dev->sensor_formats = NULL;
+}
+
 static int bcap_open(struct file *file)
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
 	struct video_device *vfd = bcap_dev->video_dev;
-	struct v4l2_mbus_framefmt mbus_fmt;
-	struct v4l2_pix_format *pixfmt = &bcap_dev->fmt;
-	const struct bcap_format *bcap_fmt;
 	struct bcap_fh *bcap_fh;
-	int ret, i;
 
 	if (!bcap_dev->sd) {
 		v4l2_err(&bcap_dev->v4l2_dev, "No sub device registered\n");
 		return -ENODEV;
 	}
 
-	/* if first open, query format of subdevice as default format */
-	if (!bcap_dev->usrs) {
-		ret = v4l2_subdev_call(bcap_dev->sd, video,
-					g_mbus_fmt, &mbus_fmt);
-		if (ret < 0)
-			return ret;
-
-		for (i = 0; i < BCAP_MAX_FMTS; i++) {
-			if (mbus_fmt.code != bcap_formats[i].mbus_code)
-				continue;
-			bcap_fmt = &bcap_formats[i];
-			v4l2_fill_pix_format(pixfmt, &mbus_fmt);
-			pixfmt->pixelformat = bcap_fmt->pixelformat;
-			pixfmt->bytesperline = pixfmt->width * bcap_fmt->bpp / 8;
-			pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
-			break;
-		}
-		if (i == BCAP_MAX_FMTS) {
-			v4l2_err(&bcap_dev->v4l2_dev,
-					"subdev fmt is not supported by bcap\n");
-			return -EINVAL;
-		}
-	}
-
 	bcap_fh = kzalloc(sizeof(*bcap_fh), GFP_KERNEL);
 	if (!bcap_fh) {
 		v4l2_err(&bcap_dev->v4l2_dev,
@@ -630,17 +648,18 @@ static int bcap_try_format(struct bcap_device *bcap,
 				enum v4l2_mbus_pixelcode *mbus_code,
 				int *bpp)
 {
-	const struct bcap_format *fmt;
+	struct bcap_format *sf = bcap->sensor_formats;
+	struct bcap_format *fmt = NULL;
 	struct v4l2_mbus_framefmt mbus_fmt;
 	int ret, i;
 
-	for (i = 0; i < BCAP_MAX_FMTS; i++) {
-		fmt = &bcap_formats[i];
+	for (i = 0; i < bcap->num_sensor_formats; i++) {
+		fmt = &sf[i];
 		if (pixfmt->pixelformat == fmt->pixelformat)
 			break;
 	}
-	if (i == BCAP_MAX_FMTS)
-		fmt = &bcap_formats[0];
+	if (i == bcap->num_sensor_formats)
+		fmt = &sf[0];
 
 	if (mbus_code)
 		*mbus_code = fmt->mbus_code;
@@ -661,27 +680,16 @@ static int bcap_enum_fmt_vid_cap(struct file *file, void  *priv,
 					struct v4l2_fmtdesc *fmt)
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
-	enum v4l2_mbus_pixelcode mbus_code;
-	u32 index = fmt->index;
-	int ret, i;
+	struct bcap_format *sf = bcap_dev->sensor_formats;
 
-	ret = v4l2_subdev_call(bcap_dev->sd, video,
-				enum_mbus_fmt, index, &mbus_code);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < BCAP_MAX_FMTS; i++)
-		if (mbus_code == bcap_formats[i].mbus_code)
-			break;
-
-	if (i == BCAP_MAX_FMTS)
+	if (fmt->index >= bcap_dev->num_sensor_formats)
 		return -EINVAL;
 
 	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	strlcpy(fmt->description,
-		bcap_formats[i].desc,
+		sf[fmt->index].desc,
 		sizeof(fmt->description));
-	fmt->pixelformat = bcap_formats[i].pixelformat;
+	fmt->pixelformat = sf[fmt->index].pixelformat;
 	return 0;
 }
 
@@ -698,28 +706,8 @@ static int bcap_g_fmt_vid_cap(struct file *file, void *priv,
 				struct v4l2_format *fmt)
 {
 	struct bcap_device *bcap_dev = video_drvdata(file);
-	struct v4l2_mbus_framefmt mbus_fmt;
-	const struct bcap_format *bcap_fmt;
-	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-	int ret, i;
-
-	ret = v4l2_subdev_call(bcap_dev->sd, video,
-				g_mbus_fmt, &mbus_fmt);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < BCAP_MAX_FMTS; i++)
-		if (mbus_fmt.code == bcap_formats[i].mbus_code)
-			break;
-
-	if (i == BCAP_MAX_FMTS)
-		return -EINVAL;
 
-	bcap_fmt = &bcap_formats[i];
-	v4l2_fill_pix_format(pixfmt, &mbus_fmt);
-	pixfmt->pixelformat = bcap_fmt->pixelformat;
-	pixfmt->bytesperline = pixfmt->width * bcap_fmt->bpp / 8;
-	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
+	fmt->fmt.pix = bcap_dev->fmt;
 	return 0;
 }
 
@@ -974,14 +962,31 @@ static int __devinit bcap_probe(struct platform_device *pdev)
 		/* update tvnorms from the sub devices */
 		for (i = 0; i < config->num_inputs; i++)
 			vfd->tvnorms |= config->inputs[i].std;
-		/* set default std */
-		bcap_dev->std = vfd->tvnorms;
 	} else {
 		v4l2_err(&bcap_dev->v4l2_dev,
 				"Unable to register sub device\n");
 		goto err_unreg_vdev;
 	}
+
 	v4l2_info(&bcap_dev->v4l2_dev, "v4l2 sub device registered\n");
+
+	/* now we can probe the default state */
+	if (vfd->tvnorms) {
+		v4l2_std_id std;
+		ret = v4l2_subdev_call(bcap_dev->sd, core, g_std, &std);
+		if (ret) {
+			v4l2_err(&bcap_dev->v4l2_dev,
+					"Unable to get std\n");
+			goto err_unreg_vdev;
+		}
+		bcap_dev->std = std;
+	}
+	ret = bcap_init_sensor_formats(bcap_dev);
+	if (ret) {
+		v4l2_err(&bcap_dev->v4l2_dev,
+				"Unable to create sensor formats table\n");
+		goto err_unreg_vdev;
+	}
 	return 0;
 err_unreg_vdev:
 	video_unregister_device(bcap_dev->video_dev);
@@ -1006,6 +1011,7 @@ static int __devexit bcap_remove(struct platform_device *pdev)
 	struct bcap_device *bcap_dev = container_of(v4l2_dev,
 						struct bcap_device, v4l2_dev);
 
+	bcap_free_sensor_formats(bcap_dev);
 	video_unregister_device(bcap_dev->video_dev);
 	v4l2_device_unregister(v4l2_dev);
 	vb2_dma_contig_cleanup_ctx(bcap_dev->alloc_ctx);
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 257da1a..45651d1 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -158,6 +158,7 @@ struct v4l2_subdev_core_ops {
 	int (*s_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
 	int (*try_ext_ctrls)(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls);
 	int (*querymenu)(struct v4l2_subdev *sd, struct v4l2_querymenu *qm);
+	int (*g_std)(struct v4l2_subdev *sd, v4l2_std_id *norm);
 	int (*s_std)(struct v4l2_subdev *sd, v4l2_std_id norm);
 	long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
_______________________________________________
Linux-kernel-commits mailing list
[email protected]
https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits

Reply via email to