Hi, Enric: Enric Balletbo i Serra <enric.balletbo@xxxxxxxxxxxxx> 於 2020年6月16日 週二 上午4:31寫道: > > Convert mtk_dsi to a bridge driver with built-in encoder support for > compatibility with existing component drivers. Applied to mediatek-drm-next [1], thanks. [1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next Regards, Chun-Kuang. > > Signed-off-by: Enric Balletbo i Serra <enric.balletbo@xxxxxxxxxxxxx> > Acked-by: Sam Ravnborg <sam@xxxxxxxxxxxx> > Reviewed-by: Chun-Kuang Hu <chunkuang.hu@xxxxxxxxxx> > --- > > Changes in v4: > - Remove double call to drm_encoder_init(). (Chun-Kuang Hu) > - Cleanup the encoder in mtk_dsi_unbind(). (Chun-Kuang Hu) > > Changes in v3: > - Add the bridge.type. (Laurent Pinchart) > > Changes in v2: None > > drivers/gpu/drm/mediatek/mtk_dsi.c | 117 +++++++++++++++++++---------- > 1 file changed, 79 insertions(+), 38 deletions(-) > > diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c > index 208f49bf14a01..759a5b37fb4d2 100644 > --- a/drivers/gpu/drm/mediatek/mtk_dsi.c > +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c > @@ -181,6 +181,7 @@ struct mtk_dsi { > struct device *dev; > struct mipi_dsi_host host; > struct drm_encoder encoder; > + struct drm_bridge bridge; > struct drm_connector conn; > struct drm_panel *panel; > struct drm_bridge *next_bridge; > @@ -206,9 +207,9 @@ struct mtk_dsi { > const struct mtk_dsi_driver_data *driver_data; > }; > > -static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e) > +static inline struct mtk_dsi *bridge_to_dsi(struct drm_bridge *b) > { > - return container_of(e, struct mtk_dsi, encoder); > + return container_of(b, struct mtk_dsi, bridge); > } > > static inline struct mtk_dsi *connector_to_dsi(struct drm_connector *c) > @@ -788,32 +789,52 @@ static void mtk_output_dsi_disable(struct mtk_dsi *dsi) > dsi->enabled = false; > } > > -static bool mtk_dsi_encoder_mode_fixup(struct drm_encoder *encoder, > - const struct drm_display_mode *mode, > - struct drm_display_mode *adjusted_mode) > +static void mtk_dsi_encoder_destroy(struct drm_encoder *encoder) > { > - return true; > + drm_encoder_cleanup(encoder); > } > > -static void mtk_dsi_encoder_mode_set(struct drm_encoder *encoder, > - struct drm_display_mode *mode, > - struct drm_display_mode *adjusted) > +static const struct drm_encoder_funcs mtk_dsi_encoder_funcs = { > + .destroy = mtk_dsi_encoder_destroy, > +}; > + > +static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi); > +static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi); > + > +static int mtk_dsi_bridge_attach(struct drm_bridge *bridge, > + enum drm_bridge_attach_flags flags) > +{ > + struct mtk_dsi *dsi = bridge_to_dsi(bridge); > + > + return mtk_dsi_create_conn_enc(bridge->dev, dsi); > +} > + > +static void mtk_dsi_bridge_detach(struct drm_bridge *bridge) > { > - struct mtk_dsi *dsi = encoder_to_dsi(encoder); > + struct mtk_dsi *dsi = bridge_to_dsi(bridge); > + > + mtk_dsi_destroy_conn_enc(dsi); > +} > + > +static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge, > + const struct drm_display_mode *mode, > + const struct drm_display_mode *adjusted) > +{ > + struct mtk_dsi *dsi = bridge_to_dsi(bridge); > > drm_display_mode_to_videomode(adjusted, &dsi->vm); > } > > -static void mtk_dsi_encoder_disable(struct drm_encoder *encoder) > +static void mtk_dsi_bridge_disable(struct drm_bridge *bridge) > { > - struct mtk_dsi *dsi = encoder_to_dsi(encoder); > + struct mtk_dsi *dsi = bridge_to_dsi(bridge); > > mtk_output_dsi_disable(dsi); > } > > -static void mtk_dsi_encoder_enable(struct drm_encoder *encoder) > +static void mtk_dsi_bridge_enable(struct drm_bridge *bridge) > { > - struct mtk_dsi *dsi = encoder_to_dsi(encoder); > + struct mtk_dsi *dsi = bridge_to_dsi(bridge); > > mtk_output_dsi_enable(dsi); > } > @@ -825,11 +846,12 @@ static int mtk_dsi_connector_get_modes(struct drm_connector *connector) > return drm_panel_get_modes(dsi->panel, connector); > } > > -static const struct drm_encoder_helper_funcs mtk_dsi_encoder_helper_funcs = { > - .mode_fixup = mtk_dsi_encoder_mode_fixup, > - .mode_set = mtk_dsi_encoder_mode_set, > - .disable = mtk_dsi_encoder_disable, > - .enable = mtk_dsi_encoder_enable, > +static const struct drm_bridge_funcs mtk_dsi_bridge_funcs = { > + .attach = mtk_dsi_bridge_attach, > + .detach = mtk_dsi_bridge_detach, > + .disable = mtk_dsi_bridge_disable, > + .enable = mtk_dsi_bridge_enable, > + .mode_set = mtk_dsi_bridge_mode_set, > }; > > static const struct drm_connector_funcs mtk_dsi_connector_funcs = { > @@ -880,20 +902,6 @@ static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi) > { > int ret; > > - ret = drm_simple_encoder_init(drm, &dsi->encoder, > - DRM_MODE_ENCODER_DSI); > - if (ret) { > - DRM_ERROR("Failed to encoder init to drm\n"); > - return ret; > - } > - drm_encoder_helper_add(&dsi->encoder, &mtk_dsi_encoder_helper_funcs); > - > - /* > - * Currently display data paths are statically assigned to a crtc each. > - * crtc 0 is OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 > - */ > - dsi->encoder.possible_crtcs = 1; > - > /* If there's a next bridge, attach to it and let it create the connector */ > if (dsi->next_bridge) { > ret = drm_bridge_attach(&dsi->encoder, dsi->next_bridge, NULL, > @@ -1115,6 +1123,34 @@ static const struct mipi_dsi_host_ops mtk_dsi_ops = { > .transfer = mtk_dsi_host_transfer, > }; > > +static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) > +{ > + int ret; > + > + ret = drm_encoder_init(drm, &dsi->encoder, &mtk_dsi_encoder_funcs, > + DRM_MODE_ENCODER_DSI, NULL); > + if (ret) { > + DRM_ERROR("Failed to encoder init to drm\n"); > + return ret; > + } > + > + /* > + * Currently display data paths are statically assigned to a crtc each. > + * crtc 0 is OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 > + */ > + dsi->encoder.possible_crtcs = 1; > + > + ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, 0); > + if (ret) > + goto err_cleanup_encoder; > + > + return 0; > + > +err_cleanup_encoder: > + drm_encoder_cleanup(&dsi->encoder); > + return ret; > +} > + > static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) > { > int ret; > @@ -1128,11 +1164,9 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data) > return ret; > } > > - ret = mtk_dsi_create_conn_enc(drm, dsi); > - if (ret) { > - DRM_ERROR("Encoder create failed with %d\n", ret); > + ret = mtk_dsi_encoder_init(drm, dsi); > + if (ret) > goto err_unregister; > - } > > return 0; > > @@ -1147,7 +1181,7 @@ static void mtk_dsi_unbind(struct device *dev, struct device *master, > struct drm_device *drm = data; > struct mtk_dsi *dsi = dev_get_drvdata(dev); > > - mtk_dsi_destroy_conn_enc(dsi); > + drm_encoder_cleanup(&dsi->encoder); > mtk_ddp_comp_unregister(drm, &dsi->ddp_comp); > } > > @@ -1257,6 +1291,12 @@ static int mtk_dsi_probe(struct platform_device *pdev) > > platform_set_drvdata(pdev, dsi); > > + dsi->bridge.funcs = &mtk_dsi_bridge_funcs; > + dsi->bridge.of_node = dev->of_node; > + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI; > + > + drm_bridge_add(&dsi->bridge); > + > ret = component_add(&pdev->dev, &mtk_dsi_component_ops); > if (ret) { > dev_err(&pdev->dev, "failed to add component: %d\n", ret); > @@ -1275,6 +1315,7 @@ static int mtk_dsi_remove(struct platform_device *pdev) > struct mtk_dsi *dsi = platform_get_drvdata(pdev); > > mtk_output_dsi_disable(dsi); > + drm_bridge_remove(&dsi->bridge); > component_del(&pdev->dev, &mtk_dsi_component_ops); > mipi_dsi_host_unregister(&dsi->host); > > -- > 2.27.0 > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel