]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: iris: Add HEVC and VP9 formats for decoder
authorDikshita Agarwal <quic_dikshita@quicinc.com>
Fri, 9 May 2025 08:39:08 +0000 (14:09 +0530)
committerHans Verkuil <hverkuil@xs4all.nl>
Thu, 3 Jul 2025 09:02:44 +0000 (11:02 +0200)
Extend the decoder driver's supported formats to include HEVC (H.265)
and VP9. This change updates the format enumeration (VIDIOC_ENUM_FMT)
and allows setting these formats via VIDIOC_S_FMT.

Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Acked-by: Vikash Garodia <quic_vgarodia@quicinc.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-HDK
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-QRD
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8650-HDK
Signed-off-by: Dikshita Agarwal <quic_dikshita@quicinc.com>
Tested-by: Vikash Garodia <quic_vgarodia@quicinc.com> # on sa8775p-ride
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c
drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
drivers/media/platform/qcom/iris/iris_instance.h
drivers/media/platform/qcom/iris/iris_vdec.c
drivers/media/platform/qcom/iris/iris_vdec.h
drivers/media/platform/qcom/iris/iris_vidc.c

index bd9d86220e611e2eb39c9e114bceceac757f4d7b..dbb1b1dab09701ec614088d495f43640ecdb9f99 100644 (file)
@@ -88,16 +88,29 @@ static int iris_hfi_gen1_sys_pc_prep(struct iris_core *core)
 static int iris_hfi_gen1_session_open(struct iris_inst *inst)
 {
        struct hfi_session_open_pkt packet;
+       u32 codec = 0;
        int ret;
 
        if (inst->state != IRIS_INST_DEINIT)
                return -EALREADY;
 
+       switch (inst->codec) {
+       case V4L2_PIX_FMT_H264:
+               codec = HFI_VIDEO_CODEC_H264;
+               break;
+       case V4L2_PIX_FMT_HEVC:
+               codec = HFI_VIDEO_CODEC_HEVC;
+               break;
+       case V4L2_PIX_FMT_VP9:
+               codec = HFI_VIDEO_CODEC_VP9;
+               break;
+       }
+
        packet.shdr.hdr.size = sizeof(struct hfi_session_open_pkt);
        packet.shdr.hdr.pkt_type = HFI_CMD_SYS_SESSION_INIT;
        packet.shdr.session_id = inst->session_id;
        packet.session_domain = HFI_SESSION_TYPE_DEC;
-       packet.session_codec = HFI_VIDEO_CODEC_H264;
+       packet.session_codec = codec;
 
        reinit_completion(&inst->completion);
 
index adffcead58ea770f992d991dd6bb3c3c7cb843b7..d4d119ca98b0cb313db351f3794bf278216bd539 100644 (file)
@@ -13,6 +13,8 @@
 #define HFI_SESSION_TYPE_DEC                           2
 
 #define HFI_VIDEO_CODEC_H264                           0x00000002
+#define HFI_VIDEO_CODEC_HEVC                           0x00002000
+#define HFI_VIDEO_CODEC_VP9                            0x00004000
 
 #define HFI_ERR_NONE                                   0x0
 
index 802fa62c26ebef619c5b5c3e5f50637a6e9693a2..f23be2340658605a6266ac168ae7346af503a683 100644 (file)
@@ -416,7 +416,19 @@ static int iris_hfi_gen2_session_set_config_params(struct iris_inst *inst, u32 p
 static int iris_hfi_gen2_session_set_codec(struct iris_inst *inst)
 {
        struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst);
-       u32 codec = HFI_CODEC_DECODE_AVC;
+       u32 codec = 0;
+
+       switch (inst->codec) {
+       case V4L2_PIX_FMT_H264:
+               codec = HFI_CODEC_DECODE_AVC;
+               break;
+       case V4L2_PIX_FMT_HEVC:
+               codec = HFI_CODEC_DECODE_HEVC;
+               break;
+       case V4L2_PIX_FMT_VP9:
+               codec = HFI_CODEC_DECODE_VP9;
+               break;
+       }
 
        iris_hfi_gen2_packet_session_property(inst,
                                              HFI_PROP_CODEC,
index 666061a612c304698067337f63ac9332c75c5d36..283d2f27e4c8e80554cafed816b0951fa5a9ee76 100644 (file)
@@ -104,6 +104,9 @@ enum hfi_color_format {
 enum hfi_codec_type {
        HFI_CODEC_DECODE_AVC                    = 1,
        HFI_CODEC_ENCODE_AVC                    = 2,
+       HFI_CODEC_DECODE_HEVC                   = 3,
+       HFI_CODEC_ENCODE_HEVC                   = 4,
+       HFI_CODEC_DECODE_VP9                    = 5,
 };
 
 enum hfi_picture_type {
index 5ec6368b2af711fd0b78854ddbf18ae58e3dcdc6..0e1f5799b72d993b25820608969e0011eabdb6bc 100644 (file)
@@ -43,6 +43,7 @@
  * @sequence_out: a sequence counter for output queue
  * @tss: timestamp metadata
  * @metadata_idx: index for metadata buffer
+ * @codec: codec type
  * @last_buffer_dequeued: a flag to indicate that last buffer is sent by driver
  */
 
@@ -75,6 +76,7 @@ struct iris_inst {
        u32                             sequence_out;
        struct iris_ts_metadata         tss[VIDEO_MAX_FRAME];
        u32                             metadata_idx;
+       u32                             codec;
        bool                            last_buffer_dequeued;
 };
 
index ce97c555192a9a4eed5c6b1287f4dfa201a017d1..d670b51c5839d1fad54d34f373cf71d5f3973a96 100644 (file)
@@ -32,6 +32,7 @@ int iris_vdec_inst_init(struct iris_inst *inst)
        f->fmt.pix_mp.width = DEFAULT_WIDTH;
        f->fmt.pix_mp.height = DEFAULT_HEIGHT;
        f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+       inst->codec = f->fmt.pix_mp.pixelformat;
        f->fmt.pix_mp.num_planes = 1;
        f->fmt.pix_mp.plane_fmt[0].bytesperline = 0;
        f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT);
@@ -67,14 +68,67 @@ void iris_vdec_inst_deinit(struct iris_inst *inst)
        kfree(inst->fmt_src);
 }
 
+static const struct iris_fmt iris_vdec_formats[] = {
+       [IRIS_FMT_H264] = {
+               .pixfmt = V4L2_PIX_FMT_H264,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       [IRIS_FMT_HEVC] = {
+               .pixfmt = V4L2_PIX_FMT_HEVC,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+       [IRIS_FMT_VP9] = {
+               .pixfmt = V4L2_PIX_FMT_VP9,
+               .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+       },
+};
+
+static const struct iris_fmt *
+find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
+{
+       unsigned int size = ARRAY_SIZE(iris_vdec_formats);
+       const struct iris_fmt *fmt = iris_vdec_formats;
+       unsigned int i;
+
+       for (i = 0; i < size; i++) {
+               if (fmt[i].pixfmt == pixfmt)
+                       break;
+       }
+
+       if (i == size || fmt[i].type != type)
+               return NULL;
+
+       return &fmt[i];
+}
+
+static const struct iris_fmt *
+find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
+{
+       const struct iris_fmt *fmt = iris_vdec_formats;
+       unsigned int size = ARRAY_SIZE(iris_vdec_formats);
+
+       if (index >= size || fmt[index].type != type)
+               return NULL;
+
+       return &fmt[index];
+}
+
 int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
 {
+       const struct iris_fmt *fmt;
+
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               f->pixelformat = V4L2_PIX_FMT_H264;
+               fmt = find_format_by_index(inst, f->index, f->type);
+               if (!fmt)
+                       return -EINVAL;
+
+               f->pixelformat = fmt->pixfmt;
                f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION;
                break;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               if (f->index)
+                       return -EINVAL;
                f->pixelformat = V4L2_PIX_FMT_NV12;
                break;
        default:
@@ -88,13 +142,15 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
 {
        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
        struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
+       const struct iris_fmt *fmt;
        struct v4l2_format *f_inst;
        struct vb2_queue *src_q;
 
        memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
+       fmt = find_format(inst, pixmp->pixelformat, f->type);
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264) {
+               if (!fmt) {
                        f_inst = inst->fmt_src;
                        f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
                        f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height;
@@ -102,7 +158,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
                }
                break;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
+               if (!fmt) {
                        f_inst = inst->fmt_dst;
                        f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
                        f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
@@ -145,13 +201,14 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
 
        switch (f->type) {
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264)
+               if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
                        return -EINVAL;
 
                fmt = inst->fmt_src;
                fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-
-               codec_align = DEFAULT_CODEC_ALIGNMENT;
+               fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
+               inst->codec = fmt->fmt.pix_mp.pixelformat;
+               codec_align = inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16;
                fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, codec_align);
                fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, codec_align);
                fmt->fmt.pix_mp.num_planes = 1;
index b24932dc511a65017b1cadbcb984544475bd0723..cd7aab66dc7c82dc50acef9e654a3d6c1ddb088f 100644 (file)
@@ -8,6 +8,17 @@
 
 struct iris_inst;
 
+enum iris_fmt_type {
+       IRIS_FMT_H264,
+       IRIS_FMT_HEVC,
+       IRIS_FMT_VP9,
+};
+
+struct iris_fmt {
+       u32 pixfmt;
+       u32 type;
+};
+
 int iris_vdec_inst_init(struct iris_inst *inst);
 void iris_vdec_inst_deinit(struct iris_inst *inst);
 int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f);
index a8144595cc78e8fbe33ad5bfa9688f96f2ef8ea6..c417e8c31f806e03555cd5e2a662a6efe5d58f3e 100644 (file)
@@ -278,9 +278,6 @@ static int iris_enum_fmt(struct file *filp, void *fh, struct v4l2_fmtdesc *f)
 {
        struct iris_inst *inst = iris_get_inst(filp, NULL);
 
-       if (f->index)
-               return -EINVAL;
-
        return iris_vdec_enum_fmt(inst, f);
 }