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@xxxxxxxxxxxx> > > > > 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@xxxxxxxxxxxx> > > Signed-off-by: Paul-pl.Chen <paul-pl.chen@xxxxxxxxxxxx> > > --- > > 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