diff options
Diffstat (limited to 'drivers/gpu/ipu-v3/ipu-cpmem.c')
-rw-r--r-- | drivers/gpu/ipu-v3/ipu-cpmem.c | 117 |
1 files changed, 99 insertions, 18 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index cfe2f53f2c17..c55f3620e84a 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c @@ -193,8 +193,14 @@ 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_NV16: + return DRM_FORMAT_NV16; } return -EINVAL; @@ -394,6 +400,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); @@ -403,6 +410,12 @@ 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; } } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full); @@ -422,6 +435,19 @@ 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; } } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); @@ -475,11 +501,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) { @@ -491,6 +526,25 @@ 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: + /* 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: + /* 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); @@ -538,7 +592,7 @@ EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt); int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image) { struct v4l2_pix_format *pix = &image->pix; - int offset, y_offset, u_offset, v_offset; + int offset, u_offset, v_offset; pr_debug("%s: resolution: %dx%d stride: %d\n", __func__, pix->width, pix->height, @@ -552,43 +606,70 @@ int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image) switch (pix->pixelformat) { case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: - y_offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + offset = Y_OFFSET(pix, image->rect.left, image->rect.top); u_offset = U_OFFSET(pix, image->rect.left, - image->rect.top) - y_offset; + image->rect.top) - offset; v_offset = V_OFFSET(pix, image->rect.left, - image->rect.top) - y_offset; + image->rect.top) - offset; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + break; + case V4L2_PIX_FMT_YUV422P: + offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = U2_OFFSET(pix, image->rect.left, + image->rect.top) - offset; + v_offset = V2_OFFSET(pix, image->rect.left, + image->rect.top) - offset; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); + break; + case V4L2_PIX_FMT_NV12: + offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = UV_OFFSET(pix, image->rect.left, + image->rect.top) - 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); + pix->bytesperline, + u_offset, v_offset); + break; + case V4L2_PIX_FMT_NV16: + offset = Y_OFFSET(pix, image->rect.left, image->rect.top); + u_offset = UV2_OFFSET(pix, image->rect.left, + image->rect.top) - offset; + v_offset = 0; + + ipu_cpmem_set_yuv_planar_full(ch, pix->pixelformat, + pix->bytesperline, + u_offset, v_offset); break; case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_RGB565: offset = image->rect.left * 2 + image->rect.top * pix->bytesperline; - ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset); - ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset); break; case V4L2_PIX_FMT_RGB32: case V4L2_PIX_FMT_BGR32: offset = image->rect.left * 4 + image->rect.top * pix->bytesperline; - ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset); - ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset); break; case V4L2_PIX_FMT_RGB24: case V4L2_PIX_FMT_BGR24: offset = image->rect.left * 3 + image->rect.top * pix->bytesperline; - ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset); - ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset); break; default: return -EINVAL; } + ipu_cpmem_set_buffer(ch, 0, image->phys0 + offset); + ipu_cpmem_set_buffer(ch, 1, image->phys1 + offset); + return 0; } EXPORT_SYMBOL_GPL(ipu_cpmem_set_image); |