All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Paul-pl Chen (陳柏霖)" <Paul-pl.Chen@mediatek.com>
To: "CK Hu (胡俊光)" <ck.hu@mediatek.com>,
	"robh@kernel.org" <robh@kernel.org>,
	"krzk+dt@kernel.org" <krzk+dt@kernel.org>,
	"conor+dt@kernel.org" <conor+dt@kernel.org>,
	"chunkuang.hu@kernel.org" <chunkuang.hu@kernel.org>,
	"AngeloGioacchino Del Regno"
	<angelogioacchino.delregno@collabora.com>
Cc: "Sunny Shen (沈姍姍)" <Sunny.Shen@mediatek.com>,
	"Singo Chang (張興國)" <Singo.Chang@mediatek.com>,
	"treapking@chromium.org" <treapking@chromium.org>,
	Project_Global_Chrome_Upstream_Group
	<Project_Global_Chrome_Upstream_Group@mediatek.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"Jason-JH Lin (林睿祥)" <Jason-JH.Lin@mediatek.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"Nancy Lin (林欣螢)" <Nancy.Lin@mediatek.com>,
	"Xiandong Wang (王先冬)" <Xiandong.Wang@mediatek.com>,
	"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"p.zabel@pengutronix.de" <p.zabel@pengutronix.de>,
	"Sirius Wang (王皓昱)" <Sirius.Wang@mediatek.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
Date: Fri, 21 Feb 2025 12:39:33 +0000	[thread overview]
Message-ID: <773cbb9b4bc8b03c06a5d48a6df7e2faeb3fb49a.camel@mediatek.com> (raw)
In-Reply-To: <a9e782eacbd88d41eee7bf7475b3c6e48e437923.camel@mediatek.com>

On Wed, 2025-02-12 at 09:30 +0000, CK Hu (胡俊光) wrote:
> Hi, Paul:
> 
> On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> > From: "Nancy.Lin" <nancy.lin@mediatek.com>
> > 
> > To support multiple mmsys instances in the one mediatek-drm
> > instance,
> > providing improved flexibility and scalability by the following
> > changes:
> > 
> > 1. Defined new DRM component IDs DDP_COMPONENT_DRM_OVLSYS_ADAPTOR*
> >   to support different mmsys composition.
> > 2. Added new component types MTK_DISP_VIRTUAL to support the
> >   routing to virtual display components.
> > 3. Added and adjusted the existed structure or interface to extend
> >   the support of multiple mmsys instances.
> > 4. Modified the component matching and binding logic to support
> >   multiple mmsys instances.
> 
> I think the title would confuse me.
> Original mediatek-drm driver already support multiple mmsys.
> I try to understand MT8196 display.
> Is one display pipeline separated into two mmsys?
> The first is ovlsys and the second is dispsys?
> If so, I would like mediatek-drm driver see only mmsys (dispsys),
> and let ovlsys control is hidden in ovlsys sub driver, so mediatek-
> drm driver would not change so much.
> 
> > 
> > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_crtc.c     | 350 +++++++++++++++++++-
> > ----
> >  drivers/gpu/drm/mediatek/mtk_crtc.h     |   6 +-
> >  drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 106 +++++--
> >  drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   2 +
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.c  | 223 ++++++++++++---
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  16 +-
> >  6 files changed, 578 insertions(+), 125 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c
> > b/drivers/gpu/drm/mediatek/mtk_crtc.c
> > index eb0e1233ad04..eca6941bfaa2 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_crtc.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
> > @@ -58,13 +58,17 @@ struct mtk_crtc {
> >  	wait_queue_head_t		cb_blocking_queue;
> >  #endif
> >  
> > -	struct device			*mmsys_dev;
> > +	struct device			*mmsys_dev[MAX_MMSYS];
> >  	struct device			*dma_dev;
> > -	struct mtk_mutex		*mutex;
> > +	struct device			*vdisp_ao_dev;
> > +	struct mtk_mutex		*mutex[MAX_MMSYS];
> >  	unsigned int			ddp_comp_nr;
> >  	struct mtk_ddp_comp		**ddp_comp;
> > +	enum mtk_drm_mmsys		*ddp_comp_sys;
> > +	bool				exist[MAX_MMSYS];
> >  	unsigned int			num_conn_routes;
> >  	const struct mtk_drm_route	*conn_routes;
> > +	enum mtk_drm_mmsys		conn_routes_sys;
> >  
> >  	/* lock for display hardware access */
> >  	struct mutex			hw_lock;
> > @@ -82,6 +86,11 @@ struct mtk_crtc_state {
> >  	unsigned int			pending_vrefresh;
> >  };
> >  
> > +struct mtk_crtc_comp_info {
> > +	enum mtk_drm_mmsys sys;
> > +	unsigned int comp_id;
> > +};
> > +
> >  static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
> >  {
> >  	return container_of(c, struct mtk_crtc, base);
> > @@ -125,7 +134,9 @@ static void mtk_crtc_destroy(struct drm_crtc
> > *crtc)
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	int i;
> >  
> > -	mtk_mutex_put(mtk_crtc->mutex);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->mutex[i])
> > +			mtk_mutex_put(mtk_crtc->mutex[i]);
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	if (mtk_crtc->cmdq_client.chan) {
> >  		cmdq_pkt_destroy(&mtk_crtc->cmdq_client,
> > &mtk_crtc->cmdq_handle);
> > @@ -223,7 +234,14 @@ static int mtk_crtc_ddp_clk_enable(struct
> > mtk_crtc *mtk_crtc)
> >  	int i;
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > +		enum mtk_drm_mmsys mmsys;
> > +
> >  		ret = mtk_ddp_comp_clk_enable(mtk_crtc-
> > >ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL) {
> > +			mmsys = mtk_crtc->ddp_comp_sys[i];
> > +			ret = mtk_mmsys_ddp_clk_enable(mtk_crtc-
> > >mmsys_dev[mmsys],
> > +						       mtk_crtc-
> > >ddp_comp[i]->id);
> > +		}
> >  		if (ret) {
> >  			DRM_ERROR("Failed to enable clock %d:
> > %d\n", i, ret);
> >  			goto err;
> > @@ -232,17 +250,28 @@ static int mtk_crtc_ddp_clk_enable(struct
> > mtk_crtc *mtk_crtc)
> >  
> >  	return 0;
> >  err:
> > -	while (--i >= 0)
> > +	while (--i >= 0) {
> >  		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL)
> > +			mtk_mmsys_ddp_clk_disable(mtk_crtc-
> > >mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
> > +						  mtk_crtc-
> > >ddp_comp[i]->id);
> > +	}
> >  	return ret;
> >  }
> >  
> >  static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
> >  {
> >  	int i;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> > -	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> > +	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL) {
> > +			mmsys = mtk_crtc->ddp_comp_sys[i];
> > +			mtk_mmsys_ddp_clk_disable(mtk_crtc-
> > >mmsys_dev[mmsys],
> > +						  mtk_crtc-
> > >ddp_comp[i]->id);
> > +		}
> > +	}
> >  }
> >  
> >  static
> > @@ -332,7 +361,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc
> > *mtk_crtc)
> >  	struct drm_connector_list_iter conn_iter;
> >  	unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
> >  	int ret;
> > -	int i;
> > +	int i, j;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> >  	if (WARN_ON(!crtc->state))
> >  		return -EINVAL;
> > @@ -362,10 +392,18 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		return ret;
> >  	}
> >  
> > -	ret = mtk_mutex_prepare(mtk_crtc->mutex);
> > -	if (ret < 0) {
> > -		DRM_ERROR("Failed to enable mutex clock: %d\n",
> > ret);
> > -		goto err_pm_runtime_put;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_top_clk_enable(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++) {
> > +		if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
> > +			continue;
> > +		ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
> > +		if (ret < 0) {
> > +			DRM_ERROR("Failed to enable mmsys%d mutex
> > clock: %d\n", i, ret);
> > +			goto err_pm_runtime_put;
> > +		}
> >  	}
> >  
> >  	ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
> > @@ -374,19 +412,36 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		goto err_mutex_unprepare;
> >  	}
> >  
> > +	if (mtk_crtc->vdisp_ao_dev)
> > +		mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_default_config(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
> > -		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mmsys_dev,
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mmsys_dev[mmsys],
> >  					  mtk_crtc->ddp_comp[i +
> > 1]->id))
> > -			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
> > +			mtk_mmsys_ddp_connect(mtk_crtc-
> > >mmsys_dev[mmsys],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id,
> >  					      mtk_crtc->ddp_comp[i
> > + 1]->id);
> > -		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_add_comp(mtk_crtc->mutex,
> > +		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex[mmsys]))
> > +			mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
> >  					   mtk_crtc->ddp_comp[i]-
> > >id);
> >  	}
> > -	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex))
> > -		mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc-
> > >ddp_comp[i]->id);
> > -	mtk_mutex_enable(mtk_crtc->mutex);
> > +	mmsys = mtk_crtc->ddp_comp_sys[i];
> > +	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex[mmsys]))
> > +		mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
> > mtk_crtc->ddp_comp[i]->id);
> > +
> > +	/* Need to set sof source for all mmsys mutexs in this
> > crtc */
> > +	for (j = 0; j < MAX_MMSYS; j++)
> > +		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
> > +			mtk_mutex_write_comp_sof(mtk_crtc-
> > >mutex[j], mtk_crtc->ddp_comp[i]->id);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_enable(mtk_crtc->mutex[i]);
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
> > @@ -394,7 +449,11 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		if (i == 1)
> >  			mtk_ddp_comp_bgclr_in_on(comp);
> >  
> > -		mtk_ddp_comp_config(comp, width, height, vrefresh,
> > bpc, NULL);
> > +		if (mtk_ddp_comp_get_type(comp->id) ==
> > MTK_DISP_VIRTUAL)
> > +			mtk_mmsys_ddp_config(mtk_crtc-
> > >mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
> > +					     comp->id, width,
> > height, NULL);
> > +		else
> > +			mtk_ddp_comp_config(comp, width, height,
> > vrefresh, bpc, NULL);
> >  		mtk_ddp_comp_start(comp);
> >  	}
> >  
> > @@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  	return 0;
> >  
> >  err_mutex_unprepare:
> > -	mtk_mutex_unprepare(mtk_crtc->mutex);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> > +
> >  err_pm_runtime_put:
> >  	pm_runtime_put(crtc->dev->dev);
> >  	return ret;
> > @@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct
> > mtk_crtc *mtk_crtc)
> >  	struct drm_crtc *crtc = &mtk_crtc->base;
> >  	unsigned long flags;
> >  	int i;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
> > @@ -437,27 +500,46 @@ static void mtk_crtc_ddp_hw_fini(struct
> > mtk_crtc *mtk_crtc)
> >  			mtk_ddp_comp_bgclr_in_off(mtk_crtc-
> > >ddp_comp[i]);
> >  	}
> >  
> > -	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> > -		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_remove_comp(mtk_crtc->mutex,
> > +	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex[mmsys]))
> > +			mtk_mutex_remove_comp(mtk_crtc-
> > >mutex[mtk_crtc->ddp_comp_sys[i]],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id);
> > -	mtk_mutex_disable(mtk_crtc->mutex);
> > +	}
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_disable(mtk_crtc->mutex[i]);
> > +
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
> > -		if (!mtk_ddp_comp_disconnect(mtk_crtc-
> > >ddp_comp[i], mtk_crtc->mmsys_dev,
> > -					     mtk_crtc->ddp_comp[i
> > + 1]->id))
> > -			mtk_mmsys_ddp_disconnect(mtk_crtc-
> > >mmsys_dev,
> > -						 mtk_crtc-
> > >ddp_comp[i]->id,
> > -						 mtk_crtc-
> > >ddp_comp[i + 1]->id);
> > -		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_remove_comp(mtk_crtc->mutex,
> > +		struct mtk_ddp_comp *comp;
> > +		unsigned int curr, next;
> > +
> > +		comp = mtk_crtc->ddp_comp[i];
> > +		curr = mtk_crtc->ddp_comp[i]->id;
> > +		next = mtk_crtc->ddp_comp[i + 1]->id;
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_disconnect(comp, mtk_crtc-
> > >mmsys_dev[mmsys], next))
> > +			mtk_mmsys_ddp_disconnect(mtk_crtc-
> > >mmsys_dev[mmsys], curr, next);
> > +		if (!mtk_ddp_comp_remove(comp, mtk_crtc-
> > >mutex[mmsys]))
> > +			mtk_mutex_remove_comp(mtk_crtc-
> > >mutex[mtk_crtc->ddp_comp_sys[i]],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id);
> >  	}
> > -	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex))
> > -		mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc-
> > >ddp_comp[i]->id);
> > +
> > +	mmsys = mtk_crtc->ddp_comp_sys[i];
> > +	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex[mmsys]))
> > +		mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys],
> > mtk_crtc->ddp_comp[i]->id);
> > +
> >  	mtk_crtc_ddp_clk_disable(mtk_crtc);
> > -	mtk_mutex_unprepare(mtk_crtc->mutex);
> >  
> > -	pm_runtime_put(drm->dev);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_top_clk_disable(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> > +	pm_runtime_put_sync(drm->dev);
> >  
> >  	if (crtc->state->event && !crtc->state->active) {
> >  		spin_lock_irqsave(&crtc->dev->event_lock, flags);
> > @@ -581,9 +663,15 @@ static void mtk_crtc_update_config(struct
> > mtk_crtc *mtk_crtc, bool needs_vblank)
> >  		mtk_crtc->pending_async_planes = true;
> >  
> >  	if (priv->data->shadow_register) {
> > -		mtk_mutex_acquire(mtk_crtc->mutex);
> > +		for (i = 0; i < MAX_MMSYS; i++)
> > +			if (mtk_crtc->exist[i] && mtk_crtc-
> > >mutex[i])
> > +				mtk_mutex_acquire(mtk_crtc-
> > >mutex[i]);
> > +
> >  		mtk_crtc_ddp_config(crtc, NULL);
> > -		mtk_mutex_release(mtk_crtc->mutex);
> > +
> > +		for (i = 0; i < MAX_MMSYS; i++)
> > +			if (mtk_crtc->exist[i] && mtk_crtc-
> > >mutex[i])
> > +				mtk_mutex_release(mtk_crtc-
> > >mutex[i]);
> >  	}
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	if (mtk_crtc->cmdq_client.chan) {
> > @@ -659,6 +747,7 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  {
> >  	int crtc_index = drm_crtc_index(crtc);
> >  	int i;
> > +	unsigned int mmsys;
> >  	struct device *dev;
> >  	struct drm_crtc_state *crtc_state = state-
> > >crtcs[crtc_index].new_state;
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> > @@ -671,7 +760,8 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  	if (!mtk_crtc->num_conn_routes)
> >  		return;
> >  
> > -	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)-
> > >all_drm_private[crtc_index];
> > +	mmsys = mtk_crtc->conn_routes_sys;
> > +	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)-
> > >all_drm_private[mmsys];
> >  	dev = priv->dev;
> >  
> >  	dev_dbg(dev, "connector change:%d, encoder mask:0x%x for
> > crtc:%d\n",
> > @@ -684,6 +774,8 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  		if (comp->encoder_index >= 0 &&
> >  		    (encoder_mask & BIT(comp->encoder_index))) {
> >  			mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr -
> > 1] = comp;
> > +			mtk_crtc->ddp_comp_sys[mtk_crtc-
> > >ddp_comp_nr - 1] = mmsys;
> > +			mtk_crtc->exist[mmsys] = true;
> >  			dev_dbg(dev, "Add comp_id: %d at path
> > index %d\n",
> >  				comp->id, mtk_crtc->ddp_comp_nr -
> > 1);
> >  			break;
> > @@ -720,13 +812,35 @@ static void mtk_crtc_atomic_enable(struct
> > drm_crtc *crtc,
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
> >  	int ret;
> > +	int i, j;
> > +	int mmsys_cnt = 0;
> >  
> >  	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
> >  
> > -	ret = mtk_ddp_comp_power_on(comp);
> > -	if (ret < 0) {
> > -		DRM_DEV_ERROR(comp->dev, "Failed to enable power
> > domain: %d\n", ret);
> > -		return;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mmsys_cnt++;
> > +
> > +	if (mmsys_cnt == 1) {
> > +		ret = pm_runtime_resume_and_get(comp->dev);
> > +		if (ret < 0) {
> > +			DRM_DEV_ERROR(comp->dev, "Failed to enable
> > power domain: %d\n", ret);
> > +			return;
> > +		}
> > +	} else {
> > +		for (i = 0; i < MAX_MMSYS; i++) {
> > +			if (!mtk_crtc->exist[i])
> > +				continue;
> > +			ret = pm_runtime_resume_and_get(mtk_crtc-
> > >mmsys_dev[i]);
> > +			if (ret < 0) {
> > +				DRM_DEV_ERROR(mtk_crtc-
> > >mmsys_dev[i],
> > +					      "Failed to enable
> > power domain: %d\n", ret);
> > +				for (j = i - 1; j >= 0; j--)
> > +					if (mtk_crtc->exist[i])
> > +						pm_runtime_put(com
> > p->dev);
> > +				return;
> > +			}
> > +		}
> >  	}
> >  
> >  	mtk_crtc_update_output(crtc, state);
> > @@ -746,12 +860,17 @@ static void mtk_crtc_atomic_disable(struct
> > drm_crtc *crtc,
> >  {
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
> > -	int i;
> > +	int i, ret;
> > +	int mmsys_cnt = 0;
> >  
> >  	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
> >  	if (!mtk_crtc->enabled)
> >  		return;
> >  
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mmsys_cnt++;
> > +
> >  	/* Set all pending plane state to disabled */
> >  	for (i = 0; i < mtk_crtc->layer_nr; i++) {
> >  		struct drm_plane *plane = &mtk_crtc->planes[i];
> > @@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct
> > drm_crtc *crtc,
> >  
> >  	drm_crtc_vblank_off(crtc);
> >  	mtk_crtc_ddp_hw_fini(mtk_crtc);
> > -	mtk_ddp_comp_power_off(comp);
> > +
> > +	if (mmsys_cnt > 1) {
> > +		for (i = 0; i < MAX_MMSYS; i++) {
> > +			if (mtk_crtc->exist[i]) {
> > +				ret = pm_runtime_put(mtk_crtc-
> > >mmsys_dev[i]);
> > +				if (ret < 0)
> > +					DRM_DEV_ERROR(mtk_crtc-
> > >mmsys_dev[i],
> > +						      "Failed to
> > disable power domain: %d\n", ret);
> > +			}
> > +		}
> > +	} else {
> > +		ret = pm_runtime_put(comp->dev);
> > +		if (ret < 0)
> > +			DRM_DEV_ERROR(comp->dev, "Failed to
> > disable power domain: %d\n", ret);
> > +	}
> >  
> >  	mtk_crtc->enabled = false;
> >  }
> > @@ -937,49 +1070,108 @@ struct device *mtk_crtc_dma_dev_get(struct
> > drm_crtc *crtc)
> >  	return mtk_crtc->dma_dev;
> >  }
> >  
> > -int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int
> > *path,
> > -		    unsigned int path_len, int priv_data_index,
> > -		    const struct mtk_drm_route *conn_routes,
> > -		    unsigned int num_conn_routes)
> > +int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path
> > path_sel)
> >  {
> >  	struct mtk_drm_private *priv = drm_dev->dev_private;
> >  	struct device *dev = drm_dev->dev;
> >  	struct mtk_crtc *mtk_crtc;
> >  	unsigned int num_comp_planes = 0;
> >  	int ret;
> > -	int i;
> > +	int i, j, k;
> >  	bool has_ctm = false;
> >  	uint gamma_lut_size = 0;
> >  	struct drm_crtc *tmp;
> >  	int crtc_i = 0;
> > -
> > -	if (!path)
> > -		return 0;
> > -
> > -	priv = priv->all_drm_private[priv_data_index];
> > +	struct mtk_drm_private *subsys_priv;
> > +	struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
> > +	unsigned int path_len = 0;
> > +	const struct mtk_drm_route *conn_routes = NULL;
> > +	unsigned int num_conn_routes = 0;
> > +	enum mtk_drm_mmsys conn_mmsys;
> >  
> >  	drm_for_each_crtc(tmp, drm_dev)
> >  		crtc_i++;
> >  
> > +	for (j = 0; j < priv->data->mmsys_dev_num; j++) {
> > +		for (k = 0; k < MAX_MMSYS; k++) {
> > +			const unsigned int *subsys_path;
> > +			unsigned int subsys_path_len;
> > +			unsigned int order = 0;
> > +
> > +			subsys_priv = priv->all_drm_private[k];
> > +			if (!subsys_priv)
> > +				continue;
> > +
> > +			if (path_sel == CRTC_MAIN) {
> > +				subsys_path = subsys_priv->data-
> > >main_path;
> > +				subsys_path_len = subsys_priv-
> > >data->main_len;
> > +				order = subsys_priv->data-
> > >main_order;
> > +			} else if (path_sel == CRTC_EXT) {
> > +				subsys_path = subsys_priv->data-
> > >ext_path;
> > +				subsys_path_len = subsys_priv-
> > >data->ext_len;
> > +				order = subsys_priv->data-
> > >ext_order;
> > +			} else if (path_sel == CRTC_THIRD) {
> > +				subsys_path = subsys_priv->data-
> > >third_path;
> > +				subsys_path_len = subsys_priv-
> > >data->third_len;
> > +				order = subsys_priv->data-
> > >third_order;
> > +			}
> > +
> > +			if (subsys_priv->data->num_conn_routes) {
> > +				conn_routes = subsys_priv->data-
> > >conn_routes;
> > +				num_conn_routes = subsys_priv-
> > >data->num_conn_routes;
> > +				conn_mmsys = subsys_priv->data-
> > >mmsys_id;
> > +			}
> > +
> > +			if (j != order)
> > +				continue;
> > +			if (!subsys_path_len)
> > +				continue;
> > +
> > +			for (i = 0; i < subsys_path_len; i++) {
> > +				path[path_len].sys = subsys_priv-
> > >data->mmsys_id;
> > +				path[path_len].comp_id =
> > subsys_path[i];
> > +				path_len++;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!path_len)
> > +		return 0;
> > +
> > +	if (num_conn_routes) {
> > +		for (i = 0; i < num_conn_routes; i++)
> > +			if (conn_routes->crtc_id == crtc_i)
> > +				break;
> > +		if (i == num_conn_routes) {
> > +			num_conn_routes = 0;
> > +			conn_routes = NULL;
> > +		}
> > +	}
> > +
> >  	for (i = 0; i < path_len; i++) {
> > -		enum mtk_ddp_comp_id comp_id = path[i];
> > +		enum mtk_ddp_comp_id comp_id = path[i].comp_id;
> >  		struct device_node *node;
> >  		struct mtk_ddp_comp *comp;
> >  
> > +		priv = priv->all_drm_private[path[i].sys];
> >  		node = priv->comp_node[comp_id];
> >  		comp = &priv->ddp_comp[comp_id];
> >  
> >  		/* Not all drm components have a DTS device node,
> > such as ovl_adaptor,
> >  		 * which is the drm bring up sub driver
> >  		 */
> > -		if (!node && comp_id !=
> > DDP_COMPONENT_DRM_OVL_ADAPTOR) {
> > +		if (!node && comp_id !=
> > DDP_COMPONENT_DRM_OVL_ADAPTOR &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1
> > &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2
> > &&
> > +		    mtk_ddp_comp_get_type(comp_id) !=
> > MTK_DISP_VIRTUAL) {
> >  			dev_info(dev,
> >  				"Not creating crtc %d because
> > component %d is disabled or missing\n",
> >  				crtc_i, comp_id);
> >  			return 0;
> >  		}
> >  
> > -		if (!comp->dev) {
> > +		if (!comp->dev && mtk_ddp_comp_get_type(comp_id)
> > != MTK_DISP_VIRTUAL) {
> >  			dev_err(dev, "Component %pOF not
> > initialized\n", node);
> >  			return -ENODEV;
> >  		}
> > @@ -989,7 +1181,9 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	if (!mtk_crtc)
> >  		return -ENOMEM;
> >  
> > -	mtk_crtc->mmsys_dev = priv->mmsys_dev;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (priv->all_drm_private[i])
> > +			mtk_crtc->mmsys_dev[i] = priv-
> > >all_drm_private[i]->mmsys_dev;
> >  	mtk_crtc->ddp_comp_nr = path_len;
> >  	mtk_crtc->ddp_comp = devm_kcalloc(dev,
> >  					  mtk_crtc->ddp_comp_nr +
> > (conn_routes ? 1 : 0),
> > @@ -998,19 +1192,36 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	if (!mtk_crtc->ddp_comp)
> >  		return -ENOMEM;
> >  
> > -	mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
> > -	if (IS_ERR(mtk_crtc->mutex)) {
> > -		ret = PTR_ERR(mtk_crtc->mutex);
> > -		dev_err(dev, "Failed to get mutex: %d\n", ret);
> > -		return ret;
> > +	mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc-
> > >ddp_comp_nr +
> > +						    (conn_routes ?
> > 1 : 0),
> > +						   
> > sizeof(mtk_crtc->ddp_comp_sys), GFP_KERNEL);
> > +	if (!mtk_crtc->ddp_comp_sys)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++) {
> > +		if (!priv->all_drm_private[i])
> > +			continue;
> > +
> > +		priv = priv->all_drm_private[i];
> > +		mtk_crtc->mutex[i] = mtk_mutex_get(priv-
> > >mutex_dev);
> > +		if (IS_ERR(mtk_crtc->mutex[i])) {
> > +			ret = PTR_ERR(mtk_crtc->mutex[i]);
> > +			dev_err(dev, "Failed to get mutex: %d\n",
> > ret);
> > +			return ret;
> > +		}
> >  	}
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > -		unsigned int comp_id = path[i];
> > +		unsigned int comp_id = path[i].comp_id;
> >  		struct mtk_ddp_comp *comp;
> >  
> > +		priv = priv->all_drm_private[path[i].sys];
> >  		comp = &priv->ddp_comp[comp_id];
> > +		if (mtk_ddp_comp_get_type(comp_id) ==
> > MTK_DISP_VIRTUAL)
> > +			comp->id = comp_id;
> >  		mtk_crtc->ddp_comp[i] = comp;
> > +		mtk_crtc->ddp_comp_sys[i] = path[i].sys;
> > +		mtk_crtc->exist[path[i].sys] = true;
> >  
> >  		if (comp->funcs) {
> >  			if (comp->funcs->gamma_set && comp->funcs-
> > >gamma_get_lut_size) {
> > @@ -1047,8 +1258,10 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	 * In the case of ovl_adaptor sub driver, it needs to use
> > the
> >  	 * dma_dev_get function to get representative dma dev.
> >  	 */
> > -	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv-
> > >ddp_comp[path[0]]);
> > +	priv = priv->all_drm_private[path[0].sys];
> > +	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv-
> > >ddp_comp[path[0].comp_id]);
> >  
> > +	mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
> >  	ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
> >  	if (ret < 0)
> >  		return ret;
> > @@ -1061,7 +1274,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	i = priv->mbox_index++;
> > -	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
> > +	mtk_crtc->cmdq_client.client.dev = mtk_crtc-
> > >mmsys_dev[priv->data->mmsys_id];
> >  	mtk_crtc->cmdq_client.client.tx_block = false;
> >  	mtk_crtc->cmdq_client.client.knows_txdone = true;
> >  	mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
> > @@ -1101,6 +1314,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  #endif
> >  
> >  	if (conn_routes) {
> > +		priv = priv->all_drm_private[conn_mmsys];
> >  		for (i = 0; i < num_conn_routes; i++) {
> >  			unsigned int comp_id =
> > conn_routes[i].route_ddp;
> >  			struct device_node *node = priv-
> > >comp_node[comp_id];
> > @@ -1117,6 +1331,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  			mtk_ddp_comp_encoder_index_set(&priv-
> > >ddp_comp[comp_id]);
> >  		}
> >  
> > +		mtk_crtc->conn_routes_sys = conn_mmsys;
> >  		mtk_crtc->num_conn_routes = num_conn_routes;
> >  		mtk_crtc->conn_routes = conn_routes;
> >  
> > @@ -1124,5 +1339,10 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  		mtk_crtc->ddp_comp_nr++;
> >  	}
> >  
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			device_link_add(mtk_crtc->base.dev->dev,
> > +					priv->all_drm_private[i]-
> > >mutex_dev, 0);
> > +
> >  	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h
> > b/drivers/gpu/drm/mediatek/mtk_crtc.h
> > index 388e900b6f4d..255f2823d17a 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_crtc.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
> > @@ -15,10 +15,8 @@
> >  #define MTK_MIN_BPC	3
> >  
> >  void mtk_crtc_commit(struct drm_crtc *crtc);
> > -int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int
> > *path,
> > -		    unsigned int path_len, int priv_data_index,
> > -		    const struct mtk_drm_route *conn_routes,
> > -		    unsigned int num_conn_routes);
> > +int mtk_crtc_create(struct drm_device *drm_dev,
> > +		    enum mtk_crtc_path path_sel);
> >  int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane
> > *plane,
> >  			 struct mtk_plane_state *state);
> >  void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane
> > *plane,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index 492b8d965309..f841184d1e06 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -464,6 +464,7 @@ static const char * const
> > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> >  	[MTK_DISP_PWM] = "pwm",
> >  	[MTK_DISP_RDMA] = "rdma",
> >  	[MTK_DISP_UFOE] = "ufoe",
> > +	[MTK_DISP_VIRTUAL] = "virtual",
> >  	[MTK_DISP_WDMA] = "wdma",
> >  	[MTK_DP_INTF] = "dp-intf",
> >  	[MTK_DPI] = "dpi",
> > @@ -487,6 +488,15 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_COLOR0]		= {
> > MTK_DISP_COLOR,		0, &ddp_color },
> >  	[DDP_COMPONENT_COLOR1]		= {
> > MTK_DISP_COLOR,		1, &ddp_color },
> >  	[DDP_COMPONENT_DITHER0]		= {
> > MTK_DISP_DITHER,		0, &ddp_dither },
> > +	[DDP_COMPONENT_DLI_ASYNC0]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC1]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC8]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC21]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC22]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC23]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC1]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC2]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC3]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_DP_INTF0]	= {
> > MTK_DP_INTF,		0, &ddp_dpi },
> >  	[DDP_COMPONENT_DP_INTF1]	= {
> > MTK_DP_INTF,		1, &ddp_dpi },
> >  	[DDP_COMPONENT_DPI0]		= {
> > MTK_DPI,			0, &ddp_dpi },
> > @@ -494,6 +504,9 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= {
> > MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
> >  	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> >  	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
> >  	[DDP_COMPONENT_DSC0]		= {
> > MTK_DISP_DSC,		0, &ddp_dsc },
> >  	[DDP_COMPONENT_DSC1]		= {
> > MTK_DISP_DSC,		1, &ddp_dsc },
> >  	[DDP_COMPONENT_DSI0]		= {
> > MTK_DSI,			0, &ddp_dsi },
> > @@ -510,7 +523,10 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_OD0]		= {
> > MTK_DISP_OD,		0, &ddp_od },
> >  	[DDP_COMPONENT_OD1]		= {
> > MTK_DISP_OD,		1, &ddp_od },
> >  	[DDP_COMPONENT_OVL0]		= {
> > MTK_DISP_OVL,		0, &ddp_ovl },
> > +	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_OVL1]		= {
> > MTK_DISP_OVL,		1, &ddp_ovl },
> > +	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_OVL_2L0]		= {
> > MTK_DISP_OVL_2L,		0, &ddp_ovl },
> >  	[DDP_COMPONENT_OVL_2L1]		= {
> > MTK_DISP_OVL_2L,		1, &ddp_ovl },
> >  	[DDP_COMPONENT_OVL_2L2]		= {
> > MTK_DISP_OVL_2L,		2, &ddp_ovl },
> > @@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const
> > unsigned int *path,
> >  {
> >  	unsigned int i;
> >  
> > +	if (!path_len)
> > +		return true;
> > +
> >  	if (!path || !path_len)
> >  		return false;
> >  
> >  	for (i = 0U; i < path_len; i++) {
> >  		/* OVL_ADAPTOR doesn't have a device node */
> > -		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
> > +		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
> > +		    path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > ||
> > +			path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
> > +			path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
> > +			mtk_ddp_comp_get_type(path[i]) ==
> > MTK_DISP_VIRTUAL)
> >  			continue;
> >  
> >  		if (!comp_node[path[i]])
> > @@ -597,44 +620,81 @@ int mtk_ddp_comp_get_id(struct device_node
> > *node,
> >  	return -EINVAL;
> >  }
> >  
> > +enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
> > +{
> > +	return mtk_ddp_matches[comp_id].type;
> > +}
> > +
> >  int mtk_find_possible_crtcs(struct drm_device *drm, struct device
> > *dev)
> >  {
> >  	struct mtk_drm_private *private = drm->dev_private;
> >  	const struct mtk_mmsys_driver_data *data;
> >  	struct mtk_drm_private *priv_n;
> > -	int i = 0, j;
> >  	int ret;
> > +	int i = 0, j, count = 0;
> > +	bool found = false;
> >  
> >  	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> >  		priv_n = private->all_drm_private[j];
> >  		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->main_path, data-
> > >main_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data-
> > >main_path,
> > -					      data->main_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					   priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->main_path, data-
> > >main_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> > +	}
> > +
> > +	count = 0;
> > +	found = false;
> > +
> > +	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> > +		priv_n = private->all_drm_private[j];
> > +		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->ext_path, data-
> > >ext_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data->ext_path,
> > -					      data->ext_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					   priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->ext_path, data-
> > >ext_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> > +	}
> > +
> > +	count = 0;
> > +	found = false;
> > +
> > +	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> > +		priv_n = private->all_drm_private[j];
> > +		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->third_path, data-
> > >third_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data-
> > >third_path,
> > -					      data->third_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->third_path, data-
> > >third_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> >  	}
> >  
> >  	ret = mtk_ddp_comp_find_in_route(dev,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index ef64ce7a071f..badb42bd4f7c 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
> >  	MTK_DISP_PWM,
> >  	MTK_DISP_RDMA,
> >  	MTK_DISP_UFOE,
> > +	MTK_DISP_VIRTUAL,
> >  	MTK_DISP_WDMA,
> >  	MTK_DPI,
> >  	MTK_DP_INTF,
> > @@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
> >  	MTK_OVL_BLENDER,
> >  	MTK_OVL_EXDMA,
> >  	MTK_OVL_OUTPROC,
> > +	MTK_VDISP_AO,
> >  	MTK_DDP_COMP_TYPE_MAX,
> >  };
> >  
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > index 7526bc38bcc7..0665a6feb546 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > @@ -193,6 +193,10 @@ static const struct mtk_drm_route
> > mt8188_mtk_ddp_main_routes[] = {
> >  	{0, DDP_COMPONENT_DSI0},
> >  };
> >  
> > +static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
> > +	{2, DDP_COMPONENT_DSI0},
> > +};
> > +
> >  static const unsigned int mt8192_mtk_ddp_main[] = {
> >  	DDP_COMPONENT_OVL0,
> >  	DDP_COMPONENT_OVL_2L0,
> > @@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[]
> > = {
> >  	DDP_COMPONENT_DP_INTF1,
> >  };
> >  
> > +static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
> > +	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
> > +	DDP_COMPONENT_OVL0_DLO_ASYNC5,
> > +};
> 
> Separate MT8196 part to another patch which add support MT8196.
> Let this patch not related to specific SoC.
> 
> Regards,
> CK

Sure, I will separate this patch to 2 part, first patch is to supprt
the multiple MMSYS for mediatek drm driver. Second patch is to support
MT8196 SOC.

Best, 
Paul  

WARNING: multiple messages have this Message-ID (diff)
From: "Paul-pl Chen (陳柏霖)" <Paul-pl.Chen@mediatek.com>
To: "CK Hu (胡俊光)" <ck.hu@mediatek.com>,
	"robh@kernel.org" <robh@kernel.org>,
	"krzk+dt@kernel.org" <krzk+dt@kernel.org>,
	"conor+dt@kernel.org" <conor+dt@kernel.org>,
	"chunkuang.hu@kernel.org" <chunkuang.hu@kernel.org>,
	"AngeloGioacchino Del Regno"
	<angelogioacchino.delregno@collabora.com>
Cc: "Sunny Shen (沈姍姍)" <Sunny.Shen@mediatek.com>,
	"Singo Chang (張興國)" <Singo.Chang@mediatek.com>,
	"treapking@chromium.org" <treapking@chromium.org>,
	Project_Global_Chrome_Upstream_Group
	<Project_Global_Chrome_Upstream_Group@mediatek.com>,
	"dri-devel@lists.freedesktop.org"
	<dri-devel@lists.freedesktop.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"Jason-JH Lin (林睿祥)" <Jason-JH.Lin@mediatek.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"Nancy Lin (林欣螢)" <Nancy.Lin@mediatek.com>,
	"Xiandong Wang (王先冬)" <Xiandong.Wang@mediatek.com>,
	"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"p.zabel@pengutronix.de" <p.zabel@pengutronix.de>,
	"Sirius Wang (王皓昱)" <Sirius.Wang@mediatek.com>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver
Date: Fri, 21 Feb 2025 12:39:33 +0000	[thread overview]
Message-ID: <773cbb9b4bc8b03c06a5d48a6df7e2faeb3fb49a.camel@mediatek.com> (raw)
In-Reply-To: <a9e782eacbd88d41eee7bf7475b3c6e48e437923.camel@mediatek.com>

[-- Attachment #1: Type: text/plain, Size: 37562 bytes --]

On Wed, 2025-02-12 at 09:30 +0000, CK Hu (胡俊光) wrote:
> Hi, Paul:
> 
> On Fri, 2025-01-10 at 20:34 +0800, paul-pl.chen wrote:
> > From: "Nancy.Lin" <nancy.lin@mediatek.com>
> > 
> > To support multiple mmsys instances in the one mediatek-drm
> > instance,
> > providing improved flexibility and scalability by the following
> > changes:
> > 
> > 1. Defined new DRM component IDs DDP_COMPONENT_DRM_OVLSYS_ADAPTOR*
> >   to support different mmsys composition.
> > 2. Added new component types MTK_DISP_VIRTUAL to support the
> >   routing to virtual display components.
> > 3. Added and adjusted the existed structure or interface to extend
> >   the support of multiple mmsys instances.
> > 4. Modified the component matching and binding logic to support
> >   multiple mmsys instances.
> 
> I think the title would confuse me.
> Original mediatek-drm driver already support multiple mmsys.
> I try to understand MT8196 display.
> Is one display pipeline separated into two mmsys?
> The first is ovlsys and the second is dispsys?
> If so, I would like mediatek-drm driver see only mmsys (dispsys),
> and let ovlsys control is hidden in ovlsys sub driver, so mediatek-
> drm driver would not change so much.
> 
> > 
> > Signed-off-by: Nancy.Lin <nancy.lin@mediatek.com>
> > Signed-off-by: Paul-pl.Chen <paul-pl.chen@mediatek.com>
> > ---
> >  drivers/gpu/drm/mediatek/mtk_crtc.c     | 350 +++++++++++++++++++-
> > ----
> >  drivers/gpu/drm/mediatek/mtk_crtc.h     |   6 +-
> >  drivers/gpu/drm/mediatek/mtk_ddp_comp.c | 106 +++++--
> >  drivers/gpu/drm/mediatek/mtk_ddp_comp.h |   2 +
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.c  | 223 ++++++++++++---
> >  drivers/gpu/drm/mediatek/mtk_drm_drv.h  |  16 +-
> >  6 files changed, 578 insertions(+), 125 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.c
> > b/drivers/gpu/drm/mediatek/mtk_crtc.c
> > index eb0e1233ad04..eca6941bfaa2 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_crtc.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c
> > @@ -58,13 +58,17 @@ struct mtk_crtc {
> >  	wait_queue_head_t		cb_blocking_queue;
> >  #endif
> >  
> > -	struct device			*mmsys_dev;
> > +	struct device			*mmsys_dev[MAX_MMSYS];
> >  	struct device			*dma_dev;
> > -	struct mtk_mutex		*mutex;
> > +	struct device			*vdisp_ao_dev;
> > +	struct mtk_mutex		*mutex[MAX_MMSYS];
> >  	unsigned int			ddp_comp_nr;
> >  	struct mtk_ddp_comp		**ddp_comp;
> > +	enum mtk_drm_mmsys		*ddp_comp_sys;
> > +	bool				exist[MAX_MMSYS];
> >  	unsigned int			num_conn_routes;
> >  	const struct mtk_drm_route	*conn_routes;
> > +	enum mtk_drm_mmsys		conn_routes_sys;
> >  
> >  	/* lock for display hardware access */
> >  	struct mutex			hw_lock;
> > @@ -82,6 +86,11 @@ struct mtk_crtc_state {
> >  	unsigned int			pending_vrefresh;
> >  };
> >  
> > +struct mtk_crtc_comp_info {
> > +	enum mtk_drm_mmsys sys;
> > +	unsigned int comp_id;
> > +};
> > +
> >  static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c)
> >  {
> >  	return container_of(c, struct mtk_crtc, base);
> > @@ -125,7 +134,9 @@ static void mtk_crtc_destroy(struct drm_crtc
> > *crtc)
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	int i;
> >  
> > -	mtk_mutex_put(mtk_crtc->mutex);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->mutex[i])
> > +			mtk_mutex_put(mtk_crtc->mutex[i]);
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	if (mtk_crtc->cmdq_client.chan) {
> >  		cmdq_pkt_destroy(&mtk_crtc->cmdq_client,
> > &mtk_crtc->cmdq_handle);
> > @@ -223,7 +234,14 @@ static int mtk_crtc_ddp_clk_enable(struct
> > mtk_crtc *mtk_crtc)
> >  	int i;
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > +		enum mtk_drm_mmsys mmsys;
> > +
> >  		ret = mtk_ddp_comp_clk_enable(mtk_crtc-
> > >ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL) {
> > +			mmsys = mtk_crtc->ddp_comp_sys[i];
> > +			ret = mtk_mmsys_ddp_clk_enable(mtk_crtc-
> > >mmsys_dev[mmsys],
> > +						       mtk_crtc-
> > >ddp_comp[i]->id);
> > +		}
> >  		if (ret) {
> >  			DRM_ERROR("Failed to enable clock %d:
> > %d\n", i, ret);
> >  			goto err;
> > @@ -232,17 +250,28 @@ static int mtk_crtc_ddp_clk_enable(struct
> > mtk_crtc *mtk_crtc)
> >  
> >  	return 0;
> >  err:
> > -	while (--i >= 0)
> > +	while (--i >= 0) {
> >  		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL)
> > +			mtk_mmsys_ddp_clk_disable(mtk_crtc-
> > >mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
> > +						  mtk_crtc-
> > >ddp_comp[i]->id);
> > +	}
> >  	return ret;
> >  }
> >  
> >  static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc)
> >  {
> >  	int i;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> > -	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> > +	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		mtk_ddp_comp_clk_disable(mtk_crtc->ddp_comp[i]);
> > +		if (mtk_ddp_comp_get_type(mtk_crtc->ddp_comp[i]-
> > >id) == MTK_DISP_VIRTUAL) {
> > +			mmsys = mtk_crtc->ddp_comp_sys[i];
> > +			mtk_mmsys_ddp_clk_disable(mtk_crtc-
> > >mmsys_dev[mmsys],
> > +						  mtk_crtc-
> > >ddp_comp[i]->id);
> > +		}
> > +	}
> >  }
> >  
> >  static
> > @@ -332,7 +361,8 @@ static int mtk_crtc_ddp_hw_init(struct mtk_crtc
> > *mtk_crtc)
> >  	struct drm_connector_list_iter conn_iter;
> >  	unsigned int width, height, vrefresh, bpc = MTK_MAX_BPC;
> >  	int ret;
> > -	int i;
> > +	int i, j;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> >  	if (WARN_ON(!crtc->state))
> >  		return -EINVAL;
> > @@ -362,10 +392,18 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		return ret;
> >  	}
> >  
> > -	ret = mtk_mutex_prepare(mtk_crtc->mutex);
> > -	if (ret < 0) {
> > -		DRM_ERROR("Failed to enable mutex clock: %d\n",
> > ret);
> > -		goto err_pm_runtime_put;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_top_clk_enable(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++) {
> > +		if (!mtk_crtc->mutex[i] || !mtk_crtc->exist[i])
> > +			continue;
> > +		ret = mtk_mutex_prepare(mtk_crtc->mutex[i]);
> > +		if (ret < 0) {
> > +			DRM_ERROR("Failed to enable mmsys%d mutex
> > clock: %d\n", i, ret);
> > +			goto err_pm_runtime_put;
> > +		}
> >  	}
> >  
> >  	ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
> > @@ -374,19 +412,36 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		goto err_mutex_unprepare;
> >  	}
> >  
> > +	if (mtk_crtc->vdisp_ao_dev)
> > +		mtk_mmsys_default_config(mtk_crtc->vdisp_ao_dev);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_default_config(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
> > -		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mmsys_dev,
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_connect(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mmsys_dev[mmsys],
> >  					  mtk_crtc->ddp_comp[i +
> > 1]->id))
> > -			mtk_mmsys_ddp_connect(mtk_crtc->mmsys_dev,
> > +			mtk_mmsys_ddp_connect(mtk_crtc-
> > >mmsys_dev[mmsys],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id,
> >  					      mtk_crtc->ddp_comp[i
> > + 1]->id);
> > -		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_add_comp(mtk_crtc->mutex,
> > +		if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex[mmsys]))
> > +			mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
> >  					   mtk_crtc->ddp_comp[i]-
> > >id);
> >  	}
> > -	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex))
> > -		mtk_mutex_add_comp(mtk_crtc->mutex, mtk_crtc-
> > >ddp_comp[i]->id);
> > -	mtk_mutex_enable(mtk_crtc->mutex);
> > +	mmsys = mtk_crtc->ddp_comp_sys[i];
> > +	if (!mtk_ddp_comp_add(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex[mmsys]))
> > +		mtk_mutex_add_comp(mtk_crtc->mutex[mmsys],
> > mtk_crtc->ddp_comp[i]->id);
> > +
> > +	/* Need to set sof source for all mmsys mutexs in this
> > crtc */
> > +	for (j = 0; j < MAX_MMSYS; j++)
> > +		if (mtk_crtc->exist[j] && mtk_crtc->mutex[j])
> > +			mtk_mutex_write_comp_sof(mtk_crtc-
> > >mutex[j], mtk_crtc->ddp_comp[i]->id);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_enable(mtk_crtc->mutex[i]);
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
> > @@ -394,7 +449,11 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  		if (i == 1)
> >  			mtk_ddp_comp_bgclr_in_on(comp);
> >  
> > -		mtk_ddp_comp_config(comp, width, height, vrefresh,
> > bpc, NULL);
> > +		if (mtk_ddp_comp_get_type(comp->id) ==
> > MTK_DISP_VIRTUAL)
> > +			mtk_mmsys_ddp_config(mtk_crtc-
> > >mmsys_dev[mtk_crtc->ddp_comp_sys[i]],
> > +					     comp->id, width,
> > height, NULL);
> > +		else
> > +			mtk_ddp_comp_config(comp, width, height,
> > vrefresh, bpc, NULL);
> >  		mtk_ddp_comp_start(comp);
> >  	}
> >  
> > @@ -418,7 +477,10 @@ static int mtk_crtc_ddp_hw_init(struct
> > mtk_crtc *mtk_crtc)
> >  	return 0;
> >  
> >  err_mutex_unprepare:
> > -	mtk_mutex_unprepare(mtk_crtc->mutex);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> > +
> >  err_pm_runtime_put:
> >  	pm_runtime_put(crtc->dev->dev);
> >  	return ret;
> > @@ -430,6 +492,7 @@ static void mtk_crtc_ddp_hw_fini(struct
> > mtk_crtc *mtk_crtc)
> >  	struct drm_crtc *crtc = &mtk_crtc->base;
> >  	unsigned long flags;
> >  	int i;
> > +	enum mtk_drm_mmsys mmsys;
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> >  		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
> > @@ -437,27 +500,46 @@ static void mtk_crtc_ddp_hw_fini(struct
> > mtk_crtc *mtk_crtc)
> >  			mtk_ddp_comp_bgclr_in_off(mtk_crtc-
> > >ddp_comp[i]);
> >  	}
> >  
> > -	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
> > -		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_remove_comp(mtk_crtc->mutex,
> > +	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex[mmsys]))
> > +			mtk_mutex_remove_comp(mtk_crtc-
> > >mutex[mtk_crtc->ddp_comp_sys[i]],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id);
> > -	mtk_mutex_disable(mtk_crtc->mutex);
> > +	}
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_disable(mtk_crtc->mutex[i]);
> > +
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
> > -		if (!mtk_ddp_comp_disconnect(mtk_crtc-
> > >ddp_comp[i], mtk_crtc->mmsys_dev,
> > -					     mtk_crtc->ddp_comp[i
> > + 1]->id))
> > -			mtk_mmsys_ddp_disconnect(mtk_crtc-
> > >mmsys_dev,
> > -						 mtk_crtc-
> > >ddp_comp[i]->id,
> > -						 mtk_crtc-
> > >ddp_comp[i + 1]->id);
> > -		if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i],
> > mtk_crtc->mutex))
> > -			mtk_mutex_remove_comp(mtk_crtc->mutex,
> > +		struct mtk_ddp_comp *comp;
> > +		unsigned int curr, next;
> > +
> > +		comp = mtk_crtc->ddp_comp[i];
> > +		curr = mtk_crtc->ddp_comp[i]->id;
> > +		next = mtk_crtc->ddp_comp[i + 1]->id;
> > +		mmsys = mtk_crtc->ddp_comp_sys[i];
> > +		if (!mtk_ddp_comp_disconnect(comp, mtk_crtc-
> > >mmsys_dev[mmsys], next))
> > +			mtk_mmsys_ddp_disconnect(mtk_crtc-
> > >mmsys_dev[mmsys], curr, next);
> > +		if (!mtk_ddp_comp_remove(comp, mtk_crtc-
> > >mutex[mmsys]))
> > +			mtk_mutex_remove_comp(mtk_crtc-
> > >mutex[mtk_crtc->ddp_comp_sys[i]],
> >  					      mtk_crtc-
> > >ddp_comp[i]->id);
> >  	}
> > -	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex))
> > -		mtk_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc-
> > >ddp_comp[i]->id);
> > +
> > +	mmsys = mtk_crtc->ddp_comp_sys[i];
> > +	if (!mtk_ddp_comp_remove(mtk_crtc->ddp_comp[i], mtk_crtc-
> > >mutex[mmsys]))
> > +		mtk_mutex_remove_comp(mtk_crtc->mutex[mmsys],
> > mtk_crtc->ddp_comp[i]->id);
> > +
> >  	mtk_crtc_ddp_clk_disable(mtk_crtc);
> > -	mtk_mutex_unprepare(mtk_crtc->mutex);
> >  
> > -	pm_runtime_put(drm->dev);
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i] && mtk_crtc->mutex[i])
> > +			mtk_mutex_unprepare(mtk_crtc->mutex[i]);
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mtk_mmsys_top_clk_disable(mtk_crtc-
> > >mmsys_dev[i]);
> > +
> > +	pm_runtime_put_sync(drm->dev);
> >  
> >  	if (crtc->state->event && !crtc->state->active) {
> >  		spin_lock_irqsave(&crtc->dev->event_lock, flags);
> > @@ -581,9 +663,15 @@ static void mtk_crtc_update_config(struct
> > mtk_crtc *mtk_crtc, bool needs_vblank)
> >  		mtk_crtc->pending_async_planes = true;
> >  
> >  	if (priv->data->shadow_register) {
> > -		mtk_mutex_acquire(mtk_crtc->mutex);
> > +		for (i = 0; i < MAX_MMSYS; i++)
> > +			if (mtk_crtc->exist[i] && mtk_crtc-
> > >mutex[i])
> > +				mtk_mutex_acquire(mtk_crtc-
> > >mutex[i]);
> > +
> >  		mtk_crtc_ddp_config(crtc, NULL);
> > -		mtk_mutex_release(mtk_crtc->mutex);
> > +
> > +		for (i = 0; i < MAX_MMSYS; i++)
> > +			if (mtk_crtc->exist[i] && mtk_crtc-
> > >mutex[i])
> > +				mtk_mutex_release(mtk_crtc-
> > >mutex[i]);
> >  	}
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	if (mtk_crtc->cmdq_client.chan) {
> > @@ -659,6 +747,7 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  {
> >  	int crtc_index = drm_crtc_index(crtc);
> >  	int i;
> > +	unsigned int mmsys;
> >  	struct device *dev;
> >  	struct drm_crtc_state *crtc_state = state-
> > >crtcs[crtc_index].new_state;
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> > @@ -671,7 +760,8 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  	if (!mtk_crtc->num_conn_routes)
> >  		return;
> >  
> > -	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)-
> > >all_drm_private[crtc_index];
> > +	mmsys = mtk_crtc->conn_routes_sys;
> > +	priv = ((struct mtk_drm_private *)crtc->dev->dev_private)-
> > >all_drm_private[mmsys];
> >  	dev = priv->dev;
> >  
> >  	dev_dbg(dev, "connector change:%d, encoder mask:0x%x for
> > crtc:%d\n",
> > @@ -684,6 +774,8 @@ static void mtk_crtc_update_output(struct
> > drm_crtc *crtc,
> >  		if (comp->encoder_index >= 0 &&
> >  		    (encoder_mask & BIT(comp->encoder_index))) {
> >  			mtk_crtc->ddp_comp[mtk_crtc->ddp_comp_nr -
> > 1] = comp;
> > +			mtk_crtc->ddp_comp_sys[mtk_crtc-
> > >ddp_comp_nr - 1] = mmsys;
> > +			mtk_crtc->exist[mmsys] = true;
> >  			dev_dbg(dev, "Add comp_id: %d at path
> > index %d\n",
> >  				comp->id, mtk_crtc->ddp_comp_nr -
> > 1);
> >  			break;
> > @@ -720,13 +812,35 @@ static void mtk_crtc_atomic_enable(struct
> > drm_crtc *crtc,
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
> >  	int ret;
> > +	int i, j;
> > +	int mmsys_cnt = 0;
> >  
> >  	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
> >  
> > -	ret = mtk_ddp_comp_power_on(comp);
> > -	if (ret < 0) {
> > -		DRM_DEV_ERROR(comp->dev, "Failed to enable power
> > domain: %d\n", ret);
> > -		return;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mmsys_cnt++;
> > +
> > +	if (mmsys_cnt == 1) {
> > +		ret = pm_runtime_resume_and_get(comp->dev);
> > +		if (ret < 0) {
> > +			DRM_DEV_ERROR(comp->dev, "Failed to enable
> > power domain: %d\n", ret);
> > +			return;
> > +		}
> > +	} else {
> > +		for (i = 0; i < MAX_MMSYS; i++) {
> > +			if (!mtk_crtc->exist[i])
> > +				continue;
> > +			ret = pm_runtime_resume_and_get(mtk_crtc-
> > >mmsys_dev[i]);
> > +			if (ret < 0) {
> > +				DRM_DEV_ERROR(mtk_crtc-
> > >mmsys_dev[i],
> > +					      "Failed to enable
> > power domain: %d\n", ret);
> > +				for (j = i - 1; j >= 0; j--)
> > +					if (mtk_crtc->exist[i])
> > +						pm_runtime_put(com
> > p->dev);
> > +				return;
> > +			}
> > +		}
> >  	}
> >  
> >  	mtk_crtc_update_output(crtc, state);
> > @@ -746,12 +860,17 @@ static void mtk_crtc_atomic_disable(struct
> > drm_crtc *crtc,
> >  {
> >  	struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc);
> >  	struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
> > -	int i;
> > +	int i, ret;
> > +	int mmsys_cnt = 0;
> >  
> >  	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
> >  	if (!mtk_crtc->enabled)
> >  		return;
> >  
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			mmsys_cnt++;
> > +
> >  	/* Set all pending plane state to disabled */
> >  	for (i = 0; i < mtk_crtc->layer_nr; i++) {
> >  		struct drm_plane *plane = &mtk_crtc->planes[i];
> > @@ -776,7 +895,21 @@ static void mtk_crtc_atomic_disable(struct
> > drm_crtc *crtc,
> >  
> >  	drm_crtc_vblank_off(crtc);
> >  	mtk_crtc_ddp_hw_fini(mtk_crtc);
> > -	mtk_ddp_comp_power_off(comp);
> > +
> > +	if (mmsys_cnt > 1) {
> > +		for (i = 0; i < MAX_MMSYS; i++) {
> > +			if (mtk_crtc->exist[i]) {
> > +				ret = pm_runtime_put(mtk_crtc-
> > >mmsys_dev[i]);
> > +				if (ret < 0)
> > +					DRM_DEV_ERROR(mtk_crtc-
> > >mmsys_dev[i],
> > +						      "Failed to
> > disable power domain: %d\n", ret);
> > +			}
> > +		}
> > +	} else {
> > +		ret = pm_runtime_put(comp->dev);
> > +		if (ret < 0)
> > +			DRM_DEV_ERROR(comp->dev, "Failed to
> > disable power domain: %d\n", ret);
> > +	}
> >  
> >  	mtk_crtc->enabled = false;
> >  }
> > @@ -937,49 +1070,108 @@ struct device *mtk_crtc_dma_dev_get(struct
> > drm_crtc *crtc)
> >  	return mtk_crtc->dma_dev;
> >  }
> >  
> > -int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int
> > *path,
> > -		    unsigned int path_len, int priv_data_index,
> > -		    const struct mtk_drm_route *conn_routes,
> > -		    unsigned int num_conn_routes)
> > +int mtk_crtc_create(struct drm_device *drm_dev, enum mtk_crtc_path
> > path_sel)
> >  {
> >  	struct mtk_drm_private *priv = drm_dev->dev_private;
> >  	struct device *dev = drm_dev->dev;
> >  	struct mtk_crtc *mtk_crtc;
> >  	unsigned int num_comp_planes = 0;
> >  	int ret;
> > -	int i;
> > +	int i, j, k;
> >  	bool has_ctm = false;
> >  	uint gamma_lut_size = 0;
> >  	struct drm_crtc *tmp;
> >  	int crtc_i = 0;
> > -
> > -	if (!path)
> > -		return 0;
> > -
> > -	priv = priv->all_drm_private[priv_data_index];
> > +	struct mtk_drm_private *subsys_priv;
> > +	struct mtk_crtc_comp_info path[DDP_COMPONENT_ID_MAX];
> > +	unsigned int path_len = 0;
> > +	const struct mtk_drm_route *conn_routes = NULL;
> > +	unsigned int num_conn_routes = 0;
> > +	enum mtk_drm_mmsys conn_mmsys;
> >  
> >  	drm_for_each_crtc(tmp, drm_dev)
> >  		crtc_i++;
> >  
> > +	for (j = 0; j < priv->data->mmsys_dev_num; j++) {
> > +		for (k = 0; k < MAX_MMSYS; k++) {
> > +			const unsigned int *subsys_path;
> > +			unsigned int subsys_path_len;
> > +			unsigned int order = 0;
> > +
> > +			subsys_priv = priv->all_drm_private[k];
> > +			if (!subsys_priv)
> > +				continue;
> > +
> > +			if (path_sel == CRTC_MAIN) {
> > +				subsys_path = subsys_priv->data-
> > >main_path;
> > +				subsys_path_len = subsys_priv-
> > >data->main_len;
> > +				order = subsys_priv->data-
> > >main_order;
> > +			} else if (path_sel == CRTC_EXT) {
> > +				subsys_path = subsys_priv->data-
> > >ext_path;
> > +				subsys_path_len = subsys_priv-
> > >data->ext_len;
> > +				order = subsys_priv->data-
> > >ext_order;
> > +			} else if (path_sel == CRTC_THIRD) {
> > +				subsys_path = subsys_priv->data-
> > >third_path;
> > +				subsys_path_len = subsys_priv-
> > >data->third_len;
> > +				order = subsys_priv->data-
> > >third_order;
> > +			}
> > +
> > +			if (subsys_priv->data->num_conn_routes) {
> > +				conn_routes = subsys_priv->data-
> > >conn_routes;
> > +				num_conn_routes = subsys_priv-
> > >data->num_conn_routes;
> > +				conn_mmsys = subsys_priv->data-
> > >mmsys_id;
> > +			}
> > +
> > +			if (j != order)
> > +				continue;
> > +			if (!subsys_path_len)
> > +				continue;
> > +
> > +			for (i = 0; i < subsys_path_len; i++) {
> > +				path[path_len].sys = subsys_priv-
> > >data->mmsys_id;
> > +				path[path_len].comp_id =
> > subsys_path[i];
> > +				path_len++;
> > +			}
> > +		}
> > +	}
> > +
> > +	if (!path_len)
> > +		return 0;
> > +
> > +	if (num_conn_routes) {
> > +		for (i = 0; i < num_conn_routes; i++)
> > +			if (conn_routes->crtc_id == crtc_i)
> > +				break;
> > +		if (i == num_conn_routes) {
> > +			num_conn_routes = 0;
> > +			conn_routes = NULL;
> > +		}
> > +	}
> > +
> >  	for (i = 0; i < path_len; i++) {
> > -		enum mtk_ddp_comp_id comp_id = path[i];
> > +		enum mtk_ddp_comp_id comp_id = path[i].comp_id;
> >  		struct device_node *node;
> >  		struct mtk_ddp_comp *comp;
> >  
> > +		priv = priv->all_drm_private[path[i].sys];
> >  		node = priv->comp_node[comp_id];
> >  		comp = &priv->ddp_comp[comp_id];
> >  
> >  		/* Not all drm components have a DTS device node,
> > such as ovl_adaptor,
> >  		 * which is the drm bring up sub driver
> >  		 */
> > -		if (!node && comp_id !=
> > DDP_COMPONENT_DRM_OVL_ADAPTOR) {
> > +		if (!node && comp_id !=
> > DDP_COMPONENT_DRM_OVL_ADAPTOR &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1
> > &&
> > +		    comp_id != DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2
> > &&
> > +		    mtk_ddp_comp_get_type(comp_id) !=
> > MTK_DISP_VIRTUAL) {
> >  			dev_info(dev,
> >  				"Not creating crtc %d because
> > component %d is disabled or missing\n",
> >  				crtc_i, comp_id);
> >  			return 0;
> >  		}
> >  
> > -		if (!comp->dev) {
> > +		if (!comp->dev && mtk_ddp_comp_get_type(comp_id)
> > != MTK_DISP_VIRTUAL) {
> >  			dev_err(dev, "Component %pOF not
> > initialized\n", node);
> >  			return -ENODEV;
> >  		}
> > @@ -989,7 +1181,9 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	if (!mtk_crtc)
> >  		return -ENOMEM;
> >  
> > -	mtk_crtc->mmsys_dev = priv->mmsys_dev;
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (priv->all_drm_private[i])
> > +			mtk_crtc->mmsys_dev[i] = priv-
> > >all_drm_private[i]->mmsys_dev;
> >  	mtk_crtc->ddp_comp_nr = path_len;
> >  	mtk_crtc->ddp_comp = devm_kcalloc(dev,
> >  					  mtk_crtc->ddp_comp_nr +
> > (conn_routes ? 1 : 0),
> > @@ -998,19 +1192,36 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	if (!mtk_crtc->ddp_comp)
> >  		return -ENOMEM;
> >  
> > -	mtk_crtc->mutex = mtk_mutex_get(priv->mutex_dev);
> > -	if (IS_ERR(mtk_crtc->mutex)) {
> > -		ret = PTR_ERR(mtk_crtc->mutex);
> > -		dev_err(dev, "Failed to get mutex: %d\n", ret);
> > -		return ret;
> > +	mtk_crtc->ddp_comp_sys = devm_kmalloc_array(dev, mtk_crtc-
> > >ddp_comp_nr +
> > +						    (conn_routes ?
> > 1 : 0),
> > +						   
> > sizeof(mtk_crtc->ddp_comp_sys), GFP_KERNEL);
> > +	if (!mtk_crtc->ddp_comp_sys)
> > +		return -ENOMEM;
> > +
> > +	for (i = 0; i < MAX_MMSYS; i++) {
> > +		if (!priv->all_drm_private[i])
> > +			continue;
> > +
> > +		priv = priv->all_drm_private[i];
> > +		mtk_crtc->mutex[i] = mtk_mutex_get(priv-
> > >mutex_dev);
> > +		if (IS_ERR(mtk_crtc->mutex[i])) {
> > +			ret = PTR_ERR(mtk_crtc->mutex[i]);
> > +			dev_err(dev, "Failed to get mutex: %d\n",
> > ret);
> > +			return ret;
> > +		}
> >  	}
> >  
> >  	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
> > -		unsigned int comp_id = path[i];
> > +		unsigned int comp_id = path[i].comp_id;
> >  		struct mtk_ddp_comp *comp;
> >  
> > +		priv = priv->all_drm_private[path[i].sys];
> >  		comp = &priv->ddp_comp[comp_id];
> > +		if (mtk_ddp_comp_get_type(comp_id) ==
> > MTK_DISP_VIRTUAL)
> > +			comp->id = comp_id;
> >  		mtk_crtc->ddp_comp[i] = comp;
> > +		mtk_crtc->ddp_comp_sys[i] = path[i].sys;
> > +		mtk_crtc->exist[path[i].sys] = true;
> >  
> >  		if (comp->funcs) {
> >  			if (comp->funcs->gamma_set && comp->funcs-
> > >gamma_get_lut_size) {
> > @@ -1047,8 +1258,10 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  	 * In the case of ovl_adaptor sub driver, it needs to use
> > the
> >  	 * dma_dev_get function to get representative dma dev.
> >  	 */
> > -	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv-
> > >ddp_comp[path[0]]);
> > +	priv = priv->all_drm_private[path[0].sys];
> > +	mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv-
> > >ddp_comp[path[0].comp_id]);
> >  
> > +	mtk_crtc->vdisp_ao_dev = priv->vdisp_ao_dev;
> >  	ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i);
> >  	if (ret < 0)
> >  		return ret;
> > @@ -1061,7 +1274,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  
> >  #if IS_REACHABLE(CONFIG_MTK_CMDQ)
> >  	i = priv->mbox_index++;
> > -	mtk_crtc->cmdq_client.client.dev = mtk_crtc->mmsys_dev;
> > +	mtk_crtc->cmdq_client.client.dev = mtk_crtc-
> > >mmsys_dev[priv->data->mmsys_id];
> >  	mtk_crtc->cmdq_client.client.tx_block = false;
> >  	mtk_crtc->cmdq_client.client.knows_txdone = true;
> >  	mtk_crtc->cmdq_client.client.rx_callback = ddp_cmdq_cb;
> > @@ -1101,6 +1314,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  #endif
> >  
> >  	if (conn_routes) {
> > +		priv = priv->all_drm_private[conn_mmsys];
> >  		for (i = 0; i < num_conn_routes; i++) {
> >  			unsigned int comp_id =
> > conn_routes[i].route_ddp;
> >  			struct device_node *node = priv-
> > >comp_node[comp_id];
> > @@ -1117,6 +1331,7 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  			mtk_ddp_comp_encoder_index_set(&priv-
> > >ddp_comp[comp_id]);
> >  		}
> >  
> > +		mtk_crtc->conn_routes_sys = conn_mmsys;
> >  		mtk_crtc->num_conn_routes = num_conn_routes;
> >  		mtk_crtc->conn_routes = conn_routes;
> >  
> > @@ -1124,5 +1339,10 @@ int mtk_crtc_create(struct drm_device
> > *drm_dev, const unsigned int *path,
> >  		mtk_crtc->ddp_comp_nr++;
> >  	}
> >  
> > +	for (i = 0; i < MAX_MMSYS; i++)
> > +		if (mtk_crtc->exist[i])
> > +			device_link_add(mtk_crtc->base.dev->dev,
> > +					priv->all_drm_private[i]-
> > >mutex_dev, 0);
> > +
> >  	return 0;
> >  }
> > diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h
> > b/drivers/gpu/drm/mediatek/mtk_crtc.h
> > index 388e900b6f4d..255f2823d17a 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_crtc.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_crtc.h
> > @@ -15,10 +15,8 @@
> >  #define MTK_MIN_BPC	3
> >  
> >  void mtk_crtc_commit(struct drm_crtc *crtc);
> > -int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int
> > *path,
> > -		    unsigned int path_len, int priv_data_index,
> > -		    const struct mtk_drm_route *conn_routes,
> > -		    unsigned int num_conn_routes);
> > +int mtk_crtc_create(struct drm_device *drm_dev,
> > +		    enum mtk_crtc_path path_sel);
> >  int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane
> > *plane,
> >  			 struct mtk_plane_state *state);
> >  void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane
> > *plane,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > index 492b8d965309..f841184d1e06 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c
> > @@ -464,6 +464,7 @@ static const char * const
> > mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
> >  	[MTK_DISP_PWM] = "pwm",
> >  	[MTK_DISP_RDMA] = "rdma",
> >  	[MTK_DISP_UFOE] = "ufoe",
> > +	[MTK_DISP_VIRTUAL] = "virtual",
> >  	[MTK_DISP_WDMA] = "wdma",
> >  	[MTK_DP_INTF] = "dp-intf",
> >  	[MTK_DPI] = "dpi",
> > @@ -487,6 +488,15 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_COLOR0]		= {
> > MTK_DISP_COLOR,		0, &ddp_color },
> >  	[DDP_COMPONENT_COLOR1]		= {
> > MTK_DISP_COLOR,		1, &ddp_color },
> >  	[DDP_COMPONENT_DITHER0]		= {
> > MTK_DISP_DITHER,		0, &ddp_dither },
> > +	[DDP_COMPONENT_DLI_ASYNC0]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC1]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC8]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC21]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC22]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLI_ASYNC23]     = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC1]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC2]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_DLO_ASYNC3]      = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_DP_INTF0]	= {
> > MTK_DP_INTF,		0, &ddp_dpi },
> >  	[DDP_COMPONENT_DP_INTF1]	= {
> > MTK_DP_INTF,		1, &ddp_dpi },
> >  	[DDP_COMPONENT_DPI0]		= {
> > MTK_DPI,			0, &ddp_dpi },
> > @@ -494,6 +504,9 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_DRM_OVL_ADAPTOR]	= {
> > MTK_DISP_OVL_ADAPTOR,	0, &ddp_ovl_adaptor },
> >  	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> >  	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 0, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 1, &ddp_ovlsys_adaptor},
> > +	[DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2] = {
> > MTK_DISP_OVLSYS_ADAPTOR, 2, &ddp_ovlsys_adaptor},
> >  	[DDP_COMPONENT_DSC0]		= {
> > MTK_DISP_DSC,		0, &ddp_dsc },
> >  	[DDP_COMPONENT_DSC1]		= {
> > MTK_DISP_DSC,		1, &ddp_dsc },
> >  	[DDP_COMPONENT_DSI0]		= {
> > MTK_DSI,			0, &ddp_dsi },
> > @@ -510,7 +523,10 @@ static const struct mtk_ddp_comp_match
> > mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX]
> >  	[DDP_COMPONENT_OD0]		= {
> > MTK_DISP_OD,		0, &ddp_od },
> >  	[DDP_COMPONENT_OD1]		= {
> > MTK_DISP_OD,		1, &ddp_od },
> >  	[DDP_COMPONENT_OVL0]		= {
> > MTK_DISP_OVL,		0, &ddp_ovl },
> > +	[DDP_COMPONENT_OVL0_DLO_ASYNC5] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> > +	[DDP_COMPONENT_OVL0_DLO_ASYNC6] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_OVL1]		= {
> > MTK_DISP_OVL,		1, &ddp_ovl },
> > +	[DDP_COMPONENT_OVL1_DLO_ASYNC5] = {
> > MTK_DISP_VIRTUAL,           -1, NULL },
> >  	[DDP_COMPONENT_OVL_2L0]		= {
> > MTK_DISP_OVL_2L,		0, &ddp_ovl },
> >  	[DDP_COMPONENT_OVL_2L1]		= {
> > MTK_DISP_OVL_2L,		1, &ddp_ovl },
> >  	[DDP_COMPONENT_OVL_2L2]		= {
> > MTK_DISP_OVL_2L,		2, &ddp_ovl },
> > @@ -567,12 +583,19 @@ static bool mtk_ddp_path_available(const
> > unsigned int *path,
> >  {
> >  	unsigned int i;
> >  
> > +	if (!path_len)
> > +		return true;
> > +
> >  	if (!path || !path_len)
> >  		return false;
> >  
> >  	for (i = 0U; i < path_len; i++) {
> >  		/* OVL_ADAPTOR doesn't have a device node */
> > -		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR)
> > +		if (path[i] == DDP_COMPONENT_DRM_OVL_ADAPTOR ||
> > +		    path[i] == DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0
> > ||
> > +			path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR1 ||
> > +			path[i] ==
> > DDP_COMPONENT_DRM_OVLSYS_ADAPTOR2 ||
> > +			mtk_ddp_comp_get_type(path[i]) ==
> > MTK_DISP_VIRTUAL)
> >  			continue;
> >  
> >  		if (!comp_node[path[i]])
> > @@ -597,44 +620,81 @@ int mtk_ddp_comp_get_id(struct device_node
> > *node,
> >  	return -EINVAL;
> >  }
> >  
> > +enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id)
> > +{
> > +	return mtk_ddp_matches[comp_id].type;
> > +}
> > +
> >  int mtk_find_possible_crtcs(struct drm_device *drm, struct device
> > *dev)
> >  {
> >  	struct mtk_drm_private *private = drm->dev_private;
> >  	const struct mtk_mmsys_driver_data *data;
> >  	struct mtk_drm_private *priv_n;
> > -	int i = 0, j;
> >  	int ret;
> > +	int i = 0, j, count = 0;
> > +	bool found = false;
> >  
> >  	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> >  		priv_n = private->all_drm_private[j];
> >  		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->main_path, data-
> > >main_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data-
> > >main_path,
> > -					      data->main_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					   priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->main_path, data-
> > >main_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> > +	}
> > +
> > +	count = 0;
> > +	found = false;
> > +
> > +	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> > +		priv_n = private->all_drm_private[j];
> > +		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->ext_path, data-
> > >ext_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data->ext_path,
> > -					      data->ext_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					   priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->ext_path, data-
> > >ext_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> > +	}
> > +
> > +	count = 0;
> > +	found = false;
> > +
> > +	for (j = 0; j < private->data->mmsys_dev_num; j++) {
> > +		priv_n = private->all_drm_private[j];
> > +		data = priv_n->data;
> >  
> >  		if (mtk_ddp_path_available(data->third_path, data-
> > >third_len,
> > -					   priv_n->comp_node)) {
> > -			if (mtk_ddp_comp_find(dev, data-
> > >third_path,
> > -					      data->third_len,
> > -					      priv_n->ddp_comp))
> > -				return BIT(i);
> > -			i++;
> > -		}
> > +					priv_n->comp_node))
> > +			count++;
> > +
> > +		if (mtk_ddp_comp_find(dev, data->third_path, data-
> > >third_len,
> > +				      priv_n->ddp_comp))
> > +			found = true;
> > +	}
> > +
> > +	if (count == private->data->mmsys_dev_num) {
> > +		if (found)
> > +			return BIT(i);
> > +		i++;
> >  	}
> >  
> >  	ret = mtk_ddp_comp_find_in_route(dev,
> > diff --git a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > index ef64ce7a071f..badb42bd4f7c 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h
> > @@ -40,6 +40,7 @@ enum mtk_ddp_comp_type {
> >  	MTK_DISP_PWM,
> >  	MTK_DISP_RDMA,
> >  	MTK_DISP_UFOE,
> > +	MTK_DISP_VIRTUAL,
> >  	MTK_DISP_WDMA,
> >  	MTK_DPI,
> >  	MTK_DP_INTF,
> > @@ -47,6 +48,7 @@ enum mtk_ddp_comp_type {
> >  	MTK_OVL_BLENDER,
> >  	MTK_OVL_EXDMA,
> >  	MTK_OVL_OUTPROC,
> > +	MTK_VDISP_AO,
> >  	MTK_DDP_COMP_TYPE_MAX,
> >  };
> >  
> > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > index 7526bc38bcc7..0665a6feb546 100644
> > --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> > @@ -193,6 +193,10 @@ static const struct mtk_drm_route
> > mt8188_mtk_ddp_main_routes[] = {
> >  	{0, DDP_COMPONENT_DSI0},
> >  };
> >  
> > +static const struct mtk_drm_route mt8196_mtk_ddp_routes[] = {
> > +	{2, DDP_COMPONENT_DSI0},
> > +};
> > +
> >  static const unsigned int mt8192_mtk_ddp_main[] = {
> >  	DDP_COMPONENT_OVL0,
> >  	DDP_COMPONENT_OVL_2L0,
> > @@ -231,6 +235,50 @@ static const unsigned int mt8195_mtk_ddp_ext[]
> > = {
> >  	DDP_COMPONENT_DP_INTF1,
> >  };
> >  
> > +static const unsigned int mt8196_mtk_ddp_ovl0_main[] = {
> > +	DDP_COMPONENT_DRM_OVLSYS_ADAPTOR0,
> > +	DDP_COMPONENT_OVL0_DLO_ASYNC5,
> > +};
> 
> Separate MT8196 part to another patch which add support MT8196.
> Let this patch not related to specific SoC.
> 
> Regards,
> CK

Sure, I will separate this patch to 2 part, first patch is to supprt
the multiple MMSYS for mediatek drm driver. Second patch is to support
MT8196 SOC.

Best, 
Paul  

[-- Attachment #2: Type: text/html, Size: 65362 bytes --]

  reply	other threads:[~2025-02-21 12:42 UTC|newest]

Thread overview: 108+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-10 12:33 [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 paul-pl.chen
2025-01-10 12:33 ` paul-pl.chen
2025-01-10 12:33 ` [PATCH 01/12] dt-bindings: arm: mediatek: mmsys: add compatible for MT8196 paul-pl.chen
2025-01-10 12:33   ` paul-pl.chen
2025-01-10 12:58   ` Krzysztof Kozlowski
2025-01-10 12:58     ` Krzysztof Kozlowski
2025-01-13 11:25     ` Fei Shao
2025-01-13 11:30       ` Krzysztof Kozlowski
2025-01-15  9:18     ` Paul-pl Chen (陳柏霖)
2025-01-15  9:18       ` Paul-pl Chen (陳柏霖)
2025-01-15  9:18       ` Paul-pl Chen (陳柏霖)
2025-01-10 12:33 ` [PATCH 02/12] dt-bindings: soc: mediatek: add mutex yaml " paul-pl.chen
2025-01-10 12:33   ` paul-pl.chen
2025-01-10 12:33 ` [PATCH 03/12] dt-bindings: display: mediatek: add EXDMA " paul-pl.chen
2025-01-10 12:33   ` paul-pl.chen
2025-01-10 13:01   ` Krzysztof Kozlowski
2025-01-10 13:01     ` Krzysztof Kozlowski
2025-01-17 10:36     ` Paul-pl Chen (陳柏霖)
2025-01-17 10:36       ` Paul-pl Chen (陳柏霖)
2025-01-17 10:36       ` Paul-pl Chen (陳柏霖)
2025-01-18  8:37       ` Krzysztof Kozlowski
2025-01-18  8:37         ` Krzysztof Kozlowski
2025-01-21 17:07         ` Paul-pl Chen (陳柏霖)
2025-01-21 17:07           ` Paul-pl Chen (陳柏霖)
2025-01-21 17:07           ` Paul-pl Chen (陳柏霖)
2025-02-11  8:23         ` Paul-pl Chen (陳柏霖)
2025-02-11  8:23           ` Paul-pl Chen (陳柏霖)
2025-02-11  8:23           ` Paul-pl Chen (陳柏霖)
2025-02-12  5:40           ` Krzysztof Kozlowski
2025-02-12  5:40             ` Krzysztof Kozlowski
2025-01-10 12:33 ` paul-pl.chen
2025-01-10 12:33   ` paul-pl.chen
2025-01-10 13:54   ` Rob Herring (Arm)
2025-01-10 13:54     ` Rob Herring (Arm)
2025-01-14  5:49     ` Paul-pl Chen (陳柏霖)
2025-01-14  5:49       ` Paul-pl Chen (陳柏霖)
2025-01-14  5:49       ` Paul-pl Chen (陳柏霖)
2025-01-14 10:34       ` AngeloGioacchino Del Regno
2025-01-14 10:34         ` AngeloGioacchino Del Regno
2025-01-15 12:13         ` Paul-pl Chen (陳柏霖)
2025-01-15 12:13           ` Paul-pl Chen (陳柏霖)
2025-01-15 12:13           ` Paul-pl Chen (陳柏霖)
2025-01-18  9:22       ` Krzysztof Kozlowski
2025-01-18  9:22         ` Krzysztof Kozlowski
2025-01-21 17:14         ` Paul-pl Chen (陳柏霖)
2025-01-21 17:14           ` Paul-pl Chen (陳柏霖)
2025-01-21 17:14           ` Paul-pl Chen (陳柏霖)
2025-01-23  6:11         ` Paul-pl Chen (陳柏霖)
2025-01-23  6:11           ` Paul-pl Chen (陳柏霖)
2025-01-23  6:11           ` Paul-pl Chen (陳柏霖)
2025-01-23  6:25           ` Chen-Yu Tsai
2025-01-23  6:25             ` Chen-Yu Tsai
2025-01-23 16:09             ` Paul-pl Chen (陳柏霖)
2025-01-23 16:09               ` Paul-pl Chen (陳柏霖)
2025-01-23 16:09               ` Paul-pl Chen (陳柏霖)
2025-01-23  7:21           ` Krzysztof Kozlowski
2025-01-23  7:21             ` Krzysztof Kozlowski
2025-01-23 16:14             ` Paul-pl Chen (陳柏霖)
2025-01-23 16:14               ` Paul-pl Chen (陳柏霖)
2025-01-23 16:14               ` Paul-pl Chen (陳柏霖)
2025-01-23 16:20               ` Chen-Yu Tsai
2025-01-23 16:20                 ` Chen-Yu Tsai
2025-01-10 12:34 ` [PATCH 04/12] dt-bindings: display: mediatek: add BLENDER " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-01-10 13:54   ` Rob Herring (Arm)
2025-01-10 13:54     ` Rob Herring (Arm)
2025-01-10 12:34 ` [PATCH 05/12] dt-bindings: display: mediatek: add OUTPROC " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-01-10 13:54   ` Rob Herring (Arm)
2025-01-10 13:54     ` Rob Herring (Arm)
2025-01-10 12:34 ` [PATCH 06/12] soc: mediatek: add mmsys support " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-01-10 12:34 ` [PATCH 07/12] soc: mediatek: mutex: add mutex " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-01-20  8:04   ` Chen-Yu Tsai
2025-01-10 12:34 ` [PATCH 08/12] drm/mediatek: add EXDMA " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-01-16  1:45   ` CK Hu (胡俊光)
2025-01-16  1:45     ` CK Hu (胡俊光)
2025-01-20  9:54   ` Chen-Yu Tsai
2025-01-10 12:34 ` [PATCH 09/12] drm/mediatek: add BLENDER " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-02-12  3:45   ` CK Hu (胡俊光)
2025-02-12  3:45     ` CK Hu (胡俊光)
2025-02-20 10:11     ` Paul-pl Chen (陳柏霖)
2025-01-10 12:34 ` [PATCH 10/12] drm/mediatek: add OUTPROC " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-02-12  4:08   ` CK Hu (胡俊光)
2025-02-12  4:08     ` CK Hu (胡俊光)
2025-02-21 11:54     ` Paul-pl Chen (陳柏霖)
2025-02-21 11:54       ` Paul-pl Chen (陳柏霖)
2025-01-10 12:34 ` [PATCH 11/12] drm/mediatek: add ovlsys_adaptor " paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-02-12  7:09   ` CK Hu (胡俊光)
2025-02-12  7:09     ` CK Hu (胡俊光)
2025-02-21 12:34     ` Paul-pl Chen (陳柏霖)
2025-02-21 12:34       ` Paul-pl Chen (陳柏霖)
2025-01-10 12:34 ` [PATCH 12/12] drm/mediatek: Add support for multiple mmsys in the one mediatek-drm driver paul-pl.chen
2025-01-10 12:34   ` paul-pl.chen
2025-02-12  9:30   ` CK Hu (胡俊光)
2025-02-12  9:30     ` CK Hu (胡俊光)
2025-02-21 12:39     ` Paul-pl Chen (陳柏霖) [this message]
2025-02-21 12:39       ` Paul-pl Chen (陳柏霖)
2025-01-13 12:50 ` [PATCH 00/12] Add Mediatek Soc DRM support for mt8196 AngeloGioacchino Del Regno
2025-01-13 12:50   ` AngeloGioacchino Del Regno
2025-01-15  8:05   ` Paul-pl Chen (陳柏霖)
2025-01-15  8:05     ` Paul-pl Chen (陳柏霖)
2025-01-15  8:05     ` Paul-pl Chen (陳柏霖)

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=773cbb9b4bc8b03c06a5d48a6df7e2faeb3fb49a.camel@mediatek.com \
    --to=paul-pl.chen@mediatek.com \
    --cc=Jason-JH.Lin@mediatek.com \
    --cc=Nancy.Lin@mediatek.com \
    --cc=Project_Global_Chrome_Upstream_Group@mediatek.com \
    --cc=Singo.Chang@mediatek.com \
    --cc=Sirius.Wang@mediatek.com \
    --cc=Sunny.Shen@mediatek.com \
    --cc=Xiandong.Wang@mediatek.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=chunkuang.hu@kernel.org \
    --cc=ck.hu@mediatek.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=matthias.bgg@gmail.com \
    --cc=p.zabel@pengutronix.de \
    --cc=robh@kernel.org \
    --cc=treapking@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.