Hi Chaoyi,

At 2025-05-07 11:51:48, "Chaoyi Chen" <ker...@airkyi.com> wrote:
>From: Chaoyi Chen <chaoyi.c...@rock-chips.com>
>
>Convert it to drm bridge driver, it will be convenient for us to
>migrate the connector part to the display driver later.
>
>Tested with RK3399 EVB IND board.
>
>Signed-off-by: Chaoyi Chen <chaoyi.c...@rock-chips.com>
>---
> drivers/gpu/drm/rockchip/cdn-dp-core.c | 163 +++++++++++++------------
> drivers/gpu/drm/rockchip/cdn-dp-core.h |   5 +-
> 2 files changed, 86 insertions(+), 82 deletions(-)
>
>diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c 
>b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>index 292c31de18f1..bc70dae8ff72 100644
>--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
>+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
>@@ -25,9 +25,9 @@
> #include "cdn-dp-core.h"
> #include "cdn-dp-reg.h"
> 
>-static inline struct cdn_dp_device *connector_to_dp(struct drm_connector 
>*connector)
>+static inline struct cdn_dp_device *bridge_to_dp(struct drm_bridge *bridge)
> {
>-      return container_of(connector, struct cdn_dp_device, connector);
>+      return container_of(bridge, struct cdn_dp_device, bridge);
> }
> 
> static inline struct cdn_dp_device *encoder_to_dp(struct drm_encoder *encoder)
>@@ -231,9 +231,9 @@ static bool cdn_dp_check_sink_connection(struct 
>cdn_dp_device *dp)
> }
> 
> static enum drm_connector_status
>-cdn_dp_connector_detect(struct drm_connector *connector, bool force)
>+cdn_dp_bridge_detect(struct drm_bridge *bridge)
> {
>-      struct cdn_dp_device *dp = connector_to_dp(connector);
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>       enum drm_connector_status status = connector_status_disconnected;
> 
>       mutex_lock(&dp->lock);
>@@ -244,41 +244,26 @@ cdn_dp_connector_detect(struct drm_connector *connector, 
>bool force)
>       return status;
> }
> 
>-static void cdn_dp_connector_destroy(struct drm_connector *connector)
>+static const struct drm_edid *
>+cdn_dp_connector_edid_read(struct drm_bridge *bridge, struct drm_connector 
>*connector)

This should be cdn_dp_bridge_edid_read

> {
>-      drm_connector_unregister(connector);
>-      drm_connector_cleanup(connector);
>-}
>-
>-static const struct drm_connector_funcs cdn_dp_atomic_connector_funcs = {
>-      .detect = cdn_dp_connector_detect,
>-      .destroy = cdn_dp_connector_destroy,
>-      .fill_modes = drm_helper_probe_single_connector_modes,
>-      .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 int cdn_dp_connector_get_modes(struct drm_connector *connector)
>-{
>-      struct cdn_dp_device *dp = connector_to_dp(connector);
>-      int ret = 0;
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>+      const struct drm_edid *drm_edid;
> 
>       mutex_lock(&dp->lock);
>-
>-      ret = drm_edid_connector_add_modes(connector);
>-
>+      drm_edid = drm_edid_read_custom(dp->connector,
>+                                      cdn_dp_get_edid_block, dp);

Use drm_edid_read_ddc

>       mutex_unlock(&dp->lock);
> 
>-      return ret;
>+      return drm_edid;
> }
> 
> static enum drm_mode_status
>-cdn_dp_connector_mode_valid(struct drm_connector *connector,
>-                          const struct drm_display_mode *mode)
>+cdn_dp_bridge_mode_valid(struct drm_bridge *bridge,
>+                       const struct drm_display_info *display_info,
>+                       const struct drm_display_mode *mode)
> {
>-      struct cdn_dp_device *dp = connector_to_dp(connector);
>-      struct drm_display_info *display_info = &dp->connector.display_info;
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>       u32 requested, actual, rate, sink_max, source_max = 0;
>       u8 lanes, bpc;
> 
>@@ -323,11 +308,6 @@ cdn_dp_connector_mode_valid(struct drm_connector 
>*connector,
>       return MODE_OK;
> }
> 
>-static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = {
>-      .get_modes = cdn_dp_connector_get_modes,
>-      .mode_valid = cdn_dp_connector_mode_valid,
>-};
>-
> static int cdn_dp_firmware_init(struct cdn_dp_device *dp)
> {
>       int ret;
>@@ -360,7 +340,7 @@ static int cdn_dp_firmware_init(struct cdn_dp_device *dp)
> 
> static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp)
> {
>-      const struct drm_display_info *info = &dp->connector.display_info;
>+      const struct drm_display_info *info = &dp->connector->display_info;
>       int ret;
> 
>       if (!cdn_dp_check_sink_connection(dp))
>@@ -374,9 +354,9 @@ static int cdn_dp_get_sink_capability(struct cdn_dp_device 
>*dp)
>       }
> 
>       drm_edid_free(dp->drm_edid);
>-      dp->drm_edid = drm_edid_read_custom(&dp->connector,
>+      dp->drm_edid = drm_edid_read_custom(dp->connector,
>                                           cdn_dp_get_edid_block, dp);
>-      drm_edid_connector_update(&dp->connector, dp->drm_edid);
>+      drm_edid_connector_update(dp->connector, dp->drm_edid);
> 
>       dp->sink_has_audio = info->has_audio;
> 
>@@ -416,11 +396,11 @@ static int cdn_dp_enable_phy(struct cdn_dp_device *dp, 
>struct cdn_dp_port *port)
>               goto err_power_on;
>       }
> 
>-      ret = extcon_get_property(port->extcon, EXTCON_DISP_DP,
>-                                EXTCON_PROP_USB_TYPEC_POLARITY, &property);
>-      if (ret) {
>-              DRM_DEV_ERROR(dp->dev, "get property failed\n");
>-              goto err_power_on;
>+              ret = extcon_get_property(port->extcon, EXTCON_DISP_DP,
>+                                      EXTCON_PROP_USB_TYPEC_POLARITY, 
>&property);
>+              if (ret) {
>+                      DRM_DEV_ERROR(dp->dev, "get property failed\n");
>+                      goto err_power_on;
>       }
> 
>       port->lanes = cdn_dp_get_port_lanes(port);
>@@ -551,7 +531,7 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder 
>*encoder,
>                                   struct drm_display_mode *adjusted)
> {
>       struct cdn_dp_device *dp = encoder_to_dp(encoder);
>-      struct drm_display_info *display_info = &dp->connector.display_info;
>+      struct drm_display_info *display_info = &dp->connector->display_info;
>       struct video_info *video = &dp->video_info;
> 
>       switch (display_info->bpc) {
>@@ -599,12 +579,12 @@ static void cdn_dp_audio_handle_plugged_change(struct 
>cdn_dp_device *dp,
>               dp->plugged_cb(dp->codec_dev, plugged);
> }
> 
>-static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
>+static void cdn_dp_bridge_atomic_enable(struct drm_bridge *bridge, struct 
>drm_atomic_state *state)
> {
>-      struct cdn_dp_device *dp = encoder_to_dp(encoder);
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>       int ret, val;
> 
>-      ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
>+      ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, 
>&dp->encoder.encoder);
>       if (ret < 0) {
>               DRM_DEV_ERROR(dp->dev, "Could not get vop id, %d", ret);
>               return;
>@@ -625,7 +605,7 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
>*encoder)
> 
>       ret = cdn_dp_enable(dp);
>       if (ret) {
>-              DRM_DEV_ERROR(dp->dev, "Failed to enable encoder %d\n",
>+              DRM_DEV_ERROR(dp->dev, "Failed to enable bridge %d\n",
>                             ret);
>               goto out;
>       }
>@@ -661,9 +641,9 @@ static void cdn_dp_encoder_enable(struct drm_encoder 
>*encoder)
>       mutex_unlock(&dp->lock);
> }
> 
>-static void cdn_dp_encoder_disable(struct drm_encoder *encoder)
>+static void cdn_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct 
>drm_atomic_state *state)
> {
>-      struct cdn_dp_device *dp = encoder_to_dp(encoder);
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>       int ret;
> 
>       mutex_lock(&dp->lock);
>@@ -672,7 +652,7 @@ static void cdn_dp_encoder_disable(struct drm_encoder 
>*encoder)
>       if (dp->active) {
>               ret = cdn_dp_disable(dp);
>               if (ret) {
>-                      DRM_DEV_ERROR(dp->dev, "Failed to disable encoder %d\n",
>+                      DRM_DEV_ERROR(dp->dev, "Failed to disable bridge %d\n",
>                                     ret);
>               }
>       }
>@@ -703,13 +683,31 @@ static int cdn_dp_encoder_atomic_check(struct 
>drm_encoder *encoder,
>       return 0;
> }
> 
>+static void cdn_dp_hpd_notify(struct drm_bridge *bridge,
>+                         enum drm_connector_status status)
>+{
>+      struct cdn_dp_device *dp = bridge_to_dp(bridge);
>+
>+      schedule_work(&dp->event_work);
>+}
>+
> static const struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = {
>       .mode_set = cdn_dp_encoder_mode_set,
>-      .enable = cdn_dp_encoder_enable,
>-      .disable = cdn_dp_encoder_disable,
>       .atomic_check = cdn_dp_encoder_atomic_check,
> };
> 
>+static const struct drm_bridge_funcs cdn_dp_bridge_funcs = {
>+      .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>+      .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
>+      .atomic_reset = drm_atomic_helper_bridge_reset,
>+      .detect = cdn_dp_bridge_detect,
>+      .edid_read = cdn_dp_connector_edid_read,
>+      .atomic_enable = cdn_dp_bridge_atomic_enable,
>+      .atomic_disable = cdn_dp_bridge_atomic_disable,
>+      .mode_valid = cdn_dp_bridge_mode_valid,
>+      .hpd_notify = cdn_dp_hpd_notify,
>+};
>+
> static int cdn_dp_parse_dt(struct cdn_dp_device *dp)
> {
>       struct device *dev = dp->dev;
>@@ -859,7 +857,7 @@ static int cdn_dp_audio_get_eld(struct device *dev, void 
>*data,
> {
>       struct cdn_dp_device *dp = dev_get_drvdata(dev);
> 
>-      memcpy(buf, dp->connector.eld, min(sizeof(dp->connector.eld), len));
>+      memcpy(buf, dp->connector->eld, min(sizeof(dp->connector->eld), len));
> 
>       return 0;
> }
>@@ -1006,7 +1004,6 @@ static void cdn_dp_pd_event_work(struct work_struct 
>*work)
> 
> out:
>       mutex_unlock(&dp->lock);
>-      drm_connector_helper_hpd_irq_event(&dp->connector);
> }
> 
> static int cdn_dp_pd_event(struct notifier_block *nb,
>@@ -1030,7 +1027,6 @@ static int cdn_dp_bind(struct device *dev, struct device 
>*master, void *data)
> {
>       struct cdn_dp_device *dp = dev_get_drvdata(dev);
>       struct drm_encoder *encoder;
>-      struct drm_connector *connector;
>       struct cdn_dp_port *port;
>       struct drm_device *drm_dev = data;
>       int ret, i;
>@@ -1053,6 +1049,15 @@ static int cdn_dp_bind(struct device *dev, struct 
>device *master, void *data)
>                                                            dev->of_node);
>       DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
> 
>+      /*
>+       * If we failed to find the CRTC(s) which this encoder is
>+       * supposed to be connected to, it's because the CRTC has
>+       * not been registered yet. Defer probing, and hope that
>+       * the required CRTC is added later.
>+       */
>+      if (encoder->possible_crtcs == 0)
>+              return -EPROBE_DEFER;
>+
>       ret = drm_simple_encoder_init(drm_dev, encoder,
>                                     DRM_MODE_ENCODER_TMDS);
>       if (ret) {
>@@ -1062,26 +1067,31 @@ static int cdn_dp_bind(struct device *dev, struct 
>device *master, void *data)
> 
>       drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs);
> 
>-      connector = &dp->connector;
>-      connector->polled = DRM_CONNECTOR_POLL_HPD;
>-      connector->dpms = DRM_MODE_DPMS_OFF;
>+      dp->bridge.driver_private = dp;
>+      dp->bridge.funcs = &cdn_dp_bridge_funcs;

Try use devm_drm_bridge_alloc

>+      dp->bridge.ops = DRM_BRIDGE_OP_DETECT |
>+                         DRM_BRIDGE_OP_EDID |
>+                         DRM_BRIDGE_OP_HPD;
>+      dp->bridge.of_node = dp->dev->of_node;
>+      dp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
> 
>-      ret = drm_connector_init(drm_dev, connector,
>-                               &cdn_dp_atomic_connector_funcs,
>-                               DRM_MODE_CONNECTOR_DisplayPort);
>-      if (ret) {
>-              DRM_ERROR("failed to initialize connector with drm\n");
>-              goto err_free_encoder;
>-      }
>+      ret = devm_drm_bridge_add(dev, &dp->bridge);
>+      if (ret)
>+              return ret;
> 
>-      drm_connector_helper_add(connector, &cdn_dp_connector_helper_funcs);
>+      ret = drm_bridge_attach(encoder, &dp->bridge, NULL, 
>DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>+      if (ret)
>+              return ret;
> 
>-      ret = drm_connector_attach_encoder(connector, encoder);
>-      if (ret) {
>-              DRM_ERROR("failed to attach connector and encoder\n");
>-              goto err_free_connector;
>+      dp->connector = drm_bridge_connector_init(drm_dev, encoder);
>+      if (IS_ERR(dp->connector)) {
>+              ret = PTR_ERR(dp->connector);
>+              dev_err(dp->dev, "failed to init bridge connector: %d\n", ret);
>+              return ret;
>       }
       Don't store connector here, we will move connector init to display 
controller side in the future.

      You can get connector by: connector = 
drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
      at atomic enable.


> 
>+      drm_connector_attach_encoder(dp->connector, encoder);
>+
>       for (i = 0; i < dp->ports; i++) {
>               port = dp->port[i];
> 
>@@ -1092,7 +1102,7 @@ static int cdn_dp_bind(struct device *dev, struct device 
>*master, void *data)
>               if (ret) {
>                       DRM_DEV_ERROR(dev,
>                                     "register EXTCON_DISP_DP notifier err\n");
>-                      goto err_free_connector;
>+                      return ret;
>               }
>       }
> 
>@@ -1101,24 +1111,15 @@ static int cdn_dp_bind(struct device *dev, struct 
>device *master, void *data)
>       schedule_work(&dp->event_work);
> 
>       return 0;
>-
>-err_free_connector:
>-      drm_connector_cleanup(connector);
>-err_free_encoder:
>-      drm_encoder_cleanup(encoder);
>-      return ret;
> }
> 
> static void cdn_dp_unbind(struct device *dev, struct device *master, void 
> *data)
> {
>       struct cdn_dp_device *dp = dev_get_drvdata(dev);
>       struct drm_encoder *encoder = &dp->encoder.encoder;
>-      struct drm_connector *connector = &dp->connector;
> 
>       cancel_work_sync(&dp->event_work);
>-      cdn_dp_encoder_disable(encoder);
>       encoder->funcs->destroy(encoder);
>-      connector->funcs->destroy(connector);
> 
>       pm_runtime_disable(dev);
>       if (dp->fw_loaded)
>diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h 
>b/drivers/gpu/drm/rockchip/cdn-dp-core.h
>index 17498f576ce7..d2778f7a5b31 100644
>--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
>+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
>@@ -8,6 +8,8 @@
> #define _CDN_DP_CORE_H
> 
> #include <drm/display/drm_dp_helper.h>
>+#include <drm/drm_bridge.h>
>+#include <drm/drm_bridge_connector.h>
> #include <drm/drm_panel.h>
> #include <drm/drm_probe_helper.h>
> #include <sound/hdmi-codec.h>
>@@ -65,7 +67,8 @@ struct cdn_dp_port {
> struct cdn_dp_device {
>       struct device *dev;
>       struct drm_device *drm_dev;
>-      struct drm_connector connector;
>+      struct drm_bridge bridge;
>+      struct drm_connector *connector;
>       struct rockchip_encoder encoder;
>       struct drm_display_mode mode;
>       struct platform_device *audio_pdev;
>-- 
>2.49.0

Reply via email to