media: rcar-vin: Add support for outputting NV12

Most Gen3 boards can output frames in NV12 format, add support for this
with a runtime check that the running hardware supports it.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Niklas Söderlund 2019-10-13 21:16:15 -03:00 committed by Mauro Carvalho Chehab
parent f8fe466aa7
commit 9b744a3ec8
2 changed files with 37 additions and 7 deletions

View File

@ -118,6 +118,7 @@
#define VNDMR_ABIT (1 << 2)
#define VNDMR_DTMD_YCSEP (1 << 1)
#define VNDMR_DTMD_ARGB (1 << 0)
#define VNDMR_DTMD_YCSEP_420 (3 << 0)
/* Video n Data Mode Register 2 bits */
#define VNDMR2_VPS (1 << 30)
@ -701,11 +702,13 @@ static int rvin_setup(struct rvin_dev *vin)
* Output format
*/
switch (vin->format.pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV16:
rvin_write(vin,
ALIGN(vin->format.bytesperline * vin->format.height,
0x80), VNUVAOF_REG);
dmr = VNDMR_DTMD_YCSEP;
dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ?
VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP;
output_is_yuv = true;
break;
case V4L2_PIX_FMT_YUYV:

View File

@ -30,6 +30,10 @@
*/
static const struct rvin_video_format rvin_formats[] = {
{
.fourcc = V4L2_PIX_FMT_NV12,
.bpp = 1,
},
{
.fourcc = V4L2_PIX_FMT_NV16,
.bpp = 1,
@ -72,6 +76,9 @@ const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
if (vin->info->model == RCAR_M1 && pixelformat == V4L2_PIX_FMT_XBGR32)
return NULL;
if (pixelformat == V4L2_PIX_FMT_NV12 && !vin->info->nv12)
return NULL;
for (i = 0; i < ARRAY_SIZE(rvin_formats); i++)
if (rvin_formats[i].fourcc == pixelformat)
return rvin_formats + i;
@ -90,17 +97,29 @@ static u32 rvin_format_bytesperline(struct rvin_dev *vin,
if (WARN_ON(!fmt))
return -EINVAL;
align = pix->pixelformat == V4L2_PIX_FMT_NV16 ? 0x20 : 0x10;
switch (pix->pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV16:
align = 0x20;
break;
default:
align = 0x10;
break;
}
return ALIGN(pix->width, align) * fmt->bpp;
}
static u32 rvin_format_sizeimage(struct v4l2_pix_format *pix)
{
if (pix->pixelformat == V4L2_PIX_FMT_NV16)
switch (pix->pixelformat) {
case V4L2_PIX_FMT_NV12:
return pix->bytesperline * pix->height * 3 / 2;
case V4L2_PIX_FMT_NV16:
return pix->bytesperline * pix->height * 2;
return pix->bytesperline * pix->height;
default:
return pix->bytesperline * pix->height;
}
}
static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
@ -124,8 +143,16 @@ static void rvin_format_align(struct rvin_dev *vin, struct v4l2_pix_format *pix)
break;
}
/* HW limit width to a multiple of 32 (2^5) for NV16 else 2 (2^1) */
walign = vin->format.pixelformat == V4L2_PIX_FMT_NV16 ? 5 : 1;
/* HW limit width to a multiple of 32 (2^5) for NV12/16 else 2 (2^1) */
switch (vin->format.pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV16:
walign = 5;
break;
default:
walign = 1;
break;
}
/* Limit to VIN capabilities */
v4l_bound_align_image(&pix->width, 2, vin->info->max_width, walign,