diff options
author | Alberto Panizzo <maramaopercheseimorto@gmail.com> | 2011-01-17 04:52:10 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:32:14 -0400 |
commit | a48be1d626ceb05b58a980a962214431af8041e8 (patch) | |
tree | ba83dcc99d9884dfbc4f731aeed61f7985f00728 /drivers/media/video/mx3_camera.c | |
parent | 44facdc8c43a8b5172d6cbe995845c9889561aa0 (diff) |
[media] V4L: mx3_camera: fix capture issues for non 8-bit per pixel formats
If the camera was set to output formats like RGB565 YUYV or SBGGR10,
the resulting image was scrambled due to erroneous interpretations of
horizontal parameter's units.
This patch in fourcc_to_ipu_pix, eliminate also the pixel formats mappings
that, first are not used within mainline code and second, standing at
the datasheets, they will not work properly:
The IPU internal bus support only the following data formatting
(44.1.1.3 Data Flows and Formats):
1 YUV 4:4:4 or RGB-8 bits per color component
2 YUV 4:4:4 or RGB-10 bits per color component
3 Generic data (from sensor to the system memory only)
And format conversions are done:
- from memory: unpacking from other formats to IPU supported ones
- to memory: packing in the inverse order.
So, assigning a packing/unpacking strategy to the IPU for those formats
will produce a packing to memory and not the inverse.
Signed-off-by: Alberto Panizzo <maramaopercheseimorto@gmail.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mx3_camera.c')
-rw-r--r-- | drivers/media/video/mx3_camera.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index 1cfff4132a0b..c8c6c03a6a62 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -324,14 +324,10 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) | |||
324 | { | 324 | { |
325 | /* Add more formats as need arises and test possibilities appear... */ | 325 | /* Add more formats as need arises and test possibilities appear... */ |
326 | switch (fourcc) { | 326 | switch (fourcc) { |
327 | case V4L2_PIX_FMT_RGB565: | ||
328 | return IPU_PIX_FMT_RGB565; | ||
329 | case V4L2_PIX_FMT_RGB24: | 327 | case V4L2_PIX_FMT_RGB24: |
330 | return IPU_PIX_FMT_RGB24; | 328 | return IPU_PIX_FMT_RGB24; |
331 | case V4L2_PIX_FMT_RGB332: | 329 | case V4L2_PIX_FMT_UYVY: |
332 | return IPU_PIX_FMT_RGB332; | 330 | case V4L2_PIX_FMT_RGB565: |
333 | case V4L2_PIX_FMT_YUV422P: | ||
334 | return IPU_PIX_FMT_YVU422P; | ||
335 | default: | 331 | default: |
336 | return IPU_PIX_FMT_GENERIC; | 332 | return IPU_PIX_FMT_GENERIC; |
337 | } | 333 | } |
@@ -359,9 +355,31 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq, | |||
359 | 355 | ||
360 | /* This is the configuration of one sg-element */ | 356 | /* This is the configuration of one sg-element */ |
361 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); | 357 | video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc); |
362 | video->out_width = icd->user_width; | 358 | |
363 | video->out_height = icd->user_height; | 359 | if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) { |
364 | video->out_stride = icd->user_width; | 360 | /* |
361 | * If the IPU DMA channel is configured to transport | ||
362 | * generic 8-bit data, we have to set up correctly the | ||
363 | * geometry parameters upon the current pixel format. | ||
364 | * So, since the DMA horizontal parameters are expressed | ||
365 | * in bytes not pixels, convert these in the right unit. | ||
366 | */ | ||
367 | int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, | ||
368 | icd->current_fmt->host_fmt); | ||
369 | BUG_ON(bytes_per_line <= 0); | ||
370 | |||
371 | video->out_width = bytes_per_line; | ||
372 | video->out_height = icd->user_height; | ||
373 | video->out_stride = bytes_per_line; | ||
374 | } else { | ||
375 | /* | ||
376 | * For IPU known formats the pixel unit will be managed | ||
377 | * successfully by the IPU code | ||
378 | */ | ||
379 | video->out_width = icd->user_width; | ||
380 | video->out_height = icd->user_height; | ||
381 | video->out_stride = icd->user_width; | ||
382 | } | ||
365 | 383 | ||
366 | #ifdef DEBUG | 384 | #ifdef DEBUG |
367 | /* helps to see what DMA actually has written */ | 385 | /* helps to see what DMA actually has written */ |
@@ -734,18 +752,36 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int id | |||
734 | if (xlate) { | 752 | if (xlate) { |
735 | xlate->host_fmt = fmt; | 753 | xlate->host_fmt = fmt; |
736 | xlate->code = code; | 754 | xlate->code = code; |
755 | dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n", | ||
756 | (fmt->fourcc >> (0*8)) & 0xFF, | ||
757 | (fmt->fourcc >> (1*8)) & 0xFF, | ||
758 | (fmt->fourcc >> (2*8)) & 0xFF, | ||
759 | (fmt->fourcc >> (3*8)) & 0xFF); | ||
737 | xlate++; | 760 | xlate++; |
738 | dev_dbg(dev, "Providing format %x in pass-through mode\n", | ||
739 | xlate->host_fmt->fourcc); | ||
740 | } | 761 | } |
741 | 762 | ||
742 | return formats; | 763 | return formats; |
743 | } | 764 | } |
744 | 765 | ||
745 | static void configure_geometry(struct mx3_camera_dev *mx3_cam, | 766 | static void configure_geometry(struct mx3_camera_dev *mx3_cam, |
746 | unsigned int width, unsigned int height) | 767 | unsigned int width, unsigned int height, |
768 | enum v4l2_mbus_pixelcode code) | ||
747 | { | 769 | { |
748 | u32 ctrl, width_field, height_field; | 770 | u32 ctrl, width_field, height_field; |
771 | const struct soc_mbus_pixelfmt *fmt; | ||
772 | |||
773 | fmt = soc_mbus_get_fmtdesc(code); | ||
774 | BUG_ON(!fmt); | ||
775 | |||
776 | if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { | ||
777 | /* | ||
778 | * As the CSI will be configured to output BAYER, here | ||
779 | * the width parameter count the number of samples to | ||
780 | * capture to complete the whole image width. | ||
781 | */ | ||
782 | width *= soc_mbus_samples_per_pixel(fmt); | ||
783 | BUG_ON(width < 0); | ||
784 | } | ||
749 | 785 | ||
750 | /* Setup frame size - this cannot be changed on-the-fly... */ | 786 | /* Setup frame size - this cannot be changed on-the-fly... */ |
751 | width_field = width - 1; | 787 | width_field = width - 1; |
@@ -854,7 +890,7 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd, | |||
854 | return ret; | 890 | return ret; |
855 | } | 891 | } |
856 | 892 | ||
857 | configure_geometry(mx3_cam, mf.width, mf.height); | 893 | configure_geometry(mx3_cam, mf.width, mf.height, mf.code); |
858 | } | 894 | } |
859 | 895 | ||
860 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", | 896 | dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n", |
@@ -897,7 +933,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd, | |||
897 | * mxc_v4l2_s_fmt() | 933 | * mxc_v4l2_s_fmt() |
898 | */ | 934 | */ |
899 | 935 | ||
900 | configure_geometry(mx3_cam, pix->width, pix->height); | 936 | configure_geometry(mx3_cam, pix->width, pix->height, xlate->code); |
901 | 937 | ||
902 | mf.width = pix->width; | 938 | mf.width = pix->width; |
903 | mf.height = pix->height; | 939 | mf.height = pix->height; |