diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-03-21 07:16:05 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-15 15:13:22 -0400 |
commit | fc13baff743cf9fa49035974471c17378bfe6146 (patch) | |
tree | 9bd286e49b1dfb0abec5d12fecd429ce1fd39a0e /drivers/media/video | |
parent | 914f05c8118e17d65c4626ae3ed2edcf79f00031 (diff) |
[media] sh_mobile_ceu_camera: Support user-configurable line stride
In image mode, the CEU allows configurable line strides up to 8188
pixels.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[g.liakhovetski@gmx.de: unify sh_mobile_ceu_set_rect() in data-fetch mode]
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/sh_mobile_ceu_camera.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 79bec15cc4a3..2ffeb21dfe33 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -342,19 +342,15 @@ static int sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev) | |||
342 | 342 | ||
343 | ceu_write(pcdev, top1, phys_addr_top); | 343 | ceu_write(pcdev, top1, phys_addr_top); |
344 | if (V4L2_FIELD_NONE != pcdev->field) { | 344 | if (V4L2_FIELD_NONE != pcdev->field) { |
345 | if (planar) | 345 | phys_addr_bottom = phys_addr_top + icd->bytesperline; |
346 | phys_addr_bottom = phys_addr_top + icd->user_width; | ||
347 | else | ||
348 | phys_addr_bottom = phys_addr_top + icd->bytesperline; | ||
349 | ceu_write(pcdev, bottom1, phys_addr_bottom); | 346 | ceu_write(pcdev, bottom1, phys_addr_bottom); |
350 | } | 347 | } |
351 | 348 | ||
352 | if (planar) { | 349 | if (planar) { |
353 | phys_addr_top += icd->user_width * | 350 | phys_addr_top += icd->bytesperline * icd->user_height; |
354 | icd->user_height; | ||
355 | ceu_write(pcdev, top2, phys_addr_top); | 351 | ceu_write(pcdev, top2, phys_addr_top); |
356 | if (V4L2_FIELD_NONE != pcdev->field) { | 352 | if (V4L2_FIELD_NONE != pcdev->field) { |
357 | phys_addr_bottom = phys_addr_top + icd->user_width; | 353 | phys_addr_bottom = phys_addr_top + icd->bytesperline; |
358 | ceu_write(pcdev, bottom2, phys_addr_bottom); | 354 | ceu_write(pcdev, bottom2, phys_addr_bottom); |
359 | } | 355 | } |
360 | } | 356 | } |
@@ -681,10 +677,7 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) | |||
681 | in_width *= 2; | 677 | in_width *= 2; |
682 | left_offset *= 2; | 678 | left_offset *= 2; |
683 | } | 679 | } |
684 | cdwdr_width = width; | ||
685 | } else { | 680 | } else { |
686 | int bytes_per_line = soc_mbus_bytes_per_line(width, | ||
687 | icd->current_fmt->host_fmt); | ||
688 | unsigned int w_factor; | 681 | unsigned int w_factor; |
689 | 682 | ||
690 | switch (icd->current_fmt->host_fmt->packing) { | 683 | switch (icd->current_fmt->host_fmt->packing) { |
@@ -697,13 +690,10 @@ static void sh_mobile_ceu_set_rect(struct soc_camera_device *icd) | |||
697 | 690 | ||
698 | in_width = cam->width * w_factor; | 691 | in_width = cam->width * w_factor; |
699 | left_offset *= w_factor; | 692 | left_offset *= w_factor; |
700 | |||
701 | if (bytes_per_line < 0) | ||
702 | cdwdr_width = width; | ||
703 | else | ||
704 | cdwdr_width = bytes_per_line; | ||
705 | } | 693 | } |
706 | 694 | ||
695 | cdwdr_width = icd->bytesperline; | ||
696 | |||
707 | height = icd->user_height; | 697 | height = icd->user_height; |
708 | in_height = cam->height; | 698 | in_height = cam->height; |
709 | if (V4L2_FIELD_NONE != pcdev->field) { | 699 | if (V4L2_FIELD_NONE != pcdev->field) { |
@@ -1848,6 +1838,8 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd, | |||
1848 | return 0; | 1838 | return 0; |
1849 | } | 1839 | } |
1850 | 1840 | ||
1841 | #define CEU_CHDW_MAX 8188U /* Maximum line stride */ | ||
1842 | |||
1851 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | 1843 | static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, |
1852 | struct v4l2_format *f) | 1844 | struct v4l2_format *f) |
1853 | { | 1845 | { |
@@ -1926,10 +1918,20 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
1926 | pix->width = width; | 1918 | pix->width = width; |
1927 | if (mf.height > height) | 1919 | if (mf.height > height) |
1928 | pix->height = height; | 1920 | pix->height = height; |
1921 | |||
1922 | pix->bytesperline = max(pix->bytesperline, pix->width); | ||
1923 | pix->bytesperline = min(pix->bytesperline, CEU_CHDW_MAX); | ||
1924 | pix->bytesperline &= ~3; | ||
1925 | break; | ||
1926 | |||
1927 | default: | ||
1928 | /* Configurable stride isn't supported in pass-through mode. */ | ||
1929 | pix->bytesperline = 0; | ||
1929 | } | 1930 | } |
1930 | 1931 | ||
1931 | pix->width &= ~3; | 1932 | pix->width &= ~3; |
1932 | pix->height &= ~3; | 1933 | pix->height &= ~3; |
1934 | pix->sizeimage = 0; | ||
1933 | 1935 | ||
1934 | dev_geo(icd->parent, "%s(): return %d, fmt 0x%x, %ux%u\n", | 1936 | dev_geo(icd->parent, "%s(): return %d, fmt 0x%x, %ux%u\n", |
1935 | __func__, ret, pix->pixelformat, pix->width, pix->height); | 1937 | __func__, ret, pix->pixelformat, pix->width, pix->height); |
@@ -2148,6 +2150,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) | |||
2148 | pcdev->ici.nr = pdev->id; | 2150 | pcdev->ici.nr = pdev->id; |
2149 | pcdev->ici.drv_name = dev_name(&pdev->dev); | 2151 | pcdev->ici.drv_name = dev_name(&pdev->dev); |
2150 | pcdev->ici.ops = &sh_mobile_ceu_host_ops; | 2152 | pcdev->ici.ops = &sh_mobile_ceu_host_ops; |
2153 | pcdev->ici.capabilities = SOCAM_HOST_CAP_STRIDE; | ||
2151 | 2154 | ||
2152 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | 2155 | pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); |
2153 | if (IS_ERR(pcdev->alloc_ctx)) { | 2156 | if (IS_ERR(pcdev->alloc_ctx)) { |