media: imx-jpeg: Decoder add support for 12bit jpeg
authorMing Qian <ming.qian@nxp.com>
Wed, 22 Mar 2023 05:13:12 +0000 (05:13 +0000)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Sat, 15 Apr 2023 08:13:59 +0000 (09:13 +0100)
enable decoding 12-bit extended jpeg

Signed-off-by: Ming Qian <ming.qian@nxp.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c

index b2becf4625d7a0eef6ea6ff25977e312168ee972..9a2d44fe9b6de3923a810d4bdcef7ff200d6cb67 100644 (file)
@@ -87,6 +87,20 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .precision      = 8,
                .is_rgb         = 1,
        },
+       {
+               .name           = "BGR 12bit", /*12-bit BGR packed format*/
+               .fourcc         = V4L2_PIX_FMT_BGR48_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 36,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+               .is_rgb         = 1,
+       },
        {
                .name           = "ABGR", /* ABGR packed format */
                .fourcc         = V4L2_PIX_FMT_ABGR32,
@@ -101,6 +115,20 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .precision      = 8,
                .is_rgb         = 1,
        },
+       {
+               .name           = "ABGR 12bit", /* 12-bit ABGR packed format */
+               .fourcc         = V4L2_PIX_FMT_ABGR64_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 4,
+               .depth          = 48,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+               .is_rgb         = 1,
+       },
        {
                .name           = "YUV420", /* 1st plane = Y, 2nd plane = UV */
                .fourcc         = V4L2_PIX_FMT_NV12M,
@@ -127,6 +155,32 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */
+               .fourcc         = V4L2_PIX_FMT_P012M,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+               .nc             = 3,
+               .depth          = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */
+               .mem_planes     = 2,
+               .comp_planes    = 2, /* 1 plane Y, 1 plane UV interleaved */
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
+       {
+               .name           = "YUV420 12bit", /* 1st plane = Y, 2nd plane = UV */
+               .fourcc         = V4L2_PIX_FMT_P012,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+               .nc             = 3,
+               .depth          = 18, /* 6 x 12 bits (4Y + UV) for 4 pixels */
+               .mem_planes     = 1,
+               .comp_planes    = 2, /* 1 plane Y, 1 plane UV interleaved */
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "YUV422", /* YUYV */
                .fourcc         = V4L2_PIX_FMT_YUYV,
@@ -140,6 +194,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV422 12bit", /* YUYV */
+               .fourcc         = V4L2_PIX_FMT_Y212,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+               .nc             = 3,
+               .depth          = 24,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 4,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "YUV444", /* YUVYUV */
                .fourcc         = V4L2_PIX_FMT_YUV24,
@@ -153,6 +220,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "YUV444 12bit", /* YUVYUV */
+               .fourcc         = V4L2_PIX_FMT_YUV48_12,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+               .nc             = 3,
+               .depth          = 36,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
        {
                .name           = "Gray", /* Gray (Y8/Y12) or Single Comp */
                .fourcc         = V4L2_PIX_FMT_GREY,
@@ -166,6 +246,19 @@ static const struct mxc_jpeg_fmt mxc_formats[] = {
                .flags          = MXC_JPEG_FMT_TYPE_RAW,
                .precision      = 8,
        },
+       {
+               .name           = "Gray 12bit", /* Gray (Y8/Y12) or Single Comp */
+               .fourcc         = V4L2_PIX_FMT_Y012,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+               .nc             = 1,
+               .depth          = 12,
+               .mem_planes     = 1,
+               .comp_planes    = 1,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = MXC_JPEG_FMT_TYPE_RAW,
+               .precision      = 12,
+       },
 };
 
 #define MXC_JPEG_NUM_FORMATS ARRAY_SIZE(mxc_formats)
@@ -437,17 +530,24 @@ static enum mxc_jpeg_image_format mxc_jpeg_fourcc_to_imgfmt(u32 fourcc)
 {
        switch (fourcc) {
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                return MXC_JPEG_GRAY;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                return MXC_JPEG_YUV422;
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                return MXC_JPEG_YUV420;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
                return MXC_JPEG_YUV444;
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
                return MXC_JPEG_BGR;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                return MXC_JPEG_ABGR;
        default:
                return MXC_JPEG_INVALID;
@@ -483,6 +583,17 @@ static void mxc_jpeg_addrs(struct mxc_jpeg_desc *desc,
                offset;
 }
 
+static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt)
+{
+       if (!fmt || !(fmt->flags & MXC_JPEG_FMT_TYPE_RAW))
+               return false;
+
+       if (fmt->precision > 8)
+               return true;
+
+       return false;
+}
+
 static void notify_eos(struct mxc_jpeg_ctx *ctx)
 {
        const struct v4l2_event ev = {
@@ -771,24 +882,31 @@ static int mxc_jpeg_fixup_sof(struct mxc_jpeg_sof *sof,
        switch (fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                sof->components_no = 3;
                sof->comp[0].v = 0x2;
                sof->comp[0].h = 0x2;
                break;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                sof->components_no = 3;
                sof->comp[0].v = 0x1;
                sof->comp[0].h = 0x2;
                break;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
        default:
                sof->components_no = 3;
                break;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                sof->components_no = 4;
                break;
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                sof->components_no = 1;
                break;
        }
@@ -808,20 +926,27 @@ static int mxc_jpeg_fixup_sos(struct mxc_jpeg_sos *sos,
        switch (fourcc) {
        case V4L2_PIX_FMT_NV12:
        case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_P012:
+       case V4L2_PIX_FMT_P012M:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_Y212:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_YUV24:
+       case V4L2_PIX_FMT_YUV48_12:
        case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_BGR48_12:
        default:
                sos->components_no = 3;
                break;
        case V4L2_PIX_FMT_ABGR32:
+       case V4L2_PIX_FMT_ABGR64_12:
                sos->components_no = 4;
                break;
        case V4L2_PIX_FMT_GREY:
+       case V4L2_PIX_FMT_Y012:
                sos->components_no = 1;
                break;
        }
@@ -851,12 +976,15 @@ static unsigned int mxc_jpeg_setup_cfg_stream(void *cfg_stream_vaddr,
        u8 *cfg = (u8 *)cfg_stream_vaddr;
        struct mxc_jpeg_sof *sof;
        struct mxc_jpeg_sos *sos;
+       const struct mxc_jpeg_fmt *fmt = mxc_jpeg_find_format(fourcc);
+
+       if (!fmt)
+               return 0;
 
        memcpy(cfg + offset, jpeg_soi, ARRAY_SIZE(jpeg_soi));
        offset += ARRAY_SIZE(jpeg_soi);
 
-       if (fourcc == V4L2_PIX_FMT_BGR24 ||
-           fourcc == V4L2_PIX_FMT_ABGR32) {
+       if (fmt->is_rgb) {
                memcpy(cfg + offset, jpeg_app14, sizeof(jpeg_app14));
                offset += sizeof(jpeg_app14);
        } else {
@@ -922,6 +1050,10 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
        desc->stm_ctrl &= ~STM_CTRL_IMAGE_FORMAT(0xF); /* clear image format */
        desc->stm_ctrl |= STM_CTRL_IMAGE_FORMAT(img_fmt);
        desc->stm_ctrl |= STM_CTRL_BITBUF_PTR_CLR(1);
+       if (mxc_jpeg_is_extended_sequential(jpeg_src_buf->fmt))
+               desc->stm_ctrl |= STM_CTRL_PIXEL_PRECISION;
+       else
+               desc->stm_ctrl &= ~STM_CTRL_PIXEL_PRECISION;
        desc->line_pitch = q_data_cap->bytesperline[0];
        mxc_jpeg_addrs(desc, dst_buf, src_buf, 0);
        mxc_jpeg_set_bufsize(desc, ALIGN(vb2_plane_size(src_buf, 0), 1024));