From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
To: Linux Media Mailing List <linux-media@vger.kernel.org>
Cc: Hans Verkuil <hverkuil@xs4all.nl>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Mauro Carvalho Chehab <mchehab@infradead.org>
Subject: [PATCH/RFC 4/4] V4L: sh_mobile_ceu_camera: support multi-size video-buffers
Date: Fri, 1 Apr 2011 10:13:18 +0200 (CEST) [thread overview]
Message-ID: <Pine.LNX.4.64.1104011012210.9530@axis700.grange> (raw)
In-Reply-To: <Pine.LNX.4.64.1104010959470.9530@axis700.grange>
With this patch it is possible to prequeue buffers of different sizes
in the driver and switch between them by just stopping streaming,
setting a new format, queuing the suitable buffers and re-starting the
streaming escaping the need to allocate buffers on this time-critical
path.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/media/video/sh_mobile_ceu_camera.c | 104 ++++++++++++++++++++++++----
1 files changed, 91 insertions(+), 13 deletions(-)
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index d1446ad..3245fff 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -100,6 +100,7 @@ struct sh_mobile_ceu_dev {
unsigned int irq;
void __iomem *base;
unsigned long video_limit;
+ unsigned long buf_total;
spinlock_t lock; /* Protects video buffer lists */
struct list_head capture;
@@ -215,38 +216,110 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
/*
* Videobuf operations
*/
-static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
+
+/*
+ * .queue_add() can be called in two situations:
+ * (1) to add a new buffer set. In this case create->count is the number of
+ * buffers to be added, *count == 0. We have to return the number of
+ * added buffers in *count.
+ * (2) to try to adjust the number of buffers down. In this case create->count
+ * is the (smaller) number of buffers, that the caller wants to have, and
+ * *count is the number of buffers, that we actually allocated in step (1)
+ * above. If the smaller create->count is still sufficient for us, we have
+ * to adjust our internal configuration and return *count = create->count.
+ */
+static int sh_mobile_ceu_videobuf_add(struct vb2_queue *vq,
+ struct v4l2_create_buffers *create,
unsigned int *count, unsigned int *num_planes,
unsigned long sizes[], void *alloc_ctxs[])
{
struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct sh_mobile_ceu_dev *pcdev = ici->priv;
- int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
- icd->current_fmt->host_fmt);
+ const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
+ create->format.fmt.pix.pixelformat);
+ const struct soc_mbus_pixelfmt *fmt;
+ int bytes_per_line;
+ ssize_t size;
+
+ if (!xlate)
+ return -ENOENT;
+ fmt = xlate->host_fmt;
+
+ /* fmt must be != NULL */
+ bytes_per_line = soc_mbus_bytes_per_line(create->format.fmt.pix.width, fmt);
if (bytes_per_line < 0)
return bytes_per_line;
+ if (create->count < 2)
+ create->count = 2;
+
*num_planes = 1;
- pcdev->sequence = 0;
- sizes[0] = bytes_per_line * icd->user_height;
+ if (!pcdev->buf_total)
+ pcdev->sequence = 0;
+ /* Ignore possible user-provided size, we cannot use it */
+ sizes[0] = bytes_per_line * create->format.fmt.pix.height;
alloc_ctxs[0] = pcdev->alloc_ctx;
- if (!*count)
- *count = 2;
+ size = PAGE_ALIGN(sizes[0]) * (create->count - *count);
+
+ if (pcdev->video_limit &&
+ pcdev->buf_total + size > pcdev->video_limit) {
+ /* This can only be entered in case (1) in the above comment */
+ unsigned int cnt = (pcdev->video_limit - pcdev->buf_total) /
+ PAGE_ALIGN(sizes[0]);
+
+ /*
+ * Normally *count would be 0 here, but add it anyway in case
+ * someone decides to call this function to increase the number
+ * of buffers from != 0
+ */
+ if (cnt + *count < 2)
+ return -ENOBUFS;
- if (pcdev->video_limit) {
- if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit)
- *count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
+ size = PAGE_ALIGN(sizes[0]) * cnt;
+ *count += cnt;
+ } else {
+ *count = create->count;
}
- dev_dbg(icd->dev.parent, "count=%d, size=%lu\n", *count, sizes[0]);
+ pcdev->buf_total += size;
+
+ dev_dbg(icd->dev.parent, "count=%d, size=%lu, fmt=0x%x\n",
+ *count, sizes[0], fmt->fourcc);
return 0;
}
+static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
+ unsigned int *count, unsigned int *num_planes,
+ unsigned long sizes[], void *alloc_ctxs[])
+{
+ struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct sh_mobile_ceu_dev *pcdev = ici->priv;
+ struct v4l2_create_buffers create = {
+ .count = *count,
+ .format.fmt.pix = {
+ .width = icd->user_width,
+ .height = icd->user_height,
+ .pixelformat = icd->current_fmt->host_fmt->fourcc,
+ },
+ };
+
+ if (vq->num_buffers)
+ /* The core failed to allocate the required number of buffers */
+ *count = pcdev->buf_total / PAGE_ALIGN(sizes[0]);
+ else
+ *count = 0;
+
+ /* Normal allocation */
+ return sh_mobile_ceu_videobuf_add(vq, &create, count, num_planes, sizes,
+ alloc_ctxs);
+}
+
#define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */
#define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */
#define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */
@@ -371,8 +444,8 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
size = icd->user_height * bytes_per_line;
if (vb2_plane_size(vb, 0) < size) {
- dev_err(icd->dev.parent, "Buffer too small (%lu < %lu)\n",
- vb2_plane_size(vb, 0), size);
+ dev_err(icd->dev.parent, "Buffer #%d too small (%lu < %lu)\n",
+ vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
return -ENOBUFS;
}
@@ -424,6 +497,8 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
/* Doesn't hurt also if the list is empty */
list_del_init(&buf->queue);
+ pcdev->buf_total -= vb2_plane_size(vb, 0);
+
spin_unlock_irq(&pcdev->lock);
}
@@ -455,6 +530,7 @@ static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q)
static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
.queue_setup = sh_mobile_ceu_videobuf_setup,
+ .queue_add = sh_mobile_ceu_videobuf_add,
.buf_prepare = sh_mobile_ceu_videobuf_prepare,
.buf_queue = sh_mobile_ceu_videobuf_queue,
.buf_cleanup = sh_mobile_ceu_videobuf_release,
@@ -515,6 +591,8 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
pm_runtime_get_sync(ici->v4l2_dev.dev);
+ pcdev->buf_total = 0;
+
ret = sh_mobile_ceu_soft_reset(pcdev);
if (!ret)
pcdev->icd = icd;
--
1.7.2.5
next prev parent reply other threads:[~2011-04-01 8:13 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-01 8:12 [PATCH/RFC 0/4] V4L: new ioctl()s to support multi-sized video-buffers Guennadi Liakhovetski
2011-04-01 8:13 ` [PATCH/RFC 1/4] V4L: add three new ioctl()s for multi-size videobuffer management Guennadi Liakhovetski
2011-04-04 7:05 ` Hans Verkuil
2011-04-04 7:38 ` Guennadi Liakhovetski
2011-04-04 8:06 ` Hans Verkuil
2011-04-04 8:23 ` Guennadi Liakhovetski
2011-04-05 12:02 ` Laurent Pinchart
2011-04-05 12:40 ` Guennadi Liakhovetski
2011-04-05 12:40 ` Hans Verkuil
2011-04-05 12:53 ` Laurent Pinchart
2011-04-05 11:59 ` Laurent Pinchart
2011-04-05 12:39 ` Guennadi Liakhovetski
2011-04-05 12:56 ` Laurent Pinchart
2011-04-05 14:53 ` Sakari Ailus
2011-04-05 12:21 ` Laurent Pinchart
2011-04-05 12:34 ` Hans Verkuil
2011-04-05 12:50 ` Laurent Pinchart
2011-04-05 12:52 ` Guennadi Liakhovetski
2011-04-05 12:58 ` Laurent Pinchart
2011-04-06 16:19 ` Guennadi Liakhovetski
2011-04-07 7:06 ` Hans Verkuil
2011-04-07 7:15 ` Guennadi Liakhovetski
2011-04-07 7:50 ` Hans Verkuil
2011-04-07 8:53 ` Guennadi Liakhovetski
2011-04-07 9:13 ` Hans Verkuil
2011-04-07 9:17 ` Laurent Pinchart
2011-04-07 9:28 ` Hans Verkuil
2011-04-11 11:27 ` Sakari Ailus
2011-04-11 8:54 ` Sakari Ailus
2011-05-13 7:45 ` Guennadi Liakhovetski
2011-05-14 11:12 ` Hans Verkuil
2011-05-16 13:32 ` Sakari Ailus
2011-05-16 20:34 ` Guennadi Liakhovetski
2011-05-17 5:52 ` Sakari Ailus
2011-05-18 14:01 ` Laurent Pinchart
2011-05-18 14:48 ` Guennadi Liakhovetski
2011-05-18 19:58 ` Sakari Ailus
2011-06-06 13:10 ` Guennadi Liakhovetski
2011-06-06 17:28 ` Sakari Ailus
2011-06-07 12:14 ` Guennadi Liakhovetski
2011-06-08 9:04 ` Sakari Ailus
2011-05-22 10:18 ` Guennadi Liakhovetski
2011-05-22 12:17 ` Sakari Ailus
2011-05-18 13:59 ` Laurent Pinchart
2011-05-18 15:15 ` Guennadi Liakhovetski
2011-05-18 18:02 ` Sakari Ailus
2011-04-01 8:13 ` [PATCH/RFC 2/4] V4L: add videobuf2 helper functions to support multi-size video-buffers Guennadi Liakhovetski
2011-04-01 14:06 ` [PATCH/RFC 2/4 v2] " Guennadi Liakhovetski
2011-04-03 17:34 ` Pawel Osciak
2011-04-04 7:55 ` Guennadi Liakhovetski
2011-04-05 12:42 ` Laurent Pinchart
2011-04-05 12:38 ` Laurent Pinchart
2011-04-05 13:01 ` Guennadi Liakhovetski
2011-04-01 8:13 ` [PATCH/RFC 3/4] V4L: soc-camera: add support for new multi-size video-buffer ioctl()s Guennadi Liakhovetski
2011-04-01 8:13 ` Guennadi Liakhovetski [this message]
2011-04-03 17:34 ` [PATCH/RFC 0/4] V4L: new ioctl()s to support multi-sized video-buffers Pawel Osciak
2011-04-04 7:15 ` Guennadi Liakhovetski
2011-04-05 12:19 ` Laurent Pinchart
2011-04-05 12:48 ` Guennadi Liakhovetski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.1104011012210.9530@axis700.grange \
--to=g.liakhovetski@gmx.de \
--cc=hverkuil@xs4all.nl \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox