aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/sh_mobile_ceu_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/sh_mobile_ceu_camera.c')
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c148
1 files changed, 131 insertions, 17 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 134e86bf6d9..3ae5c9c58cb 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -17,6 +17,7 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/completion.h>
20#include <linux/delay.h> 21#include <linux/delay.h>
21#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
22#include <linux/errno.h> 23#include <linux/errno.h>
@@ -106,6 +107,7 @@ struct sh_mobile_ceu_dev {
106 struct vb2_alloc_ctx *alloc_ctx; 107 struct vb2_alloc_ctx *alloc_ctx;
107 108
108 struct sh_mobile_ceu_info *pdata; 109 struct sh_mobile_ceu_info *pdata;
110 struct completion complete;
109 111
110 u32 cflcr; 112 u32 cflcr;
111 113
@@ -114,6 +116,7 @@ struct sh_mobile_ceu_dev {
114 116
115 unsigned int image_mode:1; 117 unsigned int image_mode:1;
116 unsigned int is_16bit:1; 118 unsigned int is_16bit:1;
119 unsigned int frozen:1;
117}; 120};
118 121
119struct sh_mobile_ceu_cam { 122struct sh_mobile_ceu_cam {
@@ -273,7 +276,8 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
273 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK); 276 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~CEU_CEIER_MASK);
274 status = ceu_read(pcdev, CETCR); 277 status = ceu_read(pcdev, CETCR);
275 ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC); 278 ceu_write(pcdev, CETCR, ~status & CEU_CETCR_MAGIC);
276 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK); 279 if (!pcdev->frozen)
280 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | CEU_CEIER_MASK);
277 ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP); 281 ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~CEU_CAPCR_CTNCP);
278 ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW); 282 ceu_write(pcdev, CETCR, CEU_CETCR_MAGIC ^ CEU_CETCR_IGRW);
279 283
@@ -287,6 +291,11 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
287 ret = -EIO; 291 ret = -EIO;
288 } 292 }
289 293
294 if (pcdev->frozen) {
295 complete(&pcdev->complete);
296 return ret;
297 }
298
290 if (!pcdev->active) 299 if (!pcdev->active)
291 return ret; 300 return ret;
292 301
@@ -378,12 +387,11 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
378 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 387 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
379 struct sh_mobile_ceu_dev *pcdev = ici->priv; 388 struct sh_mobile_ceu_dev *pcdev = ici->priv;
380 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); 389 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
381 unsigned long flags;
382 390
383 dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, 391 dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
384 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); 392 vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
385 393
386 spin_lock_irqsave(&pcdev->lock, flags); 394 spin_lock_irq(&pcdev->lock);
387 list_add_tail(&buf->queue, &pcdev->capture); 395 list_add_tail(&buf->queue, &pcdev->capture);
388 396
389 if (!pcdev->active) { 397 if (!pcdev->active) {
@@ -395,7 +403,7 @@ static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
395 pcdev->active = vb; 403 pcdev->active = vb;
396 sh_mobile_ceu_capture(pcdev); 404 sh_mobile_ceu_capture(pcdev);
397 } 405 }
398 spin_unlock_irqrestore(&pcdev->lock, flags); 406 spin_unlock_irq(&pcdev->lock);
399} 407}
400 408
401static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) 409static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
@@ -404,9 +412,8 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
404 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 412 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
405 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb); 413 struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
406 struct sh_mobile_ceu_dev *pcdev = ici->priv; 414 struct sh_mobile_ceu_dev *pcdev = ici->priv;
407 unsigned long flags;
408 415
409 spin_lock_irqsave(&pcdev->lock, flags); 416 spin_lock_irq(&pcdev->lock);
410 417
411 if (pcdev->active == vb) { 418 if (pcdev->active == vb) {
412 /* disable capture (release DMA buffer), reset */ 419 /* disable capture (release DMA buffer), reset */
@@ -417,7 +424,7 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
417 /* Doesn't hurt also if the list is empty */ 424 /* Doesn't hurt also if the list is empty */
418 list_del_init(&buf->queue); 425 list_del_init(&buf->queue);
419 426
420 spin_unlock_irqrestore(&pcdev->lock, flags); 427 spin_unlock_irq(&pcdev->lock);
421} 428}
422 429
423static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) 430static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
@@ -427,6 +434,25 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
427 return 0; 434 return 0;
428} 435}
429 436
437static int sh_mobile_ceu_stop_streaming(struct vb2_queue *q)
438{
439 struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq);
440 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
441 struct sh_mobile_ceu_dev *pcdev = ici->priv;
442 struct list_head *buf_head, *tmp;
443
444 spin_lock_irq(&pcdev->lock);
445
446 pcdev->active = NULL;
447
448 list_for_each_safe(buf_head, tmp, &pcdev->capture)
449 list_del_init(buf_head);
450
451 spin_unlock_irq(&pcdev->lock);
452
453 return sh_mobile_ceu_soft_reset(pcdev);
454}
455
430static struct vb2_ops sh_mobile_ceu_videobuf_ops = { 456static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
431 .queue_setup = sh_mobile_ceu_videobuf_setup, 457 .queue_setup = sh_mobile_ceu_videobuf_setup,
432 .buf_prepare = sh_mobile_ceu_videobuf_prepare, 458 .buf_prepare = sh_mobile_ceu_videobuf_prepare,
@@ -435,6 +461,7 @@ static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
435 .buf_init = sh_mobile_ceu_videobuf_init, 461 .buf_init = sh_mobile_ceu_videobuf_init,
436 .wait_prepare = soc_camera_unlock, 462 .wait_prepare = soc_camera_unlock,
437 .wait_finish = soc_camera_lock, 463 .wait_finish = soc_camera_lock,
464 .stop_streaming = sh_mobile_ceu_stop_streaming,
438}; 465};
439 466
440static irqreturn_t sh_mobile_ceu_irq(int irq, void *data) 467static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
@@ -500,7 +527,6 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
500{ 527{
501 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 528 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
502 struct sh_mobile_ceu_dev *pcdev = ici->priv; 529 struct sh_mobile_ceu_dev *pcdev = ici->priv;
503 unsigned long flags;
504 530
505 BUG_ON(icd != pcdev->icd); 531 BUG_ON(icd != pcdev->icd);
506 532
@@ -509,13 +535,13 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
509 sh_mobile_ceu_soft_reset(pcdev); 535 sh_mobile_ceu_soft_reset(pcdev);
510 536
511 /* make sure active buffer is canceled */ 537 /* make sure active buffer is canceled */
512 spin_lock_irqsave(&pcdev->lock, flags); 538 spin_lock_irq(&pcdev->lock);
513 if (pcdev->active) { 539 if (pcdev->active) {
514 list_del_init(&to_ceu_vb(pcdev->active)->queue); 540 list_del_init(&to_ceu_vb(pcdev->active)->queue);
515 vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR); 541 vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR);
516 pcdev->active = NULL; 542 pcdev->active = NULL;
517 } 543 }
518 spin_unlock_irqrestore(&pcdev->lock, flags); 544 spin_unlock_irq(&pcdev->lock);
519 545
520 pm_runtime_put_sync(ici->v4l2_dev.dev); 546 pm_runtime_put_sync(ici->v4l2_dev.dev);
521 547
@@ -891,8 +917,8 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
891 917
892 fmt = soc_mbus_get_fmtdesc(code); 918 fmt = soc_mbus_get_fmtdesc(code);
893 if (!fmt) { 919 if (!fmt) {
894 dev_err(dev, "Invalid format code #%u: %d\n", idx, code); 920 dev_warn(dev, "unsupported format code #%u: %d\n", idx, code);
895 return -EINVAL; 921 return 0;
896 } 922 }
897 923
898 if (!pcdev->pdata->csi2_dev) { 924 if (!pcdev->pdata->csi2_dev) {
@@ -1330,7 +1356,7 @@ static int client_scale(struct soc_camera_device *icd,
1330/* 1356/*
1331 * CEU can scale and crop, but we don't want to waste bandwidth and kill the 1357 * CEU can scale and crop, but we don't want to waste bandwidth and kill the
1332 * framerate by always requesting the maximum image from the client. See 1358 * framerate by always requesting the maximum image from the client. See
1333 * Documentation/video4linux/sh_mobile_camera_ceu.txt for a description of 1359 * Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of
1334 * scaling and cropping algorithms and for the meaning of referenced here steps. 1360 * scaling and cropping algorithms and for the meaning of referenced here steps.
1335 */ 1361 */
1336static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, 1362static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
@@ -1377,10 +1403,6 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1377 if (mf.width > 2560 || mf.height > 1920) 1403 if (mf.width > 2560 || mf.height > 1920)
1378 return -EINVAL; 1404 return -EINVAL;
1379 1405
1380 /* Cache camera output window */
1381 cam->width = mf.width;
1382 cam->height = mf.height;
1383
1384 /* 4. Calculate camera scales */ 1406 /* 4. Calculate camera scales */
1385 scale_cam_h = calc_generic_scale(cam_rect->width, mf.width); 1407 scale_cam_h = calc_generic_scale(cam_rect->width, mf.width);
1386 scale_cam_v = calc_generic_scale(cam_rect->height, mf.height); 1408 scale_cam_v = calc_generic_scale(cam_rect->height, mf.height);
@@ -1389,6 +1411,39 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
1389 interm_width = scale_down(rect->width, scale_cam_h); 1411 interm_width = scale_down(rect->width, scale_cam_h);
1390 interm_height = scale_down(rect->height, scale_cam_v); 1412 interm_height = scale_down(rect->height, scale_cam_v);
1391 1413
1414 if (interm_width < icd->user_width) {
1415 u32 new_scale_h;
1416
1417 new_scale_h = calc_generic_scale(rect->width, icd->user_width);
1418
1419 mf.width = scale_down(cam_rect->width, new_scale_h);
1420 }
1421
1422 if (interm_height < icd->user_height) {
1423 u32 new_scale_v;
1424
1425 new_scale_v = calc_generic_scale(rect->height, icd->user_height);
1426
1427 mf.height = scale_down(cam_rect->height, new_scale_v);
1428 }
1429
1430 if (interm_width < icd->user_width || interm_height < icd->user_height) {
1431 ret = v4l2_device_call_until_err(sd->v4l2_dev, (int)icd, video,
1432 s_mbus_fmt, &mf);
1433 if (ret < 0)
1434 return ret;
1435
1436 dev_geo(dev, "New camera output %ux%u\n", mf.width, mf.height);
1437 scale_cam_h = calc_generic_scale(cam_rect->width, mf.width);
1438 scale_cam_v = calc_generic_scale(cam_rect->height, mf.height);
1439 interm_width = scale_down(rect->width, scale_cam_h);
1440 interm_height = scale_down(rect->height, scale_cam_v);
1441 }
1442
1443 /* Cache camera output window */
1444 cam->width = mf.width;
1445 cam->height = mf.height;
1446
1392 if (pcdev->image_mode) { 1447 if (pcdev->image_mode) {
1393 out_width = min(interm_width, icd->user_width); 1448 out_width = min(interm_width, icd->user_width);
1394 out_height = min(interm_height, icd->user_height); 1449 out_height = min(interm_height, icd->user_height);
@@ -1704,6 +1759,63 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
1704 return ret; 1759 return ret;
1705} 1760}
1706 1761
1762static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
1763 struct v4l2_crop *a)
1764{
1765 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
1766 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
1767 struct sh_mobile_ceu_dev *pcdev = ici->priv;
1768 u32 out_width = icd->user_width, out_height = icd->user_height;
1769 int ret;
1770
1771 /* Freeze queue */
1772 pcdev->frozen = 1;
1773 /* Wait for frame */
1774 ret = wait_for_completion_interruptible(&pcdev->complete);
1775 /* Stop the client */
1776 ret = v4l2_subdev_call(sd, video, s_stream, 0);
1777 if (ret < 0)
1778 dev_warn(icd->dev.parent,
1779 "Client failed to stop the stream: %d\n", ret);
1780 else
1781 /* Do the crop, if it fails, there's nothing more we can do */
1782 sh_mobile_ceu_set_crop(icd, a);
1783
1784 dev_geo(icd->dev.parent, "Output after crop: %ux%u\n", icd->user_width, icd->user_height);
1785
1786 if (icd->user_width != out_width || icd->user_height != out_height) {
1787 struct v4l2_format f = {
1788 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
1789 .fmt.pix = {
1790 .width = out_width,
1791 .height = out_height,
1792 .pixelformat = icd->current_fmt->host_fmt->fourcc,
1793 .field = pcdev->field,
1794 .colorspace = icd->colorspace,
1795 },
1796 };
1797 ret = sh_mobile_ceu_set_fmt(icd, &f);
1798 if (!ret && (out_width != f.fmt.pix.width ||
1799 out_height != f.fmt.pix.height))
1800 ret = -EINVAL;
1801 if (!ret) {
1802 icd->user_width = out_width;
1803 icd->user_height = out_height;
1804 ret = sh_mobile_ceu_set_bus_param(icd,
1805 icd->current_fmt->host_fmt->fourcc);
1806 }
1807 }
1808
1809 /* Thaw the queue */
1810 pcdev->frozen = 0;
1811 spin_lock_irq(&pcdev->lock);
1812 sh_mobile_ceu_capture(pcdev);
1813 spin_unlock_irq(&pcdev->lock);
1814 /* Start the client */
1815 ret = v4l2_subdev_call(sd, video, s_stream, 1);
1816 return ret;
1817}
1818
1707static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) 1819static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt)
1708{ 1820{
1709 struct soc_camera_device *icd = file->private_data; 1821 struct soc_camera_device *icd = file->private_data;
@@ -1790,6 +1902,7 @@ static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
1790 .put_formats = sh_mobile_ceu_put_formats, 1902 .put_formats = sh_mobile_ceu_put_formats,
1791 .get_crop = sh_mobile_ceu_get_crop, 1903 .get_crop = sh_mobile_ceu_get_crop,
1792 .set_crop = sh_mobile_ceu_set_crop, 1904 .set_crop = sh_mobile_ceu_set_crop,
1905 .set_livecrop = sh_mobile_ceu_set_livecrop,
1793 .set_fmt = sh_mobile_ceu_set_fmt, 1906 .set_fmt = sh_mobile_ceu_set_fmt,
1794 .try_fmt = sh_mobile_ceu_try_fmt, 1907 .try_fmt = sh_mobile_ceu_try_fmt,
1795 .set_ctrl = sh_mobile_ceu_set_ctrl, 1908 .set_ctrl = sh_mobile_ceu_set_ctrl,
@@ -1856,6 +1969,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
1856 1969
1857 INIT_LIST_HEAD(&pcdev->capture); 1970 INIT_LIST_HEAD(&pcdev->capture);
1858 spin_lock_init(&pcdev->lock); 1971 spin_lock_init(&pcdev->lock);
1972 init_completion(&pcdev->complete);
1859 1973
1860 pcdev->pdata = pdev->dev.platform_data; 1974 pcdev->pdata = pdev->dev.platform_data;
1861 if (!pcdev->pdata) { 1975 if (!pcdev->pdata) {