mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
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>
This commit is contained in:
parent
fedd73ccce
commit
92a8337b38
@ -162,6 +162,13 @@
|
||||
CICR0_PERRM | CICR0_QDM | CICR0_CDM | CICR0_SOFM | \
|
||||
CICR0_EOFM | CICR0_FOM)
|
||||
|
||||
/*
|
||||
* YUV422P picture size should be a multiple of 16, so the heuristic aligns
|
||||
* height, width on 4 byte boundaries to reach the 16 multiple for the size.
|
||||
*/
|
||||
#define YUV422P_X_Y_ALIGN 4
|
||||
#define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN
|
||||
|
||||
/*
|
||||
* Structures
|
||||
*/
|
||||
@ -236,20 +243,11 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
|
||||
unsigned int *size)
|
||||
{
|
||||
struct soc_camera_device *icd = vq->priv_data;
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
struct pxa_camera_dev *pcdev = ici->priv;
|
||||
|
||||
dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
|
||||
|
||||
/* planar capture requires Y, U and V buffers to be page aligned */
|
||||
if (pcdev->channels == 3) {
|
||||
*size = PAGE_ALIGN(icd->width * icd->height); /* Y pages */
|
||||
*size += PAGE_ALIGN(icd->width * icd->height / 2); /* U pages */
|
||||
*size += PAGE_ALIGN(icd->width * icd->height / 2); /* V pages */
|
||||
} else {
|
||||
*size = icd->width * icd->height *
|
||||
((icd->current_fmt->depth + 7) >> 3);
|
||||
}
|
||||
*size = roundup(icd->width * icd->height *
|
||||
((icd->current_fmt->depth + 7) >> 3), 8);
|
||||
|
||||
if (0 == *count)
|
||||
*count = 32;
|
||||
@ -1265,6 +1263,18 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
|
||||
pix->width = 2048;
|
||||
pix->width &= ~0x01;
|
||||
|
||||
/*
|
||||
* YUV422P planar format requires images size to be a 16 bytes
|
||||
* multiple. If not, zeros will be inserted between Y and U planes, and
|
||||
* U and V planes, and YUV422P standard would be violated.
|
||||
*/
|
||||
if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) {
|
||||
if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
|
||||
pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN);
|
||||
if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN))
|
||||
pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN);
|
||||
}
|
||||
|
||||
pix->bytesperline = pix->width *
|
||||
DIV_ROUND_UP(xlate->host_fmt->depth, 8);
|
||||
pix->sizeimage = pix->height * pix->bytesperline;
|
||||
|
Loading…
Reference in New Issue
Block a user