diff options
Diffstat (limited to 'drivers/media/video/sh_mobile_ceu_camera.c')
-rw-r--r-- | drivers/media/video/sh_mobile_ceu_camera.c | 274 |
1 files changed, 113 insertions, 161 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 954222bc3458..3fe54bf41142 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,8 @@ 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 | phys_addr_top = vb2_dma_contig_plane_paddr(pcdev->active, 0); |
306 | |||
313 | ceu_write(pcdev, top1, phys_addr_top); | 307 | ceu_write(pcdev, top1, phys_addr_top); |
314 | if (V4L2_FIELD_NONE != pcdev->field) { | 308 | if (V4L2_FIELD_NONE != pcdev->field) { |
315 | phys_addr_bottom = phys_addr_top + icd->user_width; | 309 | phys_addr_bottom = phys_addr_top + icd->user_width; |
@@ -330,87 +324,67 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
330 | } | 324 | } |
331 | } | 325 | } |
332 | 326 | ||
333 | pcdev->active->state = VIDEOBUF_ACTIVE; | ||
334 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ | 327 | ceu_write(pcdev, CAPSR, 0x1); /* start capture */ |
335 | 328 | ||
336 | return ret; | 329 | return ret; |
337 | } | 330 | } |
338 | 331 | ||
339 | static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq, | 332 | static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) |
340 | struct videobuf_buffer *vb, | ||
341 | enum v4l2_field field) | ||
342 | { | 333 | { |
343 | struct soc_camera_device *icd = vq->priv_data; | 334 | struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq); |
344 | struct sh_mobile_ceu_buffer *buf; | 335 | struct sh_mobile_ceu_buffer *buf; |
345 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | 336 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, |
346 | icd->current_fmt->host_fmt); | 337 | icd->current_fmt->host_fmt); |
347 | int ret; | 338 | unsigned long size; |
348 | 339 | ||
349 | if (bytes_per_line < 0) | 340 | if (bytes_per_line < 0) |
350 | return bytes_per_line; | 341 | return bytes_per_line; |
351 | 342 | ||
352 | buf = container_of(vb, struct sh_mobile_ceu_buffer, vb); | 343 | buf = to_ceu_vb(vb); |
353 | 344 | ||
354 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | 345 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
355 | vb, vb->baddr, vb->bsize); | 346 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
356 | 347 | ||
357 | /* Added list head initialization on alloc */ | 348 | /* Added list head initialization on alloc */ |
358 | WARN_ON(!list_empty(&vb->queue)); | 349 | WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb); |
359 | 350 | ||
360 | #ifdef DEBUG | 351 | #ifdef DEBUG |
361 | /* | 352 | /* |
362 | * This can be useful if you want to see if we actually fill | 353 | * This can be useful if you want to see if we actually fill |
363 | * the buffer with something | 354 | * the buffer with something |
364 | */ | 355 | */ |
365 | memset((void *)vb->baddr, 0xaa, vb->bsize); | 356 | if (vb2_plane_vaddr(vb, 0)) |
357 | memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); | ||
366 | #endif | 358 | #endif |
367 | 359 | ||
368 | BUG_ON(NULL == icd->current_fmt); | 360 | BUG_ON(NULL == icd->current_fmt); |
369 | 361 | ||
370 | if (buf->code != icd->current_fmt->code || | 362 | 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 | 363 | ||
381 | vb->size = vb->height * bytes_per_line; | 364 | if (vb2_plane_size(vb, 0) < size) { |
382 | if (0 != vb->baddr && vb->bsize < vb->size) { | 365 | dev_err(icd->dev.parent, "Buffer too small (%lu < %lu)\n", |
383 | ret = -EINVAL; | 366 | vb2_plane_size(vb, 0), size); |
384 | goto out; | 367 | return -ENOBUFS; |
385 | } | 368 | } |
386 | 369 | ||
387 | if (vb->state == VIDEOBUF_NEEDS_INIT) { | 370 | 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 | 371 | ||
394 | return 0; | 372 | return 0; |
395 | fail: | ||
396 | free_buffer(vq, buf); | ||
397 | out: | ||
398 | return ret; | ||
399 | } | 373 | } |
400 | 374 | ||
401 | /* Called under spinlock_irqsave(&pcdev->lock, ...) */ | 375 | 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 | { | 376 | { |
405 | struct soc_camera_device *icd = vq->priv_data; | 377 | 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); | 378 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
407 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 379 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
380 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | ||
381 | unsigned long flags; | ||
408 | 382 | ||
409 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__, | 383 | dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, |
410 | vb, vb->baddr, vb->bsize); | 384 | vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); |
411 | 385 | ||
412 | vb->state = VIDEOBUF_QUEUED; | 386 | spin_lock_irqsave(&pcdev->lock, flags); |
413 | list_add_tail(&vb->queue, &pcdev->capture); | 387 | list_add_tail(&buf->queue, &pcdev->capture); |
414 | 388 | ||
415 | if (!pcdev->active) { | 389 | if (!pcdev->active) { |
416 | /* | 390 | /* |
@@ -421,13 +395,14 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq, | |||
421 | pcdev->active = vb; | 395 | pcdev->active = vb; |
422 | sh_mobile_ceu_capture(pcdev); | 396 | sh_mobile_ceu_capture(pcdev); |
423 | } | 397 | } |
398 | spin_unlock_irqrestore(&pcdev->lock, flags); | ||
424 | } | 399 | } |
425 | 400 | ||
426 | static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, | 401 | static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) |
427 | struct videobuf_buffer *vb) | ||
428 | { | 402 | { |
429 | struct soc_camera_device *icd = vq->priv_data; | 403 | 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); | 404 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
405 | struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); | ||
431 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 406 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
432 | unsigned long flags; | 407 | unsigned long flags; |
433 | 408 | ||
@@ -439,53 +414,60 @@ static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq, | |||
439 | pcdev->active = NULL; | 414 | pcdev->active = NULL; |
440 | } | 415 | } |
441 | 416 | ||
442 | if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) && | 417 | /* Doesn't hurt also if the list is empty */ |
443 | !list_empty(&vb->queue)) { | 418 | list_del_init(&buf->queue); |
444 | vb->state = VIDEOBUF_ERROR; | ||
445 | list_del_init(&vb->queue); | ||
446 | } | ||
447 | 419 | ||
448 | spin_unlock_irqrestore(&pcdev->lock, flags); | 420 | spin_unlock_irqrestore(&pcdev->lock, flags); |
421 | } | ||
449 | 422 | ||
450 | free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb)); | 423 | static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) |
424 | { | ||
425 | /* This is for locking debugging only */ | ||
426 | INIT_LIST_HEAD(&to_ceu_vb(vb)->queue); | ||
427 | return 0; | ||
451 | } | 428 | } |
452 | 429 | ||
453 | static struct videobuf_queue_ops sh_mobile_ceu_videobuf_ops = { | 430 | static struct vb2_ops sh_mobile_ceu_videobuf_ops = { |
454 | .buf_setup = sh_mobile_ceu_videobuf_setup, | 431 | .queue_setup = sh_mobile_ceu_videobuf_setup, |
455 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, | 432 | .buf_prepare = sh_mobile_ceu_videobuf_prepare, |
456 | .buf_queue = sh_mobile_ceu_videobuf_queue, | 433 | .buf_queue = sh_mobile_ceu_videobuf_queue, |
457 | .buf_release = sh_mobile_ceu_videobuf_release, | 434 | .buf_cleanup = sh_mobile_ceu_videobuf_release, |
435 | .buf_init = sh_mobile_ceu_videobuf_init, | ||
436 | .wait_prepare = soc_camera_unlock, | ||
437 | .wait_finish = soc_camera_lock, | ||
458 | }; | 438 | }; |
459 | 439 | ||
460 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) | 440 | static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) |
461 | { | 441 | { |
462 | struct sh_mobile_ceu_dev *pcdev = data; | 442 | struct sh_mobile_ceu_dev *pcdev = data; |
463 | struct videobuf_buffer *vb; | 443 | struct vb2_buffer *vb; |
464 | unsigned long flags; | 444 | int ret; |
465 | 445 | ||
466 | spin_lock_irqsave(&pcdev->lock, flags); | 446 | spin_lock(&pcdev->lock); |
467 | 447 | ||
468 | vb = pcdev->active; | 448 | vb = pcdev->active; |
469 | if (!vb) | 449 | if (!vb) |
470 | /* Stale interrupt from a released buffer */ | 450 | /* Stale interrupt from a released buffer */ |
471 | goto out; | 451 | goto out; |
472 | 452 | ||
473 | list_del_init(&vb->queue); | 453 | list_del_init(&to_ceu_vb(vb)->queue); |
474 | 454 | ||
475 | if (!list_empty(&pcdev->capture)) | 455 | if (!list_empty(&pcdev->capture)) |
476 | pcdev->active = list_entry(pcdev->capture.next, | 456 | pcdev->active = &list_entry(pcdev->capture.next, |
477 | struct videobuf_buffer, queue); | 457 | struct sh_mobile_ceu_buffer, queue)->vb; |
478 | else | 458 | else |
479 | pcdev->active = NULL; | 459 | pcdev->active = NULL; |
480 | 460 | ||
481 | vb->state = (sh_mobile_ceu_capture(pcdev) < 0) ? | 461 | ret = sh_mobile_ceu_capture(pcdev); |
482 | VIDEOBUF_ERROR : VIDEOBUF_DONE; | 462 | do_gettimeofday(&vb->v4l2_buf.timestamp); |
483 | do_gettimeofday(&vb->ts); | 463 | if (!ret) { |
484 | vb->field_count++; | 464 | vb->v4l2_buf.field = pcdev->field; |
485 | wake_up(&vb->done); | 465 | vb->v4l2_buf.sequence = pcdev->sequence++; |
466 | } | ||
467 | vb2_buffer_done(vb, ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); | ||
486 | 468 | ||
487 | out: | 469 | out: |
488 | spin_unlock_irqrestore(&pcdev->lock, flags); | 470 | spin_unlock(&pcdev->lock); |
489 | 471 | ||
490 | return IRQ_HANDLED; | 472 | return IRQ_HANDLED; |
491 | } | 473 | } |
@@ -529,9 +511,8 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd) | |||
529 | /* make sure active buffer is canceled */ | 511 | /* make sure active buffer is canceled */ |
530 | spin_lock_irqsave(&pcdev->lock, flags); | 512 | spin_lock_irqsave(&pcdev->lock, flags); |
531 | if (pcdev->active) { | 513 | if (pcdev->active) { |
532 | list_del(&pcdev->active->queue); | 514 | list_del_init(&to_ceu_vb(pcdev->active)->queue); |
533 | pcdev->active->state = VIDEOBUF_ERROR; | 515 | vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); |
534 | wake_up_all(&pcdev->active->done); | ||
535 | pcdev->active = NULL; | 516 | pcdev->active = NULL; |
536 | } | 517 | } |
537 | spin_unlock_irqrestore(&pcdev->lock, flags); | 518 | spin_unlock_irqrestore(&pcdev->lock, flags); |
@@ -686,6 +667,7 @@ static void capture_restore(struct sh_mobile_ceu_dev *pcdev, u32 capsr) | |||
686 | ceu_write(pcdev, CAPSR, capsr); | 667 | ceu_write(pcdev, CAPSR, capsr); |
687 | } | 668 | } |
688 | 669 | ||
670 | /* Capture is not running, no interrupts, no locking needed */ | ||
689 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | 671 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, |
690 | __u32 pixfmt) | 672 | __u32 pixfmt) |
691 | { | 673 | { |
@@ -1364,7 +1346,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1364 | struct device *dev = icd->dev.parent; | 1346 | struct device *dev = icd->dev.parent; |
1365 | struct v4l2_mbus_framefmt mf; | 1347 | struct v4l2_mbus_framefmt mf; |
1366 | unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v, | 1348 | unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v, |
1367 | out_width, out_height, scale_h, scale_v; | 1349 | out_width, out_height; |
1368 | int interm_width, interm_height; | 1350 | int interm_width, interm_height; |
1369 | u32 capsr, cflcr; | 1351 | u32 capsr, cflcr; |
1370 | int ret; | 1352 | int ret; |
@@ -1422,10 +1404,6 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1422 | scale_ceu_h = calc_scale(interm_width, &out_width); | 1404 | scale_ceu_h = calc_scale(interm_width, &out_width); |
1423 | scale_ceu_v = calc_scale(interm_height, &out_height); | 1405 | scale_ceu_v = calc_scale(interm_height, &out_height); |
1424 | 1406 | ||
1425 | /* Calculate camera scales */ | ||
1426 | scale_h = calc_generic_scale(cam_rect->width, out_width); | ||
1427 | scale_v = calc_generic_scale(cam_rect->height, out_height); | ||
1428 | |||
1429 | dev_geo(dev, "5: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); | 1407 | dev_geo(dev, "5: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v); |
1430 | 1408 | ||
1431 | /* Apply CEU scales. */ | 1409 | /* Apply CEU scales. */ |
@@ -1437,8 +1415,8 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1437 | 1415 | ||
1438 | icd->user_width = out_width; | 1416 | icd->user_width = out_width; |
1439 | icd->user_height = out_height; | 1417 | icd->user_height = out_height; |
1440 | cam->ceu_left = scale_down(rect->left - cam_rect->left, scale_h) & ~1; | 1418 | cam->ceu_left = scale_down(rect->left - cam_rect->left, scale_cam_h) & ~1; |
1441 | cam->ceu_top = scale_down(rect->top - cam_rect->top, scale_v) & ~1; | 1419 | cam->ceu_top = scale_down(rect->top - cam_rect->top, scale_cam_v) & ~1; |
1442 | 1420 | ||
1443 | /* 6. Use CEU cropping to crop to the new window. */ | 1421 | /* 6. Use CEU cropping to crop to the new window. */ |
1444 | sh_mobile_ceu_set_rect(icd); | 1422 | sh_mobile_ceu_set_rect(icd); |
@@ -1449,7 +1427,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, | |||
1449 | icd->user_width, icd->user_height, | 1427 | icd->user_width, icd->user_height, |
1450 | cam->ceu_left, cam->ceu_top); | 1428 | cam->ceu_left, cam->ceu_top); |
1451 | 1429 | ||
1452 | /* Restore capture */ | 1430 | /* Restore capture. The CE bit can be cleared by the hardware */ |
1453 | if (pcdev->active) | 1431 | if (pcdev->active) |
1454 | capsr |= 1; | 1432 | capsr |= 1; |
1455 | capture_restore(pcdev, capsr); | 1433 | capture_restore(pcdev, capsr); |
@@ -1726,43 +1704,11 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1726 | return ret; | 1704 | return ret; |
1727 | } | 1705 | } |
1728 | 1706 | ||
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) | 1707 | static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) |
1752 | { | 1708 | { |
1753 | struct soc_camera_device *icd = file->private_data; | 1709 | 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 | 1710 | ||
1761 | if (buf->vb.state == VIDEOBUF_DONE || | 1711 | return vb2_poll(&icd->vb2_vidq, file, pt); |
1762 | buf->vb.state == VIDEOBUF_ERROR) | ||
1763 | return POLLIN|POLLRDNORM; | ||
1764 | |||
1765 | return 0; | ||
1766 | } | 1712 | } |
1767 | 1713 | ||
1768 | static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, | 1714 | static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, |
@@ -1774,19 +1720,17 @@ static int sh_mobile_ceu_querycap(struct soc_camera_host *ici, | |||
1774 | return 0; | 1720 | return 0; |
1775 | } | 1721 | } |
1776 | 1722 | ||
1777 | static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q, | 1723 | static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q, |
1778 | struct soc_camera_device *icd) | 1724 | struct soc_camera_device *icd) |
1779 | { | 1725 | { |
1780 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 1726 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1781 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 1727 | q->io_modes = VB2_MMAP | VB2_USERPTR; |
1782 | 1728 | q->drv_priv = icd; | |
1783 | videobuf_queue_dma_contig_init(q, | 1729 | q->ops = &sh_mobile_ceu_videobuf_ops; |
1784 | &sh_mobile_ceu_videobuf_ops, | 1730 | q->mem_ops = &vb2_dma_contig_memops; |
1785 | icd->dev.parent, &pcdev->lock, | 1731 | q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer); |
1786 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1732 | |
1787 | pcdev->field, | 1733 | return vb2_queue_init(q); |
1788 | sizeof(struct sh_mobile_ceu_buffer), | ||
1789 | icd, &icd->video_lock); | ||
1790 | } | 1734 | } |
1791 | 1735 | ||
1792 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, | 1736 | static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd, |
@@ -1850,11 +1794,10 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = { | |||
1850 | .try_fmt = sh_mobile_ceu_try_fmt, | 1794 | .try_fmt = sh_mobile_ceu_try_fmt, |
1851 | .set_ctrl = sh_mobile_ceu_set_ctrl, | 1795 | .set_ctrl = sh_mobile_ceu_set_ctrl, |
1852 | .get_ctrl = sh_mobile_ceu_get_ctrl, | 1796 | .get_ctrl = sh_mobile_ceu_get_ctrl, |
1853 | .reqbufs = sh_mobile_ceu_reqbufs, | ||
1854 | .poll = sh_mobile_ceu_poll, | 1797 | .poll = sh_mobile_ceu_poll, |
1855 | .querycap = sh_mobile_ceu_querycap, | 1798 | .querycap = sh_mobile_ceu_querycap, |
1856 | .set_bus_param = sh_mobile_ceu_set_bus_param, | 1799 | .set_bus_param = sh_mobile_ceu_set_bus_param, |
1857 | .init_videobuf = sh_mobile_ceu_init_videobuf, | 1800 | .init_videobuf2 = sh_mobile_ceu_init_videobuf, |
1858 | .controls = sh_mobile_ceu_controls, | 1801 | .controls = sh_mobile_ceu_controls, |
1859 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), | 1802 | .num_controls = ARRAY_SIZE(sh_mobile_ceu_controls), |
1860 | }; | 1803 | }; |
@@ -2005,12 +1948,20 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2005 | } | 1948 | } |
2006 | } | 1949 | } |
2007 | 1950 | ||
1951 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1952 | if (IS_ERR(pcdev->alloc_ctx)) { | ||
1953 | err = PTR_ERR(pcdev->alloc_ctx); | ||
1954 | goto exit_module_put; | ||
1955 | } | ||
1956 | |||
2008 | err = soc_camera_host_register(&pcdev->ici); | 1957 | err = soc_camera_host_register(&pcdev->ici); |
2009 | if (err) | 1958 | if (err) |
2010 | goto exit_module_put; | 1959 | goto exit_free_ctx; |
2011 | 1960 | ||
2012 | return 0; | 1961 | return 0; |
2013 | 1962 | ||
1963 | exit_free_ctx: | ||
1964 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
2014 | exit_module_put: | 1965 | exit_module_put: |
2015 | if (csi2 && csi2->driver) | 1966 | if (csi2 && csi2->driver) |
2016 | module_put(csi2->driver->owner); | 1967 | module_put(csi2->driver->owner); |
@@ -2041,6 +1992,7 @@ static int __devexit sh_mobile_ceu_remove(struct platform_device *pdev) | |||
2041 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) | 1992 | if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) |
2042 | dma_release_declared_memory(&pdev->dev); | 1993 | dma_release_declared_memory(&pdev->dev); |
2043 | iounmap(pcdev->base); | 1994 | iounmap(pcdev->base); |
1995 | vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); | ||
2044 | if (csi2 && csi2->driver) | 1996 | if (csi2 && csi2->driver) |
2045 | module_put(csi2->driver->owner); | 1997 | module_put(csi2->driver->owner); |
2046 | kfree(pcdev); | 1998 | kfree(pcdev); |