diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2011-02-18 03:30:15 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:32:15 -0400 |
commit | a616898d6df29b8ffaea5742f678b3ac223b307c (patch) | |
tree | f49c16a3327faa19d9739ded261202ff99108cc4 /drivers/media/video | |
parent | 8eb4476d44b39fe2f5829de030328223bda2abaf (diff) |
[media] V4L: sh_mobile_ceu_camera: convert to videobuf2
Convert the sh_mobile_ceu_camera driver to the videobuf2 API.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 264 |
2 files changed, 112 insertions, 154 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 07c5baaa2d0f..cf81bd536a71 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -877,7 +877,7 @@ config VIDEO_SH_MOBILE_CSI2 | |||
877 | config VIDEO_SH_MOBILE_CEU | 877 | config VIDEO_SH_MOBILE_CEU |
878 | tristate "SuperH Mobile CEU Interface driver" | 878 | tristate "SuperH Mobile CEU Interface driver" |
879 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK | 879 | depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK |
880 | select VIDEOBUF_DMA_CONTIG | 880 | select VIDEOBUF2_DMA_CONTIG |
881 | ---help--- | 881 | ---help--- |
882 | This is a v4l2 driver for the SuperH Mobile CEU Interface | 882 | This is a v4l2 driver for the SuperH Mobile CEU Interface |
883 | 883 | ||
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 954222bc3458..325f50d0adee 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <media/v4l2-dev.h> | 38 | #include <media/v4l2-dev.h> |
39 | #include <media/soc_camera.h> | 39 | #include <media/soc_camera.h> |
40 | #include <media/sh_mobile_ceu.h> | 40 | #include <media/sh_mobile_ceu.h> |
41 | #include <media/videobuf-dma-contig.h> | 41 | #include <media/videobuf2-dma-contig.h> |
42 | #include <media/v4l2-mediabus.h> | 42 | #include <media/v4l2-mediabus.h> |
43 | #include <media/soc_mediabus.h> | 43 | #include <media/soc_mediabus.h> |
44 | 44 | ||
@@ -87,7 +87,8 @@ | |||
87 | 87 | ||
88 | /* per video frame buffer */ | 88 | /* per video frame buffer */ |
89 | struct sh_mobile_ceu_buffer { | 89 | struct sh_mobile_ceu_buffer { |
90 | struct videobuf_buffer vb; /* v4l buffer must be first */ | 90 | struct vb2_buffer vb; /* v4l buffer must be first */ |
91 | struct list_head queue; | ||
91 | enum v4l2_mbus_pixelcode code; | 92 | enum v4l2_mbus_pixelcode code; |
92 | }; | 93 | }; |
93 | 94 | ||
@@ -99,16 +100,17 @@ struct sh_mobile_ceu_dev { | |||
99 | void __iomem *base; | 100 | void __iomem *base; |
100 | unsigned long video_limit; | 101 | unsigned long video_limit; |
101 | 102 | ||
102 | /* lock used to protect videobuf */ | 103 | spinlock_t lock; /* Protects video buffer lists */ |
103 | spinlock_t lock; | ||
104 | struct list_head capture; | 104 | struct list_head capture; |
105 | struct videobuf_buffer *active; | 105 | struct vb2_buffer *active; |
106 | struct vb2_alloc_ctx *alloc_ctx; | ||
106 | 107 | ||
107 | struct sh_mobile_ceu_info *pdata; | 108 | struct sh_mobile_ceu_info *pdata; |
108 | 109 | ||
109 | u32 cflcr; | 110 | u32 cflcr; |
110 | 111 | ||
111 | enum v4l2_field field; | 112 | enum v4l2_field field; |
113 | int sequence; | ||
112 | 114 | ||
113 | unsigned int image_mode:1; | 115 | unsigned int image_mode:1; |
114 | unsigned int is_16bit:1; | 116 | unsigned int is_16bit:1; |
@@ -133,6 +135,11 @@ struct sh_mobile_ceu_cam { | |||
133 | enum v4l2_mbus_pixelcode code; | 135 | enum v4l2_mbus_pixelcode code; |
134 | }; | 136 | }; |
135 | 137 | ||
138 | static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb) | ||
139 | { | ||
140 | return container_of(vb, struct sh_mobile_ceu_buffer, vb); | ||
141 | } | ||
142 | |||
136 | static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) | 143 | static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev) |
137 | { | 144 | { |
138 | unsigned long flags; | 145 | unsigned long flags; |
@@ -205,11 +212,11 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev) | |||
205 | /* | 212 | /* |
206 | * Videobuf operations | 213 | * Videobuf operations |
207 | */ | 214 | */ |
208 | static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, | 215 | static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, |
209 | unsigned int *count, | 216 | unsigned int *count, unsigned int *num_planes, |
210 | unsigned int *size) | 217 | unsigned long sizes[], void *alloc_ctxs[]) |
211 | { | 218 | { |
212 | struct soc_camera_device *icd = vq->priv_data; | 219 | struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq); |
213 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 220 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
214 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 221 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
215 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 222 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
@@ -218,39 +225,25 @@ static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq, | |||
218 | if (bytes_per_line < 0) | 225 | if (bytes_per_line < 0) |
219 | return bytes_per_line; | 226 | return bytes_per_line; |
220 | 227 | ||
221 | *size = bytes_per_line * icd->user_height; | 228 | *num_planes = 1; |
229 | |||
230 | pcdev->sequence = 0; | ||
231 | sizes[0] = bytes_per_line * icd->user_height; | ||
232 | alloc_ctxs[0] = pcdev->alloc_ctx; | ||
222 | 233 | ||
223 | if (0 == *count) | 234 | if (!*count) |
224 | *count = 2; | 235 | *count = 2; |
225 | 236 | ||
226 | if (pcdev->video_limit) { | 237 | if (pcdev->video_limit) { |
227 | if (PAGE_ALIGN(*size) * *count > pcdev->video_limit) | 238 | if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit) |
228 | *count = pcdev->video_limit / PAGE_ALIGN(*size); | 239 | *count = pcdev->video_limit / PAGE_ALIGN(sizes[0]); |
229 | } | 240 | } |
230 | 241 | ||
231 | dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size); | 242 | dev_dbg(icd->dev.parent, "count=%d, size=%lu\n", *count, sizes[0]); |
232 | 243 | ||
233 | return 0; | 244 | return 0; |
234 | } | 245 | } |
235 | 246 | ||
236 | static void free_buffer(struct videobuf_queue *vq, | ||
237 | struct sh_mobile_ceu_buffer *buf) | ||
238 | { | ||
239 | struct soc_camera_device *icd = vq->priv_data; | ||
240 | struct device *dev = icd->dev.parent; | ||
241 | |||
242 | dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | ||
243 | &buf->vb, buf->vb.baddr, buf->vb.bsize); | ||
244 | |||
245 | if (in_interrupt()) | ||
246 | BUG(); | ||
247 | |||
248 | videobuf_waiton(vq, &buf->vb, 0, 0); | ||
249 | videobuf_dma_contig_free(vq, &buf->vb); | ||
250 | dev_dbg(dev, "%s freed\n", __func__); | ||
251 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
252 | } | ||
253 | |||
254 | #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */ | 247 | #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */ |
255 | #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */ | 248 | #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */ |
256 | #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */ | 249 | #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */ |
@@ -309,7 +302,10 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
309 | bottom2 = CDBCR; | 302 | bottom2 = CDBCR; |
310 | } | 303 | } |
311 | 304 | ||
312 | phys_addr_top = videobuf_to_dma_contig(pcdev->active); | 305 | /* mem_ops->cookie must not be NULL */ |
306 | phys_addr_top = (dma_addr_t)icd->vb2_vidq.mem_ops->cookie(pcdev-> | ||
307 | active->planes[0].mem_priv); | ||
308 | |||
313 | ceu_write(pcdev, top1, phys_addr_top); | 309 | ceu_write(pcdev, top1, phys_addr_top); |
314 | if (V4L2_FIELD_NONE != pcdev->field) { | 310 | if (V4L2_FIELD_NONE != pcdev->field) { |
315 | phys_addr_bottom = phys_addr_top + icd->user_width; | 311 | phys_addr_bottom = phys_addr_top + icd->user_width; |
@@ -330,87 +326,67 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
330 | } | 326 | } |
331 | } | 327 | } |
332 | 328 | ||
333 | pcdev->active->state = VIDEOBUF_ACTIVE; | ||
334 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ | 329 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ |
335 | 330 | ||
336 | return ret; | 331 | return ret; |
337 | } | 332 | } |
338 | 333 | ||
339 | static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, | 334 | static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) |
340 | struct videobuf_buffer *vb, | ||
341 | enum v4l2_field field) | ||
342 | { | 335 | { |
343 | struct soc_camera_device *icd = vq->priv_data; | 336 | struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); |
344 | struct sh_mobile_ceu_buffer *buf; | 337 | struct sh_mobile_ceu_buffer *buf; |
345 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 338 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
346 | icd->current_fmt->host_fmt); | 339 | icd->current_fmt->host_fmt); |
347 | int ret; | 340 | unsigned long size; |
348 | 341 | ||
349 | if (bytes_per_line < 0) | 342 | if (bytes_per_line < 0) |
350 | return bytes_per_line; | 343 | return bytes_per_line; |
351 | 344 | ||
352 | buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); | 345 | buf = to_ceu_vb(vb); |
353 | 346 | ||
354 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | 347 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
355 | vb, vb->baddr, vb->bsize); | 348 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
356 | 349 | ||
357 | /* Added list head initialization on alloc */ | 350 | /* Added list head initialization on alloc */ |
358 | WARN_ON(!list_empty(&vb->queue)); | 351 | WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb); |
359 | 352 | ||
360 | #ifdef DEBUG | 353 | #ifdef DEBUG |
361 | /* | 354 | /* |
362 | * This can be useful if you want to see if we actually fill | 355 | * This can be useful if you want to see if we actually fill |
363 | * the buffer with something | 356 | * the buffer with something |
364 | */ | 357 | */ |
365 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 358 | if (vb2_plane_vaddr(vb, 0)) |
359 | memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); | ||
366 | #endif | 360 | #endif |
367 | 361 | ||
368 | BUG_ON(NULL == icd->current_fmt); | 362 | BUG_ON(NULL == icd->current_fmt); |
369 | 363 | ||
370 | if (buf->code != icd->current_fmt->code || | 364 | size = icd->user_height * bytes_per_line; |
371 | vb->width != icd->user_width || | ||
372 | vb->height != icd->user_height || | ||
373 | vb->field != field) { | ||
374 | buf->code = icd->current_fmt->code; | ||
375 | vb->width = icd->user_width; | ||
376 | vb->height = icd->user_height; | ||
377 | vb->field = field; | ||
378 | vb->state = VIDEOBUF_NEEDS_INIT; | ||
379 | } | ||
380 | 365 | ||
381 | vb->size = vb->height * bytes_per_line; | 366 | if (vb2_plane_size(vb, 0) < size) { |
382 | if (0 != vb->baddr && vb->bsize < vb->size) { | 367 | dev_err(icd->dev.parent, "Buffer too small (%lu < %lu)\n", |
383 | ret = -EINVAL; | 368 | vb2_plane_size(vb, 0), size); |
384 | goto out; | 369 | return -ENOBUFS; |
385 | } | 370 | } |
386 | 371 | ||
387 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | 372 | vb2_set_plane_payload(vb, 0, size); |
388 | ret = videobuf_iolock(vq, vb, NULL); | ||
389 | if (ret) | ||
390 | goto fail; | ||
391 | vb->state = VIDEOBUF_PREPARED; | ||
392 | } | ||
393 | 373 | ||
394 | return 0; | 374 | return 0; |
395 | fail: | ||
396 | free_buffer(vq, buf); | ||
397 | out: | ||
398 | return ret; | ||
399 | } | 375 | } |
400 | 376 | ||
401 | /* Called under spinlock_irqsave(&pcdev->lock, ...) */ | 377 | static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) |
402 | static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, | ||
403 | struct videobuf_buffer *vb) | ||
404 | { | 378 | { |
405 | struct soc_camera_device *icd = vq->priv_data; | 379 | struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); |
406 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 380 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
407 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 381 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
382 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | ||
383 | unsigned long flags; | ||
408 | 384 | ||
409 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | 385 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
410 | vb, vb->baddr, vb->bsize); | 386 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
411 | 387 | ||
412 | vb->state = VIDEOBUF_QUEUED; | 388 | spin_lock_irqsave(&pcdev->lock, flags); |
413 | list_add_tail(&vb->queue, &pcdev->capture); | 389 | list_add_tail(&buf->queue, &pcdev->capture); |
414 | 390 | ||
415 | if (!pcdev->active) { | 391 | if (!pcdev->active) { |
416 | /* | 392 | /* |
@@ -421,13 +397,14 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, | |||
421 | pcdev->active = vb; | 397 | pcdev->active = vb; |
422 | sh_mobile_ceu_capture(pcdev); | 398 | sh_mobile_ceu_capture(pcdev); |
423 | } | 399 | } |
400 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
424 | } | 401 | } |
425 | 402 | ||
426 | static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, | 403 | static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) |
427 | struct videobuf_buffer *vb) | ||
428 | { | 404 | { |
429 | struct soc_camera_device *icd = vq->priv_data; | 405 | struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); |
430 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 406 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
407 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | ||
431 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 408 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
432 | unsigned long flags; | 409 | unsigned long flags; |
433 | 410 | ||
@@ -439,53 +416,60 @@ static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, | |||
439 | pcdev->active = NULL; | 416 | pcdev->active = NULL; |
440 | } | 417 | } |
441 | 418 | ||
442 | if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && | 419 | /* Doesn't hurt also if the list is empty */ |
443 | !list_empty(&vb->queue)) { | 420 | list_del_init(&buf->queue); |
444 | vb->state = VIDEOBUF_ERROR; | ||
445 | list_del_init(&vb->queue); | ||
446 | } | ||
447 | 421 | ||
448 | spin_unlock_irqrestore(&pcdev->lock, flags); | 422 | spin_unlock_irqrestore(&pcdev->lock, flags); |
423 | } | ||
449 | 424 | ||
450 | free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); | 425 | static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) |
426 | { | ||
427 | /* This is for locking debugging only */ | ||
428 | INIT_LIST_HEAD(&to_ceu_vb(vb)->queue); | ||
429 | return 0; | ||
451 | } | 430 | } |
452 | 431 | ||
453 | static struct videobuf_queue_ops sh_mobile_ceu_videobuf_ops = { | 432 | static struct vb2_ops sh_mobile_ceu_videobuf_ops = { |
454 | .buf_setup = sh_mobile_ceu_videobuf_setup, | 433 | .queue_setup = sh_mobile_ceu_videobuf_setup, |
455 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, | 434 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, |
456 | .buf_queue = sh_mobile_ceu_videobuf_queue, | 435 | .buf_queue = sh_mobile_ceu_videobuf_queue, |
457 | .buf_release = sh_mobile_ceu_videobuf_release, | 436 | .buf_cleanup = sh_mobile_ceu_videobuf_release, |
437 | .buf_init = sh_mobile_ceu_videobuf_init, | ||
438 | .wait_prepare = soc_camera_unlock, | ||
439 | .wait_finish = soc_camera_lock, | ||
458 | }; | 440 | }; |
459 | 441 | ||
460 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) | 442 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) |
461 | { | 443 | { |
462 | struct sh_mobile_ceu_dev *pcdev = data; | 444 | struct sh_mobile_ceu_dev *pcdev = data; |
463 | struct videobuf_buffer *vb; | 445 | struct vb2_buffer *vb; |
464 | unsigned long flags; | 446 | int ret; |
465 | 447 | ||
466 | spin_lock_irqsave(&pcdev->lock, flags); | 448 | spin_lock(&pcdev->lock); |
467 | 449 | ||
468 | vb = pcdev->active; | 450 | vb = pcdev->active; |
469 | if (!vb) | 451 | if (!vb) |
470 | /* Stale interrupt from a released buffer */ | 452 | /* Stale interrupt from a released buffer */ |
471 | goto out; | 453 | goto out; |
472 | 454 | ||
473 | list_del_init(&vb->queue); | 455 | list_del_init(&to_ceu_vb(vb)->queue); |
474 | 456 | ||
475 | if (!list_empty(&pcdev->capture)) | 457 | if (!list_empty(&pcdev->capture)) |
476 | pcdev->active = list_entry(pcdev->capture.next, | 458 | pcdev->active = &list_entry(pcdev->capture.next, |
477 | struct videobuf_buffer, queue); | 459 | struct sh_mobile_ceu_buffer, queue)->vb; |
478 | else | 460 | else |
479 | pcdev->active = NULL; | 461 | pcdev->active = NULL; |
480 | 462 | ||
481 | vb->state = (sh_mobile_ceu_capture(pcdev) < 0) ? | 463 | ret = sh_mobile_ceu_capture(pcdev); |
482 | VIDEOBUF_ERROR : VIDEOBUF_DONE; | 464 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
483 | do_gettimeofday(&vb->ts); | 465 | if (!ret) { |
484 | vb->field_count++; | 466 | vb->v4l2_buf.field = pcdev->field; |
485 | wake_up(&vb->done); | 467 | vb->v4l2_buf.sequence = pcdev->sequence++; |
468 | } | ||
469 | vb2_buffer_done(vb, ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | ||
486 | 470 | ||
487 | out: | 471 | out: |
488 | spin_unlock_irqrestore(&pcdev->lock, flags); | 472 | spin_unlock(&pcdev->lock); |
489 | 473 | ||
490 | return IRQ_HANDLED; | 474 | return IRQ_HANDLED; |
491 | } | 475 | } |
@@ -529,9 +513,8 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
529 | /* make sure active buffer is canceled */ | 513 | /* make sure active buffer is canceled */ |
530 | spin_lock_irqsave(&pcdev->lock, flags); | 514 | spin_lock_irqsave(&pcdev->lock, flags); |
531 | if (pcdev->active) { | 515 | if (pcdev->active) { |
532 | list_del(&pcdev->active->queue); | 516 | list_del_init(&to_ceu_vb(pcdev->active)->queue); |
533 | pcdev->active->state = VIDEOBUF_ERROR; | 517 | vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); |
534 | wake_up_all(&pcdev->active->done); | ||
535 | pcdev->active = NULL; | 518 | pcdev->active = NULL; |
536 | } | 519 | } |
537 | spin_unlock_irqrestore(&pcdev->lock, flags); | 520 | spin_unlock_irqrestore(&pcdev->lock, flags); |
@@ -686,6 +669,7 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) | |||
686 | ceu_write(pcdev, CAPSR, capsr); | 669 | ceu_write(pcdev, CAPSR, capsr); |
687 | } | 670 | } |
688 | 671 | ||
672 | /* Capture is not running, no interrupts, no locking needed */ | ||
689 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | 673 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, |
690 | __u32 pixfmt) | 674 | __u32 pixfmt) |
691 | { | 675 | { |
@@ -1726,43 +1710,11 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1726 | return ret; | 1710 | return ret; |
1727 | } | 1711 | } |
1728 | 1712 | ||
1729 | static int sh_mobile_ceu_reqbufs(struct soc_camera_device *icd, | ||
1730 | struct v4l2_requestbuffers *p) | ||
1731 | { | ||
1732 | int i; | ||
1733 | |||
1734 | /* | ||
1735 | * This is for locking debugging only. I removed spinlocks and now I | ||
1736 | * check whether .prepare is ever called on a linked buffer, or whether | ||
1737 | * a dma IRQ can occur for an in-work or unlinked buffer. Until now | ||
1738 | * it hadn't triggered | ||
1739 | */ | ||
1740 | for (i = 0; i < p->count; i++) { | ||
1741 | struct sh_mobile_ceu_buffer *buf; | ||
1742 | |||
1743 | buf = container_of(icd->vb_vidq.bufs[i], | ||
1744 | struct sh_mobile_ceu_buffer, vb); | ||
1745 | INIT_LIST_HEAD(&buf->vb.queue); | ||
1746 | } | ||
1747 | |||
1748 | return 0; | ||
1749 | } | ||
1750 | |||
1751 | static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) | 1713 | static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) |
1752 | { | 1714 | { |
1753 | struct soc_camera_device *icd = file->private_data; | 1715 | struct soc_camera_device *icd = file->private_data; |
1754 | struct sh_mobile_ceu_buffer *buf; | ||
1755 | |||
1756 | buf = list_entry(icd->vb_vidq.stream.next, | ||
1757 | struct sh_mobile_ceu_buffer, vb.stream); | ||
1758 | |||
1759 | poll_wait(file, &buf->vb.done, pt); | ||
1760 | 1716 | ||
1761 | if (buf->vb.state == VIDEOBUF_DONE || | 1717 | return vb2_poll(&icd->vb2_vidq, file, pt); |
1762 | buf->vb.state == VIDEOBUF_ERROR) | ||
1763 | return POLLIN|POLLRDNORM; | ||
1764 | |||
1765 | return 0; | ||
1766 | } | 1718 | } |
1767 | 1719 | ||
1768 | static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, | 1720 | static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, |
@@ -1774,19 +1726,17 @@ static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, | |||
1774 | return 0; | 1726 | return 0; |
1775 | } | 1727 | } |
1776 | 1728 | ||
1777 | static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, | 1729 | static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q, |
1778 | struct soc_camera_device *icd) | 1730 | struct soc_camera_device *icd) |
1779 | { | 1731 | { |
1780 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1732 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1781 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 1733 | q->io_modes = VB2_MMAP | VB2_USERPTR; |
1782 | 1734 | q->drv_priv = icd; | |
1783 | videobuf_queue_dma_contig_init(q, | 1735 | q->ops = &sh_mobile_ceu_videobuf_ops; |
1784 | &sh_mobile_ceu_videobuf_ops, | 1736 | q->mem_ops = &vb2_dma_contig_memops; |
1785 | icd->dev.parent, &pcdev->lock, | 1737 | q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer); |
1786 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1738 | |
1787 | pcdev->field, | 1739 | return vb2_queue_init(q); |
1788 | sizeof(struct sh_mobile_ceu_buffer), | ||
1789 | icd, &icd->video_lock); | ||
1790 | } | 1740 | } |
1791 | 1741 | ||
1792 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, | 1742 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, |
@@ -1850,11 +1800,10 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1850 | .try_fmt = sh_mobile_ceu_try_fmt, | 1800 | .try_fmt = sh_mobile_ceu_try_fmt, |
1851 | .set_ctrl = sh_mobile_ceu_set_ctrl, | 1801 | .set_ctrl = sh_mobile_ceu_set_ctrl, |
1852 | .get_ctrl = sh_mobile_ceu_get_ctrl, | 1802 | .get_ctrl = sh_mobile_ceu_get_ctrl, |
1853 | .reqbufs = sh_mobile_ceu_reqbufs, | ||
1854 | .poll = sh_mobile_ceu_poll, | 1803 | .poll = sh_mobile_ceu_poll, |
1855 | .querycap = sh_mobile_ceu_querycap, | 1804 | .querycap = sh_mobile_ceu_querycap, |
1856 | .set_bus_param = sh_mobile_ceu_set_bus_param, | 1805 | .set_bus_param = sh_mobile_ceu_set_bus_param, |
1857 | .init_videobuf = sh_mobile_ceu_init_videobuf, | 1806 | .init_videobuf2 = sh_mobile_ceu_init_videobuf, |
1858 | .controls = sh_mobile_ceu_controls, | 1807 | .controls = sh_mobile_ceu_controls, |
1859 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), | 1808 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), |
1860 | }; | 1809 | }; |
@@ -2005,12 +1954,20 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2005 | } | 1954 | } |
2006 | } | 1955 | } |
2007 | 1956 | ||
1957 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1958 | if (IS_ERR(pcdev->alloc_ctx)) { | ||
1959 | err = PTR_ERR(pcdev->alloc_ctx); | ||
1960 | goto exit_module_put; | ||
1961 | } | ||
1962 | |||
2008 | err = soc_camera_host_register(&pcdev->ici); | 1963 | err = soc_camera_host_register(&pcdev->ici); |
2009 | if (err) | 1964 | if (err) |
2010 | goto exit_module_put; | 1965 | goto exit_free_ctx; |
2011 | 1966 | ||
2012 | return 0; | 1967 | return 0; |
2013 | 1968 | ||
1969 | exit_free_ctx: | ||
1970 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
2014 | exit_module_put: | 1971 | exit_module_put: |
2015 | if (csi2 && csi2->driver) | 1972 | if (csi2 && csi2->driver) |
2016 | module_put(csi2->driver->owner); | 1973 | module_put(csi2->driver->owner); |
@@ -2041,6 +1998,7 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) | |||
2041 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 1998 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
2042 | dma_release_declared_memory(&pdev->dev); | 1999 | dma_release_declared_memory(&pdev->dev); |
2043 | iounmap(pcdev->base); | 2000 | iounmap(pcdev->base); |
2001 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
2044 | if (csi2 && csi2->driver) | 2002 | if (csi2 && csi2->driver) |
2045 | module_put(csi2->driver->owner); | 2003 | module_put(csi2->driver->owner); |
2046 | kfree(pcdev); | 2004 | kfree(pcdev); |