diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2009-03-31 02:44:21 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-04-06 20:43:44 -0400 |
commit | 92a8337b380f0978ac81f096d6324d3ad689f83e (patch) | |
tree | 8a09a2d450f168a16e346167dd57d06c410049f1 /drivers/media/video/pxa_camera.c | |
parent | fedd73ccce8c77b677f8a9090feab8f8c6c9b03c (diff) |
V4L/DVB (11319): pxa_camera: Enforce YUV422P frame sizes to be 16 multiples
Due to DMA constraints, the DMA chain always transfers bytes
from the QCI fifos to memory in 8 bytes units. In planar
formats, that could mean 0 padding between Y and U plane
(and between U and V plane), which is against YUV422P
standard.
Therefore, a frame size is required to be a multiple of 16
(so U plane size is a multiple of 8). It is enforced in
try_fmt() and set_fmt() primitives, be aligning height then
width on 4 multiples as need be, to reach a 16 multiple.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pxa_camera.c')
-rw-r--r-- | drivers/media/video/pxa_camera.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index c522616ef38f..5f57e4018849 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -163,6 +163,13 @@ | |||
163 | CICR0_EOFM | CICR0_FOM) | 163 | CICR0_EOFM | CICR0_FOM) |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * YUV422P picture size should be a multiple of 16, so the heuristic aligns | ||
167 | * height, width on 4 byte boundaries to reach the 16 multiple for the size. | ||
168 | */ | ||
169 | #define YUV422P_X_Y_ALIGN 4 | ||
170 | #define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN | ||
171 | |||
172 | /* | ||
166 | * Structures | 173 | * Structures |
167 | */ | 174 | */ |
168 | enum pxa_camera_active_dma { | 175 | enum pxa_camera_active_dma { |
@@ -236,20 +243,11 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, | |||
236 | unsigned int *size) | 243 | unsigned int *size) |
237 | { | 244 | { |
238 | struct soc_camera_device *icd = vq->priv_data; | 245 | struct soc_camera_device *icd = vq->priv_data; |
239 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | ||
240 | struct pxa_camera_dev *pcdev = ici->priv; | ||
241 | 246 | ||
242 | dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); | 247 | dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size); |
243 | 248 | ||
244 | /* planar capture requires Y, U and V buffers to be page aligned */ | 249 | *size = roundup(icd->width * icd->height * |
245 | if (pcdev->channels == 3) { | 250 | ((icd->current_fmt->depth + 7) >> 3), 8); |
246 | *size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */ | ||
247 | *size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */ | ||
248 | *size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */ | ||
249 | } else { | ||
250 | *size = icd->width * icd->height * | ||
251 | ((icd->current_fmt->depth + 7) >> 3); | ||
252 | } | ||
253 | 251 | ||
254 | if (0 == *count) | 252 | if (0 == *count) |
255 | *count = 32; | 253 | *count = 32; |
@@ -1265,6 +1263,18 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, | |||
1265 | pix->width = 2048; | 1263 | pix->width = 2048; |
1266 | pix->width &= ~0x01; | 1264 | pix->width &= ~0x01; |
1267 | 1265 | ||
1266 | /* | ||
1267 | * YUV422P planar format requires images size to be a 16 bytes | ||
1268 | * multiple. If not, zeros will be inserted between Y and U planes, and | ||
1269 | * U and V planes, and YUV422P standard would be violated. | ||
1270 | */ | ||
1271 | if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { | ||
1272 | if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) | ||
1273 | pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN); | ||
1274 | if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) | ||
1275 | pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN); | ||
1276 | } | ||
1277 | |||
1268 | pix->bytesperline = pix->width * | 1278 | pix->bytesperline = pix->width * |
1269 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 1279 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); |
1270 | pix->sizeimage = pix->height * pix->bytesperline; | 1280 | pix->sizeimage = pix->height * pix->bytesperline; |