On Mon Dec 30 17:00:33 2024 +0000, Bryan O'Donoghue wrote:
> Add resource structure data and probe() logic to support static
> declarations of encoder and decoder.
> 
> Right now we rely on video encoder/decoder selection happening in the dtb
> but, this goes against the remit of device tree which is supposed to
> describe hardware, not select functional logic in Linux drivers.
> 
> Provide two strings in the venus resource structure enc_nodename and
> dec_nodename.
> 
> When set the venus driver will create an OF entry in-memory consistent
> with:
> 
> dec_nodename {
>     compat = "video-decoder";
> };
> 
> and/or
> 
> enc_nodename {
>     compat = "video-encoder";
> };
> 
> This will allow us to reuse the existing driver scheme of relying on compat
> names maintaining compatibility with old dtb files.
> 
> dec_nodename can be "video-decoder" or "video0"
> enc_nodename can be "video-encoder" or "video1"
> 
> This change relies on of_changeset() API as a result select OF_DYNAMIC will
> be added to venus/Kconfig
> 
> Tested-by: Renjiang Han <quic_renji...@quicinc.com>
> Signed-off-by: Bryan O'Donoghue <bryan.odonog...@linaro.org>
> Signed-off-by: Stanimir Varbanov <stanimir.k.varba...@gmail.com>
> Signed-off-by: Hans Verkuil <hverk...@xs4all.nl>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/platform/qcom/venus/Kconfig |  1 +
 drivers/media/platform/qcom/venus/core.c  | 95 ++++++++++++++++++++++++++++++-
 drivers/media/platform/qcom/venus/core.h  |  4 ++
 3 files changed, 99 insertions(+), 1 deletion(-)

---

diff --git a/drivers/media/platform/qcom/venus/Kconfig 
b/drivers/media/platform/qcom/venus/Kconfig
index bfd50e8f3421..bc2e410b29cb 100644
--- a/drivers/media/platform/qcom/venus/Kconfig
+++ b/drivers/media/platform/qcom/venus/Kconfig
@@ -3,6 +3,7 @@ config VIDEO_QCOM_VENUS
        depends on V4L_MEM2MEM_DRIVERS
        depends on VIDEO_DEV && QCOM_SMEM
        depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
+       select OF_DYNAMIC if ARCH_QCOM
        select QCOM_MDT_LOADER if ARCH_QCOM
        select QCOM_SCM
        select VIDEOBUF2_DMA_CONTIG
diff --git a/drivers/media/platform/qcom/venus/core.c 
b/drivers/media/platform/qcom/venus/core.c
index 807487a1f536..cffd73453cf0 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -286,6 +286,89 @@ static irqreturn_t venus_isr_thread(int irq, void *dev_id)
        return ret;
 }
 
+#if defined(CONFIG_OF_DYNAMIC)
+static int venus_add_video_core(struct venus_core *core, const char *node_name,
+                               const char *compat)
+{
+       struct of_changeset *ocs = core->ocs;
+       struct device *dev = core->dev;
+       struct device_node *np, *enp;
+       int ret;
+
+       if (!node_name)
+               return 0;
+
+       enp = of_find_node_by_name(dev->of_node, node_name);
+       if (enp) {
+               of_node_put(enp);
+               return 0;
+       }
+
+       np = of_changeset_create_node(ocs, dev->of_node, node_name);
+       if (!np) {
+               dev_err(dev, "Unable to create new node\n");
+               return -ENODEV;
+       }
+
+       ret = of_changeset_add_prop_string(ocs, np, "compatible", compat);
+       if (ret)
+               dev_err(dev, "unable to add %s\n", compat);
+
+       of_node_put(np);
+
+       return ret;
+}
+
+static int venus_add_dynamic_nodes(struct venus_core *core)
+{
+       struct device *dev = core->dev;
+       int ret;
+
+       core->ocs = kmalloc(sizeof(*core->ocs), GFP_KERNEL);
+       if (!core->ocs)
+               return -ENOMEM;
+
+       of_changeset_init(core->ocs);
+
+       ret = venus_add_video_core(core, core->res->dec_nodename, 
"venus-decoder");
+       if (ret)
+               goto err;
+
+       ret = venus_add_video_core(core, core->res->enc_nodename, 
"venus-encoder");
+       if (ret)
+               goto err;
+
+       ret = of_changeset_apply(core->ocs);
+       if (ret) {
+               dev_err(dev, "applying changeset fail ret %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+err:
+       of_changeset_destroy(core->ocs);
+       kfree(core->ocs);
+       core->ocs = NULL;
+       return ret;
+}
+
+static void venus_remove_dynamic_nodes(struct venus_core *core)
+{
+       if (core->ocs) {
+               of_changeset_revert(core->ocs);
+               of_changeset_destroy(core->ocs);
+               kfree(core->ocs);
+       }
+}
+#else
+static int venus_add_dynamic_nodes(struct venus_core *core)
+{
+       return 0;
+}
+
+static void venus_remove_dynamic_nodes(struct venus_core *core) {}
+#endif
+
 static int venus_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -365,9 +448,15 @@ static int venus_probe(struct platform_device *pdev)
        if (ret < 0)
                goto err_runtime_disable;
 
+       if (core->res->dec_nodename || core->res->enc_nodename) {
+               ret = venus_add_dynamic_nodes(core);
+               if (ret)
+                       goto err_runtime_disable;
+       }
+
        ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
        if (ret)
-               goto err_runtime_disable;
+               goto err_remove_dynamic_nodes;
 
        ret = venus_firmware_init(core);
        if (ret)
@@ -411,6 +500,8 @@ err_firmware_deinit:
        venus_firmware_deinit(core);
 err_of_depopulate:
        of_platform_depopulate(dev);
+err_remove_dynamic_nodes:
+       venus_remove_dynamic_nodes(core);
 err_runtime_disable:
        pm_runtime_put_noidle(dev);
        pm_runtime_disable(dev);
@@ -443,6 +534,8 @@ static void venus_remove(struct platform_device *pdev)
 
        venus_firmware_deinit(core);
 
+       venus_remove_dynamic_nodes(core);
+
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
 
diff --git a/drivers/media/platform/qcom/venus/core.h 
b/drivers/media/platform/qcom/venus/core.h
index 44f1c3bc4186..abeeafa86697 100644
--- a/drivers/media/platform/qcom/venus/core.h
+++ b/drivers/media/platform/qcom/venus/core.h
@@ -90,6 +90,8 @@ struct venus_resources {
        u32 cp_nonpixel_start;
        u32 cp_nonpixel_size;
        const char *fwname;
+       const char *enc_nodename;
+       const char *dec_nodename;
 };
 
 enum venus_fmt {
@@ -169,6 +171,7 @@ struct venus_format {
  * @root:      debugfs root directory
  * @venus_ver: the venus firmware version
  * @dump_core: a flag indicating that a core dump is required
+ * @ocs:       OF changeset pointer
  */
 struct venus_core {
        void __iomem *base;
@@ -231,6 +234,7 @@ struct venus_core {
                u32 rev;
        } venus_ver;
        unsigned long dump_core;
+       struct of_changeset *ocs;
 };
 
 struct vdec_controls {

Reply via email to