* [PATCH v4 01/16] media: iris: Skip UBWC configuration when not supported
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 02/16] media: iris: Filter UBWC raw formats based on hardware capabilities Dmitry Baryshkov
` (14 subsequent siblings)
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal, Konrad Dybcio
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
UBWC configuration is not applicable to all SoCs. Add a check to avoid
configuring UBWC during sys init on unsupported platforms.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
index 0d05dd2afc07..6e04175eb904 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c
@@ -140,6 +140,9 @@ void iris_hfi_gen2_packet_sys_init(struct iris_core *core, struct iris_hfi_heade
&payload,
sizeof(u32));
+ if (!ubwc->ubwc_enc_version)
+ return;
+
payload = qcom_ubwc_macrotile_mode(ubwc) ? 8 : 4;
iris_hfi_gen2_create_packet(hdr,
HFI_PROP_UBWC_MAX_CHANNELS,
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v4 02/16] media: iris: Filter UBWC raw formats based on hardware capabilities
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 01/16] media: iris: Skip UBWC configuration when not supported Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:36 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 03/16] media: iris: Introduce set_preset_register as a vpu_op Dmitry Baryshkov
` (13 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
The raw formats supported by Iris were previously advertised
unconditionally, assuming UBWC support on all platforms. However, some
platforms do not support UBWC which results in incorrect format
capability exposure.
Use the UBWC configuration provided by the platform to dynamically
filter raw formats at runtime. If UBWC is not supported, UBWC-based
formats are omitted from the advertised capability list, while linear
formats remain available.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_vdec.c | 9 +++++++++
drivers/media/platform/qcom/iris/iris_venc.c | 9 +++++++++
2 files changed, 18 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 9e228b70420e..7da43f312ba9 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -3,6 +3,7 @@
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/soc/qcom/ubwc.h>
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
@@ -71,6 +72,7 @@ static const u32 iris_vdec_formats_cap[] = {
static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
{
+ const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg;
unsigned int size, i;
const u32 *fmt;
@@ -82,6 +84,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_vdec_formats_cap;
size = ARRAY_SIZE(iris_vdec_formats_cap);
+ /* Last format is UBWC; drop it if UBWC is unsupported */
+ if (!ubwc->ubwc_enc_version)
+ size--;
break;
default:
return false;
@@ -110,6 +115,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
{
+ const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg;
unsigned int size;
const u32 *fmt;
@@ -121,6 +127,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_vdec_formats_cap;
size = ARRAY_SIZE(iris_vdec_formats_cap);
+ /* Last format is UBWC; drop it if UBWC is unsupported */
+ if (!ubwc->ubwc_enc_version)
+ size--;
break;
default:
return 0;
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index a945992f63aa..2cafbe9f8abb 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -3,6 +3,7 @@
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/soc/qcom/ubwc.h>
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
@@ -91,6 +92,7 @@ static const u32 iris_venc_formats_out[] = {
static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
{
+ const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg;
unsigned int size, i;
const u32 *fmt;
@@ -98,6 +100,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
fmt = iris_venc_formats_out;
size = ARRAY_SIZE(iris_venc_formats_out);
+ /* Last format is UBWC; drop it if UBWC is unsupported */
+ if (!ubwc->ubwc_enc_version)
+ size--;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_venc_formats_cap;
@@ -117,6 +122,7 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
{
+ const struct qcom_ubwc_cfg_data *ubwc = inst->core->ubwc_cfg;
unsigned int size;
const u32 *fmt;
@@ -124,6 +130,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
fmt = iris_venc_formats_out;
size = ARRAY_SIZE(iris_venc_formats_out);
+ /* Last format is UBWC; drop it if UBWC is unsupported */
+ if (!ubwc->ubwc_enc_version)
+ size--;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_venc_formats_cap;
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 02/16] media: iris: Filter UBWC raw formats based on hardware capabilities
2026-06-12 9:25 ` [PATCH v4 02/16] media: iris: Filter UBWC raw formats based on hardware capabilities Dmitry Baryshkov
@ 2026-06-12 9:36 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 9:36 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The logic to dynamically filter out UBWC raw formats in the video decoder is incomplete and fails to omit the 8-bit UBWC format (QC08C).
- [Medium] Incorrect use of the encoder UBWC version field to validate decoder capabilities.
--
commit a8db7d07b5e1a7229c20919b2735cd3483c3c3ab
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Filter UBWC raw formats based on hardware capabilities
The raw formats supported by Iris were previously advertised unconditionally,
assuming UBWC support on all platforms. Use the UBWC configuration provided
by the platform to dynamically filter raw formats at runtime. If UBWC is
not supported, UBWC-based formats are omitted from the advertised capability
list.
> diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
> index 9e228b70420e4..7da43f312ba98 100644
> --- a/drivers/media/platform/qcom/iris/iris_vdec.c
> +++ b/drivers/media/platform/qcom/iris/iris_vdec.c
[ ... ]
> @@ -82,6 +84,9 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
> case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> fmt = iris_vdec_formats_cap;
> size = ARRAY_SIZE(iris_vdec_formats_cap);
> + /* Last format is UBWC; drop it if UBWC is unsupported */
> + if (!ubwc->ubwc_enc_version)
> + size--;
[Severity: High]
Does this logic successfully drop all UBWC formats?
Looking at the definition of iris_vdec_formats_cap, it appears there are
multiple UBWC formats interspersed:
static const u32 iris_vdec_formats_cap[] = {
[IRIS_FMT_NV12] = V4L2_PIX_FMT_NV12,
[IRIS_FMT_QC08C] = V4L2_PIX_FMT_QC08C,
[IRIS_FMT_TP10] = V4L2_PIX_FMT_P010,
[IRIS_FMT_QC10C] = V4L2_PIX_FMT_QC10C,
};
By just decrementing the size, it seems we only omit the last format
(QC10C), but QC08C would remain within the array bounds. Could this
cause QC08C to be incorrectly accepted by check_format() on platforms
without UBWC support?
[Severity: Medium]
Should this check use the decoder version instead?
Since this is the video decoder implementation in iris_vdec.c, checking
ubwc->ubwc_enc_version might lead to incorrect filtering on future hardware
platforms where UBWC support differs between the encoder and decoder. Would
ubwc->ubwc_dec_version be more appropriate here?
> break;
> default:
> return false;
> @@ -121,6 +127,9 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
> case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> fmt = iris_vdec_formats_cap;
> size = ARRAY_SIZE(iris_vdec_formats_cap);
> + /* Last format is UBWC; drop it if UBWC is unsupported */
> + if (!ubwc->ubwc_enc_version)
> + size--;
[Severity: High]
Does this also result in find_format_by_index() returning a UBWC format?
Because QC08C remains within the decremented array bounds, would querying
index 1 still return V4L2_PIX_FMT_QC08C to userspace even when UBWC is
unsupported?
[Severity: Medium]
Similar to the issue above, should this use ubwc->ubwc_dec_version instead
of ubwc->ubwc_enc_version to properly validate decoder capabilities?
> break;
> default:
> return 0;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 03/16] media: iris: Introduce set_preset_register as a vpu_op
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 01/16] media: iris: Skip UBWC configuration when not supported Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 02/16] media: iris: Filter UBWC raw formats based on hardware capabilities Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 04/16] media: iris: Introduce interrupt_init " Dmitry Baryshkov
` (12 subsequent siblings)
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
The set_preset_registers sequence is currently shared across all
supported devices. Starting with Qualcomm QCM2290 (AR50LT), the register
programming would differ.
Move set_preset_register into a vpu_op to allow per-device
customization.
This change prepares the driver for upcoming hardware variants.
No functional change so far for existing devices.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_vpu2.c | 1 +
drivers/media/platform/qcom/iris/iris_vpu3x.c | 3 +++
drivers/media/platform/qcom/iris/iris_vpu4x.c | 1 +
drivers/media/platform/qcom/iris/iris_vpu_common.c | 2 +-
drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 +
5 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c
index b8714dcbad10..2dc121a3f5e8 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu2.c
@@ -45,4 +45,5 @@ const struct vpu_ops iris_vpu2_ops = {
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu2_calc_freq,
.set_hwmode = iris_vpu_set_hwmode,
+ .set_preset_registers = iris_vpu_set_preset_registers,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c
index 3dad47be78b5..dc02ced1b931 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c
@@ -261,6 +261,7 @@ const struct vpu_ops iris_vpu3_ops = {
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
+ .set_preset_registers = iris_vpu_set_preset_registers,
};
const struct vpu_ops iris_vpu33_ops = {
@@ -270,6 +271,7 @@ const struct vpu_ops iris_vpu33_ops = {
.power_on_controller = iris_vpu_power_on_controller,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
+ .set_preset_registers = iris_vpu_set_preset_registers,
};
const struct vpu_ops iris_vpu35_ops = {
@@ -280,4 +282,5 @@ const struct vpu_ops iris_vpu35_ops = {
.program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
+ .set_preset_registers = iris_vpu_set_preset_registers,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c
index 02e100a4045f..f608a297d4a3 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu4x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c
@@ -368,4 +368,5 @@ const struct vpu_ops iris_vpu4x_ops = {
.program_bootup_registers = iris_vpu35_vpu4x_program_bootup_registers,
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu4x_set_hwmode,
+ .set_preset_registers = iris_vpu_set_preset_registers,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index ab41da1f47c8..a49113b0da23 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -483,7 +483,7 @@ int iris_vpu_power_on(struct iris_core *core)
iris_opp_set_rate(core->dev, freq);
- iris_vpu_set_preset_registers(core);
+ core->iris_platform_data->vpu_ops->set_preset_registers(core);
iris_vpu_interrupt_init(core);
core->intr_status = 0;
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index 09799a375c14..21ed4c9bd5e3 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -22,6 +22,7 @@ struct vpu_ops {
void (*program_bootup_registers)(struct iris_core *core);
u64 (*calc_freq)(struct iris_inst *inst, size_t data_size);
int (*set_hwmode)(struct iris_core *core);
+ void (*set_preset_registers)(struct iris_core *core);
};
int iris_vpu_boot_firmware(struct iris_core *core);
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v4 04/16] media: iris: Introduce interrupt_init as a vpu_op
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (2 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 03/16] media: iris: Introduce set_preset_register as a vpu_op Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 05/16] media: iris: add vpu op hook to disable ARP buffer Dmitry Baryshkov
` (11 subsequent siblings)
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
The interrupt_init sequence is currently shared across all supported
devices. Starting with Qualcomm QCM2290 (AR50LT), the register
programming would differ.
Move interrupt_init into a vpu_op to allow per-device customization.
This change prepares the driver for upcoming hardware variants.
No functional change so far for existing devices.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_vpu2.c | 1 +
drivers/media/platform/qcom/iris/iris_vpu3x.c | 3 +++
drivers/media/platform/qcom/iris/iris_vpu4x.c | 1 +
drivers/media/platform/qcom/iris/iris_vpu_common.c | 4 ++--
drivers/media/platform/qcom/iris/iris_vpu_common.h | 2 ++
5 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c
index 2dc121a3f5e8..dd2eeae0d9eb 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu2.c
@@ -46,4 +46,5 @@ const struct vpu_ops iris_vpu2_ops = {
.calc_freq = iris_vpu2_calc_freq,
.set_hwmode = iris_vpu_set_hwmode,
.set_preset_registers = iris_vpu_set_preset_registers,
+ .interrupt_init = iris_vpu_interrupt_init,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu3x.c b/drivers/media/platform/qcom/iris/iris_vpu3x.c
index dc02ced1b931..c3b760730c98 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu3x.c
@@ -262,6 +262,7 @@ const struct vpu_ops iris_vpu3_ops = {
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
.set_preset_registers = iris_vpu_set_preset_registers,
+ .interrupt_init = iris_vpu_interrupt_init,
};
const struct vpu_ops iris_vpu33_ops = {
@@ -272,6 +273,7 @@ const struct vpu_ops iris_vpu33_ops = {
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
.set_preset_registers = iris_vpu_set_preset_registers,
+ .interrupt_init = iris_vpu_interrupt_init,
};
const struct vpu_ops iris_vpu35_ops = {
@@ -283,4 +285,5 @@ const struct vpu_ops iris_vpu35_ops = {
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu_set_hwmode,
.set_preset_registers = iris_vpu_set_preset_registers,
+ .interrupt_init = iris_vpu_interrupt_init,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu4x.c b/drivers/media/platform/qcom/iris/iris_vpu4x.c
index f608a297d4a3..90ccdc0d2a07 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu4x.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu4x.c
@@ -369,4 +369,5 @@ const struct vpu_ops iris_vpu4x_ops = {
.calc_freq = iris_vpu3x_vpu4x_calculate_frequency,
.set_hwmode = iris_vpu4x_set_hwmode,
.set_preset_registers = iris_vpu_set_preset_registers,
+ .interrupt_init = iris_vpu_interrupt_init,
};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index a49113b0da23..375bcd923476 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -31,7 +31,7 @@
#define UC_REGION_ADDR (CPU_CS_BASE_OFFS + 0x64)
#define UC_REGION_SIZE (CPU_CS_BASE_OFFS + 0x68)
-static void iris_vpu_interrupt_init(struct iris_core *core)
+void iris_vpu_interrupt_init(struct iris_core *core)
{
u32 mask_val;
@@ -485,7 +485,7 @@ int iris_vpu_power_on(struct iris_core *core)
core->iris_platform_data->vpu_ops->set_preset_registers(core);
- iris_vpu_interrupt_init(core);
+ core->iris_platform_data->vpu_ops->interrupt_init(core);
core->intr_status = 0;
enable_irq(core->irq);
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index 21ed4c9bd5e3..9151545065cd 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -23,6 +23,7 @@ struct vpu_ops {
u64 (*calc_freq)(struct iris_inst *inst, size_t data_size);
int (*set_hwmode)(struct iris_core *core);
void (*set_preset_registers)(struct iris_core *core);
+ void (*interrupt_init)(struct iris_core *core);
};
int iris_vpu_boot_firmware(struct iris_core *core);
@@ -44,5 +45,6 @@ void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core);
u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size);
void iris_vpu_set_preset_registers(struct iris_core *core);
+void iris_vpu_interrupt_init(struct iris_core *core);
#endif
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v4 05/16] media: iris: add vpu op hook to disable ARP buffer
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (3 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 04/16] media: iris: Introduce interrupt_init " Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 06/16] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
` (10 subsequent siblings)
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
On AR50LT platforms AbsolutelyPerfectRouting (ARP) needs to be disabled
so firmware can configure the ARP internal buffer as non-secure for
encoder usage. In preparation of adding support for AR50LT platforms,
add an optional disable_arp callback to the VPU ops and invoke it from
core init and resume paths.
No functional change for existing platforms.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_core.c | 4 ++++
drivers/media/platform/qcom/iris/iris_hfi_common.c | 4 ++++
drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 +
3 files changed, 9 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index 52bf56e517f9..bd22076f3557 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -45,6 +45,7 @@ static int iris_wait_for_system_response(struct iris_core *core)
int iris_core_init(struct iris_core *core)
{
+ const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops;
int ret;
mutex_lock(&core->lock);
@@ -78,6 +79,9 @@ int iris_core_init(struct iris_core *core)
if (ret)
goto error_unload_fw;
+ if (vpu_ops->disable_arp)
+ vpu_ops->disable_arp(core);
+
core->iris_firmware_data->init_hfi_ops(core);
ret = iris_hfi_core_init(core);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.c b/drivers/media/platform/qcom/iris/iris_hfi_common.c
index 8769ec61f117..8f04f3793d9a 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.c
@@ -144,6 +144,7 @@ int iris_hfi_pm_suspend(struct iris_core *core)
int iris_hfi_pm_resume(struct iris_core *core)
{
+ const struct vpu_ops *vpu_ops = core->iris_platform_data->vpu_ops;
const struct iris_hfi_sys_ops *ops = core->hfi_sys_ops;
int ret;
@@ -163,6 +164,9 @@ int iris_hfi_pm_resume(struct iris_core *core)
if (ret)
goto err_suspend_hw;
+ if (vpu_ops->disable_arp)
+ vpu_ops->disable_arp(core);
+
ret = ops->sys_interframe_powercollapse(core);
if (ret)
goto err_suspend_hw;
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index 9151545065cd..71d96921ed37 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -24,6 +24,7 @@ struct vpu_ops {
int (*set_hwmode)(struct iris_core *core);
void (*set_preset_registers)(struct iris_core *core);
void (*interrupt_init)(struct iris_core *core);
+ void (*disable_arp)(struct iris_core *core);
};
int iris_vpu_boot_firmware(struct iris_core *core);
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v4 06/16] media: iris: Add platform data field for watchdog interrupt mask
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (4 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 05/16] media: iris: add vpu op hook to disable ARP buffer Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:41 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 07/16] media: iris: Add platform flag for instantaneous bandwidth voting Dmitry Baryshkov
` (9 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
For AR50LT core, the value of WRAPPER_INTR_STATUS_A2HWD_BMASK differs
from the currently supported VPUs. In preparation for adding AR50LT
support in subsequent patches, introduce a platform data field,
wd_intr_mask, to capture the watchdog interrupt bitmask per platform.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_platform_common.h | 1 +
drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 4 ++++
drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 6 ++++++
drivers/media/platform/qcom/iris/iris_vpu_common.c | 8 +++++---
drivers/media/platform/qcom/iris/iris_vpu_register_defines.h | 1 -
5 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 55a4fa356985..81fcb2854772 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -315,6 +315,7 @@ struct iris_platform_data {
u32 tz_cp_config_data_size;
u32 num_vpp_pipe;
bool no_aon;
+ u32 wd_intr_mask;
u32 max_session_count;
/* max number of macroblocks per frame supported */
u32 max_core_mbpf;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
index 961dce2e6aa9..eeef453c583f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
@@ -16,6 +16,8 @@
#include "iris_platform_sc7280.h"
#include "iris_platform_sm8250.h"
+#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3)
+
static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = {
.firmware_data = &iris_hfi_gen1_data,
.get_vpu_buffer_size = iris_vpu_buf_size,
@@ -94,6 +96,7 @@ const struct iris_platform_data sc7280_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2),
.num_vpp_pipe = 1,
.no_aon = true,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256,
/* max spec for SC7280 is 4096x2176@60fps */
@@ -124,6 +127,7 @@ const struct iris_platform_data sm8250_data = {
.tz_cp_config_data = tz_cp_config_vpu2,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2),
.num_vpp_pipe = 4,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
index 74626b35d9cb..261db38a013b 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
@@ -18,6 +18,8 @@
#include "iris_platform_sm8750.h"
#include "iris_platform_x1p42100.h"
+#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3)
+
static const struct iris_firmware_desc iris_vpu30_p4_s6_gen2_desc = {
.firmware_data = &iris_hfi_gen2_data,
.get_vpu_buffer_size = iris_vpu_buf_size,
@@ -113,6 +115,7 @@ const struct iris_platform_data qcs8300_data = {
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 2,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = ((4096 * 2176) / 256) * 4,
.max_core_mbps = (((3840 * 2176) / 256) * 120),
@@ -142,6 +145,7 @@ const struct iris_platform_data sm8550_data = {
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
@@ -179,6 +183,7 @@ const struct iris_platform_data sm8650_data = {
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
@@ -208,6 +213,7 @@ const struct iris_platform_data sm8750_data = {
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index 375bcd923476..41498f94480e 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -109,11 +109,11 @@ void iris_vpu_raise_interrupt(struct iris_core *core)
void iris_vpu_clear_interrupt(struct iris_core *core)
{
+ u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
u32 intr_status, mask;
intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS);
- mask = (WRAPPER_INTR_STATUS_A2H_BMSK |
- WRAPPER_INTR_STATUS_A2HWD_BMSK |
+ mask = (WRAPPER_INTR_STATUS_A2H_BMSK | wd_intr_mask |
CTRL_INIT_IDLE_MSG_BMSK);
if (intr_status & mask)
@@ -124,7 +124,9 @@ void iris_vpu_clear_interrupt(struct iris_core *core)
int iris_vpu_watchdog(struct iris_core *core, u32 intr_status)
{
- if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) {
+ u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
+
+ if (intr_status & wd_intr_mask) {
dev_err(core->dev, "received watchdog interrupt\n");
return -ETIME;
}
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h
index 72168b9ffa73..4fffa094c52f 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_register_defines.h
@@ -41,7 +41,6 @@
#define MSK_CORE_POWER_ON BIT(1)
#define WRAPPER_INTR_STATUS (WRAPPER_BASE_OFFS + 0x0C)
-#define WRAPPER_INTR_STATUS_A2HWD_BMSK BIT(3)
#define WRAPPER_INTR_STATUS_A2H_BMSK BIT(2)
#define WRAPPER_INTR_MASK (WRAPPER_BASE_OFFS + 0x10)
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 06/16] media: iris: Add platform data field for watchdog interrupt mask
2026-06-12 9:25 ` [PATCH v4 06/16] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
@ 2026-06-12 9:41 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 9:41 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The newly introduced `wd_intr_mask` field is not initialized for the `x1p42100_data` platform, causing it to default to 0 and completely breaking watchdog interrupt handling for this platform.
--
commit 0965d657e0a8904cc63b8cbd790144e332d59492
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Add platform data field for watchdog interrupt mask
This commit introduces the wd_intr_mask platform data field to capture the
watchdog interrupt bitmask per platform. It also replaces hardcoded
watchdog bitmasks with this new field during interrupt handling.
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
> index 2c63adbc55791..aeffd96a4e1cb 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
[ ... ]
> @@ -208,6 +213,7 @@ const struct iris_platform_data sm8750_data = {
> .tz_cp_config_data = tz_cp_config_vpu3,
> .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
> .num_vpp_pipe = 4,
> + .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
> .max_session_count = 16,
> .max_core_mbpf = NUM_MBS_8K * 2,
> .max_core_mbps = ((7680 * 4320) / 256) * 60,
[Severity: High]
Does this patch miss updating x1p42100_data?
It appears x1p42100_data is defined further down in this file but does not
have its wd_intr_mask initialized in this commit.
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
> index 375bcd9234766..41498f94480e8 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
> @@ -109,11 +109,11 @@ void iris_vpu_raise_interrupt(struct iris_core *core)
>
> void iris_vpu_clear_interrupt(struct iris_core *core)
> {
> + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
> u32 intr_status, mask;
>
> intr_status = readl(core->reg_base + WRAPPER_INTR_STATUS);
> - mask = (WRAPPER_INTR_STATUS_A2H_BMSK |
> - WRAPPER_INTR_STATUS_A2HWD_BMSK |
> + mask = (WRAPPER_INTR_STATUS_A2H_BMSK | wd_intr_mask |
> CTRL_INIT_IDLE_MSG_BMSK);
>
> if (intr_status & mask)
[Severity: High]
Since x1p42100_data is a static global variable, its uninitialized
wd_intr_mask will default to 0.
Will this cause the watchdog interrupt bit to be omitted from this mask,
preventing watchdog interrupts from being captured into core->intr_status
for the x1p42100 platform?
> @@ -124,7 +124,9 @@ void iris_vpu_clear_interrupt(struct iris_core *core)
>
> int iris_vpu_watchdog(struct iris_core *core, u32 intr_status)
> {
> - if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK) {
> + u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
> +
> + if (intr_status & wd_intr_mask) {
> dev_err(core->dev, "received watchdog interrupt\n");
> return -ETIME;
> }
[Severity: High]
Similarly, will this cause intr_status & wd_intr_mask to always evaluate
to 0 for x1p42100, silently dropping all watchdog timeouts and breaking
firmware hang recovery?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=6
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 07/16] media: iris: Add platform flag for instantaneous bandwidth voting
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (5 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 06/16] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:46 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 08/16] media: iris: skip PIPE if it is not supported by the platform Dmitry Baryshkov
` (8 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
AR50LT require explicit instantaneous bandwidth (IB) voting in addition
to average bandwidth (AB) when configuring interconnect QoS. This
requirement is due to QSB (Qualcomm System Bus) 128b to
QNS ( Qualcomm Network Switch) 256b conversion at video noc in AR50LT
which is not needed for other IRIS cores.
In preparation of adding support for AR50LT core, introduce
platform-configurable IB multiplier and enable IB voting for all SoCs.
Existing platforms default to IB == AB, while AR50LT requires 2x peak
bandwidth.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_platform_common.h | 1 +
drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 2 ++
drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 4 ++++
drivers/media/platform/qcom/iris/iris_resources.c | 2 ++
4 files changed, 9 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 81fcb2854772..accc1627defd 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -316,6 +316,7 @@ struct iris_platform_data {
u32 num_vpp_pipe;
bool no_aon;
u32 wd_intr_mask;
+ u32 icc_ib_multiplier;
u32 max_session_count;
/* max number of macroblocks per frame supported */
u32 max_core_mbpf;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
index eeef453c583f..e2fddc29abc7 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
@@ -97,6 +97,7 @@ const struct iris_platform_data sc7280_data = {
.num_vpp_pipe = 1,
.no_aon = true,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = 4096 * 2176 / 256 * 2 + 1920 * 1088 / 256,
/* max spec for SC7280 is 4096x2176@60fps */
@@ -128,6 +129,7 @@ const struct iris_platform_data sm8250_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu2),
.num_vpp_pipe = 4,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
index 261db38a013b..64cf182d67cc 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
@@ -116,6 +116,7 @@ const struct iris_platform_data qcs8300_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 2,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = ((4096 * 2176) / 256) * 4,
.max_core_mbps = (((3840 * 2176) / 256) * 120),
@@ -146,6 +147,7 @@ const struct iris_platform_data sm8550_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
@@ -184,6 +186,7 @@ const struct iris_platform_data sm8650_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
@@ -214,6 +217,7 @@ const struct iris_platform_data sm8750_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 4,
.wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 1,
.max_session_count = 16,
.max_core_mbpf = NUM_MBS_8K * 2,
.max_core_mbps = ((7680 * 4320) / 256) * 60,
diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c
index 773f6548370a..caeaf199cef7 100644
--- a/drivers/media/platform/qcom/iris/iris_resources.c
+++ b/drivers/media/platform/qcom/iris/iris_resources.c
@@ -18,6 +18,7 @@
int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw)
{
+ u32 icc_ib_multiplier = core->iris_platform_data->icc_ib_multiplier;
unsigned long bw_kbps = 0, bw_prev = 0;
const struct icc_info *icc_tbl;
int ret = 0, i;
@@ -36,6 +37,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw)
return ret;
core->icc_tbl[i].avg_bw = bw_kbps;
+ core->icc_tbl[i].peak_bw = bw_kbps * icc_ib_multiplier;
core->power.icc_bw = bw_kbps;
break;
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 07/16] media: iris: Add platform flag for instantaneous bandwidth voting
2026-06-12 9:25 ` [PATCH v4 07/16] media: iris: Add platform flag for instantaneous bandwidth voting Dmitry Baryshkov
@ 2026-06-12 9:46 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 9:46 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] The `x1p42100_data` platform configuration is missing the `icc_ib_multiplier` initialization, causing it to incorrectly vote for 0 instantaneous bandwidth.
Pre-existing issues:
- [High] The `wd_intr_mask` field is missing in `x1p42100_data`, silently disabling watchdog interrupt handling for this platform.
--
commit 341a438b98027e7efd3119d0595101f6ec929a49
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Add platform flag for instantaneous bandwidth voting
AR50LT require explicit instantaneous bandwidth (IB) voting in addition
to average bandwidth (AB) when configuring interconnect QoS. This
requirement is due to QSB (Qualcomm System Bus) 128b to
QNS ( Qualcomm Network Switch) 256b conversion at video noc in AR50LT
which is not needed for other IRIS cores.
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
> index aeffd96a4e1cb..8706989d4da45 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
[ ... ]
> @@ -214,6 +217,7 @@ const struct iris_platform_data sm8750_data = {
> .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
> .num_vpp_pipe = 4,
> .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
> + .icc_ib_multiplier = 1,
> .max_session_count = 16,
> .max_core_mbpf = NUM_MBS_8K * 2,
> .max_core_mbps = ((7680 * 4320) / 256) * 60,
> };
[Severity: High]
Did this miss updating x1p42100_data, which is defined right after sm8750_data
in this file?
Since x1p42100_data is missing the .icc_ib_multiplier initialization, it will
default to 0.
[Severity: High]
This is a pre-existing issue, but x1p42100_data is also missing the
.wd_intr_mask initialization, causing it to default to 0.
Does this mean watchdog interrupts triggered by the VPU hardware on the
x1p42100 SoC will be silently ignored? Looking at iris_vpu_watchdog():
u32 wd_intr_mask = core->iris_platform_data->wd_intr_mask;
if (intr_status & wd_intr_mask) {
...
}
Since wd_intr_mask is 0, the check will always evaluate to 0, which means
the driver will fail to detect VPU hangs.
> diff --git a/drivers/media/platform/qcom/iris/iris_resources.c b/drivers/media/platform/qcom/iris/iris_resources.c
> index 773f6548370a2..caeaf199cef74 100644
> --- a/drivers/media/platform/qcom/iris/iris_resources.c
> +++ b/drivers/media/platform/qcom/iris/iris_resources.c
[ ... ]
> @@ -36,6 +37,7 @@ int iris_set_icc_bw(struct iris_core *core, unsigned long icc_bw)
> return ret;
>
> core->icc_tbl[i].avg_bw = bw_kbps;
> + core->icc_tbl[i].peak_bw = bw_kbps * icc_ib_multiplier;
[Severity: High]
Could this inadvertently vote for 0 peak bandwidth on the x1p42100 SoC?
Because the platform configuration for x1p42100_data is missing the
icc_ib_multiplier initialization added to the other platforms, it defaults
to 0.
This causes the peak_bw calculation here to evaluate to 0, which could
starve the hardware of instantaneous bandwidth.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=7
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 08/16] media: iris: skip PIPE if it is not supported by the platform
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (6 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 07/16] media: iris: Add platform flag for instantaneous bandwidth voting Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 09/16] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
` (7 subsequent siblings)
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
AR50Lt doesn't support HFI_PROPERTY_PARAM_WORK_ROUTE. Tables for AR50LT
won't have corresponding entry in the capability tables. Let
iris_set_pipe() silently skip propgramming the property if there is no
corresponding capability.
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_ctrls.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
index 10e33b8a73f6..33a34573391a 100644
--- a/drivers/media/platform/qcom/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/iris/iris_ctrls.c
@@ -534,6 +534,9 @@ int iris_set_pipe(struct iris_inst *inst, enum platform_inst_fw_cap_type cap_id)
u32 work_route = inst->fw_caps[PIPE].value;
u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
+ if (!hfi_id)
+ return 0;
+
return hfi_ops->session_set_property(inst, hfi_id,
HFI_HOST_FLAGS_NONE,
iris_get_port_info(inst, cap_id),
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* [PATCH v4 09/16] media: iris: Add framework support for AR50_LITE video core
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (7 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 08/16] media: iris: skip PIPE if it is not supported by the platform Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:54 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 10/16] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
` (6 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Add power sequence for ar5lt core.
Add register handling for ar50lt by hooking up vpu op with ar50lt
specific implemtation or resue from earlier generation wherever
feasible.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/Makefile | 1 +
.../platform/qcom/iris/iris_platform_common.h | 2 +
drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c | 156 +++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu_common.c | 3 +-
drivers/media/platform/qcom/iris/iris_vpu_common.h | 1 +
5 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
index 48e415cbc439..f1b204b95694 100644
--- a/drivers/media/platform/qcom/iris/Makefile
+++ b/drivers/media/platform/qcom/iris/Makefile
@@ -26,6 +26,7 @@ qcom-iris-objs += iris_buffer.o \
iris_vpu2.o \
iris_vpu3x.o \
iris_vpu4x.o \
+ iris_vpu_ar50lt.o \
iris_vpu_buffer.o \
iris_vpu_common.o \
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index accc1627defd..6a189489369f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -74,6 +74,7 @@ enum platform_clk_type {
IRIS_VPP0_HW_CLK,
IRIS_VPP1_HW_CLK,
IRIS_APV_HW_CLK,
+ IRIS_THROTTLE_CLK,
};
struct platform_clk_data {
@@ -315,6 +316,7 @@ struct iris_platform_data {
u32 tz_cp_config_data_size;
u32 num_vpp_pipe;
bool no_aon;
+ bool no_rpmh;
u32 wd_intr_mask;
u32 icc_ib_multiplier;
u32 max_session_count;
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
new file mode 100644
index 000000000000..1af20b067c03
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include <linux/bits.h>
+#include <linux/iopoll.h>
+#include <linux/reset.h>
+
+#include "iris_instance.h"
+#include "iris_vpu_common.h"
+
+#include "iris_vpu_register_defines.h"
+
+#define WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT BIT(3)
+
+#define WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT 0xb0080
+
+#define CPU_CS_VCICMD 0xa0020
+#define CPU_CS_VCICMD_ARP_OFF 0x1
+
+static void iris_vpu_ar50lt_set_preset_registers(struct iris_core *core)
+{
+ writel(0x0, core->reg_base + WRAPPER_VCODEC0_CLOCK_CONFIG_AR50LT);
+}
+
+static void iris_vpu_ar50lt_interrupt_init(struct iris_core *core)
+{
+ writel(WRAPPER_INTR_MASK_A2HVCODEC_BMSK_AR50LT, core->reg_base + WRAPPER_INTR_MASK);
+}
+
+static void iris_vpu_ar50lt_disable_arp(struct iris_core *core)
+{
+ writel(CPU_CS_VCICMD_ARP_OFF, core->reg_base + CPU_CS_VCICMD);
+}
+
+static int iris_vpu_ar50lt_power_off_controller(struct iris_core *core)
+{
+ iris_disable_unprepare_clock(core, IRIS_AHB_CLK);
+ iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
+ iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
+
+ return 0;
+}
+
+static void iris_vpu_ar50lt_power_off_hw(struct iris_core *core)
+{
+ dev_pm_genpd_set_hwmode(core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN], false);
+ iris_disable_unprepare_clock(core, IRIS_THROTTLE_CLK);
+ iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK);
+ iris_disable_unprepare_clock(core, IRIS_HW_CLK);
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+}
+
+static int iris_vpu_ar50lt_power_on_controller(struct iris_core *core)
+{
+ int ret;
+
+ ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
+ if (ret)
+ return ret;
+
+ ret = iris_prepare_enable_clock(core, IRIS_CTRL_CLK);
+ if (ret)
+ goto err_disable_power;
+
+ ret = iris_prepare_enable_clock(core, IRIS_AXI_CLK);
+ if (ret && ret != -ENOENT)
+ goto err_disable_ctrl_clock;
+
+ ret = iris_prepare_enable_clock(core, IRIS_AHB_CLK);
+ if (ret)
+ goto err_disable_axi_clock;
+
+ return 0;
+
+err_disable_axi_clock:
+ iris_disable_unprepare_clock(core, IRIS_AXI_CLK);
+err_disable_ctrl_clock:
+ iris_disable_unprepare_clock(core, IRIS_CTRL_CLK);
+err_disable_power:
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_CTRL_POWER_DOMAIN]);
+
+ return ret;
+}
+
+static int iris_vpu_ar50lt_power_on_hw(struct iris_core *core)
+{
+ int ret;
+
+ ret = iris_enable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+ if (ret)
+ return ret;
+
+ ret = iris_prepare_enable_clock(core, IRIS_HW_CLK);
+ if (ret)
+ goto err_disable_power;
+
+ ret = iris_prepare_enable_clock(core, IRIS_HW_AHB_CLK);
+ if (ret)
+ goto err_disable_hw_clock;
+
+ ret = iris_prepare_enable_clock(core, IRIS_THROTTLE_CLK);
+ if (ret)
+ goto err_disable_hw_ahb_clock;
+
+ return 0;
+
+err_disable_hw_ahb_clock:
+ iris_disable_unprepare_clock(core, IRIS_HW_AHB_CLK);
+err_disable_hw_clock:
+ iris_disable_unprepare_clock(core, IRIS_HW_CLK);
+err_disable_power:
+ iris_disable_power_domains(core, core->pmdomain_tbl->pd_devs[IRIS_HW_POWER_DOMAIN]);
+
+ return ret;
+}
+
+static u64 iris_vpu_ar50lt_calc_freq(struct iris_inst *inst, size_t data_size)
+{
+ struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
+ struct v4l2_format *inp_f = inst->fmt_src;
+ u32 mbs_per_second, mbpf, height, width;
+ unsigned long vpp_freq, vsp_freq;
+ u32 fps = DEFAULT_FPS;
+
+ width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
+ height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
+
+ mbpf = NUM_MBS_PER_FRAME(height, width);
+ mbs_per_second = mbpf * fps;
+
+ vpp_freq = mbs_per_second * caps->mb_cycles_vpp;
+
+ /* 21 / 20 is overhead factor */
+ vpp_freq += vpp_freq / 20;
+ vsp_freq = mbs_per_second * caps->mb_cycles_vsp;
+
+ /* 10 / 7 is overhead factor */
+ vsp_freq += ((fps * data_size * 8) * 10) / 7;
+
+ return max(vpp_freq, vsp_freq);
+}
+
+const struct vpu_ops iris_vpu_ar50lt_ops = {
+ .power_off_hw = iris_vpu_ar50lt_power_off_hw,
+ .power_on_hw = iris_vpu_ar50lt_power_on_hw,
+ .power_off_controller = iris_vpu_ar50lt_power_off_controller,
+ .power_on_controller = iris_vpu_ar50lt_power_on_controller,
+ .calc_freq = iris_vpu_ar50lt_calc_freq,
+ .set_hwmode = iris_vpu_set_hwmode,
+ .set_preset_registers = iris_vpu_ar50lt_set_preset_registers,
+ .interrupt_init = iris_vpu_ar50lt_interrupt_init,
+ .disable_arp = iris_vpu_ar50lt_disable_arp,
+};
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.c b/drivers/media/platform/qcom/iris/iris_vpu_common.c
index 41498f94480e..75dc051cc6cb 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.c
@@ -97,7 +97,8 @@ int iris_vpu_boot_firmware(struct iris_core *core)
}
writel(HOST2XTENSA_INTR_ENABLE, core->reg_base + CPU_CS_H2XSOFTINTEN);
- writel(0x0, core->reg_base + CPU_CS_X2RPMH);
+ if (!core->iris_platform_data->no_rpmh)
+ writel(0x0, core->reg_base + CPU_CS_X2RPMH);
return 0;
}
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index 71d96921ed37..f00e2de5fa53 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_common.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_common.h
@@ -13,6 +13,7 @@ extern const struct vpu_ops iris_vpu3_ops;
extern const struct vpu_ops iris_vpu33_ops;
extern const struct vpu_ops iris_vpu35_ops;
extern const struct vpu_ops iris_vpu4x_ops;
+extern const struct vpu_ops iris_vpu_ar50lt_ops;
struct vpu_ops {
void (*power_off_hw)(struct iris_core *core);
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 09/16] media: iris: Add framework support for AR50_LITE video core
2026-06-12 9:25 ` [PATCH v4 09/16] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
@ 2026-06-12 9:54 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 9:54 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The VPU clock frequency calculation ignores the actual stream frame rate and uses a hardcoded 30 FPS.
- [High] Calculation of VSP frequency causes severe 32-bit integer overflows on 32-bit architectures, leading to under-provisioned clocks.
--
commit 117c5206f4fac821d317f597cfe56c462e1556c1
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Add framework support for AR50_LITE video core
Add power sequence for ar5lt core.
Add register handling for ar50lt by hooking up vpu op with ar50lt
specific implemtation or resue from earlier generation wherever
feasible.
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
> new file mode 100644
> index 0000000000000..1af20b067c032
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
[ ... ]
> +static u64 iris_vpu_ar50lt_calc_freq(struct iris_inst *inst, size_t data_size)
> +{
> + struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
> + struct v4l2_format *inp_f = inst->fmt_src;
> + u32 mbs_per_second, mbpf, height, width;
> + unsigned long vpp_freq, vsp_freq;
> + u32 fps = DEFAULT_FPS;
[Severity: High]
Does this hardcode the frame rate to 30 FPS instead of using the actual
stream frame rate from the session (e.g., inst->frame_rate)? For
high-framerate streams, this might under-provision the VPU clocks and lead
to dropped frames or hardware stalls.
> +
> + width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
> + height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
> +
> + mbpf = NUM_MBS_PER_FRAME(height, width);
> + mbs_per_second = mbpf * fps;
> +
> + vpp_freq = mbs_per_second * caps->mb_cycles_vpp;
> +
> + /* 21 / 20 is overhead factor */
> + vpp_freq += vpp_freq / 20;
> + vsp_freq = mbs_per_second * caps->mb_cycles_vsp;
> +
> + /* 10 / 7 is overhead factor */
> + vsp_freq += ((fps * data_size * 8) * 10) / 7;
[Severity: High]
Can this calculation overflow on 32-bit architectures? Since size_t is 32-bit
on these platforms, the intermediate product could exceed the 32-bit unsigned
maximum before the division by 7, resulting in a wrap-around and an incorrectly
low requested clock frequency.
> +
> + return max(vpp_freq, vsp_freq);
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=9
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 10/16] media: iris: add minimal GET_PROPERTY implementation
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (8 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 09/16] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 9:56 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 11/16] media: iris: update buffer requirements based on received info Dmitry Baryshkov
` (5 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
AR50Lt with the Gen1 firmware requires host to read
HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS property, otherwie it doesn't
update internal data and fails the HFI_CMD_SESSION_LOAD_RESOURCES
command. Implement minimal support for querying the properties from the
firmware.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_hfi_common.h | 1 +
.../platform/qcom/iris/iris_hfi_gen1_command.c | 21 +++++++++++++++++++++
.../platform/qcom/iris/iris_hfi_gen1_defines.h | 15 +++++++++++++++
.../platform/qcom/iris/iris_hfi_gen1_response.c | 6 ++++++
4 files changed, 43 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h b/drivers/media/platform/qcom/iris/iris_hfi_common.h
index a27447eb2519..16099f9a25b6 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_common.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h
@@ -121,6 +121,7 @@ struct iris_hfi_session_ops {
int (*session_set_property)(struct iris_inst *inst,
u32 packet_type, u32 flag, u32 plane, u32 payload_type,
void *payload, u32 payload_size);
+ int (*session_get_property)(struct iris_inst *inst, u32 packet_type);
int (*session_open)(struct iris_inst *inst);
int (*session_start)(struct iris_inst *inst, u32 plane);
int (*session_queue_buf)(struct iris_inst *inst, struct iris_buffer *buffer);
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 7674b47ad6c4..99e82e5510ab 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -1117,10 +1117,31 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p
return 0;
}
+static int iris_hfi_gen1_session_get_property(struct iris_inst *inst, u32 packet_type)
+{
+ struct hfi_session_get_property_pkt pkt;
+ int ret;
+
+ pkt.shdr.hdr.size = sizeof(pkt);
+ pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_GET_PROPERTY;
+ pkt.shdr.session_id = inst->session_id;
+ pkt.num_properties = 1;
+ pkt.data = packet_type;
+
+ reinit_completion(&inst->completion);
+
+ ret = iris_hfi_queue_cmd_write(inst->core, &pkt, pkt.shdr.hdr.size);
+ if (ret)
+ return ret;
+
+ return iris_wait_for_session_response(inst, false);
+}
+
static const struct iris_hfi_session_ops iris_hfi_gen1_session_ops = {
.session_open = iris_hfi_gen1_session_open,
.session_set_config_params = iris_hfi_gen1_session_set_config_params,
.session_set_property = iris_hfi_gen1_session_set_property,
+ .session_get_property = iris_hfi_gen1_session_get_property,
.session_start = iris_hfi_gen1_session_start,
.session_queue_buf = iris_hfi_gen1_session_queue_buffer,
.session_release_buf = iris_hfi_gen1_session_unset_buffers,
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
index 0e4dee192384..bb495a1d2623 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h
@@ -35,6 +35,7 @@
#define HFI_CMD_SESSION_EMPTY_BUFFER 0x211004
#define HFI_CMD_SESSION_FILL_BUFFER 0x211005
#define HFI_CMD_SESSION_FLUSH 0x211008
+#define HFI_CMD_SESSION_GET_PROPERTY 0x211009
#define HFI_CMD_SESSION_RELEASE_BUFFERS 0x21100b
#define HFI_CMD_SESSION_RELEASE_RESOURCES 0x21100c
#define HFI_CMD_SESSION_CONTINUE 0x21100d
@@ -113,6 +114,7 @@
#define HFI_MSG_SESSION_FLUSH 0x221006
#define HFI_MSG_SESSION_EMPTY_BUFFER 0x221007
#define HFI_MSG_SESSION_FILL_BUFFER 0x221008
+#define HFI_MSG_SESSION_PROPERTY_INFO 0x221009
#define HFI_MSG_SESSION_RELEASE_RESOURCES 0x22100a
#define HFI_MSG_SESSION_RELEASE_BUFFERS 0x22100c
@@ -205,6 +207,12 @@ struct hfi_session_set_property_pkt {
u32 data[];
};
+struct hfi_session_get_property_pkt {
+ struct hfi_session_hdr_pkt shdr;
+ u32 num_properties;
+ u32 data;
+};
+
struct hfi_sys_pc_prep_pkt {
struct hfi_pkt_hdr hdr;
};
@@ -574,6 +582,13 @@ struct hfi_msg_session_fbd_uncompressed_plane0_pkt {
u32 data[];
};
+struct hfi_msg_session_property_info_pkt {
+ struct hfi_session_hdr_pkt shdr;
+ u32 num_properties;
+ u32 property;
+ u8 data[];
+};
+
struct hfi_msg_session_release_buffers_done_pkt {
struct hfi_msg_session_hdr_pkt shdr;
u32 num_buffers;
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index bfd7495bf44f..23fc7194b1e3 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -591,6 +591,10 @@ static const struct iris_hfi_gen1_response_pkt_info pkt_infos[] = {
.pkt = HFI_MSG_SESSION_RELEASE_BUFFERS,
.pkt_sz = sizeof(struct hfi_msg_session_release_buffers_done_pkt),
},
+ {
+ .pkt = HFI_MSG_SESSION_PROPERTY_INFO,
+ .pkt_sz = sizeof(struct hfi_msg_session_property_info_pkt),
+ },
};
static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response)
@@ -652,6 +656,8 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
iris_hfi_gen1_session_etb_done(inst, hdr);
} else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) {
iris_hfi_gen1_session_ftb_done(inst, hdr);
+ } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) {
+ complete(&inst->completion);
} else {
struct hfi_msg_session_hdr_pkt *shdr;
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 10/16] media: iris: add minimal GET_PROPERTY implementation
2026-06-12 9:25 ` [PATCH v4 10/16] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
@ 2026-06-12 9:56 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 9:56 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Possible Use-After-Free in firmware response handler due to lockless instance lookup and lack of reference counting.
--
commit ea864f98c9ad1ba57f2027e2f0fc7f82f044f629
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: iris: add minimal GET_PROPERTY implementation
AR50Lt with the Gen1 firmware requires host to read
HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS property, otherwie it doesn't
update internal data and fails the HFI_CMD_SESSION_LOAD_RESOURCES
command. Implement minimal support for querying the properties from the
firmware.
> AR50Lt with the Gen1 firmware requires host to read
> HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS property, otherwie it doesn't
This isn't a bug, but there's a typo (otherwie) in the commit message.
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> index bfd7495bf44f0..23fc7194b1e3a 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
[ ... ]
> @@ -652,6 +656,8 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
> iris_hfi_gen1_session_etb_done(inst, hdr);
> } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) {
> iris_hfi_gen1_session_ftb_done(inst, hdr);
> + } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) {
> + complete(&inst->completion);
[Severity: High]
This is a pre-existing issue, but could there be a use-after-free race condition
when handling firmware responses here?
Earlier in iris_hfi_gen1_handle_response(), the instance is looked up using
iris_get_instance():
inst = iris_get_instance(core, pkt->shdr.session_id);
...
mutex_lock(&inst->lock);
iris_get_instance() finds the instance in the core->instances list and returns
a raw pointer after dropping core->lock, without incrementing a reference count.
Concurrently, if a userspace process closes the device node, iris_close() might
remove the instance from the list, unlock inst->lock, destroy the mutex, and
call kfree(inst).
If the response handler thread calls iris_get_instance() just before iris_close()
removes the instance from the list, the response thread could receive the pointer
and block on mutex_lock(&inst->lock) while iris_close() holds it.
After iris_close() finishes teardown and frees the instance, the response thread
would be unblocked and attempt to access the freed memory and destroyed mutex.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=10
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 11/16] media: iris: update buffer requirements based on received info
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (9 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 10/16] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 10:08 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 12/16] media: iris: implement support for the Agatti platform Dmitry Baryshkov
` (4 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
Upon receiving data for HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS the
driver should update buffer sizes and counts from the received data.
Implement corresponding functionality updating buffers data. This will
be used for upcoming support of AR50Lt platforms with Gen1 firmware.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../platform/qcom/iris/iris_hfi_gen1_response.c | 74 +++++++++++++++++++++-
1 file changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
index 23fc7194b1e3..ee996eb1f41f 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
@@ -533,6 +533,78 @@ static void iris_hfi_gen1_session_ftb_done(struct iris_inst *inst, void *packet)
dev_err(core->dev, "error in ftb done\n");
}
+static enum iris_buffer_type iris_hfi_gen1_buf_type(struct iris_inst *inst, u32 type)
+{
+ switch (type) {
+ case HFI_BUFFER_INPUT:
+ return BUF_INPUT;
+ case HFI_BUFFER_OUTPUT:
+ if (iris_split_mode_enabled(inst))
+ return BUF_DPB;
+ return BUF_OUTPUT;
+ case HFI_BUFFER_OUTPUT2:
+ if (iris_split_mode_enabled(inst))
+ return BUF_OUTPUT;
+ return BUF_DPB;
+ case HFI_BUFFER_INTERNAL_PERSIST_1:
+ return BUF_PERSIST;
+ case HFI_BUFFER_INTERNAL_SCRATCH:
+ return BUF_BIN;
+ case HFI_BUFFER_INTERNAL_SCRATCH_1:
+ return BUF_SCRATCH_1;
+ case HFI_BUFFER_INTERNAL_SCRATCH_2:
+ return BUF_SCRATCH_2;
+ case HFI_BUFFER_INTERNAL_PERSIST:
+ return BUF_ARP;
+ default:
+ return -EINVAL;
+ }
+}
+
+static void iris_hfi_gen1_session_buffer_requirements(struct iris_inst *inst,
+ void *data, size_t size)
+{
+ struct hfi_buffer_requirements *req;
+
+ if (!size || size % sizeof(*req))
+ return;
+
+ for (req = data; size; size -= sizeof(*req), req++) {
+ enum iris_buffer_type type = iris_hfi_gen1_buf_type(inst, req->type);
+
+ if (type == -EINVAL)
+ continue;
+
+ inst->buffers[type].min_count = req->hold_count;
+ inst->buffers[type].size = req->size;
+
+ if (type == BUF_OUTPUT)
+ inst->fw_min_count = req->count_actual;
+ }
+}
+
+static void iris_hfi_gen1_session_property_info(struct iris_inst *inst, void *packet)
+{
+ struct hfi_msg_session_property_info_pkt *pkt = packet;
+
+ if (!pkt->num_properties) {
+ dev_err(inst->core->dev, "error, no properties\n");
+ goto out;
+ }
+
+ switch (pkt->property) {
+ case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
+ iris_hfi_gen1_session_buffer_requirements(inst, pkt->data,
+ pkt->shdr.hdr.size - sizeof(*pkt));
+ break;
+ default:
+ dev_warn(inst->core->dev, "unknown property id: %x\n", pkt->property);
+ }
+
+out:
+ complete(&inst->completion);
+}
+
struct iris_hfi_gen1_response_pkt_info {
u32 pkt;
u32 pkt_sz;
@@ -657,7 +729,7 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
} else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) {
iris_hfi_gen1_session_ftb_done(inst, hdr);
} else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) {
- complete(&inst->completion);
+ iris_hfi_gen1_session_property_info(inst, hdr);
} else {
struct hfi_msg_session_hdr_pkt *shdr;
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 11/16] media: iris: update buffer requirements based on received info
2026-06-12 9:25 ` [PATCH v4 11/16] media: iris: update buffer requirements based on received info Dmitry Baryshkov
@ 2026-06-12 10:08 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 10:08 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] The driver incorrectly assigns `req->hold_count` and `req->count_actual` from `struct hfi_buffer_requirements` instead of `req->count_min` to instance buffer counts, leading to insufficient buffer allocations.
Pre-existing issues:
- [High] Preexisting Use-After-Free (UAF) race condition due to missing reference counting in `iris_get_instance`.
- [High] Preexisting Use-After-Free (UAF) of `inst->m2m_ctx` during session teardown in `iris_close()`.
--
commit 07ef5efeab4196fd6eaca945bfba49a95c55f702
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: iris: update buffer requirements based on received info
Upon receiving data for HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS the
driver should update buffer sizes and counts from the received data.
Implement corresponding functionality updating buffers data. This will
be used for upcoming support of AR50Lt platforms with Gen1 firmware.
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> index 23fc7194b1e3a..ee996eb1f41fa 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
[ ... ]
> +static void iris_hfi_gen1_session_buffer_requirements(struct iris_inst *inst,
> + void *data, size_t size)
> +{
> + struct hfi_buffer_requirements *req;
> +
> + if (!size || size % sizeof(*req))
> + return;
> +
> + for (req = data; size; size -= sizeof(*req), req++) {
> + enum iris_buffer_type type = iris_hfi_gen1_buf_type(inst, req->type);
> +
> + if (type == -EINVAL)
> + continue;
> +
> + inst->buffers[type].min_count = req->hold_count;
[Severity: High]
Is this assignment correct? The existing firmware semantics appear to expect
req->count_min to represent the minimum required buffers for forward progress.
Will assigning req->hold_count (which is typically lower) cause the driver to
under-allocate buffers for V4L2, leading to firmware stalls?
> + inst->buffers[type].size = req->size;
> +
> + if (type == BUF_OUTPUT)
> + inst->fw_min_count = req->count_actual;
[Severity: High]
Similarly, should this be assigned to req->count_min instead of
req->count_actual to maintain consistent minimum buffer count derivations?
> + }
> +}
[ ... ]
> @@ -657,7 +729,7 @@ static void iris_hfi_gen1_handle_response(struct iris_core *core, void *response
> } else if (hdr->pkt_type == HFI_MSG_SESSION_EMPTY_BUFFER) {
> iris_hfi_gen1_session_etb_done(inst, hdr);
> } else if (hdr->pkt_type == HFI_MSG_SESSION_FILL_BUFFER) {
> iris_hfi_gen1_session_ftb_done(inst, hdr);
[Severity: High]
This isn't a bug introduced by this patch, but can this lead to a
use-after-free regression?
During session teardown, iris_close() releases the M2M context before
shutting down the firmware session:
iris_vidc.c:iris_close() {
...
v4l2_m2m_ctx_release(inst->m2m_ctx);
...
}
If an HFI_MSG_SESSION_FILL_BUFFER event arrives before the session is fully
closed, the threaded IRQ handler calls iris_hfi_gen1_session_ftb_done() which
subsequently accesses the freed context in v4l2_m2m_for_each_dst_buf_safe().
Is there a way to defer freeing the M2M context until the session is safely
stopped?
> } else if (hdr->pkt_type == HFI_MSG_SESSION_PROPERTY_INFO) {
> - complete(&inst->completion);
> + iris_hfi_gen1_session_property_info(inst, hdr);
[Severity: High]
This is a pre-existing issue, but is it safe for
iris_hfi_gen1_handle_response() to use the inst pointer here without a
reference count?
When iris_get_instance() looks up the instance, it returns the pointer without
taking a reference. If a userspace thread executing iris_close() frees the
instance:
iris_vidc.c:iris_close() {
...
kfree(inst);
}
Could the threaded IRQ handler concurrently attempt to lock the destroyed
inst->lock or dereference inst while handling responses, resulting in a
use-after-free?
> } else {
> struct hfi_msg_session_hdr_pkt *shdr;
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=11
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 12/16] media: iris: implement support for the Agatti platform
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (10 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 11/16] media: iris: update buffer requirements based on received info Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 10:25 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 13/16] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
` (3 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
Port support for the AR50Lt video codec core (present for example on the
Agatti platform) to the Iris driver. Unlike more recent cores this
generation doesn't have the PIPE property (as it always has only one
pipe). Also, unlike newer platforms, buffer sizes are requested from the
firmware instead of being calculated by the driver.
Co-developed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/Makefile | 1 +
drivers/media/platform/qcom/iris/iris_hfi_gen1.c | 227 +++++++++++++++++++++
.../platform/qcom/iris/iris_platform_common.h | 6 +
.../platform/qcom/iris/iris_platform_vpu_ar50lt.c | 110 ++++++++++
drivers/media/platform/qcom/iris/iris_probe.c | 4 +
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 13 ++
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 1 +
7 files changed, 362 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/Makefile b/drivers/media/platform/qcom/iris/Makefile
index f1b204b95694..bbd1f724963e 100644
--- a/drivers/media/platform/qcom/iris/Makefile
+++ b/drivers/media/platform/qcom/iris/Makefile
@@ -14,6 +14,7 @@ qcom-iris-objs += iris_buffer.o \
iris_hfi_queue.o \
iris_platform_vpu2.o \
iris_platform_vpu3x.o \
+ iris_platform_vpu_ar50lt.o \
iris_power.o \
iris_probe.o \
iris_resources.o \
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
index ca1545d28b53..f57af31dbd9f 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
@@ -443,3 +443,230 @@ const struct iris_firmware_data iris_hfi_gen1_data = {
.enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl,
.enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl),
};
+
+static const struct platform_inst_fw_cap iris_inst_fw_cap_gen1_ar50lt_dec[] = {
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE,
+ .set = iris_set_stage,
+ },
+};
+
+static const struct platform_inst_fw_cap inst_fw_cap_gen1_ar50lt_enc[] = {
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE,
+ .set = iris_set_stage,
+ },
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1),
+ .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .hfi_id = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile_level_gen1,
+ },
+ {
+ .cap_id = HEADER_MODE,
+ .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+ .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+ BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
+ .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_header_mode_gen1,
+ },
+ {
+ .cap_id = BITRATE,
+ .min = BITRATE_MIN,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = BITRATE_STEP,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_bitrate_gen1,
+ },
+ {
+ .cap_id = BITRATE_MODE,
+ .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+ BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
+ .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_bitrate_mode_gen1,
+ },
+ {
+ .cap_id = FRAME_SKIP_MODE,
+ .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
+ .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_RC_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ },
+ {
+ .cap_id = GOP_SIZE,
+ .min = 0,
+ .max = (1 << 16) - 1,
+ .step_or_mask = 1,
+ .value = 30,
+ .set = iris_set_u32
+ },
+ {
+ .cap_id = ENTROPY_MODE,
+ .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+ BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
+ .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_entropy_mode_gen1,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP_HEVC,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP_HEVC,
+ .step_or_mask = 1,
+ .value = MAX_QP_HEVC,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE_V2,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_qp_range,
+ },
+};
+
+static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = {
+ BUF_BIN,
+ BUF_SCRATCH_1,
+};
+
+const struct iris_firmware_data iris_hfi_gen1_ar50lt_data = {
+ .init_hfi_ops = &iris_hfi_gen1_sys_ops_init,
+
+ .inst_fw_caps_dec = iris_inst_fw_cap_gen1_ar50lt_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(iris_inst_fw_cap_gen1_ar50lt_dec),
+ .inst_fw_caps_enc = inst_fw_cap_gen1_ar50lt_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen1_ar50lt_enc),
+
+ .dec_input_config_params_default =
+ sm8250_vdec_input_config_param_default,
+ .dec_input_config_params_default_size =
+ ARRAY_SIZE(sm8250_vdec_input_config_param_default),
+ .enc_input_config_params = sm8250_venc_input_config_param,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8250_venc_input_config_param),
+
+ .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl,
+ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl),
+ .dec_op_int_buf_tbl = sm8250_dec_op_int_buf_tbl,
+ .dec_op_int_buf_tbl_size = ARRAY_SIZE(sm8250_dec_op_int_buf_tbl),
+
+ .enc_ip_int_buf_tbl = sm8250_enc_ip_int_buf_tbl,
+ .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8250_enc_ip_int_buf_tbl),
+};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 6a189489369f..bc04831ae7fc 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -39,6 +39,10 @@ struct iris_inst;
#define MAX_HEVC_VBR_LAYER_HP_SLIDING_WINDOW 5
#define MAX_HIER_CODING_LAYER_GEN1 6
+#define BITRATE_MAX_AR50LT 100000000
+#define BITRATE_DEFAULT_AR50LT 20000000
+#define MIN_QP_8BIT_AR50LT 0
+
enum stage_type {
STAGE_1 = 1,
STAGE_2 = 2,
@@ -51,8 +55,10 @@ enum pipe_type {
};
extern const struct iris_firmware_data iris_hfi_gen1_data;
+extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data;
extern const struct iris_firmware_data iris_hfi_gen2_data;
+extern const struct iris_platform_data qcm2290_data;
extern const struct iris_platform_data qcs8300_data;
extern const struct iris_platform_data sc7280_data;
extern const struct iris_platform_data sm8250_data;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
new file mode 100644
index 000000000000..393256f39112
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "iris_core.h"
+#include "iris_ctrls.h"
+#include "iris_hfi_gen2.h"
+#include "iris_hfi_gen2_defines.h"
+#include "iris_platform_common.h"
+#include "iris_vpu_buffer.h"
+#include "iris_vpu_common.h"
+
+#define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10
+
+const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_s6_desc = {
+ .firmware_data = &iris_hfi_gen1_ar50lt_data,
+ .get_vpu_buffer_size = iris_vpu_ar50lt_gen1_buf_size,
+ .fwname = "qcom/venus-6.0/venus.mbn",
+};
+
+static const u32 iris_fmts_ar50lt_dec[] = {
+ [IRIS_FMT_H264] = V4L2_PIX_FMT_H264,
+ [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC,
+ [IRIS_FMT_VP9] = V4L2_PIX_FMT_VP9,
+};
+
+static const struct bw_info iris_bw_table_dec_ar50lt[] = {
+ { ((1920 * 1080) / 256) * 60, 1564000, },
+ { ((1920 * 1080) / 256) * 30, 791000, },
+ { ((1280 * 720) / 256) * 60, 688000, },
+ { ((1280 * 720) / 256) * 30, 347000, },
+};
+
+static const struct icc_info iris_icc_info_ar50lt[] = {
+ { "cpu-cfg", 1000, 1000 },
+ { "video-mem", 1000, 6500000 },
+};
+
+static const char * const iris_pmdomain_table_ar50lt[] = { "venus", "vcodec0" };
+
+static const char * const iris_opp_pd_table_ar50lt[] = { "cx" };
+
+static const struct platform_clk_data iris_clk_table_ar50lt[] = {
+ {IRIS_CTRL_CLK, "core" },
+ {IRIS_AXI_CLK, "iface" },
+ {IRIS_AHB_CLK, "bus" },
+ {IRIS_HW_CLK, "vcodec0_core" },
+ {IRIS_HW_AHB_CLK, "vcodec0_bus" },
+ {IRIS_THROTTLE_CLK, "throttle" },
+};
+
+static const char * const iris_opp_clk_table_ar50lt[] = {
+ "vcodec0_core",
+ NULL,
+};
+
+static const struct tz_cp_config tz_cp_config_ar50lt[] = {
+ {
+ .cp_start = 0,
+ .cp_size = 0x25800000,
+ .cp_nonpixel_start = 0x01000000,
+ .cp_nonpixel_size = 0x24800000,
+ },
+};
+
+static struct platform_inst_caps platform_inst_cap_ar50lt = {
+ .min_frame_width = 128,
+ .max_frame_width = 1920,
+ .min_frame_height = 128,
+ .max_frame_height = 1920,
+ .max_mbpf = (1920 * 1088) / 256,
+ .mb_cycles_vpp = 440,
+ .mb_cycles_fw = 733003,
+ .mb_cycles_fw_vpp = 225975,
+ .max_frame_rate = 120,
+ .max_operating_rate = 120,
+};
+
+const struct iris_platform_data qcm2290_data = {
+ .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_s6_desc,
+ .vpu_ops = &iris_vpu_ar50lt_ops,
+ .icc_tbl = iris_icc_info_ar50lt,
+ .icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt),
+ .bw_tbl_dec = iris_bw_table_dec_ar50lt,
+ .bw_tbl_dec_size = ARRAY_SIZE(iris_bw_table_dec_ar50lt),
+ .pmdomain_tbl = iris_pmdomain_table_ar50lt,
+ .pmdomain_tbl_size = ARRAY_SIZE(iris_pmdomain_table_ar50lt),
+ .opp_pd_tbl = iris_opp_pd_table_ar50lt,
+ .opp_pd_tbl_size = ARRAY_SIZE(iris_opp_pd_table_ar50lt),
+ .clk_tbl = iris_clk_table_ar50lt,
+ .clk_tbl_size = ARRAY_SIZE(iris_clk_table_ar50lt),
+ .opp_clk_tbl = iris_opp_clk_table_ar50lt,
+ /* Upper bound of DMA address range */
+ .dma_mask = 0xe0000000 - 1,
+ .inst_iris_fmts = iris_fmts_ar50lt_dec,
+ .inst_iris_fmts_size = ARRAY_SIZE(iris_fmts_ar50lt_dec),
+ .inst_caps = &platform_inst_cap_ar50lt,
+ .tz_cp_config_data = tz_cp_config_ar50lt,
+ .tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_ar50lt),
+ .num_vpp_pipe = 1,
+ .no_rpmh = true,
+ .wd_intr_mask = WRAPPER_INTR_STATUS_A2HWD_BMSK,
+ .icc_ib_multiplier = 2,
+ .max_session_count = 8,
+ .max_core_mbpf = ((1920 * 1088) / 256) * 4,
+ /* Concurrency: 1080p@30 decode + 1080p@30 encode */
+ /* Concurrency: 3 * 1080p@30 decode */
+ .max_core_mbps = (((1920 * 1088) / 256) * 90),
+};
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index 7fe31136df21..472d9e293ece 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -356,6 +356,10 @@ static const struct dev_pm_ops iris_pm_ops = {
};
static const struct of_device_id iris_dt_match[] = {
+ {
+ .compatible = "qcom,qcm2290-venus",
+ .data = &qcm2290_data,
+ },
{
.compatible = "qcom,qcs8300-iris",
.data = &qcs8300_data,
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index fb6f1016415e..4a39b8fef52b 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -2194,6 +2194,19 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ
return size;
}
+u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
+{
+ const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops;
+ int ret;
+
+ /* return 0 on error to let the driver cope */
+ ret = hfi_ops->session_get_property(inst, HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS);
+ if (ret)
+ return 0;
+
+ return inst->buffers[buffer_type].size;
+}
+
static u32 internal_buffer_count(struct iris_inst *inst,
enum iris_buffer_type buffer_type)
{
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
index 8c0d6b7b5de8..1d07137c70cd 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
@@ -288,6 +288,7 @@ static inline u32 size_av1d_qp(u32 frame_width, u32 frame_height)
u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
+u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type);
#endif
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 12/16] media: iris: implement support for the Agatti platform
2026-06-12 9:25 ` [PATCH v4 12/16] media: iris: implement support for the Agatti platform Dmitry Baryshkov
@ 2026-06-12 10:25 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 10:25 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Calling a synchronous HFI command from the ISR response thread causes a deadlock.
--
commit 960bbe7059755e03232b477bd06562c01b126fdd
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: iris: implement support for the Agatti platform
Port support for the AR50Lt video codec core (present for example on the
Agatti platform) to the Iris driver. Unlike more recent cores this
generation doesn't have the PIPE property (as it always has only one
pipe). Also, unlike newer platforms, buffer sizes are requested from the
firmware instead of being calculated by the driver.
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> index fb6f1016415e2..4a39b8fef52b0 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> @@ -2194,6 +2194,19 @@ u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_typ
> return size;
> }
>
> +u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
> +{
> + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops;
> + int ret;
> +
> + /* return 0 on error to let the driver cope */
> + ret = hfi_ops->session_get_property(inst, HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS);
[Severity: High]
Could this lead to a regression by waiting for a response in the response
handler thread?
When iris_vpu_ar50lt_gen1_buf_size() calls hfi_ops->session_get_property(),
it synchronously blocks until the firmware responds:
drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c:iris_hfi_gen1_session_get_property() {
...
return iris_wait_for_session_response(inst, false);
}
However, iris_vpu_ar50lt_gen1_buf_size() (via iris_get_buffer_size()) is
invoked from iris_hfi_gen1_read_changed_params() during event processing:
drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c:iris_hfi_gen1_read_changed_params() {
...
pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
...
}
This event processing runs inside the driver's response handler:
drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c:iris_hfi_gen1_response_handler() {
...
iris_hfi_gen1_handle_response(core, core->response_packet);
...
}
If the response handler thread blocks itself waiting for a response, how will
that response ever be dequeued and processed? It appears this will stall the
response polling loop until the wait times out.
> + if (ret)
> + return 0;
> +
> + return inst->buffers[buffer_type].size;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=12
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 13/16] media: iris: Introduce buffer size calculations for AR50LT
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (11 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 12/16] media: iris: implement support for the Agatti platform Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 10:22 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 14/16] media: iris: add Gen2 firmware support on the Agatti platform Dmitry Baryshkov
` (2 subsequent siblings)
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Introduces AR50LT buffer size calculation for both encoder and
decoder. Reuse the buffer size calculation which are common, while
adding the AR50LT specific ones separately.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_vpu_buffer.c | 401 +++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 37 ++
2 files changed, 438 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index 4a39b8fef52b..ca03d6570513 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -50,6 +50,32 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p
return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
}
+static u32 size_h264d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 size_yuv, size_bin_hdr, size_bin_res;
+
+ size_yuv = ((frame_width * frame_height * 3) >> 1);
+ if (size_yuv <= 1920 * 1088 * 3 / 2) {
+ size_bin_hdr = size_yuv * H264_CABAC_HDR_RATIO_SM_TOT;
+ size_bin_res = size_yuv * H264_CABAC_RES_RATIO_SM_TOT;
+ } else {
+ size_bin_hdr = (size_yuv * 3) / 5;
+ size_bin_res = (size_yuv * 3) / 2;
+ }
+ size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT);
+ size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT);
+
+ return size_bin_hdr + size_bin_res;
+}
+
+static u32 hfi_buffer_bin_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 n_aligned_h = ALIGN(frame_height, 16);
+ u32 n_aligned_w = ALIGN(frame_width, 16);
+
+ return size_h264d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes);
+}
+
static u32 size_av1d_hw_bin_buffer(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
u32 size_yuv, size_bin_hdr, size_bin_res;
@@ -103,6 +129,21 @@ static u32 hfi_buffer_bin_vp9d(u32 frame_width, u32 frame_height, u32 num_vpp_pi
return _size * num_vpp_pipes;
}
+static u32 hfi_buffer_bin_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 size_yuv, size;
+
+ size_yuv = ALIGN(frame_width, 16) * ALIGN(frame_height, 16) * 3 / 2;
+ size_yuv = ALIGN(size_yuv, DMA_ALIGNMENT);
+
+ size = ALIGN(((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 6) / 5) /
+ num_vpp_pipes), DMA_ALIGNMENT) +
+ ALIGN((((MAX(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 4) / num_vpp_pipes),
+ DMA_ALIGNMENT);
+
+ return size * num_vpp_pipes;
+}
+
static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
u32 n_aligned_w = ALIGN(frame_width, 16);
@@ -111,6 +152,32 @@ static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_p
return size_h265d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
}
+static u32 size_h265d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 size_yuv, size_bin_hdr, size_bin_res;
+
+ size_yuv = ((frame_width * frame_height * 3) >> 1);
+ if (size_yuv <= ((BIN_BUFFER_THRESHOLD * 3) >> 1)) {
+ size_bin_hdr = size_yuv * H265_CABAC_HDR_RATIO_SM_TOT;
+ size_bin_res = size_yuv * H265_CABAC_RES_RATIO_SM_TOT;
+ } else {
+ size_bin_hdr = (size_yuv * 41) / 50;
+ size_bin_res = (size_yuv * 59) / 50;
+ }
+ size_bin_hdr = ALIGN(size_bin_hdr, DMA_ALIGNMENT);
+ size_bin_res = ALIGN(size_bin_res, DMA_ALIGNMENT);
+
+ return size_bin_hdr + size_bin_res;
+}
+
+static u32 hfi_buffer_bin_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 n_aligned_w = ALIGN(frame_width, 16);
+ u32 n_aligned_h = ALIGN(frame_height, 16);
+
+ return size_h265d_hw_bin_buffer_ar50lt(n_aligned_w, n_aligned_h, num_vpp_pipes);
+}
+
static u32 hfi_buffer_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount)
{
u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16);
@@ -174,6 +241,14 @@ static u32 size_h264d_bse_cmd_buf(u32 frame_height)
SIZE_H264D_BSE_CMD_PER_BUF;
}
+static u32 size_h264d_bse_cmd_buf_ar50lt(u32 frame_height)
+{
+ u32 height = ALIGN(frame_height, 32);
+
+ return min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) *
+ SIZE_H264D_BSE_CMD_PER_BUF;
+}
+
static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height)
{
u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) *
@@ -185,6 +260,18 @@ static u32 size_h265d_bse_cmd_buf(u32 frame_width, u32 frame_height)
return _size;
}
+static u32 size_h265d_bse_cmd_buf_ar50lt(u32 frame_width, u32 frame_height)
+{
+ u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) *
+ (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) *
+ NUM_HW_PIC_BUF, DMA_ALIGNMENT);
+
+ _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1);
+ _size = 2 * _size * SIZE_H265D_BSE_CMD_PER_BUF;
+
+ return _size;
+}
+
static u32 hfi_buffer_persist_h265d(u32 rpu_enabled)
{
return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 +
@@ -195,6 +282,13 @@ static u32 hfi_buffer_persist_h265d(u32 rpu_enabled)
DMA_ALIGNMENT);
}
+static u32 hfi_buffer_persist_h265d_ar50lt(void)
+{
+ return ALIGN((SIZE_SLIST_BUF_H265 * NUM_SLIST_BUF_H265 +
+ H265_NUM_TILE * sizeof(u32) + NUM_HW_PIC_BUF * SIZE_SEI_USERDATA),
+ DMA_ALIGNMENT);
+}
+
static inline
u32 hfi_iris3_vp9d_comv_size(void)
{
@@ -212,6 +306,13 @@ static u32 hfi_buffer_persist_vp9d(void)
HDR10_HIST_EXTRADATA_SIZE;
}
+static u32 hfi_buffer_persist_vp9d_ar50lt(void)
+{
+ return ALIGN(VP9_NUM_PROBABILITY_TABLE_BUF * VP9_PROB_TABLE_SIZE, DMA_ALIGNMENT) +
+ ALIGN(hfi_iris3_vp9d_comv_size(), DMA_ALIGNMENT) +
+ ALIGN(MAX_SUPERFRAME_HEADER_LEN, DMA_ALIGNMENT);
+}
+
static u32 size_h264d_vpp_cmd_buf(u32 frame_height)
{
u32 size, height = ALIGN(frame_height, 32);
@@ -222,6 +323,16 @@ static u32 size_h264d_vpp_cmd_buf(u32 frame_height)
return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size;
}
+static u32 size_h264d_vpp_cmd_buf_ar50lt(u32 frame_height)
+{
+ u32 size, height = ALIGN(frame_height, 32);
+
+ size = min_t(u32, (DIV_ROUND_UP(height, 16) * 12), H264D_MAX_SLICE) *
+ SIZE_H264D_VPP_CMD_PER_BUF;
+
+ return size > VPP_CMD_MAX_SIZE ? VPP_CMD_MAX_SIZE : size;
+}
+
static u32 hfi_buffer_persist_h264d(void)
{
return ALIGN(SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264 +
@@ -230,6 +341,11 @@ static u32 hfi_buffer_persist_h264d(void)
DMA_ALIGNMENT);
}
+static u32 hfi_buffer_persist_h264d_ar50lt(void)
+{
+ return ALIGN((SIZE_SLIST_BUF_H264 * NUM_SLIST_BUF_H264), DMA_ALIGNMENT);
+}
+
static u32 hfi_buffer_persist_av1d(u32 max_width, u32 max_height, u32 total_ref_count)
{
u32 comv_size, size;
@@ -255,6 +371,17 @@ static u32 hfi_buffer_non_comv_h264d(u32 frame_width, u32 frame_height, u32 num_
return ALIGN(size, DMA_ALIGNMENT);
}
+static u32 hfi_buffer_non_comv_h264d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 size_bse = size_h264d_bse_cmd_buf_ar50lt(frame_height);
+ u32 size_vpp = size_h264d_vpp_cmd_buf_ar50lt(frame_height);
+ u32 size = ALIGN(size_bse, DMA_ALIGNMENT) +
+ ALIGN(size_vpp, DMA_ALIGNMENT) +
+ ALIGN(SIZE_HW_PIC(SIZE_H264D_HW_PIC_T), DMA_ALIGNMENT);
+
+ return ALIGN(size, DMA_ALIGNMENT);
+}
+
static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height)
{
u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) *
@@ -269,6 +396,20 @@ static u32 size_h265d_vpp_cmd_buf(u32 frame_width, u32 frame_height)
return _size;
}
+static u32 size_h265d_vpp_cmd_buf_ar50lt(u32 frame_width, u32 frame_height)
+{
+ u32 _size = ALIGN(((ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) *
+ (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS)) *
+ NUM_HW_PIC_BUF, DMA_ALIGNMENT);
+ _size = min_t(u32, _size, H265D_MAX_SLICE_AR50LT + 1);
+ _size = ALIGN(_size, 4);
+ _size = 2 * _size * SIZE_H265D_VPP_CMD_PER_BUF_AR50LT;
+ if (_size > VPP_CMD_MAX_SIZE)
+ _size = VPP_CMD_MAX_SIZE;
+
+ return _size;
+}
+
static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
{
u32 _size_bse = size_h265d_bse_cmd_buf(frame_width, frame_height);
@@ -285,6 +426,20 @@ static u32 hfi_buffer_non_comv_h265d(u32 frame_width, u32 frame_height, u32 num_
return ALIGN(_size, DMA_ALIGNMENT);
}
+static u32 hfi_buffer_non_comv_h265d_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ u32 _size_bse = size_h265d_bse_cmd_buf_ar50lt(frame_width, frame_height);
+ u32 _size_vpp = size_h265d_vpp_cmd_buf_ar50lt(frame_width, frame_height);
+ u32 _size = ALIGN(_size_bse, DMA_ALIGNMENT) +
+ ALIGN(_size_vpp, DMA_ALIGNMENT) +
+ ALIGN(2 * sizeof(u16) *
+ (ALIGN(frame_width, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS) *
+ (ALIGN(frame_height, LCU_MAX_SIZE_PELS) / LCU_MIN_SIZE_PELS), DMA_ALIGNMENT) +
+ ALIGN(SIZE_HW_PIC(SIZE_H265D_HW_PIC_T), DMA_ALIGNMENT);
+
+ return ALIGN(_size, DMA_ALIGNMENT);
+}
+
static u32 size_vpss_lb(u32 frame_width, u32 frame_height)
{
u32 opb_lb_wr_llb_y_buffer_size, opb_lb_wr_llb_uv_buffer_size;
@@ -317,6 +472,13 @@ u32 size_h265d_lb_fe_top_data(u32 frame_width, u32 frame_height)
(ALIGN(frame_width, 64) + 8) * 2;
}
+static inline
+u32 size_h265d_lb_fe_top_data_ar50lt(u32 frame_width, u32 frame_height)
+{
+ return ALIGN(MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE *
+ (ALIGN(frame_width, 64) + 8), DMA_ALIGNMENT) * 2;
+}
+
static inline
u32 size_h265d_lb_fe_top_ctrl(u32 frame_width, u32 frame_height)
{
@@ -348,6 +510,17 @@ u32 size_h265d_lb_se_left_ctrl(u32 frame_width, u32 frame_height)
MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE));
}
+static inline
+u32 size_h265d_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height)
+{
+ return max_t(u32, ((frame_height + 16 - 1) / 8) *
+ MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT,
+ max_t(u32, ((frame_height + 32 - 1) / 8) *
+ MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT,
+ ((frame_height + 64 - 1) / 8) *
+ MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT));
+}
+
static inline
u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height)
{
@@ -355,6 +528,13 @@ u32 size_h265d_lb_pe_top_data(u32 frame_width, u32 frame_height)
(ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS);
}
+static inline
+u32 size_h265d_lb_pe_top_data_ar50lt(u32 frame_width, u32 frame_height)
+{
+ return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT *
+ (ALIGN(frame_width, LCU_MIN_SIZE_PELS) / LCU_MIN_SIZE_PELS);
+}
+
static inline
u32 size_h265d_lb_vsp_top(u32 frame_width, u32 frame_height)
{
@@ -404,6 +584,29 @@ u32 hfi_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, u32 nu
return ALIGN((_size + vpss_lb_size), DMA_ALIGNMENT);
}
+static inline
+u32 hfi_buffer_line_h265d_ar50lt(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes)
+{
+ u32 size;
+
+ size = ALIGN(size_h265d_lb_fe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_h265d_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_h265d_lb_fe_left_ctrl(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_h265d_lb_se_left_ctrl_ar50lt(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_h265d_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_h265d_lb_pe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_h265d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_h265d_lb_vsp_left(frame_width, frame_height),
+ DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_h265d_lb_recon_dma_metadata_wr(frame_width, frame_height),
+ DMA_ALIGNMENT) * 4 +
+ ALIGN(size_h265d_qp(frame_width, frame_height), DMA_ALIGNMENT);
+
+ return ALIGN(size, DMA_ALIGNMENT);
+}
+
static inline
u32 size_vpxd_lb_fe_left_ctrl(u32 frame_width, u32 frame_height)
{
@@ -438,6 +641,17 @@ u32 size_vpxd_lb_se_left_ctrl(u32 frame_width, u32 frame_height)
MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE));
}
+static inline
+u32 size_vpxd_lb_se_left_ctrl_ar50lt(u32 frame_width, u32 frame_height)
+{
+ return max_t(u32, ((frame_height + 15) >> 4) *
+ MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT,
+ max_t(u32, ((frame_height + 31) >> 5) *
+ MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT,
+ ((frame_height + 63) >> 6) *
+ MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT));
+}
+
static inline
u32 size_vpxd_lb_recon_dma_metadata_wr(u32 frame_width, u32 frame_height)
{
@@ -492,6 +706,19 @@ u32 hfi_iris3_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
ALIGN(size_vp9d_qp(frame_width, frame_height), DMA_ALIGNMENT);
}
+static inline
+u32 hfi_ar50lt_vp9d_lb_size(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
+{
+ return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) *
+ num_vpp_pipes +
+ ALIGN(size_vpxd_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) *
+ num_vpp_pipes +
+ ALIGN(size_vp9d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_vpxd_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_vp9d_lb_pe_top_data(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_vp9d_lb_fe_top_data(frame_width, frame_height), DMA_ALIGNMENT);
+}
+
static inline
u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min, bool is_opb,
u32 num_vpp_pipes)
@@ -507,6 +734,13 @@ u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_mi
return _lb_size + vpss_lb_size + 4096;
}
+static inline
+u32 hfi_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min,
+ bool is_opb, u32 num_vpp_pipes)
+{
+ return hfi_ar50lt_vp9d_lb_size(frame_width, frame_height, num_vpp_pipes);
+}
+
static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height,
bool is_opb, u32 num_vpp_pipes)
{
@@ -529,6 +763,25 @@ static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height,
return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT);
}
+static u32 hfi_buffer_line_h264d_ar50lt(u32 frame_width, u32 frame_height,
+ bool is_opb, u32 num_vpp_pipes)
+{
+ u32 size;
+
+ size = ALIGN(size_h264d_lb_fe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_fe_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes +
+ ALIGN(size_h264d_lb_se_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_se_left_ctrl_ar50lt(frame_height), DMA_ALIGNMENT) *
+ num_vpp_pipes +
+ ALIGN(size_h264d_lb_pe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 +
+ ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT);
+
+ return ALIGN(size, DMA_ALIGNMENT);
+}
+
static u32 size_av1d_lb_opb_wr1_nv12_ubwc(u32 frame_width, u32 frame_height)
{
u32 size, y_width, y_width_a = 128;
@@ -724,6 +977,23 @@ static u32 iris_vpu_dec_bin_size(struct iris_inst *inst)
return 0;
}
+static u32 iris_vpu_ar50lt_dec_bin_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_src;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+
+ if (inst->codec == V4L2_PIX_FMT_H264)
+ return hfi_buffer_bin_h264d_ar50lt(width, height, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_bin_h265d_ar50lt(width, height, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_VP9)
+ return hfi_buffer_bin_vp9d_ar50lt(width, height, num_vpp_pipes);
+
+ return 0;
+}
+
static u32 iris_vpu_dec_comv_size(struct iris_inst *inst)
{
u32 num_comv = VIDEO_MAX_FRAME;
@@ -785,6 +1055,18 @@ static u32 iris_vpu_dec_persist_size(struct iris_inst *inst)
return 0;
}
+static u32 iris_vpu_ar50lt_dec_persist_size(struct iris_inst *inst)
+{
+ if (inst->codec == V4L2_PIX_FMT_H264)
+ return hfi_buffer_persist_h264d_ar50lt();
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_persist_h265d_ar50lt();
+ else if (inst->codec == V4L2_PIX_FMT_VP9)
+ return hfi_buffer_persist_vp9d_ar50lt();
+
+ return 0;
+}
+
static u32 iris_vpu_dec_dpb_size(struct iris_inst *inst)
{
if (iris_split_mode_enabled(inst))
@@ -808,6 +1090,21 @@ static u32 iris_vpu_dec_non_comv_size(struct iris_inst *inst)
return 0;
}
+static u32 iris_vpu_ar50lt_dec_non_comv_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_src;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+
+ if (inst->codec == V4L2_PIX_FMT_H264)
+ return hfi_buffer_non_comv_h264d_ar50lt(width, height, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_non_comv_h265d_ar50lt(width, height, num_vpp_pipes);
+
+ return 0;
+}
+
static u32 iris_vpu_dec_line_size(struct iris_inst *inst)
{
u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
@@ -833,6 +1130,29 @@ static u32 iris_vpu_dec_line_size(struct iris_inst *inst)
return 0;
}
+static u32 iris_vpu_ar50lt_dec_line_size(struct iris_inst *inst)
+{
+ u32 num_vpp_pipes = inst->core->iris_platform_data->num_vpp_pipe;
+ struct v4l2_format *f = inst->fmt_src;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ bool is_opb = false;
+ u32 out_min_count = inst->buffers[BUF_OUTPUT].min_count;
+
+ if (iris_split_mode_enabled(inst))
+ is_opb = true;
+
+ if (inst->codec == V4L2_PIX_FMT_H264)
+ return hfi_buffer_line_h264d_ar50lt(width, height, is_opb, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_line_h265d_ar50lt(width, height, is_opb, num_vpp_pipes);
+ else if (inst->codec == V4L2_PIX_FMT_VP9)
+ return hfi_buffer_line_vp9d_ar50lt(width, height, out_min_count, is_opb,
+ num_vpp_pipes);
+
+ return 0;
+}
+
static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst)
{
return iris_vpu_dec_comv_size(inst) +
@@ -840,6 +1160,13 @@ static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst)
iris_vpu_dec_line_size(inst);
}
+static u32 iris_vpu_ar50lt_dec_scratch1_size(struct iris_inst *inst)
+{
+ return iris_vpu_dec_comv_size(inst) +
+ iris_vpu_ar50lt_dec_non_comv_size(inst) +
+ iris_vpu_ar50lt_dec_line_size(inst);
+}
+
static inline u32 iris_vpu_enc_get_bitstream_width(struct iris_inst *inst)
{
if (is_rotation_90_or_270(inst))
@@ -1470,6 +1797,15 @@ u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit)
return size;
}
+static inline
+u32 hfi_buffer_dpb_enc_ar50lt(u32 frame_width, u32 frame_height, bool is_ten_bit)
+{
+ if (!is_ten_bit)
+ return size_enc_ref_buffer(frame_width, frame_height);
+ else
+ return size_enc_ten_bit_ref_buffer(frame_width, frame_height);
+}
+
static u32 iris_vpu_enc_arp_size(struct iris_inst *inst)
{
return HFI_BUFFER_ARP_ENC;
@@ -1494,6 +1830,16 @@ u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable,
return 0;
}
+static inline
+u32 hfi_buffer_vpss_enc_ar50lt(u32 dswidth, u32 dsheight, bool ds_enable,
+ u32 blur, bool is_ten_bit)
+{
+ if (ds_enable || blur)
+ return hfi_buffer_dpb_enc_ar50lt(dswidth, dsheight, is_ten_bit);
+
+ return 0;
+}
+
static inline u32 hfi_buffer_scratch1_enc(u32 frame_width, u32 frame_height,
u32 lcu_size, u32 num_ref,
bool ten_bit, u32 num_vpp_pipes,
@@ -1752,6 +2098,16 @@ static u32 iris_vpu_enc_vpss_size(struct iris_inst *inst)
return hfi_buffer_vpss_enc(width, height, ds_enable, 0, 0);
}
+static u32 iris_vpu_ar50lt_enc_vpss_size(struct iris_inst *inst)
+{
+ u32 ds_enable = is_scaling_enabled(inst);
+ struct v4l2_format *f = inst->fmt_dst;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+
+ return hfi_buffer_vpss_enc_ar50lt(width, height, ds_enable, 0, 0);
+}
+
static inline u32 size_dpb_opb(u32 height, u32 lcu_size)
{
u32 max_tile_height = ((height + lcu_size - 1) / lcu_size) * lcu_size + 8;
@@ -2207,6 +2563,51 @@ u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type
return inst->buffers[buffer_type].size;
}
+u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
+{
+ const struct iris_vpu_buf_type_handle *buf_type_handle_arr = NULL;
+ u32 size = 0, buf_type_handle_size = 0, i;
+
+ static const struct iris_vpu_buf_type_handle dec_internal_buf_type_handle[] = {
+ {BUF_BIN, iris_vpu_ar50lt_dec_bin_size },
+ {BUF_COMV, iris_vpu_dec_comv_size },
+ {BUF_NON_COMV, iris_vpu_ar50lt_dec_non_comv_size },
+ {BUF_LINE, iris_vpu_ar50lt_dec_line_size },
+ {BUF_PERSIST, iris_vpu_ar50lt_dec_persist_size },
+ {BUF_DPB, iris_vpu_dec_dpb_size },
+ {BUF_SCRATCH_1, iris_vpu_ar50lt_dec_scratch1_size },
+ {BUF_PARTIAL, iris_vpu_dec_partial_size },
+ };
+
+ static const struct iris_vpu_buf_type_handle enc_internal_buf_type_handle[] = {
+ {BUF_BIN, iris_vpu_enc_bin_size },
+ {BUF_COMV, iris_vpu_enc_comv_size },
+ {BUF_NON_COMV, iris_vpu_enc_non_comv_size },
+ {BUF_LINE, iris_vpu_enc_line_size },
+ {BUF_ARP, iris_vpu_enc_arp_size },
+ {BUF_VPSS, iris_vpu_ar50lt_enc_vpss_size },
+ {BUF_SCRATCH_1, iris_vpu_enc_scratch1_size },
+ {BUF_SCRATCH_2, iris_vpu_enc_scratch2_size },
+ };
+
+ if (inst->domain == DECODER) {
+ buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle);
+ buf_type_handle_arr = dec_internal_buf_type_handle;
+ } else if (inst->domain == ENCODER) {
+ buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle);
+ buf_type_handle_arr = enc_internal_buf_type_handle;
+ }
+
+ for (i = 0; i < buf_type_handle_size; i++) {
+ if (buf_type_handle_arr[i].type == buffer_type) {
+ size = buf_type_handle_arr[i].handle(inst);
+ break;
+ }
+ }
+
+ return size;
+}
+
static u32 internal_buffer_count(struct iris_inst *inst,
enum iris_buffer_type buffer_type)
{
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
index 1d07137c70cd..2085e316a6bd 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h
@@ -61,17 +61,26 @@ struct iris_inst;
#define MAX_FE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE 64
#define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE (128 / 8)
#define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE (128 / 8)
+#define MAX_SE_NBR_CTRL_LCU16_LINE_BUFFER_SIZE_AR50LT (8 / 8)
+#define MAX_SE_NBR_CTRL_LCU32_LINE_BUFFER_SIZE_AR50LT (16 / 8)
+#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT (32 / 8)
#define VP9_UDC_HEADER_BUF_SIZE (3 * 128)
#define SIZE_SEI_USERDATA 4096
#define SIZE_DOLBY_RPU_METADATA (41 * 1024)
#define H264_CABAC_HDR_RATIO_HD_TOT 1
#define H264_CABAC_RES_RATIO_HD_TOT 3
+#define H264_CABAC_HDR_RATIO_SM_TOT 1
+#define H264_CABAC_RES_RATIO_SM_TOT 2
#define H265D_MAX_SLICE 3600
+#define H265D_MAX_SLICE_AR50LT 600
#define SIZE_H265D_HW_PIC_T SIZE_H264D_HW_PIC_T
#define H265_CABAC_HDR_RATIO_HD_TOT 2
#define H265_CABAC_RES_RATIO_HD_TOT 2
+#define H265_CABAC_HDR_RATIO_SM_TOT 1
+#define H265_CABAC_RES_RATIO_SM_TOT 6
#define SIZE_H265D_VPP_CMD_PER_BUF (256)
+#define SIZE_H265D_VPP_CMD_PER_BUF_AR50LT (192)
#define SIZE_THREE_DIMENSION_USERDATA 768
#define SIZE_H265D_ARP 9728
@@ -81,6 +90,7 @@ struct iris_inst;
#define VPX_DECODER_FRAME_BIN_DENOMINATOR 2
#define VPX_DECODER_FRAME_BIN_RES_BUDGET_RATIO (3 / 2)
+#define VPX_DECODER_FRAME_BIN_BUFFER_SIZE (1024 * 1024)
#define SIZE_H264D_HW_PIC_T (BIT(11))
@@ -99,6 +109,7 @@ struct iris_inst;
#define MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 64
#define MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE 16
#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE 384
+#define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE_AR50LT 176
#define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640
#define AV1_CABAC_HDR_RATIO_HD_TOT 2
@@ -155,11 +166,21 @@ static inline u32 size_h264d_lb_fe_top_data(u32 frame_width)
return MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE * ALIGN(frame_width, 16) * 3;
}
+static inline u32 size_h264d_lb_fe_top_data_ar50lt(u32 frame_width)
+{
+ return 16 * ALIGN(frame_width, 16) * 2;
+}
+
static inline u32 size_h264d_lb_fe_top_ctrl(u32 frame_width)
{
return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16);
}
+static inline u32 size_h264d_lb_fe_top_ctrl_ar50lt(u32 frame_width)
+{
+ return 16 * DIV_ROUND_UP(frame_width, 16);
+}
+
static inline u32 size_h264d_lb_fe_left_ctrl(u32 frame_height)
{
return MAX_FE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16);
@@ -170,16 +191,31 @@ static inline u32 size_h264d_lb_se_top_ctrl(u32 frame_width)
return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16);
}
+static inline u32 size_h264d_lb_se_top_ctrl_ar50lt(u32 frame_width)
+{
+ return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_width, 16);
+}
+
static inline u32 size_h264d_lb_se_left_ctrl(u32 frame_height)
{
return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_height, 16);
}
+static inline u32 size_h264d_lb_se_left_ctrl_ar50lt(u32 frame_height)
+{
+ return MAX_SE_NBR_CTRL_LCU64_LINE_BUFFER_SIZE_AR50LT * DIV_ROUND_UP(frame_height, 16);
+}
+
static inline u32 size_h264d_lb_pe_top_data(u32 frame_width)
{
return MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE * DIV_ROUND_UP(frame_width, 16);
}
+static inline u32 size_h264d_lb_pe_top_data_ar50lt(u32 frame_width)
+{
+ return 64 * DIV_ROUND_UP(frame_width, 16);
+}
+
static inline u32 size_h264d_lb_vsp_top(u32 frame_width)
{
return (DIV_ROUND_UP(frame_width, 16) << 7);
@@ -289,6 +325,7 @@ u32 iris_vpu_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type)
u32 iris_vpu33_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
u32 iris_vpu4x_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
u32 iris_vpu_ar50lt_gen1_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
+u32 iris_vpu_ar50lt_gen2_buf_size(struct iris_inst *inst, enum iris_buffer_type buffer_type);
int iris_vpu_buf_count(struct iris_inst *inst, enum iris_buffer_type buffer_type);
#endif
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 13/16] media: iris: Introduce buffer size calculations for AR50LT
2026-06-12 9:25 ` [PATCH v4 13/16] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
@ 2026-06-12 10:22 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 10:22 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The AR50LT line buffer calculations ignore the `is_opb` parameter and fail to allocate the required VPSS line buffer size when split mode is enabled.
- [High] AR50LT H264 and HEVC bin buffer size calculations lack a minimum lower-bound threshold.
--
commit 3d321c841d8d8ce0ec81cd70b48ab049db102de4
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Introduce buffer size calculations for AR50LT
Introduces AR50LT buffer size calculation for both encoder and
decoder. Reuse the buffer size calculation which are common, while
adding the AR50LT specific ones separately.
> diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> index 4a39b8fef52b0..ca03d65705136 100644
> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> @@ -50,6 +50,32 @@ static u32 hfi_buffer_bin_h264d(u32 frame_width, u32 frame_height, u32 num_vpp_p
> return size_h264d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
> }
>
> +static u32 size_h264d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
> +{
> + u32 size_yuv, size_bin_hdr, size_bin_res;
> +
> + size_yuv = ((frame_width * frame_height * 3) >> 1);
> + if (size_yuv <= 1920 * 1088 * 3 / 2) {
[Severity: High]
Does this calculation lack a minimum safe threshold for size_yuv?
The generic implementations clamp the base pixel area against
BIN_BUFFER_THRESHOLD, and the AR50LT VP9 implementation correctly applies a
lower bound. If a stream with a very small resolution is provided, could
this allocate a dangerously small bin buffer and lead to hardware memory
corruption?
[ ... ]
> @@ -111,6 +152,32 @@ static u32 hfi_buffer_bin_h265d(u32 frame_width, u32 frame_height, u32 num_vpp_p
> return size_h265d_hw_bin_buffer(n_aligned_w, n_aligned_h, num_vpp_pipes);
> }
>
> +static u32 size_h265d_hw_bin_buffer_ar50lt(u32 frame_width, u32 frame_height, u32 num_vpp_pipes)
> +{
> + u32 size_yuv, size_bin_hdr, size_bin_res;
> +
> + size_yuv = ((frame_width * frame_height * 3) >> 1);
> + if (size_yuv <= ((BIN_BUFFER_THRESHOLD * 3) >> 1)) {
[Severity: High]
Similar to the H.264 case above, does this calculation also need a
lower-bound threshold applied to prevent hardware issues with extremely
small stream resolutions?
[ ... ]
> @@ -404,6 +584,29 @@ u32 hfi_buffer_line_h265d(u32 frame_width, u32 frame_height, bool is_opb, u32 nu
> return ALIGN((_size + vpss_lb_size), DMA_ALIGNMENT);
> }
>
> +static inline
> +u32 hfi_buffer_line_h265d_ar50lt(u32 frame_width, u32 frame_height, bool is_opb, u32 num_vpp_pipes)
> +{
> + u32 size;
> +
> + size = ALIGN(size_h265d_lb_fe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_h265d_lb_fe_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_h265d_lb_fe_left_ctrl(frame_width, frame_height),
> + DMA_ALIGNMENT) * num_vpp_pipes +
> + ALIGN(size_h265d_lb_se_left_ctrl_ar50lt(frame_width, frame_height),
> + DMA_ALIGNMENT) * num_vpp_pipes +
> + ALIGN(size_h265d_lb_se_top_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_h265d_lb_pe_top_data_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_h265d_lb_vsp_top(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_h265d_lb_vsp_left(frame_width, frame_height),
> + DMA_ALIGNMENT) * num_vpp_pipes +
> + ALIGN(size_h265d_lb_recon_dma_metadata_wr(frame_width, frame_height),
> + DMA_ALIGNMENT) * 4 +
> + ALIGN(size_h265d_qp(frame_width, frame_height), DMA_ALIGNMENT);
> +
> + return ALIGN(size, DMA_ALIGNMENT);
> +}
[Severity: High]
Does this function completely ignore the is_opb parameter?
In the generic hfi_buffer_line_h265d(), is_opb is used to add the VPSS line
buffer size via size_vpss_lb(). Could missing this buffer size lead to
out-of-bounds DMA memory writes when split mode is enabled and hardware
expects the additional allocation?
[ ... ]
> @@ -507,6 +734,13 @@ u32 hfi_buffer_line_vp9d(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_mi
> return _lb_size + vpss_lb_size + 4096;
> }
>
> +static inline
> +u32 hfi_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min,
> + bool is_opb, u32 num_vpp_pipes)
> +{
> + return hfi_ar50lt_vp9d_lb_size(frame_width, frame_height, num_vpp_pipes);
> +}
[Severity: High]
Similar to the HEVC case, the is_opb parameter is accepted here but unused.
Should size_vpss_lb() be factored in for VP9 line buffers as well when
split mode is active?
[ ... ]
> @@ -529,6 +763,25 @@ static u32 hfi_buffer_line_h264d(u32 frame_width, u32 frame_height,
> return ALIGN((size + vpss_lb_size), DMA_ALIGNMENT);
> }
>
> +static u32 hfi_buffer_line_h264d_ar50lt(u32 frame_width, u32 frame_height,
> + bool is_opb, u32 num_vpp_pipes)
> +{
> + u32 size;
> +
> + size = ALIGN(size_h264d_lb_fe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) +
> + ALIGN(size_h264d_lb_fe_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) +
> + ALIGN(size_h264d_lb_fe_left_ctrl(frame_height), DMA_ALIGNMENT) * num_vpp_pipes +
> + ALIGN(size_h264d_lb_se_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) +
> + ALIGN(size_h264d_lb_se_left_ctrl_ar50lt(frame_height), DMA_ALIGNMENT) *
> + num_vpp_pipes +
> + ALIGN(size_h264d_lb_pe_top_data_ar50lt(frame_width), DMA_ALIGNMENT) +
> + ALIGN(size_h264d_lb_vsp_top(frame_width), DMA_ALIGNMENT) +
> + ALIGN(size_h264d_lb_recon_dma_metadata_wr(frame_height), DMA_ALIGNMENT) * 2 +
> + ALIGN(size_h264d_qp(frame_width, frame_height), DMA_ALIGNMENT);
> +
> + return ALIGN(size, DMA_ALIGNMENT);
> +}
[Severity: High]
Once again, is_opb is ignored in this AR50LT H.264 line buffer calculation.
Does the hardware still expect the VPSS line buffer allocation when split
mode is enabled here?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=13
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 14/16] media: iris: add Gen2 firmware support on the Agatti platform
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (12 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 13/16] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 10:39 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 15/16] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
2026-06-12 9:25 ` [PATCH v4 16/16] media: iris: constify inst_fw_cap_sm8250_dec Dmitry Baryshkov
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
From: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Agatti platform is using HFI Gen1 firmware, which is considered to be
legacy firmware branch. Follow the example of the SC7280 platform and
extend the driver with supporting both HFI Gen1 and Gen2 firmwares for
this platform. Like HFI Gen1 this firmware doesn't have PIPE property
(but unlike Gen1 buffer sizes are calculated on the driver side).
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen2.c | 613 +++++++++++++++++++++
.../platform/qcom/iris/iris_platform_common.h | 1 +
.../platform/qcom/iris/iris_platform_vpu_ar50lt.c | 11 +-
3 files changed, 623 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
index acc0ed8adda1..f89245269e8c 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
@@ -1118,3 +1118,616 @@ const struct iris_firmware_data iris_hfi_gen2_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),
};
+
+static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_dec[] = {
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = PROFILE_VP9,
+ .min = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+ .max = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_PROFILE_0),
+ .value = V4L2_MPEG_VIDEO_VP9_PROFILE_0,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1),
+ .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = LEVEL_VP9,
+ .min = V4L2_MPEG_VIDEO_VP9_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_VP9_LEVEL_4_1),
+ .value = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = TIER,
+ .min = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_TIER_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_TIER_HIGH),
+ .value = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
+ .hfi_id = HFI_PROP_TIER,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_u32_enum,
+ },
+ {
+ .cap_id = INPUT_BUF_HOST_MAX_COUNT,
+ .min = DEFAULT_MAX_HOST_BUF_COUNT,
+ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
+ .step_or_mask = 1,
+ .value = DEFAULT_MAX_HOST_BUF_COUNT,
+ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
+ .flags = CAP_FLAG_INPUT_PORT,
+ .set = iris_set_u32,
+ },
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROP_STAGE,
+ .set = iris_set_stage,
+ },
+ {
+ .cap_id = POC,
+ .min = 0,
+ .max = 2,
+ .step_or_mask = 1,
+ .value = 1,
+ .hfi_id = HFI_PROP_PIC_ORDER_CNT_TYPE,
+ },
+ {
+ .cap_id = CODED_FRAMES,
+ .min = CODED_FRAMES_PROGRESSIVE,
+ .max = CODED_FRAMES_PROGRESSIVE,
+ .step_or_mask = 0,
+ .value = CODED_FRAMES_PROGRESSIVE,
+ .hfi_id = HFI_PROP_CODED_FRAMES,
+ },
+ {
+ .cap_id = BIT_DEPTH,
+ .min = BIT_DEPTH_8,
+ .max = BIT_DEPTH_8,
+ .step_or_mask = 1,
+ .value = BIT_DEPTH_8,
+ .hfi_id = HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
+ },
+ {
+ .cap_id = RAP_FRAME,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ .hfi_id = HFI_PROP_DEC_START_FROM_RAP_FRAME,
+ .flags = CAP_FLAG_INPUT_PORT,
+ .set = iris_set_u32,
+ },
+};
+
+static const struct platform_inst_fw_cap inst_fw_cap_gen2_ar50lt_enc[] = {
+ {
+ .cap_id = PROFILE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+ .max = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH),
+ .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile,
+ },
+ {
+ .cap_id = PROFILE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE),
+ .value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+ .hfi_id = HFI_PROP_PROFILE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_profile,
+ },
+ {
+ .cap_id = LEVEL_H264,
+ .min = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+ .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2),
+ .value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_level,
+ },
+ {
+ .cap_id = LEVEL_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+ .max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1),
+ .value = V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1,
+ .hfi_id = HFI_PROP_LEVEL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_level,
+ },
+ {
+ .cap_id = STAGE,
+ .min = STAGE_1,
+ .max = STAGE_2,
+ .step_or_mask = 1,
+ .value = STAGE_2,
+ .hfi_id = HFI_PROP_STAGE,
+ .set = iris_set_stage,
+ },
+ {
+ .cap_id = HEADER_MODE,
+ .min = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+ .max = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+ BIT(V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME),
+ .value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+ .hfi_id = HFI_PROP_SEQ_HEADER_MODE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_header_mode_gen2,
+ },
+ {
+ .cap_id = PREPEND_SPSPPS_TO_IDR,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ },
+ {
+ .cap_id = BITRATE,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_TOTAL_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_bitrate_gen2,
+ },
+ {
+ .cap_id = BITRATE_PEAK,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_TOTAL_PEAK_BITRATE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_peak_bitrate,
+ },
+ {
+ .cap_id = BITRATE_MODE,
+ .min = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) |
+ BIT(V4L2_MPEG_VIDEO_BITRATE_MODE_CBR),
+ .value = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+ .hfi_id = HFI_PROP_RATE_CONTROL,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_bitrate_mode_gen2,
+ },
+ {
+ .cap_id = FRAME_SKIP_MODE,
+ .min = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .max = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT) |
+ BIT(V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT),
+ .value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = FRAME_RC_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 1,
+ },
+ {
+ .cap_id = GOP_SIZE,
+ .min = 0,
+ .max = INT_MAX,
+ .step_or_mask = 1,
+ .value = 2 * DEFAULT_FPS - 1,
+ .hfi_id = HFI_PROP_MAX_GOP_FRAMES,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_u32,
+ },
+ {
+ .cap_id = ENTROPY_MODE,
+ .min = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+ .max = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC) |
+ BIT(V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC),
+ .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+ .hfi_id = HFI_PROP_CABAC_SESSION,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_entropy_mode_gen2,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_min_qp,
+ },
+ {
+ .cap_id = MIN_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ .hfi_id = HFI_PROP_MIN_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_min_qp,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_max_qp,
+ },
+ {
+ .cap_id = MAX_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ .hfi_id = HFI_PROP_MAX_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_max_qp,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = I_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = P_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = B_FRAME_MIN_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MIN_QP_8BIT_AR50LT,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = P_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = B_FRAME_MAX_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = MAX_QP,
+ },
+ {
+ .cap_id = I_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = I_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = P_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = P_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = B_FRAME_QP_H264,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = B_FRAME_QP_HEVC,
+ .min = MIN_QP_8BIT_AR50LT,
+ .max = MAX_QP,
+ .step_or_mask = 1,
+ .value = DEFAULT_QP,
+ .hfi_id = HFI_PROP_QP_PACKED,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_frame_qp,
+ },
+ {
+ .cap_id = INPUT_BUF_HOST_MAX_COUNT,
+ .min = DEFAULT_MAX_HOST_BUF_COUNT,
+ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
+ .step_or_mask = 1,
+ .value = DEFAULT_MAX_HOST_BUF_COUNT,
+ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
+ .flags = CAP_FLAG_INPUT_PORT,
+ .set = iris_set_u32,
+ },
+ {
+ .cap_id = OUTPUT_BUF_HOST_MAX_COUNT,
+ .min = DEFAULT_MAX_HOST_BUF_COUNT,
+ .max = DEFAULT_MAX_HOST_BURST_BUF_COUNT,
+ .step_or_mask = 1,
+ .value = DEFAULT_MAX_HOST_BUF_COUNT,
+ .hfi_id = HFI_PROP_BUFFER_HOST_MAX_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_u32,
+ },
+ {
+ .cap_id = IR_TYPE,
+ .min = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
+ .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
+ .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM),
+ .value = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = IR_PERIOD,
+ .min = 0,
+ .max = INT_MAX,
+ .step_or_mask = 1,
+ .value = 0,
+ .flags = CAP_FLAG_OUTPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_ir_period_gen2,
+ },
+};
+
+static const u32 iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl[] = {
+ BUF_BIN,
+ BUF_COMV,
+ BUF_NON_COMV,
+ BUF_LINE,
+};
+
+const struct iris_firmware_data iris_hfi_gen2_ar50lt_data = {
+ .init_hfi_ops = iris_hfi_gen2_sys_ops_init,
+
+ .core_arch = VIDEO_ARCH_LX,
+
+ .inst_fw_caps_dec = inst_fw_cap_gen2_ar50lt_dec,
+ .inst_fw_caps_dec_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_dec),
+ .inst_fw_caps_enc = inst_fw_cap_gen2_ar50lt_enc,
+ .inst_fw_caps_enc_size = ARRAY_SIZE(inst_fw_cap_gen2_ar50lt_enc),
+ .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),
+ .dec_output_config_params =
+ sm8550_vdec_output_config_params,
+ .dec_output_config_params_size =
+ ARRAY_SIZE(sm8550_vdec_output_config_params),
+ .enc_input_config_params =
+ sm8550_venc_input_config_params,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(sm8550_venc_input_config_params),
+ .enc_output_config_params =
+ sm8550_venc_output_config_params,
+ .enc_output_config_params_size =
+ ARRAY_SIZE(sm8550_venc_output_config_params),
+ .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),
+ .dec_ip_int_buf_tbl = iris_hfi_gen2_ar50lt_dec_ip_int_buf_tbl,
+ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen2_ar50lt_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_ip_int_buf_tbl = sm8550_enc_ip_int_buf_tbl,
+ .enc_ip_int_buf_tbl_size = ARRAY_SIZE(sm8550_enc_ip_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),
+};
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index bc04831ae7fc..5afe395cc4a0 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -57,6 +57,7 @@ enum pipe_type {
extern const struct iris_firmware_data iris_hfi_gen1_data;
extern const struct iris_firmware_data iris_hfi_gen1_ar50lt_data;
extern const struct iris_firmware_data iris_hfi_gen2_data;
+extern const struct iris_firmware_data iris_hfi_gen2_ar50lt_data;
extern const struct iris_platform_data qcm2290_data;
extern const struct iris_platform_data qcs8300_data;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
index 393256f39112..d9de7dcb59e3 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
@@ -13,12 +13,18 @@
#define WRAPPER_INTR_STATUS_A2HWD_BMSK 0x10
-const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_s6_desc = {
+const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_desc = {
.firmware_data = &iris_hfi_gen1_ar50lt_data,
.get_vpu_buffer_size = iris_vpu_ar50lt_gen1_buf_size,
.fwname = "qcom/venus-6.0/venus.mbn",
};
+const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen2_s6_desc = {
+ .firmware_data = &iris_hfi_gen2_ar50lt_data,
+ .get_vpu_buffer_size = iris_vpu_ar50lt_gen2_buf_size,
+ .fwname = "qcom/vpu/ar50lt_p1_gen2_s6.mbn",
+};
+
static const u32 iris_fmts_ar50lt_dec[] = {
[IRIS_FMT_H264] = V4L2_PIX_FMT_H264,
[IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC,
@@ -78,7 +84,8 @@ static struct platform_inst_caps platform_inst_cap_ar50lt = {
};
const struct iris_platform_data qcm2290_data = {
- .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_s6_desc,
+ .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_desc,
+ .firmware_desc_gen2 = &iris_vpu_ar50lt_p1_gen2_s6_desc,
.vpu_ops = &iris_vpu_ar50lt_ops,
.icc_tbl = iris_icc_info_ar50lt,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_ar50lt),
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 14/16] media: iris: add Gen2 firmware support on the Agatti platform
2026-06-12 9:25 ` [PATCH v4 14/16] media: iris: add Gen2 firmware support on the Agatti platform Dmitry Baryshkov
@ 2026-06-12 10:39 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 10:39 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The `qcm2290_data` struct initialization assigns values to non-existent members `.firmware_desc_gen1` and `.firmware_desc_gen2`, causing a build failure. Additionally, the required `.firmware_desc` member is left uninitialized, leading to a NULL pointer dereference during probe.
--
commit 4f1d2454209dec3530526e228c0b4e78b6170ab3
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: add Gen2 firmware support on the Agatti platform
Agatti platform is using HFI Gen1 firmware, which is considered to be
legacy firmware branch. Follow the example of the SC7280 platform and
extend the driver with supporting both HFI Gen1 and Gen2 firmwares for
this platform. Like HFI Gen1 this firmware doesn't have PIPE property
(but unlike Gen1 buffer sizes are calculated on the driver side).
> diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
> index 393256f39112b..d9de7dcb59e3a 100644
> --- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
> +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
[ ... ]
> @@ -78,7 +84,8 @@ static struct platform_inst_caps platform_inst_cap_ar50lt = {
> };
>
> const struct iris_platform_data qcm2290_data = {
> - .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_s6_desc,
> + .firmware_desc_gen1 = &iris_vpu_ar50lt_p1_gen1_desc,
> + .firmware_desc_gen2 = &iris_vpu_ar50lt_p1_gen2_s6_desc,
[Severity: Low]
Does this cause a build failure? struct iris_platform_data does not
currently contain a firmware_desc_gen2 field (nor a firmware_desc_gen1
field).
Looking at drivers/media/platform/qcom/iris/iris_platform_common.h:
struct iris_platform_data {
/*
* XXX: replace with gen1 / gen2 pointers once we have platforms
* supporting both firmware kinds.
*/
const struct iris_firmware_desc *firmware_desc;
If these fields were added to bypass the build failure, wouldn't this
initialization leave the required firmware_desc field uninitialized?
This could result in a null pointer dereference during probe:
drivers/media/platform/qcom/iris/iris_probe.c:iris_probe()
core->iris_firmware_desc = core->iris_platform_data->firmware_desc;
core->iris_firmware_data = core->iris_firmware_desc->firmware_data;
> .vpu_ops = &iris_vpu_ar50lt_ops,
> .icc_tbl = iris_icc_info_ar50lt,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=14
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 15/16] media: venus: skip QCM2290 if Iris driver is enabled
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (13 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 14/16] media: iris: add Gen2 firmware support on the Agatti platform Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
2026-06-12 10:33 ` sashiko-bot
2026-06-12 9:25 ` [PATCH v4 16/16] media: iris: constify inst_fw_cap_sm8250_dec Dmitry Baryshkov
15 siblings, 1 reply; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
As the Iris driver now supports the QCM2290 hardware too, there is a
race between Venus and Iris drivers on binding to the corresponding
device. Follow the approach used by other platforms and skip QCM2290 in
the Venus driver if Iris is enabled.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
---
drivers/media/platform/qcom/venus/core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 243e342b0ae7..3c88594eb1d0 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -1118,7 +1118,6 @@ static const struct venus_resources sc7280_res = {
.dec_nodename = "video-decoder",
.enc_nodename = "video-encoder",
};
-#endif
static const struct bw_tbl qcm2290_bw_table_dec[] = {
{ 352800, 597000, 0, 746000, 0 }, /* 1080p@30 + 720p@30 */
@@ -1169,13 +1168,16 @@ static const struct venus_resources qcm2290_res = {
.enc_nodename = "video-encoder",
.min_fw = &min_fw,
};
+#endif
static const struct of_device_id venus_dt_match[] = {
{ .compatible = "qcom,msm8916-venus", .data = &msm8916_res, },
{ .compatible = "qcom,msm8939-venus", .data = &msm8939_res, },
{ .compatible = "qcom,msm8996-venus", .data = &msm8996_res, },
{ .compatible = "qcom,msm8998-venus", .data = &msm8998_res, },
+#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_IRIS))
{ .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, },
+#endif
{ .compatible = "qcom,sc7180-venus", .data = &sc7180_res, },
{ .compatible = "qcom,sdm660-venus", .data = &sdm660_res, },
{ .compatible = "qcom,sdm845-venus", .data = &sdm845_res, },
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread* Re: [PATCH v4 15/16] media: venus: skip QCM2290 if Iris driver is enabled
2026-06-12 9:25 ` [PATCH v4 15/16] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
@ 2026-06-12 10:33 ` sashiko-bot
0 siblings, 0 replies; 27+ messages in thread
From: sashiko-bot @ 2026-06-12 10:33 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Use-after-free of `hdev` in the IRQ handler due to incorrect teardown sequence.
--
commit a490235af4b563cc6644730f4c262f25f52e330a
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: venus: skip QCM2290 if Iris driver is enabled
As the Iris driver now supports the QCM2290 hardware too, there is a
race between Venus and Iris drivers on binding to the corresponding
device. Follow the approach used by other platforms and skip QCM2290 in
the Venus driver if Iris is enabled.
> diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
> index 243e342b0ae75..3c88594eb1d00 100644
> --- a/drivers/media/platform/qcom/venus/core.c
> +++ b/drivers/media/platform/qcom/venus/core.c
[ ... ]
> @@ -1169,13 +1168,16 @@ static const struct venus_resources qcm2290_res = {
> .enc_nodename = "video-encoder",
> .min_fw = &min_fw,
> };
> +#endif
>
> static const struct of_device_id venus_dt_match[] = {
> { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, },
> { .compatible = "qcom,msm8939-venus", .data = &msm8939_res, },
> { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, },
> { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, },
> +#if (!IS_ENABLED(CONFIG_VIDEO_QCOM_IRIS))
> { .compatible = "qcom,qcm2290-venus", .data = &qcm2290_res, },
> +#endif
> { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, },
> { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, },
> { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, },
[Severity: High]
This is a pre-existing issue, but could there be a use-after-free risk during
teardown in venus_hfi_destroy()?
In drivers/media/platform/qcom/venus/hfi_venus.c:venus_hfi_destroy(), hdev is
freed and its lock is destroyed before the IRQ is disabled:
void venus_hfi_destroy(struct venus_core *core)
{
struct venus_hfi_device *hdev = to_hfi_priv(core);
core->priv = NULL;
venus_interface_queues_release(hdev);
mutex_destroy(&hdev->lock);
kfree(hdev);
disable_irq(core->irq);
core->ops = NULL;
}
If a threaded interrupt (venus_isr_thread) is already running or scheduled
concurrently, could it pass the initial if (!hdev) check before core->priv
is set to NULL, and then access the freed hdev structure?
drivers/media/platform/qcom/venus/hfi_venus.c:venus_isr_thread()
{
struct venus_hfi_device *hdev = to_hfi_priv(core);
...
if (!hdev)
return IRQ_NONE;
...
pkt = hdev->pkt_buf;
while (!venus_iface_msgq_read(hdev, pkt)) {
...
}
Because disable_irq() waits for currently executing handlers to complete,
should it be called before freeing the structures the handler depends on?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612-iris-ar50lt-v4-0-0abfb74d5b3c@oss.qualcomm.com?part=15
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 16/16] media: iris: constify inst_fw_cap_sm8250_dec
2026-06-12 9:25 [PATCH v4 00/16] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (14 preceding siblings ...)
2026-06-12 9:25 ` [PATCH v4 15/16] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
@ 2026-06-12 9:25 ` Dmitry Baryshkov
15 siblings, 0 replies; 27+ messages in thread
From: Dmitry Baryshkov @ 2026-06-12 9:25 UTC (permalink / raw)
To: Vikash Garodia, Abhinav Kumar, Bryan O'Donoghue,
Mauro Carvalho Chehab, Bjorn Andersson, Konrad Dybcio,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Vishnu Reddy
Cc: linux-media, linux-arm-msm, linux-kernel, devicetree,
Dikshita Agarwal
Mark inst_fw_cap_sm8250_dec as a const array, the data is read-only.
Suggested-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_hfi_gen1.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
index f57af31dbd9f..a8819470f703 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
@@ -13,7 +13,7 @@
#define BITRATE_MAX 160000000
#define BITRATE_STEP 100
-static struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
+static const struct platform_inst_fw_cap inst_fw_cap_sm8250_dec[] = {
{
.cap_id = PIPE,
/* .max, .min and .value are set via platform data */
--
2.47.3
^ permalink raw reply related [flat|nested] 27+ messages in thread