From: "Andy Yan" <andyshrk@163.com>
To: "Chaoyi Chen" <kernel@airkyi.com>
Cc: "Sandy Huang" <hjc@rock-chips.com>,
"Heiko Stuebner" <heiko@sntech.de>,
"Andy Yan" <andy.yan@rock-chips.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
dri-devel@lists.freedesktop.org,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
"Chaoyi Chen" <chaoyi.chen@rock-chips.com>
Subject: Re:[PATCH] drm/rockchip: cdn-dp: Convert to drm bridge
Date: Wed, 21 May 2025 20:09:04 +0800 (CST) [thread overview]
Message-ID: <110d136.9fc9.196f2bf47dd.Coremail.andyshrk@163.com> (raw)
In-Reply-To: <20250507035148.415-1-kernel@airkyi.com>
Hi Chaoyi,
At 2025-05-07 11:51:48, "Chaoyi Chen" <kernel@airkyi.com> wrote:
>From: Chaoyi Chen <chaoyi.chen@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.chen@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
WARNING: multiple messages have this Message-ID (diff)
From: "Andy Yan" <andyshrk@163.com>
To: "Chaoyi Chen" <kernel@airkyi.com>
Cc: "Sandy Huang" <hjc@rock-chips.com>,
"Heiko Stuebner" <heiko@sntech.de>,
"Andy Yan" <andy.yan@rock-chips.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
dri-devel@lists.freedesktop.org,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org,
"Chaoyi Chen" <chaoyi.chen@rock-chips.com>
Subject: Re:[PATCH] drm/rockchip: cdn-dp: Convert to drm bridge
Date: Wed, 21 May 2025 20:09:04 +0800 (CST) [thread overview]
Message-ID: <110d136.9fc9.196f2bf47dd.Coremail.andyshrk@163.com> (raw)
In-Reply-To: <20250507035148.415-1-kernel@airkyi.com>
Hi Chaoyi,
At 2025-05-07 11:51:48, "Chaoyi Chen" <kernel@airkyi.com> wrote:
>From: Chaoyi Chen <chaoyi.chen@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.chen@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
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
next prev parent reply other threads:[~2025-05-21 12:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-07 3:51 [PATCH] drm/rockchip: cdn-dp: Convert to drm bridge Chaoyi Chen
2025-05-07 3:51 ` Chaoyi Chen
2025-05-21 12:09 ` Andy Yan [this message]
2025-05-21 12:09 ` Andy Yan
2025-05-22 1:31 ` [PATCH] " Chaoyi Chen
2025-05-22 1:31 ` Chaoyi Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=110d136.9fc9.196f2bf47dd.Coremail.andyshrk@163.com \
--to=andyshrk@163.com \
--cc=airlied@gmail.com \
--cc=andy.yan@rock-chips.com \
--cc=chaoyi.chen@rock-chips.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=heiko@sntech.de \
--cc=hjc@rock-chips.com \
--cc=kernel@airkyi.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.