* [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:37 ` sashiko-bot
2026-07-30 20:02 ` Bryan O'Donoghue
2026-07-30 15:20 ` [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported Dmitry Baryshkov
` (17 subsequent siblings)
18 siblings, 2 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
Some Iris platforms support both Gen1 and Gen2 HFI firmware images.
Update the firmware loading logic to handle this generically by
preferring Gen2 when available, while safely falling back to Gen1
when required.
The firmware loading logic is updated with the following priority:
1. Device Tree (`firmware-name`): If specified, load unconditionally.
2. Gen2 default : If no DT override exists, select the Gen2 firmware
descriptor when present and attempt to load the corresponding
firmware image.
3. Gen1 Fallback: If loading the Gen2 firmware fails and a Gen1
descriptor is available, retry with the Gen1 firmware image.
Loading and generation detection are split into two steps.
iris_load_firmware() applies the priority above and returns the loaded
image together with a candidate descriptor. iris_detect_firmware() then
runs only after qcom_mdt_load() has succeeded and publishes the chosen
descriptor, so the driver commits to a HFI generation only for an image
that has actually been loaded.
When a platform provides both Gen1 and Gen2 firmware descriptors and the
firmware is loaded via a DT override, the candidate descriptor is only a
default: iris_detect_firmware() inspects the loaded image to pick the
generation, before authentication. It scans the memory populated by
qcom_mdt_load() rather than the request_firmware() blob, so that a split
.mdt image, whose version string lives in the .bNN data segments and not
in the ELF headers, is classified correctly. The firmware is classified
as Gen2 if the QC_IMAGE_VERSION_STRING starts with "vfw" or matches the
"video-firmware.N.M" format with N >= 2.
If a Gen1 firmware image is detected in this case, the driver switches
to the Gen1 firmware descriptor and associated platform data so that
the correct HFI implementation is used.
This change makes firmware generation detection platform‑agnostic,
preserves DT overrides, prefers newer Gen2 firmware when available,
and maintains compatibility with platforms that only support Gen1.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Co-developed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_core.c | 2 +
drivers/media/platform/qcom/iris/iris_firmware.c | 186 +++++++++++++++++++--
.../platform/qcom/iris/iris_platform_common.h | 6 +-
.../media/platform/qcom/iris/iris_platform_vpu2.c | 11 +-
.../media/platform/qcom/iris/iris_platform_vpu3x.c | 10 +-
drivers/media/platform/qcom/iris/iris_probe.c | 4 -
drivers/media/platform/qcom/iris/iris_vidc.c | 1 +
7 files changed, 186 insertions(+), 34 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
index 52bf56e517f9..6dbe18be5b49 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -6,6 +6,7 @@
#include <linux/pm_runtime.h>
#include "iris_core.h"
+#include "iris_ctrls.h"
#include "iris_firmware.h"
#include "iris_state.h"
#include "iris_vpu_common.h"
@@ -79,6 +80,7 @@ int iris_core_init(struct iris_core *core)
goto error_unload_fw;
core->iris_firmware_data->init_hfi_ops(core);
+ iris_session_init_caps(core);
ret = iris_hfi_core_init(core);
if (ret)
diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c
index 1a476146d758..c5d2b9fd0502 100644
--- a/drivers/media/platform/qcom/iris/iris_firmware.c
+++ b/drivers/media/platform/qcom/iris/iris_firmware.c
@@ -14,22 +14,175 @@
#define IRIS_PAS_ID 9
-#define MAX_FIRMWARE_NAME_SIZE 128
+/* Detect Gen2 firmware by scanning the blob for:
+ * QC_IMAGE_VERSION_STRING=<version>
+ * and then checking:
+ * - version starts with "vfw", OR
+ * - version matches "video-firmware.N.M" with N >= 2
+ */
+
+static bool iris_detect_gen2_from_fwdata(const u8 *data, size_t size)
+{
+ static const char *marker = "QC_IMAGE_VERSION_STRING=";
+ const size_t mlen = strlen(marker);
+ static const char *vfw = "vfw";
+ const size_t vfwlen = strlen(vfw);
+ static const char *vf = "video-firmware.";
+ const size_t vflen = strlen(vf);
+
+ for (size_t i = 0; i + mlen < size; i++) {
+ const char *found;
+
+ if (memcmp(data + i, marker, mlen))
+ continue;
+
+ found = data + i + mlen;
+ size -= i + mlen;
+
+ /* vfw => Gen2 */
+ if (size > vfwlen && !memcmp(found, vfw, vfwlen))
+ return true;
+
+ if (size < vflen ||
+ memcmp(found, vf, vflen))
+ return false;
+
+ found += vflen;
+ size -= vflen;
+
+ /*
+ * video-firmware.1.x is Gen1.
+ * video-firmware.2.x and video-firmware.10.x are Gen2.
+ */
+ return size >= 2 &&
+ (*found >= '2' || (*found == '1' && found[1] != '.'));
+ }
+
+ return false;
+}
+
+/*
+ * Load the firmware image and return the descriptor that was used to pick the
+ * file. On a platform that provides only one generation, or when no DT
+ * firmware-name override is present, the returned descriptor is final. With a
+ * DT override on a dual-generation platform the returned descriptor is only a
+ * default; iris_detect_firmware() inspects the loaded image to confirm it.
+ */
+static const struct firmware *iris_load_firmware(struct iris_core *core,
+ const char **fw_name,
+ const struct iris_firmware_desc **fw_desc)
+{
+ const struct iris_firmware_desc *desc;
+ const struct firmware *firmware;
+ bool has_both_gens;
+ int ret;
+
+ *fw_name = NULL;
+ ret = of_property_read_string_index(dev_of_node(core->dev), "firmware-name", 0, fw_name);
+
+ /*
+ * A platform may support both Gen1 and Gen2 firmware; which one is used
+ * depends on the firmware image installed on the system, not on the
+ * hardware. That installed image does not change while the device is
+ * bound, so the generation is detected only once and the chosen
+ * descriptor is reused on later core bring-ups (e.g. after a system
+ * error recovery).
+ */
+ if (core->iris_firmware_desc) {
+ if (ret)
+ *fw_name = core->iris_firmware_desc->fwname;
+ ret = request_firmware(&firmware, *fw_name, core->dev);
+ if (ret)
+ return ERR_PTR(ret);
+ *fw_desc = core->iris_firmware_desc;
+ return firmware;
+ }
+
+ has_both_gens = core->iris_platform_data->firmware_desc_gen2 &&
+ core->iris_platform_data->firmware_desc_gen1;
+
+ if (core->iris_platform_data->firmware_desc_gen2)
+ desc = core->iris_platform_data->firmware_desc_gen2;
+ else if (core->iris_platform_data->firmware_desc_gen1)
+ desc = core->iris_platform_data->firmware_desc_gen1;
+ else
+ return ERR_PTR(-EINVAL);
-static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
+ if (ret) {
+ /* No firmware-name in DT: select by probing Gen2 then Gen1. */
+ *fw_name = desc->fwname;
+ if (has_both_gens)
+ ret = firmware_request_nowarn(&firmware, *fw_name, core->dev);
+ else
+ ret = request_firmware(&firmware, *fw_name, core->dev);
+ if (ret && has_both_gens) {
+ desc = core->iris_platform_data->firmware_desc_gen1;
+ *fw_name = desc->fwname;
+ ret = request_firmware(&firmware, *fw_name, core->dev);
+ }
+ } else {
+ /* firmware-name given: iris_detect_firmware() picks the gen. */
+ ret = request_firmware(&firmware, *fw_name, core->dev);
+ }
+ if (ret)
+ return ERR_PTR(ret);
+
+ *fw_desc = desc;
+ return firmware;
+}
+
+/*
+ * Detect the firmware generation and publish the descriptor. Run only after
+ * qcom_mdt_load() has succeeded, so the driver commits to a HFI generation
+ * only for a firmware image that has actually been loaded.
+ *
+ * The generation is detected from the loaded image (@data / @size point at the
+ * reserved memory region populated by qcom_mdt_load()) rather than from the
+ * request_firmware() blob: for a split .mdt the latter holds only the ELF
+ * headers, while QC_IMAGE_VERSION_STRING lives in the .bNN data segments.
+ *
+ * The descriptor and firmware data are published exactly once, before any
+ * session exists, so the lockless readers in the ioctl paths never observe a
+ * reassignment. Later bring-ups reuse the already published descriptor.
+ */
+static void iris_detect_firmware(struct iris_core *core, const char *fw_name,
+ const u8 *data, size_t size,
+ const struct iris_firmware_desc *desc)
{
+ if (core->iris_firmware_desc)
+ return;
+
+ /*
+ * With a DT firmware-name override on a dual-generation platform the
+ * image on disk decides the generation, so inspect it and switch to the
+ * Gen1 descriptor when a Gen1 image was loaded.
+ */
+ if (desc == core->iris_platform_data->firmware_desc_gen2 &&
+ core->iris_platform_data->firmware_desc_gen1 &&
+ of_property_present(dev_of_node(core->dev), "firmware-name") &&
+ !iris_detect_gen2_from_fwdata(data, size)) {
+ dev_info(core->dev, "Gen1 FW detected in %s\n", fw_name);
+ desc = core->iris_platform_data->firmware_desc_gen1;
+ }
+
+ /* Publish iris_firmware_data first, then iris_firmware_desc (the guard). */
+ core->iris_firmware_data = desc->firmware_data;
+ core->iris_firmware_desc = desc;
+}
+
+static int iris_load_fw_to_memory(struct iris_core *core)
+{
+ const struct iris_firmware_desc *desc;
const struct firmware *firmware = NULL;
struct device *dev = core->dev;
struct resource res;
phys_addr_t mem_phys;
+ const char *fw_name;
size_t res_size;
ssize_t fw_size;
void *mem_virt;
int ret;
- if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4)
- return -EINVAL;
-
ret = of_reserved_mem_region_to_resource(dev->of_node, 0, &res);
if (ret)
return ret;
@@ -37,9 +190,9 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
mem_phys = res.start;
res_size = resource_size(&res);
- ret = request_firmware(&firmware, fw_name, dev);
- if (ret)
- return ret;
+ firmware = iris_load_firmware(core, &fw_name, &desc);
+ if (IS_ERR(firmware))
+ return PTR_ERR(firmware);
fw_size = qcom_mdt_get_size(firmware);
if (fw_size < 0 || res_size < (size_t)fw_size) {
@@ -56,6 +209,9 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
ret = qcom_mdt_load(dev, firmware, fw_name,
IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL);
+ if (!ret)
+ iris_detect_firmware(core, fw_name, mem_virt, res_size, desc);
+
memunmap(mem_virt);
err_release_fw:
release_firmware(firmware);
@@ -66,18 +222,12 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
int iris_fw_load(struct iris_core *core)
{
const struct tz_cp_config *cp_config;
- const char *fwpath = NULL;
int i, ret;
- ret = of_property_read_string_index(core->dev->of_node, "firmware-name", 0,
- &fwpath);
- if (ret)
- fwpath = core->iris_firmware_desc->fwname;
-
- ret = iris_load_fw_to_memory(core, fwpath);
+ ret = iris_load_fw_to_memory(core);
if (ret) {
- dev_err(core->dev, "firmware download failed\n");
- return -ENOMEM;
+ dev_err(core->dev, "firmware download failed %d\n", ret);
+ return ret;
}
ret = qcom_scm_pas_auth_and_reset(IRIS_PAS_ID);
@@ -99,7 +249,7 @@ int iris_fw_load(struct iris_core *core)
}
}
- return ret;
+ return 0;
}
int iris_fw_unload(struct iris_core *core)
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index c9256f2323dc..55a4fa356985 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_common.h
+++ b/drivers/media/platform/qcom/iris/iris_platform_common.h
@@ -289,11 +289,7 @@ struct iris_firmware_desc {
};
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;
+ const struct iris_firmware_desc *firmware_desc_gen1, *firmware_desc_gen2;
const struct vpu_ops *vpu_ops;
const struct icc_info *icc_tbl;
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
index 6e06a32822bb..961dce2e6aa9 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
@@ -22,6 +22,12 @@ static const struct iris_firmware_desc iris_vpu20_p1_gen1_desc = {
.fwname = "qcom/vpu/vpu20_p1.mbn",
};
+static const struct iris_firmware_desc iris_vpu20_p1_gen2_s6_desc = {
+ .firmware_data = &iris_hfi_gen2_data,
+ .get_vpu_buffer_size = iris_vpu33_buf_size,
+ .fwname = "qcom/vpu/vpu20_p1_gen2_s6.mbn",
+};
+
static const struct iris_firmware_desc iris_vpu20_p4_gen1_desc = {
.firmware_data = &iris_hfi_gen1_data,
.get_vpu_buffer_size = iris_vpu_buf_size,
@@ -65,7 +71,8 @@ static const struct tz_cp_config tz_cp_config_vpu2[] = {
};
const struct iris_platform_data sc7280_data = {
- .firmware_desc = &iris_vpu20_p1_gen1_desc,
+ .firmware_desc_gen1 = &iris_vpu20_p1_gen1_desc,
+ .firmware_desc_gen2 = &iris_vpu20_p1_gen2_s6_desc,
.vpu_ops = &iris_vpu2_ops,
.icc_tbl = iris_icc_info_vpu2,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2),
@@ -94,7 +101,7 @@ const struct iris_platform_data sc7280_data = {
};
const struct iris_platform_data sm8250_data = {
- .firmware_desc = &iris_vpu20_p4_gen1_desc,
+ .firmware_desc_gen1 = &iris_vpu20_p4_gen1_desc,
.vpu_ops = &iris_vpu2_ops,
.icc_tbl = iris_icc_info_vpu2,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu2),
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
index 2c63adbc5579..74626b35d9cb 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
@@ -90,7 +90,7 @@ static const struct tz_cp_config tz_cp_config_vpu3[] = {
* - inst_caps to platform_inst_cap_qcs8300
*/
const struct iris_platform_data qcs8300_data = {
- .firmware_desc = &iris_vpu30_p4_s6_gen2_desc,
+ .firmware_desc_gen2 = &iris_vpu30_p4_s6_gen2_desc,
.vpu_ops = &iris_vpu3_ops,
.icc_tbl = iris_icc_info_vpu3x,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x),
@@ -119,7 +119,7 @@ const struct iris_platform_data qcs8300_data = {
};
const struct iris_platform_data sm8550_data = {
- .firmware_desc = &iris_vpu30_p4_gen2_desc,
+ .firmware_desc_gen2 = &iris_vpu30_p4_gen2_desc,
.vpu_ops = &iris_vpu3_ops,
.icc_tbl = iris_icc_info_vpu3x,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x),
@@ -154,7 +154,7 @@ const struct iris_platform_data sm8550_data = {
* - controller_rst_tbl to sm8650_controller_reset_table
*/
const struct iris_platform_data sm8650_data = {
- .firmware_desc = &iris_vpu33_p4_gen2_desc,
+ .firmware_desc_gen2 = &iris_vpu33_p4_gen2_desc,
.vpu_ops = &iris_vpu33_ops,
.icc_tbl = iris_icc_info_vpu3x,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x),
@@ -185,7 +185,7 @@ const struct iris_platform_data sm8650_data = {
};
const struct iris_platform_data sm8750_data = {
- .firmware_desc = &iris_vpu35_p4_gen2_desc,
+ .firmware_desc_gen2 = &iris_vpu35_p4_gen2_desc,
.vpu_ops = &iris_vpu35_ops,
.icc_tbl = iris_icc_info_vpu3x,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x),
@@ -220,7 +220,7 @@ const struct iris_platform_data sm8750_data = {
* - different num_vpp_pipe
*/
const struct iris_platform_data x1p42100_data = {
- .firmware_desc = &iris_vpu30_p1_gen2_desc,
+ .firmware_desc_gen2 = &iris_vpu30_p1_gen2_desc,
.vpu_ops = &iris_vpu3_ops,
.icc_tbl = iris_icc_info_vpu3x,
.icc_tbl_size = ARRAY_SIZE(iris_icc_info_vpu3x),
diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
index c2dcb50a2782..7fe31136df21 100644
--- a/drivers/media/platform/qcom/iris/iris_probe.c
+++ b/drivers/media/platform/qcom/iris/iris_probe.c
@@ -251,8 +251,6 @@ static int iris_probe(struct platform_device *pdev)
return core->irq;
core->iris_platform_data = of_device_get_match_data(core->dev);
- core->iris_firmware_desc = core->iris_platform_data->firmware_desc;
- core->iris_firmware_data = core->iris_firmware_desc->firmware_data;
core->ubwc_cfg = qcom_ubwc_config_get_data();
if (IS_ERR(core->ubwc_cfg))
@@ -271,8 +269,6 @@ static int iris_probe(struct platform_device *pdev)
if (ret)
return ret;
- iris_session_init_caps(core);
-
ret = v4l2_device_register(dev, &core->v4l2_dev);
if (ret)
return ret;
diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c b/drivers/media/platform/qcom/iris/iris_vidc.c
index 14d63dc76c9b..33edbc5cab8f 100644
--- a/drivers/media/platform/qcom/iris/iris_vidc.c
+++ b/drivers/media/platform/qcom/iris/iris_vidc.c
@@ -9,6 +9,7 @@
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>
+#include "iris_ctrls.h"
#include "iris_vidc.h"
#include "iris_instance.h"
#include "iris_vdec.h"
--
2.47.3
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback
2026-07-30 15:20 ` [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback Dmitry Baryshkov
@ 2026-07-30 15:37 ` sashiko-bot
2026-07-30 20:02 ` Bryan O'Donoghue
1 sibling, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:37 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, conor+dt, devicetree, media-ci
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Uninitialized memory scan in firmware generation detection.
Pre-existing issues:
- [High] Kernel crash: IRQ is enabled before the HFI ops are initialized, leading to a NULL pointer dereference on early interrupts.
- [High] Use-After-Free of `iris_core` due to uncancelled delayed work during module teardown.
- [High] Race condition in `iris_open` allows concurrent callers to bypass the hardware initialization wait.
--
--- Patch [1]: [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback ---
commit a2c8d521a685de60d5919ebd8f396f7a268a25cc
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Add Gen2 firmware autodetect and fallback
Some Iris platforms support both Gen1 and Gen2 HFI firmware images.
Update the firmware loading logic to handle this generically by
preferring Gen2 when available, while safely falling back to Gen1
when required.
[ ... ]
> diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
> index 52bf56e517f91..6dbe18be5b495 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.c
> +++ b/drivers/media/platform/qcom/iris/iris_core.c
> @@ -79,6 +80,7 @@ int iris_core_init(struct iris_core *core)
> goto error_unload_fw;
>
> core->iris_firmware_data->init_hfi_ops(core);
[Severity: High]
This isn't a bug introduced by this patch, but could this initialization
sequence cause a NULL pointer dereference on early interrupts?
In iris_core_init(), iris_vpu_power_on() is called earlier, which unmasks the
interrupt via enable_irq(core->irq). At that point, core->hfi_sys_ops is still
NULL because init_hfi_ops() hasn't run yet.
If an interrupt fires early (for example, from the VPU firmware booting),
iris_hfi_isr_handler() will execute and unconditionally dereference
core->hfi_sys_ops->sys_hfi_response_handler. Should init_hfi_ops() be called
before enabling the IRQ?
[Severity: High]
This is a pre-existing issue, but does this function have a race condition that
allows concurrent callers to bypass the hardware initialization wait?
When a user opens the device, iris_core_init() acquires the lock, sets
core->state = IRIS_CORE_INIT, drops the lock, and then proceeds with the
lengthy initialization and iris_wait_for_system_response().
If a concurrent thread calls iris_open() and acquires the lock, it will see
core->state == IRIS_CORE_INIT, immediately return 0, and proceed to interact
with the hardware before the firmware has actually finished booting. Could this
lead to undefined behavior?
> + iris_session_init_caps(core);
>
> ret = iris_hfi_core_init(core);
> if (ret)
[ ... ]
> diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c
> index 1a476146d7580..c5d2b9fd0502e 100644
> --- a/drivers/media/platform/qcom/iris/iris_firmware.c
> +++ b/drivers/media/platform/qcom/iris/iris_firmware.c
[ ... ]
> @@ -56,6 +209,9 @@ static int iris_load_fw_to_memory(struct iris_core *core, const char *fw_name)
> ret = qcom_mdt_load(dev, firmware, fw_name,
> IRIS_PAS_ID, mem_virt, mem_phys, res_size, NULL);
>
> + if (!ret)
> + iris_detect_firmware(core, fw_name, mem_virt, res_size, desc);
[Severity: High]
Could this scan uninitialized memory?
The memory region is mapped via memremap() using MEMREMAP_WC without being
zeroed, meaning it could retain contents from a previous boot or firmware load.
qcom_mdt_load() populates the memory but might leave gaps or leave the tail
end untouched.
Since iris_detect_firmware() is called with the total reserved memory size
(res_size) rather than the actual loaded firmware size, could the loop in
iris_detect_gen2_from_fwdata() scan past the valid loaded data and falsely
detect a leftover QC_IMAGE_VERSION_STRING from an older firmware?
> +
> memunmap(mem_virt);
> err_release_fw:
> release_firmware(firmware);
[ ... ]
> diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c
> index c2dcb50a27824..7fe31136df21b 100644
> --- a/drivers/media/platform/qcom/iris/iris_probe.c
> +++ b/drivers/media/platform/qcom/iris/iris_probe.c
> @@ -251,8 +251,6 @@ static int iris_probe(struct platform_device *pdev)
> return core->irq;
[Severity: High]
This is a pre-existing issue, but does the module teardown path leak a running
delayed work, leading to a use-after-free?
iris_probe() initializes a delayed work sys_error_handler which uses the core
pointer. In the teardown path, iris_remove() unregisters devices but does not
seem to call cancel_delayed_work_sync(&core->sys_error_handler).
Since the core struct is managed by devm_kzalloc, it is freed when
iris_remove() returns. If the delayed work was scheduled and runs after
removal, won't it dereference the freed core pointer?
> core->iris_platform_data = of_device_get_match_data(core->dev);
> - core->iris_firmware_desc = core->iris_platform_data->firmware_desc;
> - core->iris_firmware_data = core->iris_firmware_desc->firmware_data;
>
> core->ubwc_cfg = qcom_ubwc_config_get_data();
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback
2026-07-30 15:20 ` [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback Dmitry Baryshkov
2026-07-30 15:37 ` sashiko-bot
@ 2026-07-30 20:02 ` Bryan O'Donoghue
1 sibling, 0 replies; 32+ messages in thread
From: Bryan O'Donoghue @ 2026-07-30 20:02 UTC (permalink / raw)
To: Dmitry Baryshkov, Vikash Garodia, Abhinav Kumar,
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
On 30/07/2026 16:20, Dmitry Baryshkov wrote:
> From: Dikshita Agarwal<dikshita.agarwal@oss.qualcomm.com>
>
> Some Iris platforms support both Gen1 and Gen2 HFI firmware images.
> Update the firmware loading logic to handle this generically by
> preferring Gen2 when available, while safely falling back to Gen1
> when required.
>
> The firmware loading logic is updated with the following priority:
> 1. Device Tree (`firmware-name`): If specified, load unconditionally.
> 2. Gen2 default : If no DT override exists, select the Gen2 firmware
> descriptor when present and attempt to load the corresponding
> firmware image.
> 3. Gen1 Fallback: If loading the Gen2 firmware fails and a Gen1
> descriptor is available, retry with the Gen1 firmware image.
>
> Loading and generation detection are split into two steps.
> iris_load_firmware() applies the priority above and returns the loaded
> image together with a candidate descriptor. iris_detect_firmware() then
> runs only after qcom_mdt_load() has succeeded and publishes the chosen
> descriptor, so the driver commits to a HFI generation only for an image
> that has actually been loaded.
>
> When a platform provides both Gen1 and Gen2 firmware descriptors and the
> firmware is loaded via a DT override, the candidate descriptor is only a
> default: iris_detect_firmware() inspects the loaded image to pick the
> generation, before authentication. It scans the memory populated by
> qcom_mdt_load() rather than the request_firmware() blob, so that a split
> .mdt image, whose version string lives in the .bNN data segments and not
> in the ELF headers, is classified correctly. The firmware is classified
> as Gen2 if the QC_IMAGE_VERSION_STRING starts with "vfw" or matches the
> "video-firmware.N.M" format with N >= 2.
>
> If a Gen1 firmware image is detected in this case, the driver switches
> to the Gen1 firmware descriptor and associated platform data so that
> the correct HFI implementation is used.
>
> This change makes firmware generation detection platform‑agnostic,
> preserves DT overrides, prefers newer Gen2 firmware when available,
> and maintains compatibility with platforms that only support Gen1.
>
> Signed-off-by: Dikshita Agarwal<dikshita.agarwal@oss.qualcomm.com>
> Co-developed-by: Dmitry Baryshkov<dmitry.baryshkov@oss.qualcomm.com>
> Signed-off-by: Dmitry Baryshkov<dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:32 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 03/18] media: iris: drop IRIS_FMT_foo enumeration Dmitry Baryshkov
` (16 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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] 32+ messages in thread* Re: [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported
2026-07-30 15:20 ` [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported Dmitry Baryshkov
@ 2026-07-30 15:32 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:32 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, media-ci, devicetree, conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] UBWC system initialization is skipped on unsupported platforms, but UBWC V4L2 pixel formats are still unconditionally exposed and accepted, leading to invalid session configurations.
--
--- Patch [2]: [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported ---
commit 2c20085257ddd4d7a77928a6e07815a827326525
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Skip UBWC configuration when not supported
This commit skips Universal Bandwidth Compression (UBWC) configuration
during system initialization on unsupported platforms. It achieves this
by checking if the UBWC encoder version is non-zero before sending UBWC
properties to the firmware.
> 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 0d05dd2afc07d..6e04175eb904b 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;
> +
[Severity: High]
This is a pre-existing issue, but while this patch prevents UBWC system
initialization on unsupported SoCs, are UBWC V4L2 pixel formats still
unconditionally exposed and accepted by the driver?
In drivers/media/platform/qcom/iris/iris_vdec.c:check_format(), the requested
format is validated against a static array without checking for UBWC support:
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_vdec_formats_cap;
size = ARRAY_SIZE(iris_vdec_formats_cap);
break;
If userspace selects a UBWC format (like V4L2_PIX_FMT_QC08C) on an unsupported
SoC, it appears drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c:
iris_hfi_gen2_set_colorformat() will still send UBWC session properties to the
firmware:
switch (pixelformat) {
...
case V4L2_PIX_FMT_QC08C:
hfi_colorformat = HFI_COLOR_FMT_NV12_UBWC;
break;
Since system-level UBWC configuration is now skipped, will sending these UBWC
session properties cause firmware errors or stream failures? Should the driver
also filter out UBWC formats during enumeration and validation on these
platforms?
> payload = qcom_ubwc_macrotile_mode(ubwc) ? 8 : 4;
> iris_hfi_gen2_create_packet(hdr,
> HFI_PROP_UBWC_MAX_CHANNELS,
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 03/18] media: iris: drop IRIS_FMT_foo enumeration
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 01/18] media: iris: Add Gen2 firmware autodetect and fallback Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 02/18] media: iris: Skip UBWC configuration when not supported Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 04/18] media: iris: Filter UBWC raw formats based on hardware capabilities Dmitry Baryshkov
` (15 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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
The IRIS_FMT_foo defines are only used for indexing values in the format
enumeration arrays. However this kind of enumeration doesn't follow the
V4L2 logic (which expects an array with consequtive indexing rather
than a sparse array) and complicates adding support for platforms which
support different sets of formats. Drop this enumeration and use flat
lists of supported formats.
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_instance.h | 14 --------------
drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 6 +++---
drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 8 ++++----
drivers/media/platform/qcom/iris/iris_vdec.c | 8 ++++----
drivers/media/platform/qcom/iris/iris_venc.c | 8 ++++----
5 files changed, 15 insertions(+), 29 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_instance.h b/drivers/media/platform/qcom/iris/iris_instance.h
index a770331d1675..ffdbbd20901a 100644
--- a/drivers/media/platform/qcom/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/iris/iris_instance.h
@@ -17,20 +17,6 @@
struct iris_hfi_session_ops;
-enum iris_fmt_type_out {
- IRIS_FMT_H264,
- IRIS_FMT_HEVC,
- IRIS_FMT_VP9,
- IRIS_FMT_AV1,
-};
-
-enum iris_fmt_type_cap {
- IRIS_FMT_NV12,
- IRIS_FMT_QC08C,
- IRIS_FMT_TP10,
- IRIS_FMT_QC10C,
-};
-
/**
* struct iris_inst - holds per video instance parameters
*
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
index 961dce2e6aa9..ba91672df1bb 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu2.c
@@ -35,9 +35,9 @@ static const struct iris_firmware_desc iris_vpu20_p4_gen1_desc = {
};
static const u32 iris_fmts_vpu2_dec[] = {
- [IRIS_FMT_H264] = V4L2_PIX_FMT_H264,
- [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC,
- [IRIS_FMT_VP9] = V4L2_PIX_FMT_VP9,
+ V4L2_PIX_FMT_H264,
+ V4L2_PIX_FMT_HEVC,
+ V4L2_PIX_FMT_VP9,
};
static struct platform_inst_caps platform_inst_cap_vpu2 = {
diff --git a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
index 74626b35d9cb..7098b652c117 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu3x.c
@@ -49,10 +49,10 @@ static const struct iris_firmware_desc iris_vpu35_p4_gen2_desc = {
};
static const u32 iris_fmts_vpu3x_dec[] = {
- [IRIS_FMT_H264] = V4L2_PIX_FMT_H264,
- [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC,
- [IRIS_FMT_VP9] = V4L2_PIX_FMT_VP9,
- [IRIS_FMT_AV1] = V4L2_PIX_FMT_AV1,
+ V4L2_PIX_FMT_H264,
+ V4L2_PIX_FMT_HEVC,
+ V4L2_PIX_FMT_VP9,
+ V4L2_PIX_FMT_AV1,
};
static const struct icc_info iris_icc_info_vpu3x[] = {
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 9e228b70420e..4c8bc7aac135 100644
--- a/drivers/media/platform/qcom/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/iris/iris_vdec.c
@@ -63,10 +63,10 @@ int iris_vdec_inst_init(struct iris_inst *inst)
}
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,
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_QC08C,
+ V4L2_PIX_FMT_P010,
+ V4L2_PIX_FMT_QC10C,
};
static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
diff --git a/drivers/media/platform/qcom/iris/iris_venc.c b/drivers/media/platform/qcom/iris/iris_venc.c
index a945992f63aa..16c52ad07e2c 100644
--- a/drivers/media/platform/qcom/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/iris/iris_venc.c
@@ -80,13 +80,13 @@ int iris_venc_inst_init(struct iris_inst *inst)
}
static const u32 iris_venc_formats_cap[] = {
- [IRIS_FMT_H264] = V4L2_PIX_FMT_H264,
- [IRIS_FMT_HEVC] = V4L2_PIX_FMT_HEVC,
+ V4L2_PIX_FMT_H264,
+ V4L2_PIX_FMT_HEVC,
};
static const u32 iris_venc_formats_out[] = {
- [IRIS_FMT_NV12] = V4L2_PIX_FMT_NV12,
- [IRIS_FMT_QC08C] = V4L2_PIX_FMT_QC08C,
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_QC08C,
};
static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
--
2.47.3
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH v8 04/18] media: iris: Filter UBWC raw formats based on hardware capabilities
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (2 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 03/18] media: iris: drop IRIS_FMT_foo enumeration Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 05/18] media: iris: Introduce set_preset_register as a vpu_op Dmitry Baryshkov
` (14 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/media/platform/qcom/iris/iris_vdec.c | 26 ++++++++++++++++++++++----
drivers/media/platform/qcom/iris/iris_venc.c | 25 +++++++++++++++++++++----
2 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/qcom/iris/iris_vdec.c b/drivers/media/platform/qcom/iris/iris_vdec.c
index 4c8bc7aac135..9fee5f28097d 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>
@@ -69,8 +70,14 @@ static const u32 iris_vdec_formats_cap[] = {
V4L2_PIX_FMT_QC10C,
};
+static const u32 iris_vdec_formats_noubwc_cap[] = {
+ V4L2_PIX_FMT_NV12,
+ V4L2_PIX_FMT_P010,
+};
+
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;
@@ -80,8 +87,13 @@ static bool check_format(struct iris_inst *inst, u32 pixfmt, u32 type)
size = inst->core->iris_platform_data->inst_iris_fmts_size;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- fmt = iris_vdec_formats_cap;
- size = ARRAY_SIZE(iris_vdec_formats_cap);
+ if (ubwc->ubwc_enc_version) {
+ fmt = iris_vdec_formats_cap;
+ size = ARRAY_SIZE(iris_vdec_formats_cap);
+ } else {
+ fmt = iris_vdec_formats_noubwc_cap;
+ size = ARRAY_SIZE(iris_vdec_formats_noubwc_cap);
+ }
break;
default:
return false;
@@ -110,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;
@@ -119,8 +132,13 @@ static u32 find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
size = inst->core->iris_platform_data->inst_iris_fmts_size;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- fmt = iris_vdec_formats_cap;
- size = ARRAY_SIZE(iris_vdec_formats_cap);
+ if (ubwc->ubwc_enc_version) {
+ fmt = iris_vdec_formats_cap;
+ size = ARRAY_SIZE(iris_vdec_formats_cap);
+ } else {
+ fmt = iris_vdec_formats_noubwc_cap;
+ size = ARRAY_SIZE(iris_vdec_formats_noubwc_cap);
+ }
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 16c52ad07e2c..2f2c56bf9122 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>
@@ -89,15 +90,25 @@ static const u32 iris_venc_formats_out[] = {
V4L2_PIX_FMT_QC08C,
};
+static const u32 iris_venc_formats_noubwc_out[] = {
+ V4L2_PIX_FMT_NV12,
+};
+
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;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- fmt = iris_venc_formats_out;
- size = ARRAY_SIZE(iris_venc_formats_out);
+ if (ubwc->ubwc_enc_version) {
+ fmt = iris_venc_formats_out;
+ size = ARRAY_SIZE(iris_venc_formats_out);
+ } else {
+ fmt = iris_venc_formats_noubwc_out;
+ size = ARRAY_SIZE(iris_venc_formats_noubwc_out);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_venc_formats_cap;
@@ -117,13 +128,19 @@ 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;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- fmt = iris_venc_formats_out;
- size = ARRAY_SIZE(iris_venc_formats_out);
+ if (ubwc->ubwc_enc_version) {
+ fmt = iris_venc_formats_out;
+ size = ARRAY_SIZE(iris_venc_formats_out);
+ } else {
+ fmt = iris_venc_formats_noubwc_out;
+ size = ARRAY_SIZE(iris_venc_formats_noubwc_out);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_venc_formats_cap;
--
2.47.3
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH v8 05/18] media: iris: Introduce set_preset_register as a vpu_op
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (3 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 04/18] media: iris: Filter UBWC raw formats based on hardware capabilities Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 06/18] media: iris: Introduce interrupt_init " Dmitry Baryshkov
` (13 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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] 32+ messages in thread* [PATCH v8 06/18] media: iris: Introduce interrupt_init as a vpu_op
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (4 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 05/18] media: iris: Introduce set_preset_register as a vpu_op Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer Dmitry Baryshkov
` (12 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
Reviewed-by: Vishnu Reddy <busanna.reddy@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] 32+ messages in thread* [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (5 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 06/18] media: iris: Introduce interrupt_init " Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:41 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
` (11 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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 6dbe18be5b49..526f92575264 100644
--- a/drivers/media/platform/qcom/iris/iris_core.c
+++ b/drivers/media/platform/qcom/iris/iris_core.c
@@ -46,6 +46,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);
@@ -79,6 +80,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);
iris_session_init_caps(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] 32+ messages in thread* Re: [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer
2026-07-30 15:20 ` [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer Dmitry Baryshkov
@ 2026-07-30 15:41 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:41 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, conor+dt, media-ci, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Race conditions and data races in `iris_core_init` state machine allow concurrent callers to bypass initialization wait and modify `core->state` unprotected.
- [High] The `iris_core_init()` function fails to clean up initialized resources (such as DMA memory for queues, firmware mappings, and VPU power) if the hardware fails to respond in time.
--
--- Patch [7]: [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer ---
commit 53560a9c747444f7e2c1b9214a99baec4904f498
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: add vpu op hook to disable ARP buffer
This patch adds a disable_arp callback to the VPU operations for the iris
driver. This optional callback is invoked during core initialization and
resume paths to disable ARP routing on AR50LT platforms, allowing the
firmware to configure the ARP internal buffer as non-secure for encoder
usage.
> diff --git a/drivers/media/platform/qcom/iris/iris_core.c b/drivers/media/platform/qcom/iris/iris_core.c
> index 6dbe18be5b495..526f925752646 100644
> --- a/drivers/media/platform/qcom/iris/iris_core.c
> +++ b/drivers/media/platform/qcom/iris/iris_core.c
> @@ -46,6 +46,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);
[Severity: High]
This isn't a bug introduced by this patch, but is there a race condition in
the state machine of iris_core_init()?
If one thread calls iris_core_init(), it takes core->lock, sets
core->state = IRIS_CORE_INIT, drops the lock, and blocks in
iris_wait_for_system_response():
drivers/media/platform/qcom/iris/iris_core.c:iris_core_init() {
...
core->state = IRIS_CORE_INIT;
...
mutex_unlock(&core->lock);
return iris_wait_for_system_response(core);
}
Concurrently, if another thread calls iris_core_init(), it can see
core->state == IRIS_CORE_INIT and return success immediately without waiting
for firmware readiness:
drivers/media/platform/qcom/iris/iris_core.c:iris_core_init() {
mutex_lock(&core->lock);
if (core->state == IRIS_CORE_INIT) {
ret = 0;
goto exit;
}
...
}
Additionally, if the first thread's wait times out,
iris_wait_for_system_response() modifies core->state without holding
core->lock:
drivers/media/platform/qcom/iris/iris_core.c:iris_wait_for_system_response() {
...
if (!ret) {
core->state = IRIS_CORE_ERROR;
return -ETIMEDOUT;
}
...
}
Can this lead to a data race with other threads checking or modifying the
state, and allow threads to bypass initialization wait?
[Severity: High]
This is a pre-existing issue, but does iris_core_init() fail to clean up
initialized resources if the hardware fails to respond in time?
In iris_core_init(), if iris_wait_for_system_response() returns an error
(e.g., -ETIMEDOUT), it doesn't trigger the teardown labels:
drivers/media/platform/qcom/iris/iris_core.c:iris_core_init() {
...
mutex_unlock(&core->lock);
return iris_wait_for_system_response(core);
...
}
If wait_for_completion_timeout() expires, iris_wait_for_system_response()
returns -ETIMEDOUT and sets core->state to IRIS_CORE_ERROR:
drivers/media/platform/qcom/iris/iris_core.c:iris_wait_for_system_response() {
...
if (!ret) {
core->state = IRIS_CORE_ERROR;
return -ETIMEDOUT;
}
...
}
If user space retries, the next call to iris_core_init() sees
core->state == IRIS_CORE_ERROR, jumps to the error label, and sets the
state to IRIS_CORE_DEINIT without releasing the resources leaked in the
first attempt:
drivers/media/platform/qcom/iris/iris_core.c:iris_core_init() {
...
} else if (core->state == IRIS_CORE_ERROR) {
ret = -EINVAL;
goto error;
}
...
error:
core->state = IRIS_CORE_DEINIT;
...
}
A third attempt would then see IRIS_CORE_DEINIT, re-run initialization,
allocate new DMA memory (via iris_hfi_queues_init), and overwrite the
previous pointers, resulting in a permanent memory leak.
Does this sequence cause a memory leak when the firmware hangs?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=7
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (6 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 07/18] media: iris: add vpu op hook to disable ARP buffer Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:32 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 09/18] media: iris: Add platform flag for instantaneous bandwidth voting Dmitry Baryshkov
` (10 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
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_platform_common.h | 1 +
drivers/media/platform/qcom/iris/iris_platform_vpu2.c | 4 ++++
drivers/media/platform/qcom/iris/iris_platform_vpu3x.c | 7 +++++++
drivers/media/platform/qcom/iris/iris_vpu_common.c | 8 +++++---
drivers/media/platform/qcom/iris/iris_vpu_register_defines.h | 1 -
5 files changed, 17 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 ba91672df1bb..940daddbafcf 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 7098b652c117..eeedde8fc9ce 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,
@@ -243,6 +249,7 @@ const struct iris_platform_data x1p42100_data = {
.tz_cp_config_data = tz_cp_config_vpu3,
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 1,
+ .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] 32+ messages in thread* Re: [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask
2026-07-30 15:20 ` [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
@ 2026-07-30 15:32 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:32 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, robh, conor+dt, media-ci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Incomplete refactoring of watchdog interrupt bitmask. The new `wd_intr_mask` field is used for clearing and handling interrupts, but the hardware unmasking in `iris_vpu_interrupt_init()` still uses the hardcoded `WRAPPER_INTR_MASK_A2HWD_BMSK` (`BIT(3)`).
--
--- Patch [8]: [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask ---
commit 7b1829b3b98fff57fbf33321045b38db86f344d4
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Add platform data field for watchdog interrupt mask
This commit introduces a new platform data field, wd_intr_mask, to support
different watchdog interrupt bitmasks per platform. It updates the interrupt
clearing and watchdog handling routines to use this field instead of the
hardcoded WRAPPER_INTR_STATUS_A2HWD_BMSK macro.
> 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 72168b9ffa738..4fffa094c52fe 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)
[Severity: Medium]
While WRAPPER_INTR_STATUS_A2HWD_BMSK was removed and replaced with the
platform-specific wd_intr_mask, does iris_vpu_interrupt_init() still
hardcode the mask?
drivers/media/platform/qcom/iris/iris_vpu_common.c:iris_vpu_interrupt_init() {
...
mask_val &= ~(WRAPPER_INTR_MASK_A2HWD_BMSK |
WRAPPER_INTR_MASK_A2HCPU_BMSK);
...
}
If AR50LT has a different bit for the watchdog interrupt, will it
remain masked in the hardware because WRAPPER_INTR_MASK_A2HWD_BMSK is
still defined as BIT(3)?
Should the WRAPPER_INTR_MASK_A2HWD_BMSK macro also be removed and replaced
with wd_intr_mask during initialization?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=8
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 09/18] media: iris: Add platform flag for instantaneous bandwidth voting
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (7 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 08/18] media: iris: Add platform data field for watchdog interrupt mask Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:20 ` [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform Dmitry Baryshkov
` (9 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
Reviewed-by: Vishnu Reddy <busanna.reddy@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 | 5 +++++
drivers/media/platform/qcom/iris/iris_resources.c | 2 ++
4 files changed, 10 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 940daddbafcf..e194f67a6f48 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 eeedde8fc9ce..b8099d7ce556 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,
@@ -250,6 +254,7 @@ const struct iris_platform_data x1p42100_data = {
.tz_cp_config_data_size = ARRAY_SIZE(tz_cp_config_vpu3),
.num_vpp_pipe = 1,
.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 872bd09656b1..3ee38def7697 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] 32+ messages in thread* [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (8 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 09/18] media: iris: Add platform flag for instantaneous bandwidth voting Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:56 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
` (8 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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] 32+ messages in thread* Re: [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform
2026-07-30 15:20 ` [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform Dmitry Baryshkov
@ 2026-07-30 15:56 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:56 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: conor+dt, media-ci, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Omitting the PIPE capability causes a division-by-zero kernel panic in `iris_vpu3x_vpu4x_calculate_frequency()`.
- [Medium] `iris_set_stage()` lacks the fallback check for unsupported capabilities that was added to `iris_set_pipe()`.
--
--- Patch [10]: [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform ---
commit 47a09938f9dc9bf17faca2d850a92320d738ffe8
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: iris: skip PIPE if it is not supported by the platform
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.
> diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c b/drivers/media/platform/qcom/iris/iris_ctrls.c
> index 10e33b8a73f60..33a34573391a4 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;
> +
[Severity: Critical]
This isn't a bug introduced by this patch, but by allowing platforms to
legitimately omit the PIPE capability, could this lead to a division by zero
panic in iris_vpu3x_vpu4x_calculate_frequency()?
When the PIPE capability is missing (like in inst_fw_cap_sm8550_enc),
inst->fw_caps[PIPE].value is initialized to 0. During clock scaling,
iris_vpu3x_vpu4x_calculate_frequency() in iris_vpu_common.c unconditionally
uses this value:
drivers/media/platform/qcom/iris/iris_vpu_common.c:iris_vpu3x_vpu4x_calculate_frequency() {
...
vpp_cycles = mult_frac(mbs_per_second, caps->mb_cycles_vpp,
(u32)inst->fw_caps[PIPE].value);
...
}
Will this trigger a kernel panic if a stream is started on a platform where
PIPE is intentionally absent?
[Severity: Medium]
This is also a pre-existing issue, but should iris_set_stage() in
iris_ctrls.c include the exact same hfi_id check?
In iris_common.c, iris_alloc_and_queue_input_int_bufs() calls both
iris_set_stage() and iris_set_pipe(). Since iris_set_stage() lacks this
check, if a platform omits the STAGE capability, it will call
session_set_property() with an hfi_id of 0:
drivers/media/platform/qcom/iris/iris_ctrls.c:iris_set_stage() {
...
u32 hfi_id = inst->fw_caps[cap_id].hfi_id;
return hfi_ops->session_set_property(inst, hfi_id, ...);
...
}
Would this pass an invalid property ID and potentially crash the firmware?
> return hfi_ops->session_set_property(inst, hfi_id,
> HFI_HOST_FLAGS_NONE,
> iris_get_port_info(inst, cap_id),
> HFI_PAYLOAD_U32,
> &work_route, sizeof(u32));
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=10
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (9 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by the platform Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:41 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
` (7 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
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/Makefile | 1 +
.../platform/qcom/iris/iris_platform_common.h | 2 +
drivers/media/platform/qcom/iris/iris_vpu2.c | 28 +----
drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c | 130 +++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu_common.c | 29 ++++-
drivers/media/platform/qcom/iris/iris_vpu_common.h | 2 +
6 files changed, 164 insertions(+), 28 deletions(-)
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_vpu2.c b/drivers/media/platform/qcom/iris/iris_vpu2.c
index dd2eeae0d9eb..5419a5096b00 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu2.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu2.c
@@ -12,38 +12,12 @@
#include "iris_vpu_register_defines.h"
-static u64 iris_vpu2_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 = inst->frame_rate;
-
- 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_vpu2_ops = {
.power_off_hw = iris_vpu_power_off_hw,
.power_on_hw = iris_vpu_power_on_hw,
.power_off_controller = iris_vpu_power_off_controller,
.power_on_controller = iris_vpu_power_on_controller,
- .calc_freq = iris_vpu2_calc_freq,
+ .calc_freq = iris_vpu2_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_vpu_ar50lt.c b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
new file mode 100644
index 000000000000..e084a5b49f2e
--- /dev/null
+++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
@@ -0,0 +1,130 @@
+// 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;
+}
+
+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_vpu2_calculate_frequency,
+ .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..d64e7745a63d 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;
}
@@ -422,6 +423,32 @@ void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core)
writel(0x1, core->reg_base + WRAPPER_IRIS_VCODEC_VPU_WRAPPER_SPARE_0);
}
+u64 iris_vpu2_calculate_frequency(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 = inst->frame_rate;
+
+ 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);
+}
+
u64 iris_vpu3x_vpu4x_calculate_frequency(struct iris_inst *inst, size_t data_size)
{
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_common.h b/drivers/media/platform/qcom/iris/iris_vpu_common.h
index 71d96921ed37..a62b6184bde7 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);
@@ -40,6 +41,7 @@ int iris_vpu_power_on(struct iris_core *core);
int iris_vpu_power_off_controller(struct iris_core *core);
void iris_vpu_power_off_hw(struct iris_core *core);
void iris_vpu_power_off(struct iris_core *core);
+u64 iris_vpu2_calculate_frequency(struct iris_inst *inst, size_t data_size);
int iris_vpu35_vpu4x_power_off_controller(struct iris_core *core);
int iris_vpu35_vpu4x_power_on_controller(struct iris_core *core);
void iris_vpu35_vpu4x_program_bootup_registers(struct iris_core *core);
--
2.47.3
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core
2026-07-30 15:20 ` [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
@ 2026-07-30 15:41 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:41 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, conor+dt, media-ci, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Failed power domain enables or already-active domains leak the PM runtime usage counter and inappropriately abort initialization due to improper handling of `pm_runtime_get_sync()` return values.
--
--- Patch [11]: [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core ---
commit cfd8ed53c04ddb4ea2cea6f16627a62b8400f868
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..e084a5b49f2e3
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_ar50lt.c
[ ... ]
> +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;
[Severity: High]
This isn't a bug introduced by this patch, but since
iris_enable_power_domains() returns the raw value of pm_runtime_get_sync(),
does this incorrectly abort initialization if the domain is already active?
pm_runtime_get_sync() returns 1 when the device is already active. Treating
any non-zero return value as a failure causes this to return 1 and abort
the power-on sequence.
Also, if pm_runtime_get_sync() fails (returns < 0) or returns 1, the usage
counter is left incremented. Could this leak the PM runtime reference since
the error path doesn't call pm_runtime_put_noidle()? Using
pm_runtime_resume_and_get() instead of pm_runtime_get_sync() in the wrapper
would avoid both issues.
[ ... ]
> +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;
[Severity: High]
This isn't a bug introduced by this patch, but does this share the same
pm_runtime_get_sync() return value mismatch and reference leak as seen in
iris_vpu_ar50lt_power_on_controller() above?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=11
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (10 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE video core Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:39 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 13/18] media: iris: update buffer requirements based on received info Dmitry Baryshkov
` (6 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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, otherwise 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. It is used by one of the following patches, adding support for
Agatti.
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Reviewed-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_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] 32+ messages in thread* Re: [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation
2026-07-30 15:20 ` [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
@ 2026-07-30 15:39 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:39 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, robh, media-ci, conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Use-after-free race condition in `iris_hfi_gen1_handle_response` due to lack of instance refcounting.
- [High] Concurrent commands can corrupt `inst->completion` and falsely signal command completion due to lock dropping.
--
--- Patch [12]: [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation ---
commit 30243b6f486f6a7511eef1e8f6ae8cf07acc9093
Author: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
media: iris: add minimal GET_PROPERTY implementation
This commit adds minimal support for querying properties from the Gen1
firmware in the iris driver, specifically implementing
HFI_CMD_SESSION_GET_PROPERTY. This is required for AR50Lt to read
HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS.
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> --- 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
[ ... ]
> +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);
> +}
[Severity: High]
This isn't a bug introduced by this patch, but does dropping the lock in
iris_wait_for_session_response() while waiting on a single shared completion
allow concurrent ioctls to corrupt the completion state?
A thread executing a V4L2 ioctl can lock inst->lock and issue a firmware
command. It then calls iris_wait_for_session_response(), which explicitly
unlocks inst->lock and sleeps on inst->completion:
iris_wait_for_session_response()
mutex_unlock(&inst->lock);
ret = wait_for_completion_timeout(done, ...);
mutex_lock(&inst->lock);
While the first thread is waiting, another thread executing a concurrent
ioctl can acquire inst->lock, send a different firmware command, and call
reinit_completion(&inst->completion). Both threads end up sleeping on the
same completion.
When the firmware responds to the first command, the single completion is
triggered, which could incorrectly wake up the second thread prematurely.
Could this lead to corrupted driver state or commands assuming success before
the hardware has actually completed them?
> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> --- 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);
> } else {
[Severity: High]
This is a pre-existing issue, but is there a use-after-free race condition in
iris_hfi_gen1_handle_response() when dealing with inst?
When the hardware triggers an interrupt, the response handler retrieves the
instance pointer using iris_get_instance(). This function returns the pointer
without incrementing any reference count:
iris_get_instance()
mutex_lock(&core->lock);
[ ... ]
return inst;
If the response handler thread is preempted here, a concurrent close() on the
device file descriptor can execute iris_close(). This would lock inst->lock,
remove the instance from the core list, and free the instance memory.
When the response handler resumes, it attempts to lock the freed instance:
iris_hfi_gen1_handle_response()
inst = iris_get_instance(...);
[ ... ]
mutex_lock(&inst->lock);
Can this be triggered by a user space process rapidly closing the file
descriptor while firmware responses are pending, leading to memory corruption
or a kernel panic?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=12
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 13/18] media: iris: update buffer requirements based on received info
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (11 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:52 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 14/18] media: iris: implement support for the Agatti platform Dmitry Baryshkov
` (5 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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.
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../platform/qcom/iris/iris_hfi_gen1_response.c | 76 +++++++++++++++++++++-
1 file changed, 75 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..7ad6f0bb4677 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,80 @@ 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 BUF_TYPE_MAX;
+ }
+}
+
+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 == BUF_TYPE_MAX)
+ continue;
+
+ /* on relevant platforms hold_count and min_count are swapped */
+ 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 != 1) {
+ dev_warn_ratelimited(inst->core->dev, "%s: expected 1 property, got %u\n",
+ __func__, pkt->num_properties);
+ 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 +731,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] 32+ messages in thread* Re: [PATCH v8 13/18] media: iris: update buffer requirements based on received info
2026-07-30 15:20 ` [PATCH v8 13/18] media: iris: update buffer requirements based on received info Dmitry Baryshkov
@ 2026-07-30 15:52 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:52 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: robh, conor+dt, devicetree, media-ci
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Use-After-Free in threaded IRQ handler due to missing reference counting on iris_inst
--
--- Patch [13]: [PATCH v8 13/18] media: iris: update buffer requirements based on received info ---
commit eebc551c83e572d39b479f0c60f9705bbd9fe71d
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..7ad6f0bb46770 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c
> [ ... ]
> @@ -657,7 +731,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);
[Severity: High]
This is a pre-existing issue, but could this inst dereference lead to a
use-after-free if the IRQ thread races with userspace calling close(fd)?
Looking at iris_get_instance() in
drivers/media/platform/qcom/iris/iris_utils.c, it drops core->lock and
returns a raw instance pointer without incrementing a reference count:
drivers/media/platform/qcom/iris/iris_utils.c:iris_get_instance() {
...
mutex_lock(&core->lock);
list_for_each_entry(inst, &core->instances, list) {
if (inst->session_id == session_id) {
mutex_unlock(&core->lock);
return inst;
}
}
mutex_unlock(&core->lock);
return NULL;
}
Concurrently, if a userspace thread calls close(fd), iris_close() in
drivers/media/platform/qcom/iris/iris_vidc.c calls iris_remove_session(inst)
and then kfree(inst), without synchronizing with concurrent readers in the IRQ
thread.
If the threaded IRQ handler gets preempted after iris_get_instance()
returns but before acquiring inst->lock, would it wake up and
dereference the freed inst pointer when calling mutex_lock(&inst->lock)
earlier in this function?
> } else {
> struct hfi_msg_session_hdr_pkt *shdr;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=13
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 14/18] media: iris: implement support for the Agatti platform
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (12 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 13/18] media: iris: update buffer requirements based on received info Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:54 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
` (4 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
Reviewed-by: Vikash Garodia <vikash.garodia@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 | 404 +++++++++++++++++++++
.../platform/qcom/iris/iris_hfi_gen1_command.c | 9 +
.../platform/qcom/iris/iris_platform_common.h | 9 +
.../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 | 5 +
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 1 +
8 files changed, 543 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..020f55092737 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
@@ -443,3 +443,407 @@ 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,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_intra_period,
+ },
+ {
+ .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,
+ },
+ {
+ .cap_id = IR_TYPE,
+ .min = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM,
+ .max = V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC,
+ .step_or_mask = BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) |
+ BIT(V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC),
+ .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 = ((4096 * 2304) >> 8),
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_ir_period_gen1,
+ },
+ {
+ .cap_id = LTR_COUNT,
+ .min = 0,
+ .max = MAX_LTR_FRAME_COUNT_GEN1,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_PARAM_VENC_LTRMODE,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_ltr_count_gen1,
+ },
+ {
+ .cap_id = USE_LTR,
+ .min = 0,
+ .max = ((1 << MAX_LTR_FRAME_COUNT_GEN1) - 1),
+ .step_or_mask = 0,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_USELTRFRAME,
+ .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_use_ltr,
+ },
+ {
+ .cap_id = MARK_LTR,
+ .min = 0,
+ .max = (MAX_LTR_FRAME_COUNT_GEN1 - 1),
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME,
+ .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_mark_ltr,
+ },
+ {
+ .cap_id = B_FRAME,
+ .min = 0,
+ .max = 3,
+ .step_or_mask = 1,
+ .value = 0,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = INTRA_PERIOD,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_intra_period,
+ },
+ {
+ .cap_id = LAYER_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = LAYER_TYPE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ .max = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P),
+ .value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ },
+ {
+ .cap_id = LAYER_COUNT_H264,
+ .min = 0,
+ .max = MAX_HIER_CODING_LAYER_GEN1,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_layer_count_gen1,
+ },
+ {
+ .cap_id = LAYER0_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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 = LAYER1_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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 = LAYER2_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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 = LAYER3_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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 = LAYER4_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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 = LAYER5_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT,
+ .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,
+ },
+};
+
+static const u32 iris_hfi_gen1_ar50lt_dec_ip_int_buf_tbl[] = {
+ BUF_BIN,
+ BUF_SCRATCH_1,
+};
+
+/*
+ * Unlike sm8250, on AR50Lt the internal buffer sizes are provided by the
+ * firmware. Request HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL so that the encoder
+ * queries HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS before allocating them.
+ */
+static const u32 iris_hfi_gen1_ar50lt_venc_input_config_param[] = {
+ HFI_PROPERTY_CONFIG_FRAME_RATE,
+ HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO,
+ HFI_PROPERTY_PARAM_FRAME_SIZE,
+ HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT,
+ HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
+ HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL,
+};
+
+const struct iris_firmware_data iris_hfi_gen1_ar50lt_data = {
+ .init_hfi_ops = &iris_hfi_gen1_sys_ops_init,
+
+ .query_buffer_requirements = true,
+
+ .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 = iris_hfi_gen1_ar50lt_venc_input_config_param,
+ .enc_input_config_params_size =
+ ARRAY_SIZE(iris_hfi_gen1_ar50lt_venc_input_config_param),
+
+ .dec_ip_int_buf_tbl = iris_hfi_gen1_ar50lt_dec_ip_int_buf_tbl,
+ .dec_ip_int_buf_tbl_size = ARRAY_SIZE(iris_hfi_gen1_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_hfi_gen1_command.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
index 99e82e5510ab..329a9ef2fdc5 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
@@ -970,6 +970,13 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane)
struct hfi_buffer_size_actual bufsz;
int ret;
+ if (inst->core->iris_firmware_data->query_buffer_requirements) {
+ ret = inst->hfi_session_ops->session_get_property(inst,
+ HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS);
+ if (ret)
+ return ret;
+ }
+
if (iris_split_mode_enabled(inst)) {
bufsz.type = HFI_BUFFER_OUTPUT;
bufsz.size = inst->core->iris_firmware_desc->get_vpu_buffer_size(inst, BUF_DPB);
@@ -1084,6 +1091,8 @@ static int iris_hfi_gen1_session_set_config_params(struct iris_inst *inst, u32 p
iris_hfi_gen1_set_raw_format},
{HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL,
iris_hfi_gen1_set_num_bufs},
+ {HFI_PROPERTY_PARAM_BUFFER_SIZE_ACTUAL,
+ iris_hfi_gen1_set_bufsize},
};
if (inst->domain == DECODER) {
diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h b/drivers/media/platform/qcom/iris/iris_platform_common.h
index 6a189489369f..06d9f72dd6d6 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;
@@ -242,6 +248,9 @@ struct iris_firmware_data {
u32 core_arch;
+ /* Query buffer sizes from the firmware (pre-Iris HFI Gen1 platforms). */
+ bool query_buffer_requirements;
+
const struct platform_inst_fw_cap *inst_fw_caps_dec;
u32 inst_fw_caps_dec_size;
const struct platform_inst_fw_cap *inst_fw_caps_enc;
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..92f7e2546539
--- /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
+
+static 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[] = {
+ V4L2_PIX_FMT_H264,
+ V4L2_PIX_FMT_HEVC,
+ 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 faebb5472866..83dc4a1db954 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -2194,6 +2194,11 @@ 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)
+{
+ 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] 32+ messages in thread* Re: [PATCH v8 14/18] media: iris: implement support for the Agatti platform
2026-07-30 15:20 ` [PATCH v8 14/18] media: iris: implement support for the Agatti platform Dmitry Baryshkov
@ 2026-07-30 15:54 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:54 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: devicetree, robh, media-ci, conor+dt
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] Mismatch between statically calculated vb2 buffer size and the firmware's requested buffer size causes a potential buffer overflow when the firmware writes to external buffers.
- [High] Querying buffer requirements for AR50Lt overwrites the DPB buffer count (fw_min_count) with the display output buffer count.
- [High] The AR50LT platform uses `iris_vpu2_calculate_frequency` but provides capability fields intended for `iris_vpu3x_vpu4x_calculate_frequency`, resulting in severely under-calculated clock scaling.
- [Medium] The hierarchical layer bitrates (LAYER0_BITRATE_H264 to LAYER5_BITRATE_H264) in `inst_fw_cap_gen1_ar50lt_enc` use the global `BITRATE_MAX` (160Mbps) instead of the AR50LT-specific limit.
--
--- Patch [14]: [PATCH v8 14/18] media: iris: implement support for the Agatti platform ---
commit 50e74e4ea9f26a2d05a3a8800b3cde717ea582a2
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_hfi_gen1.c b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
> index ca1545d28b531..020f55092737d 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1.c
[ ... ]
> + {
> + .cap_id = LAYER0_BITRATE_H264,
> + .min = 1,
> + .max = BITRATE_MAX,
> + .step_or_mask = 1,
> + .value = BITRATE_DEFAULT,
> + .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,
> + },
[Severity: Medium]
Should these hierarchical layers use BITRATE_MAX_AR50LT instead of
BITRATE_MAX?
The base BITRATE capability uses BITRATE_MAX_AR50LT (100M), but the
hierarchical layers are using BITRATE_MAX (160M), which might allow
userspace to request a configuration that exceeds the platform's hardware
limits.
[ ... ]
> 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 99e82e5510abe..329a9ef2fdc5f 100644
> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c
[ ... ]
> @@ -970,6 +970,13 @@ static int iris_hfi_gen1_set_bufsize(struct iris_inst *inst, u32 plane)
> struct hfi_buffer_size_actual bufsz;
> int ret;
>
> + if (inst->core->iris_firmware_data->query_buffer_requirements) {
> + ret = inst->hfi_session_ops->session_get_property(inst,
> + HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS);
> + if (ret)
> + return ret;
> + }
> +
[Severity: High]
Could querying buffer requirements here overwrite the DPB buffer count
with the display buffer count?
When this queries HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS,
iris_hfi_gen1_session_buffer_requirements() processes the requirement.
For BUF_OUTPUT (which maps to the display buffer in split mode), it sets:
if (type == BUF_OUTPUT)
inst->fw_min_count = req->count_actual;
Since iris_vpu_dpb_count() relies on inst->fw_min_count for the DPB
count, does this result in allocating the wrong number of DPB buffers?
[Severity: Critical]
Could this lead to a buffer overflow when the firmware writes to
the external buffers?
When the buffer requirements are queried,
iris_hfi_gen1_session_buffer_requirements() overwrites the internal tracker:
inst->buffers[type].size = req->size;
This firmware-requested size is then sent back to the firmware. However,
when physical memory is prepared in iris_vb2_buf_prepare(), it validates the
size against the statically calculated iris_get_buffer_size():
if (vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT))
return -EINVAL;
If the firmware requires a larger size than the static calculation, it
might write beyond the statically allocated vb2_buffer bounds.
[ ... ]
> 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 0000000000000..92f7e25465399
> --- /dev/null
> +++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
[ ... ]
> +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,
> +};
[Severity: High]
Does this platform need mb_cycles_vsp defined to scale the clock properly?
This struct provides mb_cycles_fw and mb_cycles_fw_vpp, which are used by
iris_vpu3x_vpu4x_calculate_frequency(). However, qcm2290_data assigns
iris_vpu_ar50lt_ops, which uses iris_vpu2_calculate_frequency():
vsp_freq = mbs_per_second * caps->mb_cycles_vsp;
Since mb_cycles_vsp is omitted here, it defaults to 0. Will this cause the
calculated vsp_freq to be 0 and severely under-calculate the required clock
frequency?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=14
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (13 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 14/18] media: iris: implement support for the Agatti platform Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:47 ` sashiko-bot
2026-07-30 15:20 ` [PATCH v8 16/18] media: iris: add Gen2 firmware support on the Agatti platform Dmitry Baryshkov
` (3 subsequent siblings)
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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>
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_vpu_buffer.c | 365 +++++++++++++++++++++
drivers/media/platform/qcom/iris/iris_vpu_buffer.h | 37 +++
2 files changed, 402 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
index 83dc4a1db954..a8170e5fa9e6 100644
--- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
@@ -50,6 +50,26 @@ 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 hfi_buffer_bin_h264d_ar50lt(u32 frame_width, u32 frame_height)
+{
+ u32 n_aligned_h = ALIGN(frame_height, 16);
+ u32 n_aligned_w = ALIGN(frame_width, 16);
+ u32 size_yuv, size_bin_hdr, size_bin_res;
+
+ size_yuv = ((n_aligned_w * n_aligned_h * 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 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 +123,19 @@ 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 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, DMA_ALIGNMENT) +
+ ALIGN(((max(size_yuv, VPX_DECODER_FRAME_BIN_BUFFER_SIZE)) * 4), DMA_ALIGNMENT);
+
+ return size;
+}
+
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 +144,27 @@ 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 hfi_buffer_bin_h265d_ar50lt(u32 frame_width, u32 frame_height)
+{
+ u32 n_aligned_w = ALIGN(frame_width, 16);
+ u32 n_aligned_h = ALIGN(frame_height, 16);
+
+ u32 size_yuv, size_bin_hdr, size_bin_res;
+
+ size_yuv = ((n_aligned_w * n_aligned_h * 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_comv_h264d(u32 frame_width, u32 frame_height, u32 _comv_bufcount)
{
u32 frame_height_in_mbs = DIV_ROUND_UP(frame_height, 16);
@@ -174,6 +228,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 +247,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 +269,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 +293,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 +310,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 +328,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 +358,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 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 +383,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 +413,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 _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 +459,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 +497,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 +515,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 +571,25 @@ 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)
+{
+ 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) +
+ ALIGN(size_h265d_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
+ 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) +
+ 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 +624,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 +689,17 @@ 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_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min)
+{
+ return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
+ ALIGN(size_vpxd_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
+ 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)
@@ -529,6 +737,23 @@ 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)
+{
+ 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) +
+ ALIGN(size_h264d_lb_se_top_ctrl_ar50lt(frame_width), DMA_ALIGNMENT) +
+ ALIGN(size_h264d_lb_se_left_ctrl_ar50lt(frame_height), DMA_ALIGNMENT) +
+ 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 +949,22 @@ 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)
+{
+ 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);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_bin_h265d_ar50lt(width, height);
+ else if (inst->codec == V4L2_PIX_FMT_VP9)
+ return hfi_buffer_bin_vp9d_ar50lt(width, height);
+
+ return 0;
+}
+
static u32 iris_vpu_dec_comv_size(struct iris_inst *inst)
{
u32 num_comv = VIDEO_MAX_FRAME;
@@ -785,6 +1026,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 +1061,20 @@ 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)
+{
+ 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);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_non_comv_h265d_ar50lt(width, height);
+
+ 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 +1100,23 @@ 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)
+{
+ struct v4l2_format *f = inst->fmt_src;
+ u32 height = f->fmt.pix_mp.height;
+ u32 width = f->fmt.pix_mp.width;
+ u32 out_min_count = inst->buffers[BUF_OUTPUT].min_count;
+
+ if (inst->codec == V4L2_PIX_FMT_H264)
+ return hfi_buffer_line_h264d_ar50lt(width, height);
+ else if (inst->codec == V4L2_PIX_FMT_HEVC)
+ return hfi_buffer_line_h265d_ar50lt(width, height);
+ else if (inst->codec == V4L2_PIX_FMT_VP9)
+ return hfi_buffer_line_vp9d_ar50lt(width, height, out_min_count);
+
+ return 0;
+}
+
static u32 iris_vpu_dec_scratch1_size(struct iris_inst *inst)
{
return iris_vpu_dec_comv_size(inst) +
@@ -840,6 +1124,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 +1761,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 +1794,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 +2062,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;
@@ -2199,6 +2519,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] 32+ messages in thread* Re: [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT
2026-07-30 15:20 ` [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
@ 2026-07-30 15:47 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:47 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: conor+dt, devicetree, media-ci, robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The AR50LT-specific VP9 line buffer size calculation omits several essential buffer components, potentially leading to an out-of-bounds DMA write by the VPU hardware.
--
--- Patch [15]: [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT ---
commit a7ab33bf859a57941fb00808f15050baad5cf909
Author: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
media: iris: Introduce buffer size calculations for AR50LT
This commit introduces AR50LT buffer size calculations for both the encoder
and decoder. It reuses common buffer size calculations 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
> --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
> +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.c
[ ... ]
> @@ -492,6 +689,17 @@ 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_buffer_line_vp9d_ar50lt(u32 frame_width, u32 frame_height, u32 _yuv_bufcount_min)
> +{
> + return ALIGN(size_vpxd_lb_fe_left_ctrl(frame_width, frame_height), DMA_ALIGNMENT) +
> + ALIGN(size_vpxd_lb_se_left_ctrl_ar50lt(frame_width, frame_height), DMA_ALIGNMENT) +
> + 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);
> +}
> +
[Severity: Medium]
Are we missing some components in this VP9 line buffer size calculation?
Looking at the non-AR50LT VP9 calculation (hfi_iris3_vp9d_lb_size), there
are several additional components such as size_vpxd_lb_fe_top_ctrl(),
size_vpxd_lb_recon_dma_metadata_wr(), and size_vp9d_qp().
The AR50LT line buffer calculations for H.264 and HEVC also properly include
their respective recon_dma_metadata_wr and qp components.
If the AR50LT hardware expects these regions during a VP9 decode session,
omitting them could potentially lead to an out-of-bounds DMA write by the
VPU hardware. Should these components be included here as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=15
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 16/18] media: iris: add Gen2 firmware support on the Agatti platform
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (14 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 15/18] media: iris: Introduce buffer size calculations for AR50LT Dmitry Baryshkov
@ 2026-07-30 15:20 ` Dmitry Baryshkov
2026-07-30 15:21 ` [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
` (2 subsequent siblings)
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:20 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).
Add the Gen2 encoder controls supported by this firmware: the Long-Term
Reference control and hierarchical (layered) coding.
Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Co-developed-by: Vishnu Reddy <busanna.reddy@oss.qualcomm.com>
Signed-off-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_hfi_gen2.c | 825 +++++++++++++++++++++
.../platform/qcom/iris/iris_platform_common.h | 1 +
.../platform/qcom/iris/iris_platform_vpu_ar50lt.c | 7 +
3 files changed, 833 insertions(+)
diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
index acc0ed8adda1..74115e15edbc 100644
--- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
+++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c
@@ -1118,3 +1118,828 @@ 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,
+ },
+ {
+ .cap_id = LTR_COUNT,
+ .min = 0,
+ .max = MAX_LTR_FRAME_COUNT_GEN2,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROP_LTR_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ .set = iris_set_ltr_count_gen2,
+ },
+ {
+ .cap_id = USE_LTR,
+ .min = 0,
+ .max = ((1 << MAX_LTR_FRAME_COUNT_GEN2) - 1),
+ .step_or_mask = 0,
+ .value = 0,
+ .hfi_id = HFI_PROP_LTR_USE,
+ .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_use_and_mark_ltr,
+ },
+ {
+ .cap_id = MARK_LTR,
+ .min = INVALID_DEFAULT_MARK_OR_USE_LTR,
+ .max = (MAX_LTR_FRAME_COUNT_GEN2 - 1),
+ .step_or_mask = 1,
+ .value = INVALID_DEFAULT_MARK_OR_USE_LTR,
+ .hfi_id = HFI_PROP_LTR_MARK,
+ .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_use_and_mark_ltr,
+ },
+ {
+ .cap_id = LAYER_ENABLE,
+ .min = 0,
+ .max = 1,
+ .step_or_mask = 1,
+ .value = 0,
+ .flags = CAP_FLAG_OUTPUT_PORT,
+ },
+ {
+ .cap_id = LAYER_TYPE_H264,
+ .min = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
+ .max = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) |
+ BIT(V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P),
+ .value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+ .hfi_id = HFI_PROP_LAYER_ENCODING_TYPE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_layer_type,
+ },
+ {
+ .cap_id = LAYER_TYPE_HEVC,
+ .min = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+ .max = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
+ .step_or_mask = BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B) |
+ BIT(V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P),
+ .value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
+ .hfi_id = HFI_PROP_LAYER_ENCODING_TYPE,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_MENU,
+ .set = iris_set_layer_type,
+ },
+ {
+ .cap_id = LAYER_COUNT_H264,
+ .min = 0,
+ .max = 5,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROP_LAYER_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_count_gen2,
+ },
+ {
+ .cap_id = LAYER_COUNT_HEVC,
+ .min = 0,
+ .max = 5,
+ .step_or_mask = 1,
+ .value = 0,
+ .hfi_id = HFI_PROP_LAYER_COUNT,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_count_gen2,
+ },
+ {
+ .cap_id = LAYER0_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER1,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER1_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER2,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER2_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER3,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER3_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER4,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER4_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER5,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER5_BITRATE_H264,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER6,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER0_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER1,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER1_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER2,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER2_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER3,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER3_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER4,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER4_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER5,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+ {
+ .cap_id = LAYER5_BITRATE_HEVC,
+ .min = 1,
+ .max = BITRATE_MAX_AR50LT,
+ .step_or_mask = 1,
+ .value = BITRATE_DEFAULT_AR50LT,
+ .hfi_id = HFI_PROP_BITRATE_LAYER6,
+ .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_INPUT_PORT |
+ CAP_FLAG_DYNAMIC_ALLOWED,
+ .set = iris_set_layer_bitrate,
+ },
+};
+
+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 06d9f72dd6d6..de6d3954e4b0 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 92f7e2546539..99c839a0424f 100644
--- a/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
+++ b/drivers/media/platform/qcom/iris/iris_platform_vpu_ar50lt.c
@@ -19,6 +19,12 @@ static const struct iris_firmware_desc iris_vpu_ar50lt_p1_gen1_s6_desc = {
.fwname = "qcom/venus-6.0/venus.mbn",
};
+static 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[] = {
V4L2_PIX_FMT_H264,
V4L2_PIX_FMT_HEVC,
@@ -79,6 +85,7 @@ 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_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] 32+ messages in thread* [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (15 preceding siblings ...)
2026-07-30 15:20 ` [PATCH v8 16/18] media: iris: add Gen2 firmware support on the Agatti platform Dmitry Baryshkov
@ 2026-07-30 15:21 ` Dmitry Baryshkov
2026-07-30 15:39 ` sashiko-bot
2026-07-30 15:21 ` [PATCH v8 18/18] media: iris: constify inst_fw_cap_sm8250_dec Dmitry Baryshkov
2026-07-30 20:09 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Bryan O'Donoghue
18 siblings, 1 reply; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:21 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.
Reviewed-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/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] 32+ messages in thread* Re: [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled
2026-07-30 15:21 ` [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
@ 2026-07-30 15:39 ` sashiko-bot
0 siblings, 0 replies; 32+ messages in thread
From: sashiko-bot @ 2026-07-30 15:39 UTC (permalink / raw)
To: Dmitry Baryshkov; +Cc: media-ci, conor+dt, robh, devicetree
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Unbalanced teardown of delayed work core->work leads to Use-After-Free.
- [Medium] Memory and DMA allocations are leaked on the venus_probe() error path.
--
--- Patch [17]: [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled ---
commit 3f4135bbccd5abb2cbdcfce435629b2b86cda1f5
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: Medium]
This is a pre-existing issue, but does the error path in venus_probe() leak
memory and DMA allocations?
Looking at venus_probe(), if devm_request_threaded_irq() fails, the code jumps
directly to err_core_put:
drivers/media/platform/qcom/venus/core.c:venus_probe() {
...
ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
"venus", core);
if (ret)
goto err_core_put;
...
err_hfi_destroy:
hfi_destroy(core);
err_core_put:
...
}
This bypasses err_hfi_destroy and skips the hfi_destroy() cleanup, permanently
leaking the resources allocated by hfi_create(). Should the failure path jump
to err_hfi_destroy instead?
[Severity: Critical]
This is a pre-existing issue, but could the delayed work core->work lead to a
use-after-free?
In the venus_probe() error path, cancel_delayed_work_sync() is omitted entirely.
If the IRQ is successfully registered and fires before probe aborts, it can
queue core->work which could execute after the core object is freed.
Additionally, in venus_remove():
drivers/media/platform/qcom/venus/core.c:venus_remove() {
cancel_delayed_work_sync(&core->work);
...
hfi_destroy(core);
...
}
cancel_delayed_work_sync() is invoked before the IRQ is disabled in
hfi_destroy(). If an interrupt fires between these two calls, the ISR can
re-queue the work, which will subsequently execute on a freed core object.
Could we move the cancel_delayed_work_sync() call after the IRQ is disabled?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260730-iris-ar50lt-v8-0-6597c08cea6f@oss.qualcomm.com?part=17
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH v8 18/18] media: iris: constify inst_fw_cap_sm8250_dec
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (16 preceding siblings ...)
2026-07-30 15:21 ` [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled Dmitry Baryshkov
@ 2026-07-30 15:21 ` Dmitry Baryshkov
2026-07-30 20:09 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Bryan O'Donoghue
18 siblings, 0 replies; 32+ messages in thread
From: Dmitry Baryshkov @ 2026-07-30 15:21 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>
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_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 020f55092737..b7b1b852d45a 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] 32+ messages in thread* Re: [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform
2026-07-30 15:20 ` [PATCH v8 00/18] media: iris: Add AR50LT core support and enable Agatti platform Dmitry Baryshkov
` (17 preceding siblings ...)
2026-07-30 15:21 ` [PATCH v8 18/18] media: iris: constify inst_fw_cap_sm8250_dec Dmitry Baryshkov
@ 2026-07-30 20:09 ` Bryan O'Donoghue
18 siblings, 0 replies; 32+ messages in thread
From: Bryan O'Donoghue @ 2026-07-30 20:09 UTC (permalink / raw)
To: Dmitry Baryshkov, Vikash Garodia, Abhinav Kumar,
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
On 30/07/2026 16:20, Dmitry Baryshkov wrote:
> This series adds support for the AR50Lt VPU core to the iris driver and
> enables the Agatti SoC to use Gen2 firmware and HFI.
>
> AR50Lt introduces a few platform-specific requirements that need to be
> handled in the iris core and VPU abstraction layer. To accommodate
> this, the series adds minimal hooks and updates needed to allow the
> firmware to operate correctly on AR50Lt without impacting existing
> supported platforms.
>
> Additionally, the series wires up Agatti to use the Gen2 firmware and
> HFI path, aligning it with newer generations of supported Qualcomm
> video hardware.
can't apply
b4 shazam 20260730-iris-ar50lt-v8-1-6597c08cea6f@oss.qualcomm.com
Looking up
https://lore.kernel.org/all/20260730-iris-ar50lt-v8-1-6597c08cea6f@oss.qualcomm.com/
Grabbing thread from
lore.kernel.org/all/20260730-iris-ar50lt-v8-1-6597c08cea6f@oss.qualcomm.com/t.mbox.gz
Checking for newer revisions
Grabbing search results from lore.kernel.org
Analyzing 31 messages in the thread
Analyzing 225 code-review messages
Checking attestation on all messages, may take a moment...
---
✓ [PATCH v8 1/18] media: iris: Add Gen2 firmware autodetect and fallback
+ Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> (✓
DKIM/kernel.org)
✓ [PATCH v8 2/18] media: iris: Skip UBWC configuration when not supported
✓ [PATCH v8 3/18] media: iris: drop IRIS_FMT_foo enumeration
✓ [PATCH v8 4/18] media: iris: Filter UBWC raw formats based on
hardware capabilities
✓ [PATCH v8 5/18] media: iris: Introduce set_preset_register as a vpu_op
✓ [PATCH v8 6/18] media: iris: Introduce interrupt_init as a vpu_op
✓ [PATCH v8 7/18] media: iris: add vpu op hook to disable ARP buffer
✓ [PATCH v8 8/18] media: iris: Add platform data field for watchdog
interrupt mask
✓ [PATCH v8 9/18] media: iris: Add platform flag for instantaneous
bandwidth voting
✓ [PATCH v8 10/18] media: iris: skip PIPE if it is not supported by
the platform
✓ [PATCH v8 11/18] media: iris: Add framework support for AR50_LITE
video core
✓ [PATCH v8 12/18] media: iris: add minimal GET_PROPERTY implementation
✓ [PATCH v8 13/18] media: iris: update buffer requirements based on
received info
✓ [PATCH v8 14/18] media: iris: implement support for the Agatti platform
✓ [PATCH v8 15/18] media: iris: Introduce buffer size calculations
for AR50LT
✓ [PATCH v8 16/18] media: iris: add Gen2 firmware support on the
Agatti platform
✓ [PATCH v8 17/18] media: venus: skip QCM2290 if Iris driver is enabled
✓ [PATCH v8 18/18] media: iris: constify inst_fw_cap_sm8250_dec
---
✓ Signed: openpgp/dbaryshkov@gmail.com (From:
dmitry.baryshkov@oss.qualcomm.com)
✓ Signed: DKIM/oss.qualcomm.com
---
Total patches: 18
---
Applying: media: iris: Add Gen2 firmware autodetect and fallback
Patch failed at 0001 media: iris: Add Gen2 firmware autodetect and fallback
error: patch failed: drivers/media/platform/qcom/iris/iris_firmware.c:14
error: drivers/media/platform/qcom/iris/iris_firmware.c: patch does not
apply
error: patch failed:
drivers/media/platform/qcom/iris/iris_platform_common.h:289
error: drivers/media/platform/qcom/iris/iris_platform_common.h: patch
does not apply
error: patch failed:
drivers/media/platform/qcom/iris/iris_platform_vpu2.c:22
error: drivers/media/platform/qcom/iris/iris_platform_vpu2.c: patch does
not apply
error: patch failed:
drivers/media/platform/qcom/iris/iris_platform_vpu3x.c:90
error: drivers/media/platform/qcom/iris/iris_platform_vpu3x.c: patch
does not apply
error: patch failed: drivers/media/platform/qcom/iris/iris_probe.c:251
error: drivers/media/platform/qcom/iris/iris_probe.c: patch does not apply
error: patch failed: drivers/media/platform/qcom/iris/iris_vidc.c:9
error: drivers/media/platform/qcom/iris/iris_vidc.c: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am
--abort".
hint: Disable this message with "git config set advice.mergeConflict false"
^ permalink raw reply [flat|nested] 32+ messages in thread