aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2011-11-03 09:11:11 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-03 16:28:38 -0400
commitb5518a415158320d41bc31d6887d5c2aa1c9a164 (patch)
tree90b9d857b5219231906526673bac62eaf47eeaa4 /drivers
parent91b6286ff3190fece7314b61ef330da96c4d644f (diff)
[media] V4L: sh-mobile-ceu-camera: prepare to support multi-size buffers
Prepare the sh_mobile_ceu_camera friver to support the new VIDIOC_CREATE_BUFS and VIDIOC_PREPARE_BUF ioctl()s. The .queue_setup() vb2 operation must be able to handle buffer sizes, provided by the caller, and the .buf_prepare() operation must not use the currently configured frame format for its operation. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c124
1 files changed, 81 insertions, 43 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 5d5781bd144..a3153ca1408 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -90,7 +90,6 @@
90struct sh_mobile_ceu_buffer { 90struct sh_mobile_ceu_buffer {
91 struct vb2_buffer vb; /* v4l buffer must be first */ 91 struct vb2_buffer vb; /* v4l buffer must be first */
92 struct list_head queue; 92 struct list_head queue;
93 enum v4l2_mbus_pixelcode code;
94}; 93};
95 94
96struct sh_mobile_ceu_dev { 95struct sh_mobile_ceu_dev {
@@ -100,7 +99,8 @@ struct sh_mobile_ceu_dev {
100 99
101 unsigned int irq; 100 unsigned int irq;
102 void __iomem *base; 101 void __iomem *base;
103 unsigned long video_limit; 102 size_t video_limit;
103 size_t buf_total;
104 104
105 spinlock_t lock; /* Protects video buffer lists */ 105 spinlock_t lock; /* Protects video buffer lists */
106 struct list_head capture; 106 struct list_head capture;
@@ -192,6 +192,12 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
192/* 192/*
193 * Videobuf operations 193 * Videobuf operations
194 */ 194 */
195
196/*
197 * .queue_setup() is called to check, whether the driver can accept the
198 * requested number of buffers and to fill in plane sizes
199 * for the current frame format if required
200 */
195static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, 201static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
196 const struct v4l2_format *fmt, 202 const struct v4l2_format *fmt,
197 unsigned int *count, unsigned int *num_planes, 203 unsigned int *count, unsigned int *num_planes,
@@ -200,26 +206,47 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
200 struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq); 206 struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
201 struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 207 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
202 struct sh_mobile_ceu_dev *pcdev = ici->priv; 208 struct sh_mobile_ceu_dev *pcdev = ici->priv;
203 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 209 int bytes_per_line;
204 icd->current_fmt->host_fmt); 210 unsigned int height;
205 211
212 if (fmt) {
213 const struct soc_camera_format_xlate *xlate = soc_camera_xlate_by_fourcc(icd,
214 fmt->fmt.pix.pixelformat);
215 if (!xlate)
216 return -EINVAL;
217 bytes_per_line = soc_mbus_bytes_per_line(fmt->fmt.pix.width,
218 xlate->host_fmt);
219 height = fmt->fmt.pix.height;
220 } else {
221 /* Called from VIDIOC_REQBUFS or in compatibility mode */
222 bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
223 icd->current_fmt->host_fmt);
224 height = icd->user_height;
225 }
206 if (bytes_per_line < 0) 226 if (bytes_per_line < 0)
207 return bytes_per_line; 227 return bytes_per_line;
208 228
209 *num_planes = 1; 229 sizes[0] = bytes_per_line * height;
210 230
211 pcdev->sequence = 0;
212 sizes[0] = bytes_per_line * icd->user_height;
213 alloc_ctxs[0] = pcdev->alloc_ctx; 231 alloc_ctxs[0] = pcdev->alloc_ctx;
214 232
233 if (!vq->num_buffers)
234 pcdev->sequence = 0;
235
215 if (!*count) 236 if (!*count)
216 *count = 2; 237 *count = 2;
217 238
218 if (pcdev->video_limit) { 239 /* If *num_planes != 0, we have already verified *count. */
219 if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit) 240 if (pcdev->video_limit && !*num_planes) {
220 *count = pcdev->video_limit / PAGE_ALIGN(sizes[0]); 241 size_t size = PAGE_ALIGN(sizes[0]) * *count;
242
243 if (size + pcdev->buf_total > pcdev->video_limit)
244 *count = (pcdev->video_limit - pcdev->buf_total) /
245 PAGE_ALIGN(sizes[0]);
221 } 246 }
222 247
248 *num_planes = 1;
249
223 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]); 250 dev_dbg(icd->parent, "count=%d, size=%u\n", *count, sizes[0]);
224 251
225 return 0; 252 return 0;
@@ -331,23 +358,40 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
331 358
332static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) 359static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
333{ 360{
361 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
362
363 /* Added list head initialization on alloc */
364 WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
365
366 return 0;
367}
368
369static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
370{
334 struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); 371 struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
335 struct sh_mobile_ceu_buffer *buf; 372 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
373 struct sh_mobile_ceu_dev *pcdev = ici->priv;
374 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
375 unsigned long size;
336 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 376 int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
337 icd->current_fmt->host_fmt); 377 icd->current_fmt->host_fmt);
338 unsigned long size;
339 378
340 if (bytes_per_line < 0) 379 if (bytes_per_line < 0)
341 return bytes_per_line; 380 goto error;
342 381
343 buf = to_ceu_vb(vb); 382 size = icd->user_height * bytes_per_line;
383
384 if (vb2_plane_size(vb, 0) < size) {
385 dev_err(icd->parent, "Buffer #%d too small (%lu < %lu)\n",
386 vb->v4l2_buf.index, vb2_plane_size(vb, 0), size);
387 goto error;
388 }
389
390 vb2_set_plane_payload(vb, 0, size);
344 391
345 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, 392 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
346 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); 393 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
347 394
348 /* Added list head initialization on alloc */
349 WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
350
351#ifdef DEBUG 395#ifdef DEBUG
352 /* 396 /*
353 * This can be useful if you want to see if we actually fill 397 * This can be useful if you want to see if we actually fill
@@ -357,31 +401,6 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
357 memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); 401 memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
358#endif 402#endif
359 403
360 BUG_ON(NULL == icd->current_fmt);
361
362 size = icd->user_height * bytes_per_line;
363
364 if (vb2_plane_size(vb, 0) < size) {
365 dev_err(icd->parent, "Buffer too small (%lu < %lu)\n",
366 vb2_plane_size(vb, 0), size);
367 return -ENOBUFS;
368 }
369
370 vb2_set_plane_payload(vb, 0, size);
371
372 return 0;
373}
374
375static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
376{
377 struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
378 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
379 struct sh_mobile_ceu_dev *pcdev = ici->priv;
380 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
381
382 dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
383 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
384
385 spin_lock_irq(&pcdev->lock); 404 spin_lock_irq(&pcdev->lock);
386 list_add_tail(&buf->queue, &pcdev->capture); 405 list_add_tail(&buf->queue, &pcdev->capture);
387 406
@@ -395,6 +414,11 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
395 sh_mobile_ceu_capture(pcdev); 414 sh_mobile_ceu_capture(pcdev);
396 } 415 }
397 spin_unlock_irq(&pcdev->lock); 416 spin_unlock_irq(&pcdev->lock);
417
418 return;
419
420error:
421 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
398} 422}
399 423
400static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) 424static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
@@ -419,11 +443,23 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
419 if (buf->queue.next) 443 if (buf->queue.next)
420 list_del_init(&buf->queue); 444 list_del_init(&buf->queue);
421 445
446 pcdev->buf_total -= PAGE_ALIGN(vb2_plane_size(vb, 0));
447 dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
448 pcdev->buf_total);
449
422 spin_unlock_irq(&pcdev->lock); 450 spin_unlock_irq(&pcdev->lock);
423} 451}
424 452
425static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) 453static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
426{ 454{
455 struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
456 struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
457 struct sh_mobile_ceu_dev *pcdev = ici->priv;
458
459 pcdev->buf_total += PAGE_ALIGN(vb2_plane_size(vb, 0));
460 dev_dbg(icd->parent, "%s() %zu bytes buffers\n", __func__,
461 pcdev->buf_total);
462
427 /* This is for locking debugging only */ 463 /* This is for locking debugging only */
428 INIT_LIST_HEAD(&to_ceu_vb(vb)->queue); 464 INIT_LIST_HEAD(&to_ceu_vb(vb)->queue);
429 return 0; 465 return 0;
@@ -525,6 +561,8 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
525 561
526 pm_runtime_get_sync(ici->v4l2_dev.dev); 562 pm_runtime_get_sync(ici->v4l2_dev.dev);
527 563
564 pcdev->buf_total = 0;
565
528 ret = sh_mobile_ceu_soft_reset(pcdev); 566 ret = sh_mobile_ceu_soft_reset(pcdev);
529 567
530 csi2_sd = find_csi2(pcdev); 568 csi2_sd = find_csi2(pcdev);
@@ -1712,7 +1750,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
1712 image_mode = false; 1750 image_mode = false;
1713 } 1751 }
1714 1752
1715 dev_info(dev, "S_FMT(pix=0x%x, fld 0x%x, code 0x%x, %ux%u)\n", pixfmt, mf.field, mf.code, 1753 dev_geo(dev, "S_FMT(pix=0x%x, fld 0x%x, code 0x%x, %ux%u)\n", pixfmt, mf.field, mf.code,
1716 pix->width, pix->height); 1754 pix->width, pix->height);
1717 1755
1718 dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height); 1756 dev_geo(dev, "4: request camera output %ux%u\n", mf.width, mf.height);