Adds support for the following planar and partial-planar formats: YUV422 NV12 NV21 NV16 NV61 Signed-off-by: Dmitry Eremin-Solenikov <dmitry_eremin@xxxxxxxxxx> Signed-off-by: Mohsin Kazmi <mohsin_kazmi@xxxxxxxxxx> Signed-off-by: Steve Longerbeam <steve_longerbeam@xxxxxxxxxx> --- drivers/staging/imx-drm/ipu-v3/ipu-common.c | 26 +++++ drivers/staging/imx-drm/ipu-v3/ipu-cpmem.c | 146 +++++++++++++++++++++++++-- 2 files changed, 166 insertions(+), 6 deletions(-) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index b9d759d..2ee6370 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -80,6 +80,12 @@ enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) case DRM_FORMAT_UYVY: case DRM_FORMAT_YUV420: case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: return IPUV3_COLORSPACE_YUV; default: return IPUV3_COLORSPACE_UNKNOWN; @@ -92,8 +98,13 @@ enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat) switch (pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: return IPUV3_COLORSPACE_YUV; case V4L2_PIX_FMT_RGB32: case V4L2_PIX_FMT_BGR32: @@ -112,6 +123,11 @@ bool ipu_pixelformat_is_planar(u32 pixelformat) switch (pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: return true; } @@ -137,6 +153,11 @@ int ipu_stride_to_bytes(u32 pixel_stride, u32 pixelformat) switch (pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_YUV422P: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: /* * for the planar YUV formats, the stride passed to * cpmem must be the stride in bytes of the Y plane. @@ -170,10 +191,15 @@ int ipu_bits_per_pixel(u32 pixelformat) switch (pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV21: return 12; + case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_NV16: + case V4L2_PIX_FMT_NV61: return 16; case V4L2_PIX_FMT_BGR24: case V4L2_PIX_FMT_RGB24: diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-cpmem.c b/drivers/staging/imx-drm/ipu-v3/ipu-cpmem.c index 70e90b40..1ee5e11 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-cpmem.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-cpmem.c @@ -191,8 +191,18 @@ static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat) return DRM_FORMAT_YUYV; case V4L2_PIX_FMT_YUV420: return DRM_FORMAT_YUV420; + case V4L2_PIX_FMT_YUV422P: + return DRM_FORMAT_YUV422; case V4L2_PIX_FMT_YVU420: return DRM_FORMAT_YVU420; + case V4L2_PIX_FMT_NV12: + return DRM_FORMAT_NV12; + case V4L2_PIX_FMT_NV21: + return DRM_FORMAT_NV21; + case V4L2_PIX_FMT_NV16: + return DRM_FORMAT_NV16; + case V4L2_PIX_FMT_NV61: + return DRM_FORMAT_NV61; } return -EINVAL; @@ -391,6 +401,7 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch, { switch (pixel_format) { case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YUV422P: ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, (stride / 2) - 1); ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8); ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8); @@ -400,6 +411,18 @@ void ipu_cpmem_set_yuv_planar_full(struct ipuv3_channel *ch, ipu_ch_param_write_field(ch, IPU_FIELD_UBO, v_offset / 8); ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8); break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, stride - 1); + ipu_ch_param_write_field(ch, IPU_FIELD_UBO, u_offset / 8); + ipu_ch_param_write_field(ch, IPU_FIELD_VBO, u_offset / 8); + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + ipu_ch_param_write_field(ch, IPU_FIELD_SLUV, stride - 1); + ipu_ch_param_write_field(ch, IPU_FIELD_UBO, v_offset / 8); + ipu_ch_param_write_field(ch, IPU_FIELD_VBO, v_offset / 8); + break; } } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); @@ -419,6 +442,25 @@ void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch, ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride, u_offset, v_offset); break; + case V4L2_PIX_FMT_YUV422P: + uv_stride = stride / 2; + u_offset = stride * height; + v_offset = u_offset + (uv_stride * height); + ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride, + u_offset, v_offset); + break; + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV16: + u_offset = stride * height; + ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride, + u_offset, 0); + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV61: + v_offset = stride * height; + ipu_cpmem_set_yuv_planar_full(ch, pixel_format, stride, + 0, v_offset); + break; } } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); @@ -472,11 +514,20 @@ static const struct ipu_rgb def_bgr_16 = { }; #define Y_OFFSET(pix, x, y) ((x) + pix->width * (y)) -#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ - (pix->width * (y) / 4) + (x) / 2) -#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \ - (pix->width * pix->height / 4) + \ - (pix->width * (y) / 4) + (x) / 2) +#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * (y) / 4) + (x) / 2) +#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * pix->height / 4) + \ + (pix->width * (y) / 4) + (x) / 2) +#define U2_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * (y) / 2) + (x) / 2) +#define V2_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * pix->height / 2) + \ + (pix->width * (y) / 2) + (x) / 2) +#define UV_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * (y) / 2) + (x)) +#define UV2_OFFSET(pix, x, y) ((pix->width * pix->height) + \ + (pix->width * y) + (x)) int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc) { @@ -488,6 +539,27 @@ int ipu_cpmem_set_fmt(struct ipuv3_channel *ch, u32 drm_fourcc) /* burst size */ ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); break; + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + /* pix format */ + ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 1); + /* burst size */ + ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); + break; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + /* pix format */ + ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4); + /* burst size */ + ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); + break; + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + /* pix format */ + ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 3); + /* burst size */ + ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31); + break; case DRM_FORMAT_UYVY: /* bits/pixel */ ipu_ch_param_write_field(ch, IPU_FIELD_BPP, 3); @@ -556,7 +628,69 @@ int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image) image->rect.top) - y_offset; ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, - pix->bytesperline, u_offset, v_offset); + pix->bytesperline, + u_offset, v_offset); + ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); + break; + case V4L2_PIX_FMT_YUV422P: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = U2_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + v_offset = V2_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); + break; + case V4L2_PIX_FMT_NV12: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = UV_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + v_offset = 0; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); + break; + case V4L2_PIX_FMT_NV21: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = 0; + v_offset = UV_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); + break; + case V4L2_PIX_FMT_NV16: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = UV2_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + v_offset = 0; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); + break; + case V4L2_PIX_FMT_NV61: + y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = 0; + v_offset = UV2_OFFSET(pix, image->rect.left, + image->rect.top) - y_offset; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); ipu_cpmem_set_buffer(ch, 0, image->phys0 + y_offset); ipu_cpmem_set_buffer(ch, 1, image->phys1 + y_offset); break; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html