drm/msm/mdp4: switch LVDS to use drm_bridge/_connector
authorDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Fri, 25 Apr 2025 09:51:56 +0000 (12:51 +0300)
committerDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Thu, 1 May 2025 22:14:11 +0000 (01:14 +0300)
LVDS support in MDP4 driver makes use of drm_connector directly. However
LCDC encoder and LVDS connector are wrappers around drm_panel. Switch
them to use drm_panel_bridge/drm_bridge_connector. This allows using
standard interface for the drm_panel and also inserting additional
bridges between encoder and panel.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/650290/
Link: https://lore.kernel.org/r/20250425-fd-mdp4-lvds-v4-6-6b212160b44c@oss.qualcomm.com
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
drivers/gpu/drm/msm/Makefile
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.h
drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c [deleted file]

index 5df20cb..7a2ada6 100644 (file)
@@ -48,7 +48,6 @@ msm-display-$(CONFIG_DRM_MSM_MDP4) += \
        disp/mdp4/mdp4_dsi_encoder.o \
        disp/mdp4/mdp4_dtv_encoder.o \
        disp/mdp4/mdp4_lcdc_encoder.o \
-       disp/mdp4/mdp4_lvds_connector.o \
        disp/mdp4/mdp4_lvds_pll.o \
        disp/mdp4/mdp4_irq.o \
        disp/mdp4/mdp4_kms.o \
index c469e66..7e942c1 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <linux/delay.h>
 
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
 #include <drm/drm_vblank.h>
 
 #include "msm_drv.h"
@@ -189,7 +191,7 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
        struct msm_drm_private *priv = dev->dev_private;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
-       struct device_node *panel_node;
+       struct drm_bridge *next_bridge;
        int dsi_id;
        int ret;
 
@@ -199,27 +201,43 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
                 * bail out early if there is no panel node (no need to
                 * initialize LCDC encoder and LVDS connector)
                 */
-               panel_node = of_graph_get_remote_node(dev->dev->of_node, 0, 0);
-               if (!panel_node)
-                       return 0;
+               next_bridge = devm_drm_of_get_bridge(dev->dev, dev->dev->of_node, 0, 0);
+               if (IS_ERR(next_bridge)) {
+                       ret = PTR_ERR(next_bridge);
+                       if (ret == -ENODEV)
+                               return 0;
+                       return ret;
+               }
 
-               encoder = mdp4_lcdc_encoder_init(dev, panel_node);
+               encoder = mdp4_lcdc_encoder_init(dev);
                if (IS_ERR(encoder)) {
                        DRM_DEV_ERROR(dev->dev, "failed to construct LCDC encoder\n");
-                       of_node_put(panel_node);
                        return PTR_ERR(encoder);
                }
 
                /* LCDC can be hooked to DMA_P (TODO: Add DMA_S later?) */
                encoder->possible_crtcs = 1 << DMA_P;
 
-               connector = mdp4_lvds_connector_init(dev, panel_node, encoder);
+               ret = drm_bridge_attach(encoder, next_bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+               if (ret) {
+                       DRM_DEV_ERROR(dev->dev, "failed to attach LVDS panel/bridge: %d\n", ret);
+
+                       return ret;
+               }
+
+               connector = drm_bridge_connector_init(dev, encoder);
                if (IS_ERR(connector)) {
                        DRM_DEV_ERROR(dev->dev, "failed to initialize LVDS connector\n");
-                       of_node_put(panel_node);
                        return PTR_ERR(connector);
                }
 
+               ret = drm_connector_attach_encoder(connector, encoder);
+               if (ret) {
+                       DRM_DEV_ERROR(dev->dev, "failed to attach LVDS connector: %d\n", ret);
+
+                       return ret;
+               }
+
                break;
        case DRM_MODE_ENCODER_TMDS:
                encoder = mdp4_dtv_encoder_init(dev);
index 66f5009..f9d9880 100644 (file)
@@ -191,11 +191,7 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, unsigned long rate);
 struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev);
 
-struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
-               struct device_node *panel_node);
-
-struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
-               struct device_node *panel_node, struct drm_encoder *encoder);
+struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev);
 
 #ifdef CONFIG_DRM_MSM_DSI
 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev);
index 7f4e800..06a307c 100644 (file)
@@ -14,7 +14,6 @@
 
 struct mdp4_lcdc_encoder {
        struct drm_encoder base;
-       struct device_node *panel_node;
        struct drm_panel *panel;
        struct clk *lcdc_clk;
        unsigned long int pixclock;
@@ -262,19 +261,12 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
        struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
                        to_mdp4_lcdc_encoder(encoder);
        struct mdp4_kms *mdp4_kms = get_kms(encoder);
-       struct drm_panel *panel;
 
        if (WARN_ON(!mdp4_lcdc_encoder->enabled))
                return;
 
        mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 0);
 
-       panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
-       if (!IS_ERR(panel)) {
-               drm_panel_disable(panel);
-               drm_panel_unprepare(panel);
-       }
-
        /*
         * Wait for a vsync so we know the ENABLE=0 latched before
         * the (connector) source of the vsync's gets disabled,
@@ -300,7 +292,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
                        to_mdp4_lcdc_encoder(encoder);
        unsigned long pc = mdp4_lcdc_encoder->pixclock;
        struct mdp4_kms *mdp4_kms = get_kms(encoder);
-       struct drm_panel *panel;
        uint32_t config;
        int ret;
 
@@ -335,12 +326,6 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder)
        if (ret)
                DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret);
 
-       panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node);
-       if (!IS_ERR(panel)) {
-               drm_panel_prepare(panel);
-               drm_panel_enable(panel);
-       }
-
        setup_phy(encoder);
 
        mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1);
@@ -375,8 +360,7 @@ static const struct drm_encoder_helper_funcs mdp4_lcdc_encoder_helper_funcs = {
 };
 
 /* initialize encoder */
-struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
-               struct device_node *panel_node)
+struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev)
 {
        struct drm_encoder *encoder;
        struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
@@ -387,8 +371,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
        if (IS_ERR(mdp4_lcdc_encoder))
                return ERR_CAST(mdp4_lcdc_encoder);
 
-       mdp4_lcdc_encoder->panel_node = panel_node;
-
        encoder = &mdp4_lcdc_encoder->base;
 
        drm_encoder_helper_add(encoder, &mdp4_lcdc_encoder_helper_funcs);
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c
deleted file mode 100644 (file)
index 4755eb1..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2014 Red Hat
- * Author: Rob Clark <robdclark@gmail.com>
- * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
- */
-
-#include "mdp4_kms.h"
-
-struct mdp4_lvds_connector {
-       struct drm_connector base;
-       struct drm_encoder *encoder;
-       struct device_node *panel_node;
-       struct drm_panel *panel;
-};
-#define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base)
-
-static enum drm_connector_status mdp4_lvds_connector_detect(
-               struct drm_connector *connector, bool force)
-{
-       struct mdp4_lvds_connector *mdp4_lvds_connector =
-                       to_mdp4_lvds_connector(connector);
-
-       if (!mdp4_lvds_connector->panel) {
-               mdp4_lvds_connector->panel =
-                       of_drm_find_panel(mdp4_lvds_connector->panel_node);
-               if (IS_ERR(mdp4_lvds_connector->panel))
-                       mdp4_lvds_connector->panel = NULL;
-       }
-
-       return mdp4_lvds_connector->panel ?
-                       connector_status_connected :
-                       connector_status_disconnected;
-}
-
-static void mdp4_lvds_connector_destroy(struct drm_connector *connector)
-{
-       struct mdp4_lvds_connector *mdp4_lvds_connector =
-                       to_mdp4_lvds_connector(connector);
-
-       drm_connector_cleanup(connector);
-
-       kfree(mdp4_lvds_connector);
-}
-
-static int mdp4_lvds_connector_get_modes(struct drm_connector *connector)
-{
-       struct mdp4_lvds_connector *mdp4_lvds_connector =
-                       to_mdp4_lvds_connector(connector);
-       struct drm_panel *panel = mdp4_lvds_connector->panel;
-       int ret = 0;
-
-       if (panel)
-               ret = drm_panel_get_modes(panel, connector);
-
-       return ret;
-}
-
-static const struct drm_connector_funcs mdp4_lvds_connector_funcs = {
-       .detect = mdp4_lvds_connector_detect,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = mdp4_lvds_connector_destroy,
-       .reset = drm_atomic_helper_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs = {
-       .get_modes = mdp4_lvds_connector_get_modes,
-};
-
-/* initialize connector */
-struct drm_connector *mdp4_lvds_connector_init(struct drm_device *dev,
-               struct device_node *panel_node, struct drm_encoder *encoder)
-{
-       struct drm_connector *connector = NULL;
-       struct mdp4_lvds_connector *mdp4_lvds_connector;
-
-       mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL);
-       if (!mdp4_lvds_connector)
-               return ERR_PTR(-ENOMEM);
-
-       mdp4_lvds_connector->encoder = encoder;
-       mdp4_lvds_connector->panel_node = panel_node;
-
-       connector = &mdp4_lvds_connector->base;
-
-       drm_connector_init(dev, connector, &mdp4_lvds_connector_funcs,
-                       DRM_MODE_CONNECTOR_LVDS);
-       drm_connector_helper_add(connector, &mdp4_lvds_connector_helper_funcs);
-
-       connector->polled = 0;
-
-       connector->interlace_allowed = 0;
-       connector->doublescan_allowed = 0;
-
-       drm_connector_attach_encoder(connector, encoder);
-
-       return connector;
-}