[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250930040348.3702923-22-h.dewangan@samsung.com>
Date: Tue, 30 Sep 2025 09:33:40 +0530
From: Himanshu Dewangan <h.dewangan@...sung.com>
To: mchehab@...nel.org, robh@...nel.org, krzk+dt@...nel.org,
conor+dt@...nel.org, sumit.semwal@...aro.org, christian.koenig@....com,
alim.akhtar@...sung.com, manjun@...sung.com, nagaraju.s@...sung.com,
ih0206.lee@...sung.com, jehyung.lee@...sung.com
Cc: linux-arm-kernel@...ts.infradead.org, linux-media@...r.kernel.org,
devicetree@...r.kernel.org, linux-samsung-soc@...r.kernel.org,
linux-kernel@...r.kernel.org, dri-devel@...ts.freedesktop.org,
linaro-mm-sig@...ts.linaro.org, Himanshu Dewangan <h.dewangan@...sung.com>
Subject: [PATCH 21/29] media: mfc: Add multi‑codec support & QoS improvements
From: Nagaraju Siddineni <nagaraju.s@...sung.com>
- Enable HEVC, AV1, VP8/9, MPEG‑4 (incl. MVC, VC‑1 RCV) .
- Extend DPB/buffer structures for AV1 and high‑resolution/multiframe
streams.
- Add codec‑specific QoS weight parameters (10‑bit, 4:2:2, B‑frames)
and update DT bandwidth entries.
- Enhance format tables with colour‑range/space and HDR parsing for VP9.
- Detect display‑resolution changes and multiframe flags for VP9/AV1.
- Introduce utility helpers (CRC, aspect‑ratio, colour primaries)
and minor safety fixes.
Signed-off-by: Nagaraju Siddineni <nagaraju.s@...sung.com>
Signed-off-by: Himanshu Dewangan <h.dewangan@...sung.com>
---
.../samsung/exynos-mfc/base/mfc_buf.c | 70 +++++++++
.../samsung/exynos-mfc/base/mfc_common.h | 42 ++++-
.../samsung/exynos-mfc/base/mfc_data_struct.h | 20 +++
.../samsung/exynos-mfc/base/mfc_format.h | 136 ++++++++++++++++
.../samsung/exynos-mfc/base/mfc_qos.c | 58 +++++++
.../samsung/exynos-mfc/base/mfc_queue.c | 5 +
.../samsung/exynos-mfc/base/mfc_utils.c | 8 +-
.../media/platform/samsung/exynos-mfc/mfc.c | 53 +++++++
.../platform/samsung/exynos-mfc/mfc_core.c | 2 +
.../samsung/exynos-mfc/mfc_core_buf_ctrl.c | 9 ++
.../samsung/exynos-mfc/mfc_core_cmd.c | 11 ++
.../samsung/exynos-mfc/mfc_core_isr.c | 147 ++++++++++++++++--
.../samsung/exynos-mfc/mfc_core_reg_api.c | 46 +++++-
.../samsung/exynos-mfc/mfc_core_reg_api.h | 75 ++++++++-
.../samsung/exynos-mfc/mfc_core_run.c | 4 +
.../platform/samsung/exynos-mfc/mfc_dec_vb2.c | 1 +
16 files changed, 665 insertions(+), 22 deletions(-)
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
index bd1baf34e0b0..84f97ca230bb 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
@@ -116,8 +116,25 @@ int mfc_alloc_instance_context(struct mfc_core_ctx *core_ctx)
switch (ctx->codec_mode) {
case MFC_REG_CODEC_H264_DEC:
case MFC_REG_CODEC_H264_MVC_DEC:
+ case MFC_REG_CODEC_HEVC_DEC:
core_ctx->instance_ctx_buf.size = buf_size->h264_dec_ctx;
break;
+ case MFC_REG_CODEC_MPEG4_DEC:
+ case MFC_REG_CODEC_H263_DEC:
+ case MFC_REG_CODEC_VC1_RCV_DEC:
+ case MFC_REG_CODEC_VC1_DEC:
+ case MFC_REG_CODEC_MPEG2_DEC:
+ case MFC_REG_CODEC_VP8_DEC:
+ case MFC_REG_CODEC_VP9_DEC:
+ case MFC_REG_CODEC_FIMV1_DEC:
+ case MFC_REG_CODEC_FIMV2_DEC:
+ case MFC_REG_CODEC_FIMV3_DEC:
+ case MFC_REG_CODEC_FIMV4_DEC:
+ core_ctx->instance_ctx_buf.size = buf_size->other_dec_ctx;
+ break;
+ case MFC_REG_CODEC_AV1_DEC:
+ core_ctx->instance_ctx_buf.size = buf_size->av1_dec_ctx;
+ break;
default:
core_ctx->instance_ctx_buf.size = 0;
mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
@@ -155,6 +172,59 @@ static void __mfc_dec_calc_codec_buffer_size(struct mfc_core_ctx *core_ctx)
/* Codecs have different memory requirements */
switch (ctx->codec_mode) {
case MFC_REG_CODEC_H264_DEC:
+ case MFC_REG_CODEC_H264_MVC_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ ctx->mv_buf.size = dec->mv_count * ctx->mv_size;
+ break;
+ case MFC_REG_CODEC_MPEG4_DEC:
+ case MFC_REG_CODEC_FIMV1_DEC:
+ case MFC_REG_CODEC_FIMV2_DEC:
+ case MFC_REG_CODEC_FIMV3_DEC:
+ case MFC_REG_CODEC_FIMV4_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ if (dec->loop_filter_mpeg4) {
+ ctx->loopfilter_luma_size = ALIGN(ctx->raw_buf.plane_size[0], SZ_256);
+ ctx->loopfilter_chroma_size = ALIGN(ctx->raw_buf.plane_size[1] +
+ ctx->raw_buf.plane_size[2], SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size +
+ (NUM_MPEG4_LF_BUF * (ctx->loopfilter_luma_size +
+ ctx->loopfilter_chroma_size));
+ } else {
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ }
+ break;
+ case MFC_REG_CODEC_VC1_RCV_DEC:
+ case MFC_REG_CODEC_VC1_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ break;
+ case MFC_REG_CODEC_MPEG2_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ break;
+ case MFC_REG_CODEC_H263_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ break;
+ case MFC_REG_CODEC_VP8_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size = ctx->scratch_buf_size;
+ break;
+ case MFC_REG_CODEC_VP9_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size =
+ ctx->scratch_buf_size +
+ DEC_STATIC_BUFFER_SIZE;
+ break;
+ case MFC_REG_CODEC_AV1_DEC:
+ ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+ core_ctx->codec_buf.size =
+ ctx->scratch_buf_size +
+ DEC_AV1_STATIC_BUFFER_SIZE(ctx->img_width, ctx->img_height);
+ ctx->mv_buf.size = dec->mv_count * ctx->mv_size;
+ break;
+ case MFC_REG_CODEC_HEVC_DEC:
ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
core_ctx->codec_buf.size = ctx->scratch_buf_size;
ctx->mv_buf.size = dec->mv_count * ctx->mv_size;
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
index de22c28d1625..5392c8566e42 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
@@ -153,7 +153,47 @@
/* Decoder codec mode check */
#define IS_H264_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_H264_DEC)
+#define IS_H264_MVC_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_H264_MVC_DEC)
+#define IS_MPEG4_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_MPEG4_DEC)
+#define IS_FIMV1_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_FIMV1_DEC)
+#define IS_FIMV2_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_FIMV2_DEC)
+#define IS_FIMV3_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_FIMV3_DEC)
+#define IS_FIMV4_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_FIMV4_DEC)
+#define IS_VC1_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_VC1_DEC)
+#define IS_VC1_RCV_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_VC1_RCV_DEC)
+#define IS_MPEG2_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_MPEG2_DEC)
+#define IS_HEVC_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_HEVC_DEC)
+#define IS_VP8_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_VP8_DEC)
+#define IS_VP9_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_VP9_DEC)
+#define IS_AV1_DEC(ctx) ((ctx)->codec_mode == MFC_REG_CODEC_AV1_DEC)
+#define IS_MV_HEVC_DEC(ctx, profile) \
+ ((ctx)->codec_mode == MFC_REG_CODEC_HEVC_DEC && \
+ (profile) == MFC_REG_D_PROFILE_MULTIVIEW_HEVC_MAIN)
+
+#define CODEC_NOT_CODED(ctx) ({ \
+ typeof(ctx) _ctx = (ctx); \
+ (IS_MPEG4_DEC(_ctx) || IS_VC1_DEC(_ctx) || IS_VC1_RCV_DEC(_ctx) || \
+ IS_VP9_DEC(_ctx)); \
+})
+#define CODEC_INTERLACED(ctx) ({ \
+ typeof(ctx) _ctx = (ctx); \
+ (IS_H264_DEC(_ctx) || IS_H264_MVC_DEC(_ctx) || IS_MPEG2_DEC(_ctx) || \
+ IS_MPEG4_DEC(_ctx) || IS_VC1_DEC(_ctx) || IS_VC1_RCV_DEC(_ctx)); \
+})
+#define CODEC_MBAFF(ctx) ({ \
+ typeof(ctx) _ctx = (ctx); \
+ (IS_H264_DEC(_ctx) || IS_H264_MVC_DEC(_ctx)); \
+})
+#define CODEC_MULTIFRAME(ctx) ({ \
+ typeof(ctx) _ctx = (ctx); \
+ (IS_MPEG4_DEC(_ctx) || IS_VP9_DEC(_ctx) || IS_FIMV2_DEC(_ctx) || \
+ IS_FIMV3_DEC(_ctx) || IS_FIMV4_DEC(_ctx) || IS_AV1_DEC(_ctx)); \
+})
+#define CODEC_422FORMAT(ctx) ({ \
+ typeof(ctx) _ctx = (ctx); \
+ (IS_HEVC_DEC(_ctx) || IS_VP9_DEC(_ctx)); \
+})
#define ON_RES_CHANGE(ctx) ({ \
typeof(ctx) _ctx = (ctx); \
((_ctx->state >= MFCINST_RES_CHANGE_INIT) && \
@@ -177,7 +217,7 @@
})
#define CODEC_HAS_IDR(ctx) ({ \
typeof(ctx) _ctx = (ctx); \
- (IS_H264_DEC(_ctx)); \
+ (IS_H264_DEC(_ctx) || IS_H264_MVC_DEC(_ctx) || IS_HEVC_DEC(_ctx)); \
})
/*
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
index 34b4b13b4f01..6b93fe3ab138 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
@@ -503,6 +503,8 @@ struct mfc_fw {
struct mfc_ctx_buf_size {
size_t dev_ctx;
size_t h264_dec_ctx;
+ size_t av1_dec_ctx;
+ size_t other_dec_ctx;
size_t dbg_info_buf;
};
@@ -710,6 +712,14 @@ struct mfc_bw_data {
struct mfc_bw_info {
struct mfc_bw_data bw_dec_h264;
+ struct mfc_bw_data bw_dec_hevc;
+ struct mfc_bw_data bw_dec_hevc_10bit;
+ struct mfc_bw_data bw_dec_vp8;
+ struct mfc_bw_data bw_dec_vp9;
+ struct mfc_bw_data bw_dec_vp9_10bit;
+ struct mfc_bw_data bw_dec_av1;
+ struct mfc_bw_data bw_dec_av1_10bit;
+ struct mfc_bw_data bw_dec_mpeg4;
};
/*
@@ -723,6 +733,7 @@ struct mfc_qos {
unsigned int freq_int;
unsigned int freq_mif;
unsigned int mo_value;
+ unsigned int mo_10bit_value;
unsigned int time_fw;
unsigned int bts_scen_idx;
const char *name;
@@ -747,8 +758,17 @@ struct mfc_qos_ctrl {
struct mfc_qos_weight {
unsigned int weight_h264_hevc;
+ unsigned int weight_vp8_vp9;
+ unsigned int weight_av1;
+ unsigned int weight_other_codec;
unsigned int weight_3plane;
+ unsigned int weight_10bit;
+ unsigned int weight_422;
+ unsigned int weight_bframe;
+ unsigned int weight_num_of_ref;
+ unsigned int weight_gpb;
unsigned int weight_num_of_tile;
+ unsigned int weight_super64_bframe;
unsigned int weight_mbaff;
};
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
index 3307c2eeaebb..0d48f2373e8d 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
@@ -127,6 +127,142 @@ static struct mfc_fmt mfc_formats[] = {
.num_planes = 1,
.mem_planes = 1,
},
+ {
+ .name = "DEC H264/MVC",
+ .fourcc = V4L2_PIX_FMT_H264_MVC,
+ .codec_mode = MFC_REG_CODEC_H264_MVC_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC H263",
+ .fourcc = V4L2_PIX_FMT_H263,
+ .codec_mode = MFC_REG_CODEC_H263_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC MPEG1",
+ .fourcc = V4L2_PIX_FMT_MPEG1,
+ .codec_mode = MFC_REG_CODEC_MPEG2_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC MPEG2",
+ .fourcc = V4L2_PIX_FMT_MPEG2,
+ .codec_mode = MFC_REG_CODEC_MPEG2_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC MPEG4",
+ .fourcc = V4L2_PIX_FMT_MPEG4,
+ .codec_mode = MFC_REG_CODEC_MPEG4_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC FIMV",
+ .fourcc = V4L2_PIX_FMT_FIMV,
+ .codec_mode = MFC_REG_CODEC_MPEG4_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC FIMV1",
+ .fourcc = V4L2_PIX_FMT_FIMV1,
+ .codec_mode = MFC_REG_CODEC_FIMV1_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC FIMV2",
+ .fourcc = V4L2_PIX_FMT_FIMV2,
+ .codec_mode = MFC_REG_CODEC_FIMV2_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC FIMV3",
+ .fourcc = V4L2_PIX_FMT_FIMV3,
+ .codec_mode = MFC_REG_CODEC_FIMV3_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC FIMV4",
+ .fourcc = V4L2_PIX_FMT_FIMV4,
+ .codec_mode = MFC_REG_CODEC_FIMV4_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC XviD",
+ .fourcc = V4L2_PIX_FMT_XVID,
+ .codec_mode = MFC_REG_CODEC_MPEG4_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC VC1",
+ .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
+ .codec_mode = MFC_REG_CODEC_VC1_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC VC1 RCV",
+ .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+ .codec_mode = MFC_REG_CODEC_VC1_RCV_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC VP8",
+ .fourcc = V4L2_PIX_FMT_VP8,
+ .codec_mode = MFC_REG_CODEC_VP8_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC VP9",
+ .fourcc = V4L2_PIX_FMT_VP9,
+ .codec_mode = MFC_REG_CODEC_VP9_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC AV1",
+ .fourcc = V4L2_PIX_FMT_AV1,
+ .codec_mode = MFC_REG_CODEC_AV1_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
+ {
+ .name = "DEC HEVC",
+ .fourcc = V4L2_PIX_FMT_HEVC,
+ .codec_mode = MFC_REG_CODEC_HEVC_DEC,
+ .type = MFC_FMT_STREAM | MFC_FMT_DEC,
+ .num_planes = 1,
+ .mem_planes = 1,
+ },
};
#endif /* __MFC_FORMAT_H */
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
index f6548543f07c..9922c2396b94 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
@@ -38,6 +38,7 @@ static inline unsigned long __mfc_qos_add_weight(struct mfc_ctx *ctx, unsigned l
switch (ctx->codec_mode) {
case MFC_REG_CODEC_H264_DEC:
+ case MFC_REG_CODEC_H264_MVC_DEC:
weight = (weight * 100) / qos_weight->weight_h264_hevc;
mfc_ctx_debug(3, "[QoS] h264, hevc codec, weight: %d\n", weight / 10);
if (num_planes == 3) {
@@ -45,6 +46,63 @@ static inline unsigned long __mfc_qos_add_weight(struct mfc_ctx *ctx, unsigned l
mfc_ctx_debug(3, "[QoS] 3 plane, weight: %d\n", weight / 10);
}
break;
+
+ case MFC_REG_CODEC_VP8_DEC:
+ weight = (weight * 100) / qos_weight->weight_vp8_vp9;
+ mfc_ctx_debug(3, "[QoS] vp8, vp9 codec, weight: %d\n", weight / 10);
+ if (num_planes == 3) {
+ weight = (weight * 100) / qos_weight->weight_3plane;
+ mfc_ctx_debug(3, "[QoS] 3 plane, weight: %d\n", weight / 10);
+ }
+ break;
+
+ case MFC_REG_CODEC_HEVC_DEC:
+ weight = (weight * 100) / qos_weight->weight_h264_hevc;
+ mfc_ctx_debug(3, "[QoS] h264, hevc codec, weight: %d\n", weight / 10);
+ if (num_planes == 3) {
+ weight = (weight * 100) / qos_weight->weight_3plane;
+ mfc_ctx_debug(3, "[QoS] 3 plane, weight: %d\n", weight / 10);
+ } else {
+ if (ctx->is_422) {
+ weight = (weight * 100) / qos_weight->weight_422;
+ mfc_ctx_debug(3, "[QoS] 422foramt, weight: %d\n", weight / 10);
+ }
+ }
+ break;
+
+ case MFC_REG_CODEC_AV1_DEC:
+ weight = (weight * 100) / qos_weight->weight_av1;
+ mfc_ctx_debug(3, "[QoS] av1 codec, weight: %d\n", weight / 10);
+ break;
+
+ case MFC_REG_CODEC_VP9_DEC:
+ weight = (weight * 100) / qos_weight->weight_vp8_vp9;
+ mfc_ctx_debug(3, "[QoS] vp8, vp9 codec, weight: %d\n", weight / 10);
+
+ if (num_planes == 3) {
+ weight = (weight * 100) / qos_weight->weight_3plane;
+ mfc_ctx_debug(3, "[QoS] 3 plane, weight: %d\n", weight / 10);
+ } else {
+ if (ctx->is_422) {
+ weight = (weight * 100) / qos_weight->weight_422;
+ mfc_ctx_debug(3, "[QoS] 422foramt, weight: %d\n", weight / 10);
+ }
+ }
+ break;
+
+ case MFC_REG_CODEC_MPEG4_DEC:
+ case MFC_REG_CODEC_FIMV1_DEC:
+ case MFC_REG_CODEC_FIMV2_DEC:
+ case MFC_REG_CODEC_FIMV3_DEC:
+ case MFC_REG_CODEC_FIMV4_DEC:
+ case MFC_REG_CODEC_H263_DEC:
+ case MFC_REG_CODEC_VC1_RCV_DEC:
+ case MFC_REG_CODEC_VC1_DEC:
+ case MFC_REG_CODEC_MPEG2_DEC:
+ weight = (weight * 100) / qos_weight->weight_other_codec;
+ mfc_ctx_debug(3, "[QoS] other codec, weight: %d\n", weight / 10);
+ break;
+
default:
mfc_ctx_err("[QoS] wrong codec_mode (%d), no weight\n", ctx->codec_mode);
}
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
index f56e800c55f0..6dc9bc7a1873 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
@@ -154,6 +154,11 @@ struct mfc_buf *mfc_get_del_if_consumed(struct mfc_ctx *ctx,
consumed, strm_size);
}
+ if (remained && IS_MULTI_MODE(ctx) && !CODEC_MULTIFRAME(ctx)) {
+ mfc_ctx_info("[2CORE][MULTIFRAME] multicore mode couldn't handle multiframe\n");
+ remained = 0;
+ }
+
if (consumed > 0 && remained > min_bytes &&
IS_NO_ERROR(error) && !exceed) {
/* do not delete from queue */
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
index b0698b2bb0c0..83cdae3dee57 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
@@ -187,9 +187,15 @@ void mfc_dec_calc_dpb_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct
}
mfc_ctx_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
- if (IS_H264_DEC(ctx)) {
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx)) {
ctx->mv_size = DEC_MV_SIZE_MB(ctx->img_width, ctx->img_height);
ctx->mv_size = ALIGN(ctx->mv_size, 32);
+ } else if (IS_HEVC_DEC(ctx)) {
+ ctx->mv_size = DEC_HEVC_MV_SIZE(ctx->img_width, ctx->img_height);
+ ctx->mv_size = ALIGN(ctx->mv_size, 32);
+ } else if (IS_AV1_DEC(ctx)) {
+ ctx->mv_size = DEC_AV1_MV_SIZE(ctx->img_width, ctx->img_height);
+ ctx->mv_size = ALIGN(ctx->mv_size, 32);
} else {
ctx->mv_size = 0;
}
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc.c b/drivers/media/platform/samsung/exynos-mfc/mfc.c
index fb9a7317e812..293a353c49fa 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc.c
@@ -646,18 +646,69 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
of_property_read_u32_array
(np, "bw_dec_h264",
&pdata->mfc_bw_info.bw_dec_h264.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_hevc",
+ &pdata->mfc_bw_info.bw_dec_hevc.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_hevc_10bit",
+ &pdata->mfc_bw_info.bw_dec_hevc_10bit.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_vp8",
+ &pdata->mfc_bw_info.bw_dec_vp8.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_vp9",
+ &pdata->mfc_bw_info.bw_dec_vp9.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_vp9_10bit",
+ &pdata->mfc_bw_info.bw_dec_vp9_10bit.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_av1",
+ &pdata->mfc_bw_info.bw_dec_av1.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_av1_10bit",
+ &pdata->mfc_bw_info.bw_dec_av1_10bit.peak, 3);
+ of_property_read_u32_array
+ (np, "bw_dec_mpeg4",
+ &pdata->mfc_bw_info.bw_dec_mpeg4.peak, 3);
/* QoS weight */
of_property_read_u32(np, "dynamic_weight", &pdata->dynamic_weight);
of_property_read_u32
(np, "qos_weight_h264_hevc",
&pdata->qos_weight.weight_h264_hevc);
+ of_property_read_u32
+ (np, "qos_weight_vp8_vp9",
+ &pdata->qos_weight.weight_vp8_vp9);
+ of_property_read_u32
+ (np, "qos_weight_av1",
+ &pdata->qos_weight.weight_av1);
+ of_property_read_u32
+ (np, "qos_weight_other_codec",
+ &pdata->qos_weight.weight_other_codec);
of_property_read_u32
(np, "qos_weight_3plane",
&pdata->qos_weight.weight_3plane);
+ of_property_read_u32
+ (np, "qos_weight_10bit",
+ &pdata->qos_weight.weight_10bit);
+ of_property_read_u32
+ (np, "qos_weight_422",
+ &pdata->qos_weight.weight_422);
+ of_property_read_u32
+ (np, "qos_weight_bframe",
+ &pdata->qos_weight.weight_bframe);
+ of_property_read_u32
+ (np, "qos_weight_num_of_ref",
+ &pdata->qos_weight.weight_num_of_ref);
+ of_property_read_u32
+ (np, "qos_weight_gpb",
+ &pdata->qos_weight.weight_gpb);
of_property_read_u32
(np, "qos_weight_num_of_tile",
&pdata->qos_weight.weight_num_of_tile);
+ of_property_read_u32
+ (np, "qos_weight_super64_bframe",
+ &pdata->qos_weight.weight_super64_bframe);
of_property_read_u32
(np, "qos_weight_mbaff",
&pdata->qos_weight.weight_mbaff);
@@ -1075,6 +1126,8 @@ static const struct dev_pm_ops mfc_pm_ops = {
struct mfc_ctx_buf_size mfc_ctx_buf_size = {
.dev_ctx = PAGE_ALIGN(0x7800), /* 30KB */
.h264_dec_ctx = PAGE_ALIGN(0x200000), /* 1.6MB */
+ .av1_dec_ctx = PAGE_ALIGN(0x19000), /* 100KB */
+ .other_dec_ctx = PAGE_ALIGN(0xF000), /* 60KB */
.dbg_info_buf = PAGE_ALIGN(0x1000), /* 4KB for DEBUG INFO */
};
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
index af6fd088fad3..aad3273ce2ba 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
@@ -77,6 +77,8 @@ static int __mfc_core_parse_mfc_qos_platdata(struct device_node *np,
of_property_read_u32(np_qos, "freq_int", &qosdata->freq_int);
of_property_read_u32(np_qos, "freq_mif", &qosdata->freq_mif);
of_property_read_u32(np_qos, "mo_value", &qosdata->mo_value);
+ of_property_read_u32(np_qos, "mo_10bit_value",
+ &qosdata->mo_10bit_value);
of_property_read_u32(np_qos, "time_fw", &qosdata->time_fw);
of_property_read_string(np_qos, "bts_scen", &qosdata->name);
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
index 56dc3e734d02..38f09d6ef2dd 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
@@ -63,6 +63,7 @@ static int mfc_core_get_buf_ctrls(struct mfc_core *core,
struct mfc_ctx *ctx, struct list_head *head)
{
struct mfc_buf_ctrl *buf_ctrl;
+ struct mfc_dec *dec = ctx->dec_priv;
unsigned int value = 0;
list_for_each_entry(buf_ctrl, head, list) {
@@ -77,6 +78,14 @@ static int mfc_core_get_buf_ctrls(struct mfc_core *core,
buf_ctrl->val = value;
buf_ctrl->has_new = 1;
+ if (IS_VP9_DEC(ctx) && dec) {
+ if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
+ buf_ctrl->val = dec->color_range;
+ else if (buf_ctrl->id ==
+ V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
+ buf_ctrl->val = dec->color_space;
+ }
+
if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FRAME_ERROR_TYPE)
buf_ctrl->val = mfc_get_frame_error_type(ctx, value);
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_cmd.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_cmd.c
index fe7946bb49e7..aaf216741575 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_cmd.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_cmd.c
@@ -230,6 +230,10 @@ void mfc_core_cmd_dec_seq_header(struct mfc_core *core, struct mfc_ctx *ctx)
reg |= ((dec->idr_decoding & MFC_REG_D_DEC_OPT_IDR_DECODING_MASK)
<< MFC_REG_D_DEC_OPT_IDR_DECODING_SHIFT);
+ /* VC1 RCV: Discard to parse additional header as default */
+ if (IS_VC1_RCV_DEC(ctx))
+ reg |= BIT(MFC_REG_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT);
+
/* conceal control to specific color */
reg |= (0x4 << MFC_REG_D_DEC_OPT_CONCEAL_CONTROL_SHIFT);
@@ -248,6 +252,13 @@ void mfc_core_cmd_dec_seq_header(struct mfc_core *core, struct mfc_ctx *ctx)
MFC_CORE_WRITEL(MFC_CONCEAL_COLOR, MFC_REG_D_FORCE_PIXEL_VAL);
+ if (IS_FIMV1_DEC(ctx)) {
+ mfc_debug(2, "Setting FIMV1 resolution to %dx%d\n",
+ ctx->img_width, ctx->img_height);
+ MFC_CORE_WRITEL(ctx->img_width, MFC_REG_D_SET_FRAME_WIDTH);
+ MFC_CORE_WRITEL(ctx->img_height, MFC_REG_D_SET_FRAME_HEIGHT);
+ }
+
mfc_core_set_pixel_format(core, ctx, ctx->dst_fmt->fourcc);
reg = 0;
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
index 94cc3c4dfdc5..aa2c0b618c19 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
@@ -126,10 +126,11 @@ static unsigned int __mfc_handle_frame_field(struct mfc_core *core,
unsigned int interlace_type = 0, is_interlace = 0;
unsigned int field;
- if (IS_H264_DEC(ctx)) {
- dec->is_mbaff = mfc_core_is_mbaff_picture();
+ if (CODEC_INTERLACED(ctx))
is_interlace = mfc_core_is_interlace_picture();
- }
+
+ if (CODEC_MBAFF(ctx))
+ dec->is_mbaff = mfc_core_is_mbaff_picture();
if (is_interlace) {
interlace_type = mfc_core_get_interlace_type();
@@ -482,6 +483,27 @@ static struct mfc_buf *__mfc_handle_frame_output_del(struct mfc_core *core,
}
}
+ if (IS_VP9_DEC(ctx) &&
+ MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+ if (dec->color_space != MFC_REG_D_COLOR_UNKNOWN) {
+ mfc_set_mb_flag(dst_mb,
+ MFC_FLAG_HDR_COLOUR_DESC);
+ mfc_ctx_debug(2, "[HDR] color space parsed\n");
+ }
+ mfc_set_mb_flag(dst_mb, MFC_FLAG_HDR_VIDEO_SIGNAL_TYPE);
+ mfc_ctx_debug(2, "[HDR] color range parsed\n");
+ }
+
+ if ((IS_VP9_DEC(ctx) && mfc_core_get_disp_res_change()) ||
+ (IS_AV1_DEC(ctx) && mfc_core_get_disp_res_change_av1())) {
+ mfc_ctx_info("[FRAME][DRC] display resolution changed\n");
+ mutex_lock(&ctx->drc_wait_mutex);
+ ctx->wait_state = WAIT_G_FMT;
+ mfc_core_get_img_size(core, ctx, MFC_GET_RESOL_SIZE);
+ mfc_set_mb_flag(dst_mb, MFC_FLAG_DISP_RES_CHANGE);
+ mutex_unlock(&ctx->drc_wait_mutex);
+ }
+
if (dec->black_bar_updated) {
mfc_set_mb_flag(dst_mb, MFC_FLAG_BLACKBAR_DETECT);
mfc_ctx_debug(3, "[BLACKBAR] black bar detected\n");
@@ -498,6 +520,11 @@ static struct mfc_buf *__mfc_handle_frame_output_del(struct mfc_core *core,
mfc_ctx_debug(2, "[FRAME] Last display frame\n");
}
+ if ((IS_VP9_DEC(ctx) || IS_AV1_DEC(ctx)) && dec->has_multiframe) {
+ mfc_set_mb_flag(dst_mb, MFC_FLAG_MULTIFRAME);
+ mfc_ctx_debug(2, "[MULTIFRAME] multiframe detected\n");
+ }
+
if (ctx->dst_fmt->mem_planes == 1) {
vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0,
raw->total_plane_size);
@@ -542,6 +569,8 @@ static struct mfc_buf *__mfc_handle_frame_output_del(struct mfc_core *core,
mutex_unlock(&dec->dpb_mutex);
} else {
+ if (IS_AV1_DEC(ctx) && mfc_core_get_multiple_show_frame())
+ dec->is_multiple_show = 1;
mfc_print_dpb_queue_with_lock(core->core_ctx[ctx->num], dec);
}
@@ -708,11 +737,18 @@ static struct mfc_buf *__mfc_handle_frame_output(struct mfc_core *core,
{
struct mfc_dec *dec = ctx->dec_priv;
unsigned int frame_type;
+ int mvc_view_id;
frame_type = mfc_core_get_disp_frame_type();
+ mvc_view_id = mfc_core_get_mvc_disp_view_id();
- if (!ctx->multi_view_enable || ctx->select_view_irq == MFC_VIEW_ID_SUB)
- ctx->sequence++;
+ if (IS_H264_MVC_DEC(ctx)) {
+ if (mvc_view_id == 0)
+ ctx->sequence++;
+ } else {
+ if (!ctx->multi_view_enable || ctx->select_view_irq == MFC_VIEW_ID_SUB)
+ ctx->sequence++;
+ }
if (dec->immediate_display == 1)
frame_type = mfc_core_get_dec_frame_type();
@@ -721,7 +757,8 @@ static struct mfc_buf *__mfc_handle_frame_output(struct mfc_core *core,
/* If frame is same as previous then skip and do not dequeue */
if (frame_type == MFC_REG_DISPLAY_FRAME_NOT_CODED)
- return NULL;
+ if (!CODEC_NOT_CODED(ctx))
+ return NULL;
/* Dequeued display buffer for user */
return __mfc_handle_frame_output_del(core, ctx, err);
@@ -894,6 +931,7 @@ static void __mfc_handle_frame_input(struct mfc_core *core,
struct mfc_ctx *ctx,
unsigned int err)
{
+ struct mfc_dev *dev = ctx->dev;
struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
struct mfc_dec *dec = ctx->dec_priv;
struct mfc_buf *src_mb;
@@ -945,6 +983,54 @@ static void __mfc_handle_frame_input(struct mfc_core *core,
mfc_clear_mb_flag(src_mb);
+ if ((IS_VP9_DEC(ctx) || IS_AV1_DEC(ctx)) && dec->has_multiframe &&
+ mfc_core_get_disp_status() == MFC_REG_DEC_STATUS_DECODING_ONLY) {
+ mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+ mfc_debug(2, "[STREAM][MULTIFRAME] last frame is decoding only\n");
+ }
+
+ /*
+ * VP8 decoder has decoding only frame,
+ * it will be used for reference frame only not displayed.
+ * So, driver inform to user this input has no destination.
+ */
+ if (((IS_VP8_DEC(ctx) || IS_VP9_DEC(ctx)) &&
+ mfc_core_get_disp_status() == MFC_REG_DEC_STATUS_DECODING_ONLY) ||
+ mfc_core_get_int_reason() == MFC_REG_R2H_CMD_FIELD_DONE_RET) {
+ mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+ mfc_debug(2, "[STREAM] %s decoding only stream has no buffer to DQ\n",
+ ctx->src_fmt->name);
+ }
+
+ /*
+ * Because AV1 has a no show frame, there are two cases that
+ * driver should inform to user this input has no destination buffer.
+ * 1) If it's decoding only and it's not showable frame,
+ * it will be used for reference frame only not displayed.
+ * 2) If the buffer that has already DQ to display comes to new display,
+ * it is multiple show frame.
+ */
+ if (IS_AV1_DEC(ctx)) {
+ if ((mfc_core_get_disp_status() == MFC_REG_DEC_STATUS_DECODING_ONLY) &&
+ !mfc_core_get_showable_frame()) {
+ mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+ mfc_debug(2, "[STREAM] AV1 no showable frame has no buffer to DQ\n");
+ }
+ if (dec->is_multiple_show) {
+ mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+ dec->is_multiple_show = 0;
+ mfc_info("[STREAM] AV1 multiple show frame has no buffer to DQ\n");
+ }
+ }
+
+ /* If pic_output_flag is 0 in HEVC, it is no destination buffer */
+ if (IS_HEVC_DEC(ctx) &&
+ MFC_FEATURE_SUPPORT(dev, dev->pdata->hevc_pic_output_flag) &&
+ !mfc_core_get_hevc_pic_output_flag()) {
+ mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+ mfc_debug(2, "[STREAM] HEVC pic_output_flag off has no buffer to DQ\n");
+ }
+
if (mfc_core_get_disp_status() == MFC_REG_DEC_STATUS_DECODING_ONLY &&
mfc_core_get_dec_y_addr() == 0) {
mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
@@ -955,6 +1041,8 @@ static void __mfc_handle_frame_input(struct mfc_core *core,
mfc_err("failed in core_get_buf_ctrls\n");
dec->consumed = 0;
+ if (IS_VP9_DEC(ctx) || IS_AV1_DEC(ctx))
+ dec->has_multiframe = 0;
if (ctx->multi_view_enable && ctx->select_view == 0)
mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
@@ -978,7 +1066,7 @@ static void __mfc_handle_frame(struct mfc_core *core,
unsigned int res_change, need_dpb_change, need_scratch_change;
struct mfc_buf *mfc_buf = NULL;
bool qos_update = false;
- int index;
+ int index, profile;
dst_frame_status = mfc_core_get_disp_status();
res_change = mfc_core_get_res_change();
@@ -1048,6 +1136,15 @@ static void __mfc_handle_frame(struct mfc_core *core,
index = mfc_buf->vb.vb2_buf.index;
call_bop(ctx, core_restore_buf_ctrls, ctx, &ctx->src_ctrls[index]);
}
+
+ /* It could because of sub-view header (MV-HEVC) */
+ if (!ctx->multi_view_enable) {
+ profile = mfc_core_get_profile();
+ if (IS_MV_HEVC_DEC(ctx, profile)) {
+ mfc_debug(2, "Ready to enable, possibly a sub-view header.\n");
+ ctx->ready_to_be_multi_view_enable = 1;
+ }
+ }
return;
}
@@ -1110,7 +1207,7 @@ static void __mfc_handle_frame(struct mfc_core *core,
}
/* Detection for QoS weight */
- if (!dec->num_of_tile_over_4 &&
+ if (!dec->num_of_tile_over_4 && !IS_HEVC_DEC(ctx) &&
mfc_core_get_num_of_tile() >= 4) {
dec->num_of_tile_over_4 = 1;
qos_update = true;
@@ -1185,7 +1282,7 @@ static int __mfc_handle_seq_dec(struct mfc_core *core, struct mfc_ctx *ctx)
struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
struct mfc_dec *dec = ctx->dec_priv;
struct mfc_buf *src_mb;
- int i, is_interlace;
+ int i, is_interlace, profile;
unsigned int strm_size, consumed;
if (ctx->src_fmt->fourcc != V4L2_PIX_FMT_FIMV1) {
@@ -1196,13 +1293,34 @@ static int __mfc_handle_seq_dec(struct mfc_core *core, struct mfc_ctx *ctx)
mfc_info("[STREAM] resolution w: %d, h: %d\n", ctx->img_width, ctx->img_height);
}
- ctx->dpb_count = mfc_core_get_dpb_count();
+ if (IS_AV1_DEC(ctx) || (IS_VP9_DEC(ctx) && UNDER_4K_RES(ctx)))
+ ctx->dpb_count = mfc_core_get_dpb_count() + 7 - MFC_EXTRA_DPB;
+ else
+ ctx->dpb_count = mfc_core_get_dpb_count();
mfc_ctx_debug(2, "dpb_count: %d\n", ctx->dpb_count);
ctx->scratch_buf_size = mfc_core_get_scratch_size();
mfc_core_dec_get_crop_info(core, ctx);
dec->mv_count = mfc_core_get_mv_count();
+ profile = mfc_core_get_profile();
+
+ if (CODEC_422FORMAT(ctx) && dev->pdata->support_422) {
+ if (mfc_core_get_chroma_format() == MFC_REG_D_CHROMA_422) {
+ ctx->is_422 = 1;
+ mfc_info("[STREAM] 422 chroma format\n");
+ }
+ }
+
+ if (IS_MV_HEVC_DEC(ctx, profile)) {
+ if (ctx->ready_to_be_multi_view_enable) {
+ mfc_debug(2, "It will be enabled later, pending DPB_FLUSH.\n");
+ } else {
+ mfc_debug(2, "[MV-HEVC] enabled\n");
+ ctx->multi_view_enable = 1;
+ ctx->select_view = MFC_VIEW_ID_MAIN;
+ }
+ }
if (ctx->img_width == 0 || ctx->img_height == 0) {
mfc_err("[STREAM] wrong resolution w: %d, h: %d\n",
@@ -1243,7 +1361,7 @@ static int __mfc_handle_seq_dec(struct mfc_core *core, struct mfc_ctx *ctx)
strm_size = mfc_dec_get_strm_size(ctx, src_mb);
mfc_debug(2, "[STREAM] header size, %d, %#x, consumed, %d, %#x\n",
strm_size, strm_size, consumed, consumed);
- if ((IS_H264_DEC(ctx)) &&
+ if ((IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) &&
(consumed > 0 && strm_size > consumed)) {
dec->consumed += consumed;
mfc_debug(2, "[STREAM] there is remained bytes(%d) after header parsing\n",
@@ -1257,6 +1375,13 @@ static int __mfc_handle_seq_dec(struct mfc_core *core, struct mfc_ctx *ctx)
mfc_debug(2, "[FRAME] display delay for first frame %d\n",
dec->frame_display_delay);
+ if (IS_VP9_DEC(ctx)) {
+ dec->color_range = mfc_core_get_color_range();
+ dec->color_space = mfc_core_get_color_space();
+ mfc_debug(2, "color range: %d, color space: %d, It's valid for VP9\n",
+ dec->color_range, dec->color_space);
+ }
+
mfc_change_state(core_ctx, MFCINST_HEAD_PARSED);
return 0;
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.c
index 6950b8451c3d..0cc5d1d9433e 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.c
@@ -52,7 +52,8 @@ unsigned int mfc_get_frame_error_type(struct mfc_ctx *ctx, unsigned int err)
return MFC_ERR_FRAME_NO_ERR;
}
- if (mfc_get_warn(err) == MFC_REG_ERR_BROKEN_LINK) {
+ if ((IS_VC1_RCV_DEC(ctx) && (mfc_get_warn(err) == MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED)) ||
+ (mfc_get_warn(err) == MFC_REG_ERR_BROKEN_LINK)) {
mfc_ctx_debug(2, "[FRAME] Broken frame error (%d)\n", mfc_get_warn(err));
return MFC_ERR_FRAME_BROKEN;
} else if (mfc_get_warn(err) == MFC_REG_ERR_SYNC_POINT_NOT_RECEIVED) {
@@ -104,6 +105,7 @@ int mfc_core_set_dec_codec_buffers(struct mfc_core_ctx *core_ctx)
int buf_size;
int align_gap;
unsigned int reg = 0;
+ unsigned int av1_static_buf_size = 0;
buf_addr = core_ctx->codec_buf.daddr;
buf_size = core_ctx->codec_buf.size;
@@ -124,14 +126,50 @@ int mfc_core_set_dec_codec_buffers(struct mfc_core_ctx *core_ctx)
buf_addr += ctx->scratch_buf_size;
buf_size -= ctx->scratch_buf_size;
- if (IS_H264_DEC(ctx))
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_AV1_DEC(ctx))
MFC_CORE_WRITEL(ctx->mv_size, MFC_REG_D_MV_BUFFER_SIZE);
+ if (IS_VP9_DEC(ctx)) {
+ MFC_CORE_DMA_WRITEL(buf_addr, MFC_REG_D_STATIC_BUFFER_ADDR);
+ MFC_CORE_WRITEL(DEC_STATIC_BUFFER_SIZE, MFC_REG_D_STATIC_BUFFER_SIZE);
+ buf_addr += DEC_STATIC_BUFFER_SIZE;
+ buf_size -= DEC_STATIC_BUFFER_SIZE;
+ } else if (IS_AV1_DEC(ctx)) {
+ av1_static_buf_size = DEC_AV1_STATIC_BUFFER_SIZE(ctx->img_width, ctx->img_height);
+ MFC_CORE_DMA_WRITEL(buf_addr, MFC_REG_D_STATIC_BUFFER_ADDR);
+ MFC_CORE_WRITEL(av1_static_buf_size, MFC_REG_D_STATIC_BUFFER_SIZE);
+ buf_addr += av1_static_buf_size;
+ buf_size -= av1_static_buf_size;
+ }
+
+ if (IS_MPEG4_DEC(ctx) && dec->loop_filter_mpeg4) {
+ mfc_debug(2, "Add DPB for loop filter of MPEG4\n");
+ for (i = 0; i < NUM_MPEG4_LF_BUF; i++) {
+ MFC_CORE_DMA_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_LUMA_DPB0 + (4 * i));
+ buf_addr += ctx->loopfilter_luma_size;
+ buf_size -= ctx->loopfilter_luma_size;
+
+ MFC_CORE_DMA_WRITEL(buf_addr, MFC_REG_D_POST_FILTER_CHROMA_DPB0 + (4 * i));
+ buf_addr += ctx->loopfilter_chroma_size;
+ buf_size -= ctx->loopfilter_chroma_size;
+ }
+ reg |= ((dec->loop_filter_mpeg4 & MFC_REG_D_INIT_BUF_OPT_LF_CTRL_MASK)
+ << MFC_REG_D_INIT_BUF_OPT_LF_CTRL_SHIFT);
+ }
+
reg |= (dec->is_dynamic_dpb << MFC_REG_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT);
+ if (CODEC_NOT_CODED(ctx)) {
+ reg |= BIT(MFC_REG_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT);
+ mfc_debug(2, "Notcoded frame copy mode start\n");
+ }
+
/* 16byte align, It is valid only for VP9 */
reg &= ~BIT(MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
-
+ if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->vp9_stride_align)) {
+ reg &= ~(0x3 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+ reg |= (0x2 << MFC_REG_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+ }
reg &= ~BIT(MFC_REG_D_INIT_BUF_OPT_TWO_MODE_ENABLE_SHIFT);
if (IS_MULTI_MODE(ctx)) {
reg |= BIT(MFC_REG_D_INIT_BUF_OPT_TWO_MODE_ENABLE_SHIFT);
@@ -158,7 +196,7 @@ int mfc_core_set_dec_codec_buffers(struct mfc_core_ctx *core_ctx)
frame_size_mv = ctx->mv_size;
MFC_CORE_WRITEL(dec->mv_count, MFC_REG_D_NUM_MV);
- if (IS_H264_DEC(ctx)) {
+ if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_AV1_DEC(ctx)) {
if (ctx->mv_buffer_allocated && buf_size &&
buf_size > ctx->mv_buf.dma_buf->size) {
mfc_info("[MEMINFO] Not enough MV buf size %d alloc size %zu\n",
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.h b/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.h
index e7c28b2f2b5d..08f74bd56f3f 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.h
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_reg_api.h
@@ -89,12 +89,15 @@
>> MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT)\
& MFC_REG_D_H264_INFO_MBAFF_FRAME_FLAG_MASK)
+#define mfc_core_get_aspect_ratio() MFC_CORE_READL(MFC_REG_D_DISPLAY_ASPECT_RATIO)
#define mfc_core_get_img_width() MFC_CORE_READL(MFC_REG_D_DISPLAY_FRAME_WIDTH)
#define mfc_core_get_img_height() MFC_CORE_READL(MFC_REG_D_DISPLAY_FRAME_HEIGHT)
#define mfc_core_get_disp_y_addr() MFC_CORE_DMA_READL(MFC_REG_D_DISPLAY_LUMA_ADDR)
#define mfc_core_get_dec_y_addr() MFC_CORE_DMA_READL(MFC_REG_D_DECODED_LUMA_ADDR)
#define mfc_core_get_crc_luma() MFC_CORE_READL(MFC_REG_D_DISPLAY_FIRST_PLANE_CRC)
#define mfc_core_get_crc_chroma() MFC_CORE_READL(MFC_REG_D_DISPLAY_SECOND_PLANE_CRC)
+#define mfc_core_get_crc_luma_2bit() MFC_CORE_READL(MFC_REG_D_DISPLAY_FIRST_PLANE_2BIT_CRC)
+#define mfc_core_get_crc_chroma_2bit() MFC_CORE_READL(MFC_REG_D_DISPLAY_SECOND_PLANE_2BIT_CRC)
/* kind of interrupt */
#define mfc_core_get_int_err() MFC_CORE_READL(MFC_REG_ERROR_CODE)
@@ -104,10 +107,13 @@
#define mfc_core_get_dpb_count() MFC_CORE_READL(MFC_REG_D_MIN_NUM_DPB)
#define mfc_core_get_min_dpb_size(x) \
MFC_CORE_READL(MFC_REG_D_MIN_FIRST_PLANE_DPB_SIZE + ((x) * 4))
+#define mfc_core_get_min_dpb_size_2bit(x) \
+ MFC_CORE_READL(MFC_REG_D_MIN_FIRST_PLANE_2BIT_DPB_SIZE + ((x) * 4))
#define mfc_core_get_scratch_size() MFC_CORE_READL(MFC_REG_D_MIN_SCRATCH_BUFFER_SIZE)
#define mfc_core_get_stride_size(x) \
MFC_CORE_READL(MFC_REG_D_FIRST_PLANE_DPB_STRIDE_SIZE + ((x) * 4))
-
+#define mfc_core_get_stride_size_2bit(x) \
+ MFC_CORE_READL(MFC_REG_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE + ((x) * 4))
#define mfc_core_get_mv_count() MFC_CORE_READL(MFC_REG_D_MIN_NUM_MV)
#define mfc_core_get_inst_no() MFC_CORE_READL(MFC_REG_RET_INSTANCE_ID)
#define mfc_core_get_sei_avail() MFC_CORE_READL(MFC_REG_D_SEI_AVAIL)
@@ -133,14 +139,27 @@
#define mfc_core_get_sei_avail_mastering_display() ((MFC_CORE_READL(MFC_REG_D_SEI_AVAIL) \
>> MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT) \
& MFC_REG_D_SEI_AVAIL_MASTERING_DISPLAY_MASK)
-
+#define mfc_core_get_sei_avail_st_2094_40() ((MFC_CORE_READL(MFC_REG_D_SEI_AVAIL) \
+ >> MFC_REG_D_SEI_AVAIL_ST_2094_40_SHIFT) \
+ & MFC_REG_D_SEI_AVAIL_ST_2094_40_MASK)
+#define mfc_core_get_sei_nal_meta_status() ((MFC_CORE_READL(MFC_REG_METADATA_STATUS) \
+ >> MFC_REG_SEI_NAL_STATUS_SHIFT) \
+ & MFC_REG_SEI_NAL_STATUS_MASK)
#define mfc_core_get_video_signal_type() ((MFC_CORE_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
>> MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT) \
& MFC_REG_D_VIDEO_SIGNAL_TYPE_FLAG_MASK)
#define mfc_core_get_colour_description() ((MFC_CORE_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
>> MFC_REG_D_COLOUR_DESCRIPTION_FLAG_SHIFT) \
& MFC_REG_D_COLOUR_DESCRIPTION_FLAG_MASK)
-
+#define mfc_core_get_primaries() ((MFC_CORE_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
+ >> MFC_REG_D_COLOUR_PRIMARIES_SHIFT) \
+ & MFC_REG_D_COLOUR_PRIMARIES_MASK)
+#define mfc_core_get_transfer() ((MFC_CORE_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
+ >> MFC_REG_D_TRANSFER_CHARACTERISTICS_SHIFT) \
+ & MFC_REG_D_TRANSFER_CHARACTERISTICS_MASK)
+#define mfc_core_get_matrix_coeff() ((MFC_CORE_READL(MFC_REG_D_VIDEO_SIGNAL_TYPE) \
+ >> MFC_REG_D_MATRIX_COEFFICIENTS_SHIFT) \
+ & MFC_REG_D_MATRIX_COEFFICIENTS_MASK)
#define mfc_core_get_black_bar_pos_x() ((MFC_CORE_READL(MFC_REG_D_BLACK_BAR_START_POS) \
>> MFC_REG_D_BLACK_BAR_START_X_SHIFT) \
& MFC_REG_D_BLACK_BAR_START_X_MASK)
@@ -160,12 +179,25 @@
& MFC_REG_D_MVC_VIEW_ID_DEC_MASK)
#define mfc_core_get_mvc_view_id_disp_order() (MFC_CORE_READL(MFC_REG_D_MVC_VIEW_ID) \
& MFC_REG_D_MVC_VIEW_ID_DISP_MASK)
+#define mfc_core_get_mvc_left_view_id() ((MFC_CORE_READL(MFC_REG_D_MVC_VIEW_ID) \
+ >> MFC_REG_D_MVC_LEFT_VIEW_ID_SHIFT) \
+ & MFC_REG_D_MVC_LEFT_VIEW_ID_MASK)
#define mfc_core_get_mvc_right_view_id() ((MFC_CORE_READL(MFC_REG_D_MVC_VIEW_ID) \
>> MFC_REG_D_MVC_RIGHT_VIEW_ID_SHIFT) \
& MFC_REG_D_MVC_RIGHT_VIEW_ID_MASK)
#define mfc_core_get_profile() (MFC_CORE_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
& MFC_REG_D_DECODED_PIC_PROFILE_MASK)
-
+#define mfc_core_get_level() ((MFC_CORE_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ >> MFC_REG_D_PIC_LEVEL_SHIFT) \
+ & MFC_REG_D_PIC_LEVEL_MASK)
+#define mfc_core_get_luma_bit_depth_minus8() ((MFC_CORE_READL \
+ (MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ >> MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_SHIFT) \
+ & MFC_REG_D_BIT_DEPTH_LUMA_MINUS8_MASK)
+#define mfc_core_get_chroma_bit_depth_minus8() ((MFC_CORE_READL \
+ (MFC_REG_D_DECODED_PICTURE_PROFILE) \
+ >> MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT) \
+ & MFC_REG_D_BIT_DEPTH_CHROMA_MINUS8_MASK)
#define mfc_core_get_display_delay() \
((MFC_CORE_READL(MFC_REG_D_DECODED_PICTURE_PROFILE) \
>> MFC_REG_D_DISPLAY_DELAY_SHIFT) \
@@ -177,10 +209,34 @@
#define mfc_core_get_dec_used_flag() (((unsigned long)(MFC_CORE_READL \
(MFC_REG_D_USED_DPB_FLAG_UPPER)) << 32) | \
MFC_CORE_READL(MFC_REG_D_USED_DPB_FLAG_LOWER))
-
+#define mfc_core_get_chroma_format() (MFC_CORE_READL(MFC_REG_D_CHROMA_FORMAT) \
+ & MFC_REG_D_CHROMA_FORMAT_MASK)
+#define mfc_core_get_color_range() ((MFC_CORE_READL(MFC_REG_D_CHROMA_FORMAT) \
+ >> MFC_REG_D_COLOR_RANGE_SHIFT) \
+ & MFC_REG_D_COLOR_RANGE_MASK)
+#define mfc_core_get_color_space() ((MFC_CORE_READL(MFC_REG_D_CHROMA_FORMAT) \
+ >> MFC_REG_D_COLOR_SPACE_SHIFT) \
+ & MFC_REG_D_COLOR_SPACE_MASK)
#define mfc_core_get_num_of_tile() ((MFC_CORE_READL(MFC_REG_D_DECODED_STATUS) \
>> MFC_REG_DEC_STATUS_NUM_OF_TILE_SHIFT) \
& MFC_REG_DEC_STATUS_NUM_OF_TILE_MASK)
+#define mfc_core_get_lcu_size() (MFC_CORE_READL(MFC_REG_D_HEVC_INFO) \
+ & MFC_REG_D_HEVC_INFO_LCU_SIZE_MASK)
+#define mfc_core_get_disp_res_change() ((MFC_CORE_READL(MFC_REG_D_VP9_INFO) \
+ >> MFC_REG_D_VP9_INFO_DISP_RES_SHIFT) \
+ & MFC_REG_D_VP9_INFO_DISP_RES_MASK)
+#define mfc_core_get_disp_res_change_av1() ((MFC_CORE_READL(MFC_REG_D_AV1_INFO) \
+ >> MFC_REG_D_AV1_INFO_DISP_RES_SHIFT) \
+ & MFC_REG_D_AV1_INFO_DISP_RES_MASK)
+#define mfc_core_get_showable_frame() ((MFC_CORE_READL(MFC_REG_D_AV1_INFO) \
+ >> MFC_REG_D_AV1_INFO_SHOWABLE_FRAME_SHIFT) \
+ & MFC_REG_D_AV1_INFO_SHOWABLE_FRAME_MASK)
+#define mfc_core_get_multiple_show_frame() ((MFC_CORE_READL(MFC_REG_D_AV1_INFO) \
+ >> MFC_REG_D_AV1_INFO_MULTIPLE_SHOW_SHIFT) \
+ & MFC_REG_D_AV1_INFO_MULTIPLE_SHOW_MASK)
+#define mfc_core_get_hevc_pic_output_flag() ((MFC_CORE_READL(MFC_REG_D_HEVC_INFO) \
+ >> MFC_REG_D_HEVC_INFO_PIC_OUTPUT_FLAG_SHIFT) \
+ & MFC_REG_D_HEVC_INFO_PIC_OUTPUT_FLAG_MASK)
static inline void mfc_core_dec_get_crop_info(struct mfc_core *core,
struct mfc_ctx *ctx)
@@ -201,6 +257,15 @@ static inline void mfc_core_dec_get_crop_info(struct mfc_core *core,
dec->cr_bot = bottom;
}
+static inline void mfc_core_clear_roi_enable(struct mfc_core *core)
+{
+ unsigned int reg = 0;
+
+ reg = MFC_CORE_READL(MFC_REG_E_RC_ROI_CTRL);
+ reg &= ~(0x1);
+ MFC_CORE_WRITEL(reg, MFC_REG_E_RC_ROI_CTRL);
+}
+
static inline void mfc_core_update_tag(struct mfc_core *core, struct mfc_ctx *ctx,
int tag)
{
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_run.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_run.c
index 118108f910e2..127d19c4d1cb 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_run.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_run.c
@@ -369,6 +369,10 @@ int mfc_core_run_dec_frame(struct mfc_core *core, struct mfc_ctx *ctx)
last_frame = __mfc_check_last_frame(core_ctx, src_mb);
ret = mfc_core_cmd_dec_one_frame(core, ctx, last_frame, src_index);
+ if (dec->consumed && IS_MULTI_MODE(ctx) && !CODEC_MULTIFRAME(ctx)) {
+ mfc_debug(2, "[STREAM][2CORE] clear consumed for next core\n");
+ dec->consumed = 0;
+ }
return ret;
}
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_dec_vb2.c b/drivers/media/platform/samsung/exynos-mfc/mfc_dec_vb2.c
index 3097a6c0bf14..626c8db5f93b 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_dec_vb2.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_dec_vb2.c
@@ -9,6 +9,7 @@
* Himanshu Dewangan, <h.dewangan@...sung.com>
*/
+#include "mfc_dec_v4l2.h"
#include "mfc_dec_vb2.h"
#include "mfc_rm.h"
--
2.34.1
Powered by blists - more mailing lists