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