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 коммит произвёл Mauro Carvalho Chehab
Родитель f8fe466aa7
Коммит 9b744a3ec8
2 изменённых файлов: 37 добавлений и 7 удалений

Просмотреть файл

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

Просмотреть файл

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