From: "Kyrie Wu (吴晗)" <Kyrie.Wu@mediatek.com>
To: "linux-mediatek@lists.infradead.org"
<linux-mediatek@lists.infradead.org>,
"Yunfei Dong (董云飞)" <Yunfei.Dong@mediatek.com>,
"ribalda@chromium.org" <ribalda@chromium.org>,
"robh@kernel.org" <robh@kernel.org>,
"fanwu01@zju.edu.cn" <fanwu01@zju.edu.cn>,
"linux-media@vger.kernel.org" <linux-media@vger.kernel.org>,
"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
"haoxiang_li2024@163.com" <haoxiang_li2024@163.com>,
"nicolas.dufresne@collabora.com" <nicolas.dufresne@collabora.com>,
"Andrew-CT Chen (陳智迪)" <Andrew-CT.Chen@mediatek.com>,
"AngeloGioacchino Del Regno"
<angelogioacchino.delregno@collabora.com>,
"mchehab@kernel.org" <mchehab@kernel.org>,
"conor+dt@kernel.org" <conor+dt@kernel.org>,
"Tiffany Lin (林慧珊)" <tiffany.lin@mediatek.com>,
"sebastian.fricke@collabora.com" <sebastian.fricke@collabora.com>,
"benjamin.gaignard@collabora.com"
<benjamin.gaignard@collabora.com>,
"rongqianfeng@vivo.com" <rongqianfeng@vivo.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"fshao@chromium.org" <fshao@chromium.org>,
"kees@kernel.org" <kees@kernel.org>,
"Kyrie Wu (吴晗)" <Kyrie.Wu@mediatek.com>,
"krzk+dt@kernel.org" <krzk+dt@kernel.org>,
"laurent.pinchart+renesas@ideasonboard.com"
<laurent.pinchart+renesas@ideasonboard.com>,
"wenst@chromium.org" <wenst@chromium.org>,
"Irui Wang (王瑞)" <Irui.Wang@mediatek.com>,
"linux-arm-kernel@lists.infradead.org"
<linux-arm-kernel@lists.infradead.org>,
"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
"hverkuil+cisco@kernel.org" <hverkuil+cisco@kernel.org>,
"jacopo.mondi@ideasonboard.com" <jacopo.mondi@ideasonboard.com>,
"p.zabel@pengutronix.de" <p.zabel@pengutronix.de>
Cc: "tfiga@chromium.org" <tfiga@chromium.org>,
"tzungbi@kernel.org" <tzungbi@kernel.org>,
"sakari.ailus@linux.intel.com" <sakari.ailus@linux.intel.com>
Subject: Re: [PATCH v5 02/14] media: mediatek: vcodec: add driver to support vcp
Date: Fri, 17 Jul 2026 01:53:25 +0000 [thread overview]
Message-ID: <676d9876bef1886de78a2bca73ffaa6a87bc804d.camel@mediatek.com> (raw)
In-Reply-To: <2dad1d32f59b271e9cf53f0da71b584e2e04a889.camel@collabora.com>
On Wed, 2026-07-15 at 20:50 -0400, Nicolas Dufresne wrote:
> Le mercredi 03 juin 2026 à 16:40 +0800, Kyrie Wu a écrit :
> > From: Yunfei Dong <yunfei.dong@mediatek.com>
> >
> > The processor is changed from scp to vcp in mt8196 platform.
> > Adding new firmware interface to communicate kernel with vcp
> > for the communication method is changed.
> >
> > Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
> > ---
> > .../media/platform/mediatek/vcodec/Kconfig | 4 +
> > .../platform/mediatek/vcodec/common/Makefile | 4 +
> > .../mediatek/vcodec/common/mtk_vcodec_fw.c | 26 +-
> > .../vcodec/common/mtk_vcodec_fw_priv.h | 12 +
> > .../vcodec/common/mtk_vcodec_fw_scp.c | 1 +
> > .../vcodec/common/mtk_vcodec_fw_vcp.c | 505
> > ++++++++++++++++++
> > .../vcodec/common/mtk_vcodec_fw_vcp.h | 142 +++++
> > .../vcodec/common/mtk_vcodec_fw_vpu.c | 1 +
> > .../vcodec/decoder/mtk_vcodec_dec_drv.c | 3 +
> > .../vcodec/decoder/mtk_vcodec_dec_drv.h | 2 +
> > .../vcodec/encoder/mtk_vcodec_enc_drv.c | 2 +
> > .../vcodec/encoder/mtk_vcodec_enc_drv.h | 2 +
> > 12 files changed, 691 insertions(+), 13 deletions(-)
> > create mode 100644
> > drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.c
> > create mode 100644
> > drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.h
> >
> > diff --git a/drivers/media/platform/mediatek/vcodec/Kconfig
> > b/drivers/media/platform/mediatek/vcodec/Kconfig
> > index bc8292232530..d23dad5c78ce 100644
> > --- a/drivers/media/platform/mediatek/vcodec/Kconfig
> > +++ b/drivers/media/platform/mediatek/vcodec/Kconfig
> > @@ -1,4 +1,7 @@
> > # SPDX-License-Identifier: GPL-2.0-only
> > +config VIDEO_MEDIATEK_VCODEC_VCP
> > + bool
> > +
> > config VIDEO_MEDIATEK_VCODEC_SCP
> > bool
> >
> > @@ -21,6 +24,7 @@ config VIDEO_MEDIATEK_VCODEC
> > select V4L2_MEM2MEM_DEV
> > select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
> > select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP
> > + select VIDEO_MEDIATEK_VCODEC_VCP if MTK_VCP_RPROC
> > select V4L2_H264
> > select V4L2_VP9
> > select MEDIA_CONTROLLER
> > diff --git a/drivers/media/platform/mediatek/vcodec/common/Makefile
> > b/drivers/media/platform/mediatek/vcodec/common/Makefile
> > index d0479914dfb3..2f68692e8c98 100644
> > --- a/drivers/media/platform/mediatek/vcodec/common/Makefile
> > +++ b/drivers/media/platform/mediatek/vcodec/common/Makefile
> > @@ -14,6 +14,10 @@ ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),)
> > mtk-vcodec-common-y += mtk_vcodec_fw_scp.o
> > endif
> >
> > +ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_VCP),)
> > +mtk-vcodec-common-y += mtk_vcodec_fw_vcp.o
> > +endif
> > +
> > ifneq ($(CONFIG_DEBUG_FS),)
> > obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dbgfs.o
> >
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> > index 08949b08fbc6..64977bcd6abd 100644
> > --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> > +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw.c
> > @@ -3,26 +3,26 @@
> > #include "../decoder/mtk_vcodec_dec_drv.h"
> > #include "../encoder/mtk_vcodec_enc_drv.h"
> > #include "mtk_vcodec_fw_priv.h"
> > +#include "mtk_vcodec_fw_vcp.h"
> >
> > struct mtk_vcodec_fw *mtk_vcodec_fw_select(void *priv, enum
> > mtk_vcodec_fw_type type,
> > enum mtk_vcodec_fw_use
> > fw_use)
> > {
> > - struct platform_device *plat_dev;
> > + if (fw_use == ENCODER) {
> > + struct mtk_vcodec_enc_dev *enc_dev = priv;
> >
> > - if (fw_use == ENCODER)
> > - plat_dev = ((struct mtk_vcodec_enc_dev *)priv)-
> > >plat_dev;
> > - else
> > - plat_dev = ((struct mtk_vcodec_dec_dev *)priv)-
> > >plat_dev;
> > + return enc_dev->fw_init(priv, fw_use);
> > + }
> > +
> > + if (fw_use == DECODER) {
>
> Should we construct this a little safer and use some if/else if/else
> with some
> bug_on in the last entry, or same with a switch ?
Dear Nicolas,
Thanks for the suggestion.
I agree that the current helper should not infer the device type by
casting priv based on fw_use. In the next version I will rework this so
that the encoder/decoder probe code passes the selected firmware init
callback into mtk_vcodec_fw_select() directly.
With that change, mtk_vcodec_fw_select() only validates fw_use and the
callback pointer, then calls the selected callback:
dev->fw_handler = mtk_vcodec_fw_select(dev, DECODER, ev->fw_init);
function definition:
struct mtk_vcodec_fw *mtk_vcodec_fw_select(void *priv, enum
mtk_vcodec_fw_use fw_use, mtk_vcodec_fw_init_func fw_init);
This removes the encoder/decoder casts from mtk_vcodec_fw_select() and
keeps the invalid fw_use path explicit.
I will fold this into v6.
Thanks,
Kyrie
>
> > + struct mtk_vcodec_dec_dev *dec_dev = priv;
> >
> > - switch (type) {
> > - case VPU:
> > - return mtk_vcodec_fw_vpu_init(priv, fw_use);
> > - case SCP:
> > - return mtk_vcodec_fw_scp_init(priv, fw_use);
> > - default:
> > - dev_err(&plat_dev->dev, "Invalid vcodec fw type");
> > - return ERR_PTR(-EINVAL);
> > + return dec_dev->fw_init(priv, fw_use);
> > }
> > +
> > + pr_err("Error in selecting firmware, fw_use is not set");
> > +
> > + return ERR_PTR(-EINVAL);
> > }
> > EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select);
> >
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_priv.
> > h
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_priv.
> > h
> > index 99603accd82e..0a2a9b010244 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_priv.
> > h
> > +++
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_priv.
> > h
> > @@ -4,6 +4,7 @@
> > #define _MTK_VCODEC_FW_PRIV_H_
> >
> > #include "mtk_vcodec_fw.h"
> > +#include "mtk_vcodec_fw_vcp.h"
> >
> > struct mtk_vcodec_dec_dev;
> > struct mtk_vcodec_enc_dev;
> > @@ -13,6 +14,7 @@ struct mtk_vcodec_fw {
> > const struct mtk_vcodec_fw_ops *ops;
> > struct platform_device *pdev;
> > struct mtk_scp *scp;
> > + struct mtk_vcp *vcp;
> > enum mtk_vcodec_fw_use fw_use;
> > };
> >
> > @@ -49,4 +51,14 @@ mtk_vcodec_fw_scp_init(void *priv, enum
> > mtk_vcodec_fw_use fw_use)
> > }
> > #endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_SCP */
> >
> > +#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_VCP)
> > +struct mtk_vcodec_fw *mtk_vcodec_fw_vcp_init(void *priv, enum
> > mtk_vcodec_fw_use fw_use);
> > +#else
> > +static inline struct mtk_vcodec_fw *
> > +mtk_vcodec_fw_vcp_init(void *priv, enum mtk_vcodec_fw_use fw_use)
> > +{
> > + return ERR_PTR(-ENODEV);
> > +}
> > +#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_VCP */
> > +
> > #endif /* _MTK_VCODEC_FW_PRIV_H_ */
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
> > index 1b0bc47355c0..1aad5c3ef990 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
> > +++
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
> > @@ -90,3 +90,4 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void
> > *priv, enum mtk_vcodec_fw_use
> >
> > return fw;
> > }
> > +EXPORT_SYMBOL_GPL(mtk_vcodec_fw_scp_init);
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.c
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.c
> > new file mode 100644
> > index 000000000000..2f3bfcd97958
> > --- /dev/null
> > +++
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.c
> > @@ -0,0 +1,505 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + * Author: Yunfei Dong <yunfei.dong@mediatek.com>
> > + */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/dma-direction.h>
> > +#include <linux/dma-mapping.h>
> > +#include <linux/iommu.h>
> > +#include <linux/remoteproc/mtk_vcp_public.h>
> > +#include <linux/firmware/mediatek/mtk-vcp-ipc.h>
> > +
> > +#include "../decoder/mtk_vcodec_dec_drv.h"
> > +#include "../decoder/vdec_ipi_msg.h"
> > +#include "mtk_vcodec_fw_priv.h"
> > +
> > +#define IPI_SEND_TIMEOUT_MS 100U
> > +#define IPI_TIMEOUT_MS 100U
> > +
> > +#define VCP_IPI_HEADER_SIZE (sizeof(u32) * 2)
> > +#define VCP_IPI_ALIGN (4)
> > +
> > +static struct mutex *mtk_vcodec_vcp_get_ipi_lock(struct mtk_vcp
> > *vcp, u32 ipi_id)
> > +{
> > + return &vcp->ipi_desc[ipi_id].lock;
>
> Maybe add sound bound checks ?
>
> > +}
> > +
> > +static void mtk_vcodec_vcp_ipi_lock(struct mtk_vcp *vcp, u32
> > ipi_id)
> > +{
> > + struct mutex *lock = mtk_vcodec_vcp_get_ipi_lock(vcp,
> > ipi_id);
> > +
> > + if (!lock)
> > + return;
>
> mtk_vcodec_vcp_get_ipi_lock() nevers return null at the minute.
>
> > +
> > + mutex_lock(lock);
> > +}
> > +
> > +static void mtk_vcodec_vcp_ipi_unlock(struct mtk_vcp *vcp, u32
> > ipi_id)
> > +{
> > + struct mutex *lock = mtk_vcodec_vcp_get_ipi_lock(vcp,
> > ipi_id);
> > +
> > + if (!lock)
> > + return;
> > +
> > + lockdep_assert_held(lock);
> > + mutex_unlock(lock);
> > +}
> > +
> > +static spinlock_t *mtk_vcodec_vcp_get_msg_queue_lock(struct
> > mtk_vcodec_fw *fw)
> > +{
> > + return &fw->vcp->msg_queue.lock;
> > +}
> > +
> > +static void mtk_vcodec_vcp_msq_queue_lock(struct mtk_vcodec_fw
> > *fw, unsigned long *flags)
> > +{
> > + spinlock_t *lock = mtk_vcodec_vcp_get_msg_queue_lock(fw);
> > +
> > + if (!lock)
> > + return;
>
> mtk_vcodec_vcp_get_msg_queue_lock() never returns null.
>
> > +
> > + spin_lock_irqsave(lock, *flags);
> > +}
> > +
> > +static void mtk_vcodec_vcp_msq_queue_unlock(struct mtk_vcodec_fw
> > *fw, unsigned long *flags)
> > +{
> > + spinlock_t *lock = mtk_vcodec_vcp_get_msg_queue_lock(fw);
> > +
> > + if (!lock)
> > + return;
> > +
> > + spin_unlock_irqrestore(lock, *flags);
> > +}
> > +
> > +static int mtk_vcodec_vcp_notifier(struct notifier_block *nb,
> > unsigned long event, void *ptr)
> > +{
> > + struct mtk_vcp *vcp = container_of(nb, struct mtk_vcp,
> > vcp_notify);
> > +
> > + switch (event) {
> > + case VCP_EVENT_SUSPEND:
> > + case VCP_EVENT_STOP:
> > + dev_dbg(&vcp->pdev->dev, "vcp notifier suspend");
> > + break;
> > + case VCP_EVENT_READY:
> > + case VCP_EVENT_RESUME:
> > + dev_dbg(&vcp->pdev->dev, "vcp notifier ready");
> > + break;
> > + }
> > +
> > + return NOTIFY_DONE;
> > +}
> > +
> > +static void mtk_vcodec_vcp_free_msg_node(struct mtk_vcodec_fw *fw,
> > + struct mtk_vcp_msg_node
> > *msg_node)
> > +{
> > + unsigned long flags;
> > +
> > + mtk_vcodec_vcp_msq_queue_lock(fw, &flags);
> > + list_add(&msg_node->list, &fw->vcp->msg_queue.node_list);
> > + mtk_vcodec_vcp_msq_queue_unlock(fw, &flags);
> > +}
> > +
> > +static int mtk_vcodec_vcp_ipi_register(struct mtk_vcp *vcp, u32
> > ipi_id, vcp_ipi_handler_t handler,
> > + void *priv)
> > +{
> > + if (!vcp)
> > + return -EPROBE_DEFER;
> > +
> > + if (WARN_ON(ipi_id >= VCP_IPI_MAX) || WARN_ON(!handler))
> > + return -EINVAL;
>
> Ok, fair enough as a bound check I guess, thought the get/null-check
> construct
> still make no sense.
>
> Stopping there, I'm on a time crunch, but considering the
> dependencies aren't
> met, feel free to ping me again for more reviews.
>
> Nicolas
Thanks. I will fix it.
>
> > +
> > + mtk_vcodec_vcp_ipi_lock(vcp, ipi_id);
> > + vcp->ipi_desc[ipi_id].handler = handler;
> > + vcp->ipi_desc[ipi_id].priv = priv;
> > + mtk_vcodec_vcp_ipi_unlock(vcp, ipi_id);
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_vcodec_vcp_msg_process_thread(void *arg)
> > +{
> > + struct mtk_vcodec_fw *fw = arg;
> > + struct vdec_vpu_ipi_ack *msg = NULL;
> > + struct mtk_vcp_share_obj *obj;
> > + struct mtk_vcp_msg_node *msg_node;
> > + vcp_ipi_handler_t handler;
> > + unsigned long flags;
> > + int ret = 0;
> > +
> > + do {
> > + ret = wait_event_interruptible(fw->vcp-
> > >msg_queue.wq,
> > + atomic_read(&fw-
> > >vcp->msg_queue.cnt) > 0);
> > + if (ret < 0) {
> > + dev_err(&fw->pdev->dev, "wait msg queue
> > ack timeout %d %d\n",
> > + ret, atomic_read(&fw->vcp-
> > >msg_queue.cnt));
> > + continue;
> > + }
> > +
> > + mtk_vcodec_vcp_msq_queue_lock(fw, &flags);
> > + msg_node = list_entry(fw->vcp-
> > >msg_queue.msg_list.next,
> > + struct mtk_vcp_msg_node,
> > list);
> > + list_del(&msg_node->list);
> > + atomic_dec(&fw->vcp->msg_queue.cnt);
> > + mtk_vcodec_vcp_msq_queue_unlock(fw, &flags);
> > +
> > + obj = &msg_node->ipi_data;
> > + msg = (struct vdec_vpu_ipi_ack *)obj->share_buf;
> > +
> > + if (!msg->ap_inst_addr) {
> > + dev_err(&fw->pdev->dev, "invalid message
> > address\n");
> > + mtk_vcodec_vcp_free_msg_node(fw,
> > msg_node);
> > + continue;
> > + }
> > +
> > + dev_dbg(&fw->pdev->dev, "msg ack id %d len %d
> > msg_id 0x%x\n", obj->id, obj->len,
> > + msg->msg_id);
> > +
> > + mtk_vcodec_vcp_ipi_lock(fw->vcp, obj->id);
> > + handler = fw->vcp->ipi_desc[obj->id].handler;
> > + if (!handler) {
> > + dev_err(&fw->pdev->dev, "invalid ack ipi
> > handler id = %d\n", obj->id);
> > + mtk_vcodec_vcp_ipi_unlock(fw->vcp, obj-
> > >id);
> > + mtk_vcodec_vcp_free_msg_node(fw,
> > msg_node);
> > + return -EINVAL;
> > + }
> > +
> > + handler(msg, obj->len, fw->vcp->ipi_desc[obj-
> > >id].priv);
> > + mtk_vcodec_vcp_ipi_unlock(fw->vcp, obj->id);
> > +
> > + fw->vcp->msg_signaled[obj->id] = true;
> > + wake_up(&fw->vcp->msg_wq[obj->id]);
> > +
> > + mtk_vcodec_vcp_free_msg_node(fw, msg_node);
> > + } while (!kthread_should_stop());
> > +
> > + return ret;
> > +}
> > +
> > +static int mtk_vcodec_vcp_msg_ack_isr(unsigned int id, void
> > *prdata, void *data, unsigned int len)
> > +{
> > + struct mtk_vcodec_fw *fw = prdata;
> > + struct mtk_vcp_msg_queue *msg_queue = &fw->vcp->msg_queue;
> > + struct mtk_vcp_msg_node *msg_node;
> > + struct vdec_vpu_ipi_ack *msg = NULL;
> > + struct mtk_vcp_share_obj *obj = data;
> > + unsigned long flags;
> > +
> > + msg = (struct vdec_vpu_ipi_ack *)obj->share_buf;
> > +
> > + mtk_vcodec_vcp_msq_queue_lock(fw, &flags);
> > + if (!list_empty(&msg_queue->node_list)) {
> > + msg_node = list_entry(msg_queue->node_list.next,
> > struct mtk_vcp_msg_node, list);
> > +
> > + memcpy(&msg_node->ipi_data, obj, sizeof(*obj));
> > + list_move_tail(&msg_node->list, &msg_queue-
> > >msg_list);
> > + atomic_inc(&msg_queue->cnt);
> > + mtk_vcodec_vcp_msq_queue_unlock(fw, &flags);
> > +
> > + dev_dbg(&fw->pdev->dev, "push ipi_id %x msg_id %x,
> > msg cnt %d\n",
> > + obj->id, msg->msg_id,
> > atomic_read(&msg_queue->cnt));
> > +
> > + wake_up(&msg_queue->wq);
> > + } else {
> > + mtk_vcodec_vcp_msq_queue_unlock(fw, &flags);
> > + dev_err(&fw->pdev->dev, "no free nodes in msg
> > queue\n");
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_vcodec_vcp_msg_ipi_send(struct mtk_vcodec_fw *fw,
> > int id, void *buf,
> > + unsigned int len, unsigned
> > int wait)
> > +{
> > + struct mtk_vcp *vcp = fw->vcp;
> > + struct mtk_vcp_device *vcp_device = vcp->vcp_device;
> > + bool *msg_signaled = &vcp->msg_signaled[id];
> > + wait_queue_head_t *msg_wq = &vcp->msg_wq[id];
> > + int ret, ipi_size, feature_id, mailbox_id, retry_cnt = 0;
> > + unsigned long timeout_jiffies = 0;
> > + struct mtk_vcp_share_obj obj = {0};
> > + unsigned int *data;
> > +
> > + if (!vcp_device) {
> > + dev_dbg(&fw->pdev->dev, "vcp device is null\n");
> > + return -EINVAL;
> > + }
> > +
> > + mutex_lock(&vcp->ipi_mutex);
> > + feature_id = VDEC_FEATURE_ID;
> > + mailbox_id = IPI_OUT_VDEC_1;
> > +
> > + timeout_jiffies = jiffies +
> > msecs_to_jiffies(VCP_SYNC_TIMEOUT_MS);
> > + while (!vcp_device->ops->vcp_is_ready(feature_id)) {
> > + if (time_after(jiffies, timeout_jiffies)) {
> > + vcp->ipi_id_ack[id] = -EINVAL;
> > + ret = -EINVAL;
> > + goto error;
> > + }
> > + mdelay(1);
> > + }
> > +
> > + if (len > VCP_SHARE_BUF_SIZE) {
> > + vcp->ipi_id_ack[id] = -EINVAL;
> > + ret = -EINVAL;
> > + goto error;
> > + }
> > +
> > + obj.id = id;
> > + obj.len = len;
> > + memcpy(obj.share_buf, buf, len);
> > +
> > + ipi_size = round_up(VCP_IPI_HEADER_SIZE + len,
> > VCP_IPI_ALIGN);
> > + data = (unsigned int *)obj.share_buf;
> > + dev_dbg(&fw->pdev->dev, "vcp send message: id %d len %d
> > data 0x%x\n",
> > + obj.id, obj.len, data[0]);
> > +
> > + ret = mtk_vcp_ipc_send(vcp_get_ipidev(vcp_device),
> > mailbox_id, &obj, ipi_size);
> > + if (ret != IPI_ACTION_DONE) {
> > + vcp->ipi_id_ack[id] = -EIO;
> > + ret = -EIO;
> > + goto error;
> > + }
> > +
> > +wait_ack:
> > + /* wait for VCP's ACK */
> > + ret = wait_event_timeout(*msg_wq, *msg_signaled,
> > msecs_to_jiffies(IPI_TIMEOUT_MS));
> > + if (!ret || retry_cnt > 5) {
> > + vcp->ipi_id_ack[id] = VCODEC_IPI_MSG_STATUS_FAIL;
> > + dev_err(&fw->pdev->dev, "wait ipi ack timeout! %d
> > %d\n", ret, vcp->ipi_id_ack[id]);
> > + } else if (ret == -ERESTARTSYS) {
> > + dev_err(&fw->pdev->dev, "wait ipi ack err (%d)\n",
> > vcp->ipi_id_ack[id]);
> > + retry_cnt++;
> > + goto wait_ack;
> > + } else if (ret < 0) {
> > + dev_err(&fw->pdev->dev, "wait ipi ack fail ret %d
> > %d\n", ret, vcp->ipi_id_ack[id]);
> > + vcp->ipi_id_ack[id] = VCODEC_IPI_MSG_STATUS_FAIL;
> > + }
> > +
> > + dev_dbg(&fw->pdev->dev, "receive message: id %d len %d
> > data 0x%x\n",
> > + obj.id, obj.len, data[0]);
> > +
> > + *msg_signaled = false;
> > + mutex_unlock(&vcp->ipi_mutex);
> > +
> > + return vcp->ipi_id_ack[id];
> > +
> > +error:
> > + mutex_unlock(&vcp->ipi_mutex);
> > + dev_err(&fw->pdev->dev, "send msg error type:%d msg:%d >
> > %d ret:%d\n", fw->type, len,
> > + VCP_SHARE_BUF_SIZE, ret);
> > +
> > + return ret;
> > +}
> > +
> > +static int check_vcp_loaded(struct mtk_vcodec_fw *fw)
> > +{
> > + struct device *dev = &fw->pdev->dev;
> > + struct device_driver *drv;
> > +
> > + drv = driver_find("mtk-vcp", &platform_bus_type);
> > + if (!drv) {
> > + dev_err(dev, "find mtk-vcp driver failed, need to
> > reload.");
> > + return -EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_vcodec_vcp_get_vcp_device(struct mtk_vcodec_fw *fw)
> > +{
> > + struct device *dev = &fw->pdev->dev;
> > + int retry = 0, retry_cnt = 10000;
> > + phandle vcp_phandle;
> > +
> > + while (try_then_request_module(check_vcp_loaded(fw), "mtk-
> > vcp")) {
> > + if (++retry > retry_cnt) {
> > + dev_err(dev, "failed to load mtk-vcp
> > module");
> > + return -EPROBE_DEFER;
> > + }
> > + usleep_range(1000, 2000);
> > + }
> > +
> > + if (of_property_read_u32(dev->of_node, "mediatek,vcp",
> > &vcp_phandle)) {
> > + dev_err(dev, "can't get vcp handle.\n");
> > + return -ENODEV;
> > + }
> > +
> > + fw->vcp->vcp_device = mtk_vcp_get_by_phandle(vcp_phandle);
> > + if (!fw->vcp->vcp_device) {
> > + dev_err(dev, "get vcp device failed\n");
> > + return -ENODEV;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int mtk_vcodec_vcp_load_firmware(struct mtk_vcodec_fw *fw)
> > +{
> > + struct mtk_vcp_device *vcp_device;
> > + int ret, feature_id, mem_id, mailbox_id, ipi_id;
> > +
> > + if (fw->vcp->is_init_done) {
> > + dev_dbg(&fw->pdev->dev, "vcp has already been
> > initialized done.\n");
> > + return 0;
> > + }
> > +
> > + if (mtk_vcodec_vcp_get_vcp_device(fw) < 0) {
> > + dev_err(&fw->pdev->dev, "vcp device is null.\n");
> > + return -EINVAL;
> > + }
> > +
> > + vcp_device = fw->vcp->vcp_device;
> > +
> > + feature_id = VDEC_FEATURE_ID;
> > + mem_id = VDEC_MEM_ID;
> > + mailbox_id = IPI_IN_VDEC_1;
> > + ipi_id = VCP_IPI_LAT_DECODER;
> > +
> > + ret =
> > mtk_vcp_mbox_ipc_register(vcp_get_ipidev(vcp_device), mailbox_id,
> > + mtk_vcodec_vcp_msg_ack_isr
> > , fw, &fw->vcp->share_data);
> > + if (ret) {
> > + dev_dbg(&fw->pdev->dev, "ipi register fail %d %d
> > %d %d\n", ret, feature_id,
> > + mem_id, mailbox_id);
> > + return -EINVAL;
> > + }
> > +
> > + fw->vcp->vcp_notify.notifier_call =
> > mtk_vcodec_vcp_notifier;
> > + fw->vcp->vcp_notify.priority = 1;
> > + vcp_device->ops->vcp_register_notify(feature_id, &fw->vcp-
> > >vcp_notify);
> > +
> > + if (!fw->vcp->is_register_done) {
> > + ret = vcp_device->ops-
> > >vcp_register_feature(vcp_device, feature_id);
> > + if (ret < 0) {
> > + dev_err(&fw->pdev->dev, "%d register to
> > vcp fail(%d)\n", feature_id, ret);
> > + return -EINVAL;
> > + }
> > +
> > + fw->vcp->is_register_done = true;
> > + }
> > +
> > + fw->vcp->is_init_done = true;
> > +
> > + mutex_init(&fw->vcp->ipi_desc[ipi_id].lock);
> > + mutex_init(&fw->vcp->ipi_mutex);
> > +
> > + kthread_run(mtk_vcodec_vcp_msg_process_thread, fw,
> > "vcp_vdec_msq_thread");
> > +
> > + fw->vcp->vsi_addr = vcp_device->ops-
> > >vcp_get_mem_virt(mem_id);
> > + fw->vcp->vsi_core_addr = fw->vcp->vsi_addr +
> > VCODEC_VSI_LEN;
> > + fw->vcp->vsi_size = vcp_device->ops-
> > >vcp_get_mem_size(mem_id);
> > + fw->vcp->iova_addr = vcp_device->ops-
> > >vcp_get_mem_iova(mem_id);
> > +
> > + init_waitqueue_head(&fw->vcp-
> > >msg_wq[VCP_IPI_LAT_DECODER]);
> > + init_waitqueue_head(&fw->vcp-
> > >msg_wq[VCP_IPI_CORE_DECODER]);
> > +
> > + dev_dbg(&fw->pdev->dev, "vdec vcp init done => va: %p
> > size:0x%x iova:%p.\n",
> > + fw->vcp->vsi_addr, fw->vcp->vsi_size, &fw->vcp-
> > >iova_addr);
> > +
> > + return 0;
> > +}
> > +
> > +static unsigned int mtk_vcodec_vcp_get_vdec_capa(struct
> > mtk_vcodec_fw *fw)
> > +{
> > + return MTK_VDEC_FORMAT_MM21 | MTK_VDEC_FORMAT_H264_SLICE |
> > MTK_VDEC_FORMAT_VP9_FRAME |
> > + MTK_VDEC_FORMAT_AV1_FRAME |
> > MTK_VDEC_FORMAT_HEVC_FRAME |
> > + MTK_VDEC_IS_SUPPORT_10BIT |
> > MTK_VDEC_IS_SUPPORT_EXT;
> > +}
> > +
> > +static void *mtk_vcodec_vcp_dm_addr(struct mtk_vcodec_fw *fw, u32
> > dtcm_dmem_addr)
> > +{
> > + return NULL;
> > +}
> > +
> > +static int mtk_vcodec_vcp_set_ipi_register(struct mtk_vcodec_fw
> > *fw, int id,
> > + mtk_vcodec_ipi_handler
> > handler,
> > + const char *name, void
> > *priv)
> > +{
> > + return mtk_vcodec_vcp_ipi_register(fw->vcp, id, handler,
> > priv);
> > +}
> > +
> > +static int mtk_vcodec_vcp_ipi_send(struct mtk_vcodec_fw *fw, int
> > id, void *buf,
> > + unsigned int len, unsigned int
> > wait)
> > +{
> > + return mtk_vcodec_vcp_msg_ipi_send(fw, id, buf, len,
> > wait);
> > +}
> > +
> > +static void mtk_vcodec_vcp_release(struct mtk_vcodec_fw *fw)
> > +{
> > + struct mtk_vcp_device *vcp_device = fw->vcp->vcp_device;
> > + struct device *dev = &fw->pdev->dev;
> > + int ret, feature_id;
> > +
> > + if (!fw->vcp->vcp_device) {
> > + dev_err(dev, "vcp device is null\n");
> > + return;
> > + }
> > +
> > + if (!fw->vcp->is_register_done)
> > + return;
> > +
> > + feature_id = VDEC_FEATURE_ID;
> > + ret = vcp_device->ops->vcp_deregister_feature(vcp_device,
> > VDEC_FEATURE_ID);
> > + if (ret < 0) {
> > + dev_err(dev, "deregister feature_id(%d)
> > fail(%d)\n", feature_id, ret);
> > + return;
> > + }
> > +
> > + fw->vcp->is_register_done = false;
> > +}
> > +
> > +static const struct mtk_vcodec_fw_ops mtk_vcodec_vcp_msg = {
> > + .load_firmware = mtk_vcodec_vcp_load_firmware,
> > + .get_vdec_capa = mtk_vcodec_vcp_get_vdec_capa,
> > + .map_dm_addr = mtk_vcodec_vcp_dm_addr,
> > + .ipi_register = mtk_vcodec_vcp_set_ipi_register,
> > + .ipi_send = mtk_vcodec_vcp_ipi_send,
> > + .release = mtk_vcodec_vcp_release,
> > +};
> > +
> > +struct mtk_vcodec_fw *mtk_vcodec_fw_vcp_init(void *priv, enum
> > mtk_vcodec_fw_use fw_use)
> > +{
> > + struct mtk_vcp_msg_node *msg_node;
> > + struct platform_device *plat_dev;
> > + struct mtk_vcodec_fw *fw;
> > + int i;
> > +
> > + if (fw_use == DECODER) {
> > + struct mtk_vcodec_dec_dev *dec_dev = priv;
> > +
> > + plat_dev = dec_dev->plat_dev;
> > + } else {
> > + pr_err("Invalid fw_use %d (use a reasonable fw id
> > here)\n", fw_use);
> > + return ERR_PTR(-EINVAL);
> > + }
> > +
> > + fw = devm_kzalloc(&plat_dev->dev, sizeof(*fw),
> > GFP_KERNEL);
> > + if (!fw)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + fw->type = VCP;
> > + fw->pdev = plat_dev;
> > + fw->fw_use = fw_use;
> > + fw->ops = &mtk_vcodec_vcp_msg;
> > + fw->vcp = devm_kzalloc(&plat_dev->dev, sizeof(*fw->vcp),
> > GFP_KERNEL);
> > + if (!fw->vcp)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + INIT_LIST_HEAD(&fw->vcp->msg_queue.msg_list);
> > + INIT_LIST_HEAD(&fw->vcp->msg_queue.node_list);
> > + spin_lock_init(&fw->vcp->msg_queue.lock);
> > + init_waitqueue_head(&fw->vcp->msg_queue.wq);
> > + atomic_set(&fw->vcp->msg_queue.cnt, 0);
> > + fw->vcp->pdev = plat_dev;
> > +
> > + for (i = 0; i < VCP_MAX_MQ_NODE_CNT; i++) {
> > + msg_node = devm_kzalloc(&plat_dev->dev,
> > sizeof(*msg_node), GFP_KERNEL);
> > + if (!msg_node)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + list_add(&msg_node->list, &fw->vcp-
> > >msg_queue.node_list);
> > + }
> > +
> > + return fw;
> > +}
> > +EXPORT_SYMBOL_GPL(mtk_vcodec_fw_vcp_init);
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.h
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.h
> > new file mode 100644
> > index 000000000000..1072c37078f4
> > --- /dev/null
> > +++
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vcp.h
> > @@ -0,0 +1,142 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * Copyright (c) 2025 MediaTek Inc.
> > + * Author: Yunfei Dong <yunfei.dong@mediatek.com>
> > + */
> > +
> > +#ifndef _MTK_VCODEC_FW_VCP_H_
> > +#define _MTK_VCODEC_FW_VCP_H_
> > +
> > +typedef void (*vcp_ipi_handler_t) (void *data, unsigned int len,
> > void *priv);
> > +
> > +#define VCP_MAX_MQ_NODE_CNT 6
> > +#define VCP_SHARE_BUF_SIZE 64
> > +
> > +#define VCODEC_VSI_LEN (0x2000)
> > +
> > +/* enum mtk_vcp_ipi_index - index used to separate different
> > hardware */
> > +enum mtk_vcp_ipi_index {
> > + VCP_IPI_LAT_DECODER,
> > + VCP_IPI_CORE_DECODER,
> > + VCP_IPI_MAX,
> > +};
> > +
> > +/**
> > + * struct mtk_vcp_msg_queue - process the vcp message between
> > kernel with vcp
> > + *
> > + * @msg_list: store share buffer list which from vcp to kernel
> > + * @wq: waitqueue that can be used to wait for vcp message
> > + * @lock: protect msg list
> > + * @cnt: the count of share obj in msg list
> > + * @node_list: share obj list
> > + */
> > +struct mtk_vcp_msg_queue {
> > + struct list_head msg_list;
> > + wait_queue_head_t wq;
> > + /* protect msg_list and node_list */
> > + spinlock_t lock;
> > + atomic_t cnt;
> > + struct list_head node_list;
> > +};
> > +
> > +/**
> > + * struct mtk_vcp_ipi_desc - store the ack handler
> > + *
> > + * @lock: protect ack handler data
> > + * @handler: calling this handler when kernel receive ack
> > + * @priv: private data when calling handler to process
> > + */
> > +struct mtk_vcp_ipi_desc {
> > + /* protect handler and priv */
> > + struct mutex lock;
> > + vcp_ipi_handler_t handler;
> > + void *priv;
> > +};
> > +
> > +/**
> > + * struct mtk_vcp_share_obj - share buffer used to send data to
> > vcp
> > + *
> > + * @id: message index
> > + * @len: message size
> > + * @share_buf: message data
> > + */
> > +struct mtk_vcp_share_obj {
> > + unsigned int id;
> > + unsigned int len;
> > + unsigned char share_buf[VCP_SHARE_BUF_SIZE];
> > +};
> > +
> > +/* enum mtk_vcp_ipi_msg_status - the status when send message to
> > vcp */
> > +enum mtk_vcp_ipi_msg_status {
> > + VCODEC_IPI_MSG_STATUS_OK = 0,
> > + VCODEC_IPI_MSG_STATUS_FAIL = -1,
> > + VCODEC_IPI_MSG_STATUS_MAX_INST = -2,
> > + VCODEC_IPI_MSG_STATUS_ILSEQ = -3,
> > + VCODEC_IPI_MSG_STATUS_INVALID_ID = -4,
> > + VCODEC_IPI_MSG_STATUS_DMA_FAIL = -5,
> > +};
> > +
> > +/**
> > + * struct mtk_vcp_msg_node - share buffer used to send data to vcp
> > + *
> > + * @ipi_data: share obj data
> > + * @list: list to store msg node
> > + */
> > +struct mtk_vcp_msg_node {
> > + struct mtk_vcp_share_obj ipi_data;
> > + struct list_head list;
> > +};
> > +
> > +/**
> > + * struct mtk_vcp - vcp firmware private data
> > + *
> > + * @is_init_done: vcp is ready to use
> > + *
> > + * @ipi_mutex: used to protect ipi data
> > + * @msg_signaled: whether receive ack from vcp
> > + * @msg_wq: wake message queue
> > + *
> > + * @ipi_desc: store ack handler
> > + * @ipi_id_ack: the ack handler status
> > + *
> > + * @msg_queue: process vcp message
> > + * @share_data: temp share obj data
> > + *
> > + * @vcp_notify: register notifier to vcp
> > + *
> > + * @vsi_addr: vsi virtual data address
> > + * @vsi_core_addr: vsi core virtual data address
> > + * @iova_addr: vsi iova address
> > + * @vsi_size: vsi size
> > + *
> > + * @pdev: platform device
> > + * @vcp_device: vcp private data
> > + * @is_register_done: register vcodec to vcp
> > + */
> > +struct mtk_vcp {
> > + bool is_init_done;
> > +
> > + /* serialize ipi message send/receive */
> > + struct mutex ipi_mutex;
> > + bool msg_signaled[VCP_IPI_MAX];
> > + wait_queue_head_t msg_wq[VCP_IPI_MAX];
> > +
> > + struct mtk_vcp_ipi_desc ipi_desc[VCP_IPI_MAX];
> > + bool ipi_id_ack[VCP_IPI_MAX];
> > +
> > + struct mtk_vcp_msg_queue msg_queue;
> > + struct mtk_vcp_share_obj share_data;
> > +
> > + struct notifier_block vcp_notify;
> > +
> > + void *vsi_addr;
> > + void *vsi_core_addr;
> > + dma_addr_t iova_addr;
> > + int vsi_size;
> > +
> > + struct platform_device *pdev;
> > + struct mtk_vcp_device *vcp_device;
> > + bool is_register_done;
> > +};
> > +
> > +#endif
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
> > index 3632037f78f5..41643db9f4eb 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
> > +++
> > b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
> > @@ -130,3 +130,4 @@ struct mtk_vcodec_fw
> > *mtk_vcodec_fw_vpu_init(void *priv, enum mtk_vcodec_fw_use
> >
> > return fw;
> > }
> > +EXPORT_SYMBOL_GPL(mtk_vcodec_fw_vpu_init);
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .c
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .c
> > index d220b645e455..ce17b649022f 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .c
> > +++
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .c
> > @@ -376,12 +376,15 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > if (!of_property_read_u32(pdev->dev.of_node,
> > "mediatek,vpu",
> > &rproc_phandle)) {
> > fw_type = VPU;
> > + dev->fw_init = mtk_vcodec_fw_vpu_init;
> > } else if (!of_property_read_u32(pdev->dev.of_node,
> > "mediatek,scp",
> > &rproc_phandle)) {
> > fw_type = SCP;
> > + dev->fw_init = mtk_vcodec_fw_scp_init;
> > } else if (!of_property_read_u32(pdev->dev.of_node,
> > "mediatek,vcp",
> > &rproc_phandle)) {
> > fw_type = VCP;
> > + dev->fw_init = mtk_vcodec_fw_vcp_init;
> > } else {
> > dev_dbg(&pdev->dev, "Could not get vdec IPI
> > device");
> > return -ENODEV;
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > index c9d27534c63e..15e437323af5 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > +++
> > b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv
> > .h
> > @@ -251,6 +251,7 @@ struct mtk_vcodec_dec_ctx {
> > * @vdecsys_regmap: VDEC_SYS register space passed through syscon
> > *
> > * @fw_handler: used to communicate with the firmware.
> > + * @fw_init: firmware-specific init callback selected at probe
> > time
> > * @id_counter: used to identify current opened instance
> > *
> > * @dec_mutex: decoder hardware lock
> > @@ -292,6 +293,7 @@ struct mtk_vcodec_dec_dev {
> > struct regmap *vdecsys_regmap;
> >
> > struct mtk_vcodec_fw *fw_handler;
> > + struct mtk_vcodec_fw *(*fw_init)(void *priv, enum
> > mtk_vcodec_fw_use fw_use);
> > u64 id_counter;
> >
> > /* decoder hardware mutex lock */
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .c
> > b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .c
> > index 4e4541b2fc8e..dc54d445d98d 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .c
> > +++
> > b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .c
> > @@ -259,9 +259,11 @@ static int mtk_vcodec_probe(struct
> > platform_device *pdev)
> > if (!of_property_read_u32(pdev->dev.of_node,
> > "mediatek,vpu",
> > &rproc_phandle)) {
> > fw_type = VPU;
> > + dev->fw_init = mtk_vcodec_fw_vpu_init;
> > } else if (!of_property_read_u32(pdev->dev.of_node,
> > "mediatek,scp",
> > &rproc_phandle)) {
> > fw_type = SCP;
> > + dev->fw_init = mtk_vcodec_fw_scp_init;
> > } else {
> > dev_err(&pdev->dev, "[MTK VCODEC] Could not get
> > venc IPI device");
> > return -ENODEV;
> > diff --git
> > a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .h
> > b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .h
> > index 0cddfa13594f..934ff648125d 100644
> > ---
> > a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .h
> > +++
> > b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv
> > .h
> > @@ -174,6 +174,7 @@ struct mtk_vcodec_enc_ctx {
> > * @venc_pdata: encoder IC-specific data
> > *
> > * @fw_handler: used to communicate with the firmware.
> > + * @fw_init: firmware-specific init callback selected at probe
> > time
> > * @id_counter: used to identify current opened instance
> > *
> > * @enc_mutex: encoder hardware lock.
> > @@ -201,6 +202,7 @@ struct mtk_vcodec_enc_dev {
> > const struct mtk_vcodec_enc_pdata *venc_pdata;
> >
> > struct mtk_vcodec_fw *fw_handler;
> > + struct mtk_vcodec_fw *(*fw_init)(void *priv, enum
> > mtk_vcodec_fw_use fw_use);
> > u64 id_counter;
> >
> > /* encoder hardware mutex lock */
next prev parent reply other threads:[~2026-07-17 1:53 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 8:40 [PATCH v5 00/14] media: mediatek: vcodec: support video decoder in mt8196 Kyrie Wu
2026-06-03 8:40 ` [PATCH v5 01/14] media: mediatek: vcodec: support vcp architecture Kyrie Wu
2026-06-03 8:40 ` [PATCH v5 02/14] media: mediatek: vcodec: add driver to support vcp Kyrie Wu
2026-06-03 8:58 ` sashiko-bot
2026-07-16 0:50 ` Nicolas Dufresne
2026-07-17 1:53 ` Kyrie Wu (吴晗) [this message]
2026-06-03 8:40 ` [PATCH v5 03/14] media: mediatek: vcodec: add driver to support vcp encoder Kyrie Wu
2026-06-03 11:01 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 04/14] media: mediatek: vcodec: get different firmware ipi id Kyrie Wu
2026-06-03 8:40 ` [PATCH v5 05/14] media: mediatek: vcodec: get share memory address Kyrie Wu
2026-06-03 8:59 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 06/14] media: mediatek: vcodec: define MT8196 vcodec levels Kyrie Wu
2026-06-03 8:51 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 07/14] media: mediatek: vcodec: support 36bit iova address Kyrie Wu
2026-06-03 8:52 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 08/14] media: mediatek: vcodec: clean xpc status Kyrie Wu
2026-06-03 8:54 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 09/14] media: mediatek: vcodec: add debug information Kyrie Wu
2026-06-03 8:54 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 10/14] media: mediatek: vcodec: send share memory address to vcp Kyrie Wu
2026-06-03 11:09 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 11/14] dt-bindings: media: mediatek: vcodec: add decoder dt-bindings for mt8196 Kyrie Wu
2026-06-03 9:03 ` sashiko-bot
2026-06-03 16:14 ` Conor Dooley
2026-07-02 5:39 ` Kyrie Wu (吴晗)
2026-07-02 18:55 ` Conor Dooley
2026-07-13 3:16 ` Kyrie Wu (吴晗)
2026-06-03 8:40 ` [PATCH v5 12/14] media: mediatek: vcodec: add decoder compatible to support mt8196 Kyrie Wu
2026-06-03 8:59 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 13/14] media: mediatek: decoder: fill av1 buffer size with picinfo Kyrie Wu
2026-06-03 9:07 ` sashiko-bot
2026-06-03 8:40 ` [PATCH v5 14/14] media: mediatek: decoder: support av1 extend vsi Kyrie Wu
2026-06-03 9:10 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=676d9876bef1886de78a2bca73ffaa6a87bc804d.camel@mediatek.com \
--to=kyrie.wu@mediatek.com \
--cc=Andrew-CT.Chen@mediatek.com \
--cc=Irui.Wang@mediatek.com \
--cc=Yunfei.Dong@mediatek.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=benjamin.gaignard@collabora.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=fanwu01@zju.edu.cn \
--cc=fshao@chromium.org \
--cc=haoxiang_li2024@163.com \
--cc=hverkuil+cisco@kernel.org \
--cc=jacopo.mondi@ideasonboard.com \
--cc=kees@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=laurent.pinchart+renesas@ideasonboard.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=mchehab@kernel.org \
--cc=nicolas.dufresne@collabora.com \
--cc=p.zabel@pengutronix.de \
--cc=ribalda@chromium.org \
--cc=robh@kernel.org \
--cc=rongqianfeng@vivo.com \
--cc=sakari.ailus@linux.intel.com \
--cc=sebastian.fricke@collabora.com \
--cc=tfiga@chromium.org \
--cc=tiffany.lin@mediatek.com \
--cc=tzungbi@kernel.org \
--cc=wenst@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox