From: Sachin Kumar Garg <sachin.garg@oss.qualcomm.com>
To: Vikash Garodia <vikash.garodia@oss.qualcomm.com>,
Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>,
Abhinav Kumar <abhinav.kumar@linux.dev>,
Bryan O'Donoghue <bod@kernel.org>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Vedang Nagar <quic_vnagar@quicinc.com>,
Stefan Schmidt <stefan.schmidt@linaro.org>,
Hans Verkuil <hverkuil@kernel.org>
Cc: linux-media@vger.kernel.org, linux-arm-msm@vger.kernel.org,
linux-kernel@vger.kernel.org,
Sachin Kumar Garg <sachin.garg@oss.qualcomm.com>
Subject: [PATCH v4 3/3] media: iris: add support for multi_slice in iris encoder
Date: Thu, 23 Jul 2026 15:51:15 +0530 [thread overview]
Message-ID: <20260723-iris_multi_slice-v4-3-45f0a3fe7fce@oss.qualcomm.com> (raw)
In-Reply-To: <20260723-iris_multi_slice-v4-0-45f0a3fe7fce@oss.qualcomm.com>
Add multi-slice encoding support with MAX_MB and MAX_BYTES modes.
Clients can enable slice mode using V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE
control and configure slice size via V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB
or V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES controls.
Signed-off-by: Sachin Kumar Garg <sachin.garg@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_ctrls.c | 79 ++++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_ctrls.h | 1 +
drivers/media/platform/qcom/iris/iris_hfi_gen2.c | 33 ++++++++-
.../platform/qcom/iris/iris_hfi_gen2_defines.h | 2 +
.../platform/qcom/iris/iris_platform_common.h | 16 +++++
.../media/platform/qcom/iris/iris_platform_vpu3x.c | 17 +++++
6 files changed, 147 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
index d7cbf6c3614a..ed7ed4b89a5a 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
@@ -154,6 +154,12 @@ static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id)
return LAYER4_BITRATE_HEVC;
case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR:
return LAYER5_BITRATE_HEVC;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+ return SLICE_MODE;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+ return SLICE_MAX_BYTES;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+ return SLICE_MAX_MB;
default:
return INST_FW_CAP_MAX;
}
@@ -297,6 +303,12 @@ static u32 iris_get_v4l2_id(enum platform_inst_fw_cap_type cap_id)
return V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR;
case LAYER5_BITRATE_HEVC:
return V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR;
+ case SLICE_MODE:
+ return V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE;
+ case SLICE_MAX_BYTES:
+ return V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES;
+ case SLICE_MAX_MB:
+ return V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB;
default:
return 0;
}
@@ -1482,6 +1494,73 @@ int iris_set_layer_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_typ
&bitrate, sizeof(u32));
}
+int iris_set_slice_count(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
+{
+ const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops;
+ const struct platform_inst_slice_caps *slice_caps =
+ inst->core->iris_platform_data->slice_caps;
+ u32 slice_mode = inst->fw_caps[SLICE_MODE].value;
+ u32 bitrate = inst->fw_caps[BITRATE].value;
+ u32 rc_type = inst->hfi_rc_type;
+ u32 fps = inst->frame_rate;
+ u32 output_width = inst->fmt_dst->fmt.pix_mp.width;
+ u32 output_height = inst->fmt_dst->fmt.pix_mp.height;
+ u32 mbpf = NUM_MBS_PER_FRAME(output_height, output_width);
+ u32 max_width, max_height, min_width, min_height;
+ u32 max_avg_slicesize, hfi_value, hfi_id;
+
+ if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) {
+ dev_dbg(inst->core->dev, "slice mode is: %u, ignore setting to fw\n", slice_mode);
+ return 0;
+ }
+ if (fps > slice_caps->max_slice_frame_rate ||
+ (rc_type != HFI_RC_OFF && rc_type != HFI_RC_CBR_CFR &&
+ rc_type != HFI_RC_CBR_VFR && rc_type != HFI_RC_VBR_CFR)) {
+ dev_err(inst->core->dev, "slice unsupported, fps: %u, rc_type: %#x\n",
+ fps, rc_type);
+ return -EINVAL;
+ }
+
+ max_width = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ?
+ slice_caps->max_mb_slice_width : slice_caps->max_bytes_slice_width;
+ max_height = (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) ?
+ slice_caps->max_mb_slice_height : slice_caps->max_bytes_slice_height;
+ min_width = (inst->codec == V4L2_PIX_FMT_HEVC) ?
+ slice_caps->min_hevc_slice_width : slice_caps->min_avc_slice_width;
+ min_height = slice_caps->min_slice_height;
+
+ if (output_width < min_width || output_height < min_height ||
+ output_width > max_width || output_height > max_height) {
+ dev_err(inst->core->dev, "slice unsupported, codec: %#x wxh: [%dx%d]\n",
+ inst->codec, output_width, output_height);
+ return -EINVAL;
+ }
+
+ if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
+ hfi_value = inst->fw_caps[SLICE_MAX_MB].value;
+ hfi_value = max(hfi_value, DIV_ROUND_UP(mbpf, slice_caps->max_slices_per_frame));
+ if (inst->codec == V4L2_PIX_FMT_HEVC)
+ hfi_value = (hfi_value + 3) / 4;
+ hfi_id = inst->fw_caps[SLICE_MAX_MB].hfi_id;
+ } else if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
+ hfi_value = inst->fw_caps[SLICE_MAX_BYTES].value;
+ if (rc_type != HFI_RC_OFF) {
+ max_avg_slicesize = DIV_ROUND_UP((bitrate / fps) / 8,
+ slice_caps->max_slices_per_frame);
+ hfi_value = max(hfi_value, max_avg_slicesize);
+ }
+ hfi_id = inst->fw_caps[SLICE_MAX_BYTES].hfi_id;
+ } else {
+ return -EINVAL;
+ }
+
+ return hfi_ops->session_set_property(inst, hfi_id,
+ HFI_HOST_FLAGS_NONE,
+ iris_get_port_info(inst, cap_id),
+ HFI_PAYLOAD_U32,
+ &hfi_value, sizeof(u32));
+}
+
int iris_set_properties(struct iris_inst *inst, u32 plane)
{
const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops;
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h b/drivers/media/platform/qcom/iris/iris_ctrls.h
index 3c462ec9190b..5a73c7c49d36 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.h
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.h
@@ -47,6 +47,7 @@ int iris_set_layer_type(struct iris_inst *inst, enum platform_inst_fw_cap_type c
int iris_set_layer_count_gen1(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_layer_count_gen2(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_layer_bitrate(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
+int iris_set_slice_count(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id);
int iris_set_properties(struct iris_inst *inst, u32 plane);
#endif
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
index acc0ed8adda1..fcbebced05c3 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
@@ -12,6 +12,8 @@
#define VIDEO_ARCH_LX 1
#define BITRATE_MAX 245000000
+#define MAX_SLICE_MB_SIZE \
+ (((4096 + 15) >> 4) * ((2160 + 15) >> 4))
static const struct platform_inst_fw_cap inst_fw_cap_sm8550_dec[] = {
{
@@ -937,7 +939,36 @@ static const struct platform_inst_fw_cap inst_fw_cap_sm8550_enc[] = {
.flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
CAP_FLAG_DYNAMIC_ALLOWED,
.set = iris_set_layer_bitrate,
- }
+ },
+ {
+ .cap_id = SLICE_MODE,
+ .min = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+ .max = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE) |
+ BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) |
+ BIT(V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES),
+ .value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_slice_count,
+ },
+ {
+ .cap_id = SLICE_MAX_BYTES,
+ .min = 512,
+ .max = BITRATE_MAX >> 3,
+ .step_or_mask = 1,
+ .value = 512,
+ .hfi_id = HFI_PROP_MULTI_SLICE_BYTES_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = SLICE_MAX_MB,
+ .min = 1,
+ .max = MAX_SLICE_MB_SIZE,
+ .step_or_mask = 1,
+ .value = 1,
+ .hfi_id = HFI_PROP_MULTI_SLICE_MB_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
};
static const u32 sm8550_vdec_input_config_params_default[] = {
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
index 776b21cd11b2..226894b99dcc 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h
@@ -71,6 +71,8 @@ enum hfi_rate_control {
#define HFI_PROP_MIN_QP_PACKED 0x0300012f
#define HFI_PROP_MAX_QP_PACKED 0x03000130
#define HFI_PROP_IR_RANDOM_PERIOD 0x03000131
+#define HFI_PROP_MULTI_SLICE_MB_COUNT 0x03000132
+#define HFI_PROP_MULTI_SLICE_BYTES_COUNT 0x03000133
#define HFI_PROP_LTR_COUNT 0x03000134
#define HFI_PROP_LTR_MARK 0x03000135
#define HFI_PROP_LTR_USE 0x03000136
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index c9256f2323dc..ad9f2b20cd90 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -88,6 +88,18 @@ struct tz_cp_config {
u32 cp_nonpixel_size;
};
+struct platform_inst_slice_caps {
+ u32 max_slices_per_frame;
+ u32 max_slice_frame_rate;
+ u32 max_mb_slice_width;
+ u32 max_mb_slice_height;
+ u32 max_bytes_slice_width;
+ u32 max_bytes_slice_height;
+ u32 min_hevc_slice_width;
+ u32 min_avc_slice_width;
+ u32 min_slice_height;
+};
+
struct platform_inst_caps {
u32 min_frame_width;
u32 max_frame_width;
@@ -183,6 +195,9 @@ enum platform_inst_fw_cap_type {
LAYER3_BITRATE_HEVC,
LAYER4_BITRATE_HEVC,
LAYER5_BITRATE_HEVC,
+ SLICE_MODE,
+ SLICE_MAX_BYTES,
+ SLICE_MAX_MB,
INST_FW_CAP_MAX,
};
@@ -315,6 +330,7 @@ struct iris_platform_data {
const u32 *inst_iris_fmts;
u32 inst_iris_fmts_size;
struct platform_inst_caps *inst_caps;
+ const struct platform_inst_slice_caps *slice_caps;
const struct tz_cp_config *tz_cp_config_data;
u32 tz_cp_config_data_size;
u32 num_vpp_pipe;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
index 2c63adbc5579..6e44bed5ebff 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
@@ -12,6 +12,18 @@
#include "iris_vpu_buffer.h"
#include "iris_vpu_common.h"
+static const struct platform_inst_slice_caps default_slice_caps_vpu3x = {
+ .max_slices_per_frame = 128,
+ .max_slice_frame_rate = 60,
+ .max_mb_slice_width = 4096,
+ .max_mb_slice_height = 2160,
+ .max_bytes_slice_width = 1920,
+ .max_bytes_slice_height = 1088,
+ .min_hevc_slice_width = 384,
+ .min_avc_slice_width = 192,
+ .min_slice_height = 128,
+};
+
#include "iris_platform_qcs8300.h"
#include "iris_platform_sm8550.h"
#include "iris_platform_sm8650.h"
@@ -110,6 +122,7 @@ const struct iris_platform_data qcs8300_data = {
.inst_iris_fmts = iris_fmts_vpu3x_dec,
.inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec),
.inst_caps = &platform_inst_cap_qcs8300,
+ .slice_caps = &default_slice_caps_vpu3x,
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 2,
@@ -139,6 +152,7 @@ const struct iris_platform_data sm8550_data = {
.inst_iris_fmts = iris_fmts_vpu3x_dec,
.inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec),
.inst_caps = &platform_inst_cap_sm8550,
+ .slice_caps = &default_slice_caps_vpu3x,
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
@@ -176,6 +190,7 @@ const struct iris_platform_data sm8650_data = {
.inst_iris_fmts = iris_fmts_vpu3x_dec,
.inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec),
.inst_caps = &platform_inst_cap_sm8550,
+ .slice_caps = &default_slice_caps_vpu3x,
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
@@ -205,6 +220,7 @@ const struct iris_platform_data sm8750_data = {
.inst_iris_fmts = iris_fmts_vpu3x_dec,
.inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec),
.inst_caps = &platform_inst_cap_sm8550,
+ .slice_caps = &default_slice_caps_vpu3x,
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
@@ -240,6 +256,7 @@ const struct iris_platform_data x1p42100_data = {
.inst_iris_fmts = iris_fmts_vpu3x_dec,
.inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_vpu3x_dec),
.inst_caps = &platform_inst_cap_sm8550,
+ .slice_caps = &default_slice_caps_vpu3x,
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 1,
--
2.34.1
next prev parent reply other threads:[~2026-07-23 10:21 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 10:21 [PATCH v4 0/3] media: qcom: iris: add multi slice support Sachin Kumar Garg
2026-07-23 10:21 ` [PATCH v4 1/3] media: iris: cache work mode after computing it in iris_set_stage Sachin Kumar Garg
2026-07-23 16:07 ` Vikash Garodia
2026-07-23 10:21 ` [PATCH v4 2/3] media: iris: force stage 1 work mode for CBR RC on encoder Sachin Kumar Garg
2026-07-23 16:07 ` Vikash Garodia
2026-07-23 10:21 ` Sachin Kumar Garg [this message]
2026-07-23 17:17 ` [PATCH v4 3/3] media: iris: add support for multi_slice in iris encoder Vikash Garodia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260723-iris_multi_slice-v4-3-45f0a3fe7fce@oss.qualcomm.com \
--to=sachin.garg@oss.qualcomm.com \
--cc=abhinav.kumar@linux.dev \
--cc=bod@kernel.org \
--cc=dikshita.agarwal@oss.qualcomm.com \
--cc=hverkuil@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=quic_vnagar@quicinc.com \
--cc=stefan.schmidt@linaro.org \
--cc=vikash.garodia@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.