[PATCH 2/2] media: iris: Enable Gen2 HFI on SC7280

From: Dikshita Agarwal

Date: Mon Feb 09 2026 - 04:50:02 EST


SC7280 supports both Gen1 and Gen2 HFI firmware. The driver continues to
use Gen1 by default, but boards that intend to use Gen2 firmware can
opt‑in by specifying a Gen2 image through the Device Tree
'firmware-name' property.

Based on this property and the availability of the referenced
firmware binary, the driver selects the appropriate HFI generation and
updates its platform data accordingly. Boards that do not
specify a Gen2 firmware, or where the firmware is not present,
automatically fall back to Gen1.

Signed-off-by: Dikshita Agarwal <dikshita.agarwal@xxxxxxxxxxxxxxxx>
---
drivers/media/platform/qcom/iris/iris_core.c | 30 ++++++++
drivers/media/platform/qcom/iris/iris_core.h | 1 +
.../platform/qcom/iris/iris_platform_common.h | 1 +
.../media/platform/qcom/iris/iris_platform_gen1.c | 4 +-
.../media/platform/qcom/iris/iris_platform_gen2.c | 83 ++++++++++++++++++++++
.../platform/qcom/iris/iris_platform_sc7280.h | 15 ++++
drivers/media/platform/qcom/iris/iris_probe.c | 3 -
drivers/media/platform/qcom/iris/iris_vidc.c | 3 +
8 files changed, 135 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index 8e4cc6d6123069dea860062f0172f1e4b90cfc13..b14b04b32b62e324a70a558063dc673f7b9c2981 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -3,6 +3,7 @@
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/

+#include <linux/firmware.h>
#include <linux/pm_runtime.h>

#include "iris_core.h"
@@ -10,6 +11,31 @@
#include "iris_state.h"
#include "iris_vpu_common.h"

+int iris_update_platform_data(struct iris_core *core)
+{
+ const char *fwname = NULL;
+ const struct firmware *fw;
+ int ret;
+
+ if (of_device_is_compatible(core->dev->of_node, "qcom,sc7280-venus")) {
+ ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0,
+ &fwname);
+ if (ret)
+ return 0;
+
+ if (strstr(fwname, "gen2")) {
+ ret = request_firmware(&fw, fwname, core->dev);
+ if (ret) {
+ dev_err(core->dev, "Specified firmware is not present\n");
+ return ret;
+ }
+ release_firmware(fw);
+ core->iris_platform_data = &sc7280_gen2_data;
+ }
+ }
+ return 0;
+}
+
void iris_core_deinit(struct iris_core *core)
{
pm_runtime_resume_and_get(core->dev);
@@ -67,6 +93,10 @@ int iris_core_init(struct iris_core *core)
if (ret)
goto error_queue_deinit;

+ ret = iris_update_platform_data(core);
+ if (ret)
+ goto error_queue_deinit;
+
ret = iris_fw_load(core);
if (ret)
goto error_power_off;
diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h
index fb194c967ad4f9b5e00cd74f0d41e0b827ef14db..3b6ff3405f504359a094ad65d5a3252f20adba4b 100644
--- a/drivers/media/platform/qcom/iris/iris_core.h
+++ b/drivers/media/platform/qcom/iris/iris_core.h
@@ -121,5 +121,6 @@ struct iris_core {

int iris_core_init(struct iris_core *core);
void iris_core_deinit(struct iris_core *core);
+int iris_update_platform_data(struct iris_core *core);

#endif
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 5a489917580eb10022fdcb52f7321a915e8b239d..f1bbbe043e3a3ccc5eebf67091162678eb83bf45 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -43,6 +43,7 @@ enum pipe_type {

extern const struct iris_platform_data qcs8300_data;
extern const struct iris_platform_data sc7280_data;
+extern const struct iris_platform_data sc7280_gen2_data;
extern const struct iris_platform_data sm8250_data;
extern const struct iris_platform_data sm8550_data;
extern const struct iris_platform_data sm8650_data;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen1.c b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
index df8e6bf9430ed2a070e092edae9ef998d092cb5e..6dbdd0833dcdc7dfac6d7b35f99837c883e188e7 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen1.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen1.c
@@ -414,8 +414,8 @@ const struct iris_platform_data sc7280_data = {
.dma_mask = 0xe0000000 - 1,
.fwname = "qcom/vpu/vpu20_p1.mbn",
.pas_id = IRIS_PAS_ID,
- .inst_iris_fmts = platform_fmts_sm8250_dec,
- .inst_iris_fmts_size = ARRAY_SIZE(platform_fmts_sm8250_dec),
+ .inst_iris_fmts = platform_fmts_sc7280_dec,
+ .inst_iris_fmts_size = ARRAY_SIZE(platform_fmts_sc7280_dec),
.inst_caps = &platform_inst_cap_sm8250,
.inst_fw_caps_dec = inst_fw_cap_sm8250_dec,
.inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8250_dec),
diff --git a/drivers/media/platform/qcom/iris/iris_platform_gen2.c b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
index 5da90d47f9c6eab4a7e6b17841fdc0e599397bf7..8987fcc0cceb8632424e1d686ad04ca310d180bb 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_gen2.c
@@ -15,6 +15,7 @@
#include "iris_platform_qcs8300.h"
#include "iris_platform_sm8650.h"
#include "iris_platform_sm8750.h"
+#include "iris_platform_sc7280.h"

#define VIDEO_ARCH_LX 1
#define BITRATE_MAX 245000000
@@ -1317,3 +1318,85 @@ const struct iris_platform_data qcs8300_data = {
.enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl,
.enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl),
};
+
+const struct iris_platform_data sc7280_gen2_data = {
+ .get_instance = iris_hfi_gen2_get_instance,
+ .init_hfi_command_ops = iris_hfi_gen2_command_ops_init,
+ .init_hfi_response_ops = iris_hfi_gen2_response_ops_init,
+ /* Gen2 FW for SC7280 requires bigger size for line buffer for encoder */
+ .get_vpu_buffer_size = iris_vpu33_buf_size,
+ .vpu_ops = &iris_vpu2_ops,
+ .set_preset_registers = iris_set_sm8550_preset_registers,
+ .icc_tbl = sm8550_icc_table,
+ .icc_tbl_size = ARRAY_SIZE(sm8550_icc_table),
+ .bw_tbl_dec = sc7280_bw_table_dec,
+ .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec),
+ .pmdomain_tbl = sm8550_pmdomain_table,
+ .pmdomain_tbl_size = ARRAY_SIZE(sm8550_pmdomain_table),
+ .opp_pd_tbl = sc7280_opp_pd_table,
+ .opp_pd_tbl_size = ARRAY_SIZE(sc7280_opp_pd_table),
+ .clk_tbl = sc7280_clk_table,
+ .clk_tbl_size = ARRAY_SIZE(sc7280_clk_table),
+ .opp_clk_tbl = sc7280_opp_clk_table,
+ /* Upper bound of DMA address range */
+ .dma_mask = 0xe0000000 - 1,
+ .fwname = "qcom/vpu/vpu20_p1_gen2.mbn",
+ .pas_id = IRIS_PAS_ID,
+ .inst_iris_fmts = platform_fmts_sc7280_dec,
+ .inst_iris_fmts_size = ARRAY_SIZE(platform_fmts_sc7280_dec),
+ .inst_caps = &platform_inst_cap_sm8550,
+ .inst_fw_caps_dec = inst_fw_cap_sm8550_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_sm8550_dec),
+ .inst_fw_caps_enc = inst_fw_cap_sm8550_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_sm8550_enc),
+ .tz_cp_config_data = tz_cp_config_sm8550,
+ .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_sm8550),
+ .hw_response_timeout = HW_RESPONSE_TIMEOUT_VALUE,
+ .ubwc_config = &ubwc_config_sm8550,
+ .core_arch = VIDEO_ARCH_LX,
+ .num_vpp_pipe = 1,
+ .no_aon = true,
+ .max_session_count = 16,
+ .max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256,
+ /* max spec for SC7280 is 4096x2176@60fps */
+ .max_core_mbps = 4096 * 2176 / 256 * 60,
+ .dec_input_config_params_default =
+ sm8550_vdec_input_config_params_default,
+ .dec_input_config_params_default_size =
+ ARRAY_SIZE(sm8550_vdec_input_config_params_default),
+ .dec_input_config_params_hevc =
+ sm8550_vdec_input_config_param_hevc,
+ .dec_input_config_params_hevc_size =
+ ARRAY_SIZE(sm8550_vdec_input_config_param_hevc),
+ .dec_input_config_params_vp9 =
+ sm8550_vdec_input_config_param_vp9,
+ .dec_input_config_params_vp9_size =
+ ARRAY_SIZE(sm8550_vdec_input_config_param_vp9),
+ .enc_input_config_params = sm8550_venc_input_config_params,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8550_venc_input_config_params),
+ .dec_output_config_params = sm8550_vdec_output_config_params,
+ .dec_output_config_params_size = ARRAY_SIZE(sm8550_vdec_output_config_params),
+ .enc_output_config_params = sm8550_venc_output_config_params,
+ .enc_output_config_params_size = ARRAY_SIZE(sm8550_venc_output_config_params),
+
+ .dec_ip_int_buf_tbl = sm8550_dec_ip_int_buf_tbl,
+ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_ip_int_buf_tbl),
+ .dec_op_int_buf_tbl = sm8550_dec_op_int_buf_tbl,
+ .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_dec_op_int_buf_tbl),
+
+ .enc_op_int_buf_tbl = sm8550_enc_op_int_buf_tbl,
+ .enc_op_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_op_int_buf_tbl),
+
+ .dec_input_prop = sm8550_vdec_subscribe_input_properties,
+ .dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_subscribe_input_properties),
+ .dec_output_prop_avc = sm8550_vdec_subscribe_output_properties_avc,
+ .dec_output_prop_avc_size =
+ ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_avc),
+ .dec_output_prop_hevc = sm8550_vdec_subscribe_output_properties_hevc,
+ .dec_output_prop_hevc_size =
+ ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_hevc),
+ .dec_output_prop_vp9 = sm8550_vdec_subscribe_output_properties_vp9,
+ .dec_output_prop_vp9_size =
+ ARRAY_SIZE(sm8550_vdec_subscribe_output_properties_vp9),
+};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h
index 0ec8f334df670c3c1548a5ee3b8907b333e34db3..6e05f2542a5457bd0b3b6acced3bd54d166b2023 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_sc7280.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_sc7280.h
@@ -6,6 +6,21 @@
#ifndef __IRIS_PLATFORM_SC7280_H__
#define __IRIS_PLATFORM_SC7280_H__

+static struct iris_fmt platform_fmts_sc7280_dec[] = {
+ [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 bw_info sc7280_bw_table_dec[] = {
{ ((3840 * 2160) / 256) * 60, 1896000, },
{ ((3840 * 2160) / 256) * 30, 968000, },
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 22c7b3410710328b900fc49459cd399aa0e89b02..1f44d3ea337df63fbf5317b9b99139a0867267c3 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -12,7 +12,6 @@
#include <linux/reset.h>

#include "iris_core.h"
-#include "iris_ctrls.h"
#include "iris_vidc.h"

static int iris_init_icc(struct iris_core *core)
@@ -257,8 +256,6 @@ static int iris_probe(struct platform_device *pdev)
if (ret)
return ret;

- iris_session_init_caps(core);
-
ret = v4l2_device_register(dev, &core->v4l2_dev);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index bd38d84c9cc79d15585ed5dd5f905a37521cb6dc..0727d5d19cb9b7ed1f72ab840ae5dfda0162e23d 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -9,6 +9,7 @@
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>

+#include "iris_ctrls.h"
#include "iris_vidc.h"
#include "iris_instance.h"
#include "iris_vdec.h"
@@ -196,6 +197,8 @@ int iris_open(struct file *filp)
goto fail_m2m_release;
}

+ iris_session_init_caps(core);
+
if (inst->domain == DECODER)
ret = iris_vdec_inst_init(inst);
else if (inst->domain == ENCODER)

--
2.34.1