Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/rockchip: cdn-dp: Convert to drm bridge

Convert it to drm bridge driver, it will be convenient for us to
migrate the connector part to the display driver later.
Considering that some code depend on the connector, the following
changes have been made:
- Only process edid in &drm_bridge_funcs.edid_read(), so no need to
store additional edid info.
- Now cdn_dp_get_sink_capability() only focused on reading DPCD_REV.
- Update bpc info in cdn_dp_bridge_atomic_enable() instead of
cdn_dp_encoder_mode_set(). Actually, the bpc data will be used in
cdn_dp_bridge_atomic_enable().
- Switch to use DRM_BRIDGE_OP_DP_AUDIO helpers.

This patch also convert to use devm_drm_bridge_alloc() API.

Tested with RK3399 EVB IND board.

Signed-off-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://lore.kernel.org/r/20250529071334.441-1-kernel@airkyi.com

authored by

Chaoyi Chen and committed by
Heiko Stuebner
afbbca25 f9f68bf1

+110 -189
+108 -183
drivers/gpu/drm/rockchip/cdn-dp-core.c
··· 16 16 #include <sound/hdmi-codec.h> 17 17 18 18 #include <drm/display/drm_dp_helper.h> 19 + #include <drm/display/drm_hdmi_audio_helper.h> 19 20 #include <drm/drm_atomic_helper.h> 21 + #include <drm/drm_bridge_connector.h> 20 22 #include <drm/drm_edid.h> 21 23 #include <drm/drm_of.h> 22 24 #include <drm/drm_probe_helper.h> ··· 27 25 #include "cdn-dp-core.h" 28 26 #include "cdn-dp-reg.h" 29 27 30 - static inline struct cdn_dp_device *connector_to_dp(struct drm_connector *connector) 28 + static inline struct cdn_dp_device *bridge_to_dp(struct drm_bridge *bridge) 31 29 { 32 - return container_of(connector, struct cdn_dp_device, connector); 30 + return container_of(bridge, struct cdn_dp_device, bridge); 33 31 } 34 32 35 33 static inline struct cdn_dp_device *encoder_to_dp(struct drm_encoder *encoder) ··· 233 231 } 234 232 235 233 static enum drm_connector_status 236 - cdn_dp_connector_detect(struct drm_connector *connector, bool force) 234 + cdn_dp_bridge_detect(struct drm_bridge *bridge) 237 235 { 238 - struct cdn_dp_device *dp = connector_to_dp(connector); 236 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 239 237 enum drm_connector_status status = connector_status_disconnected; 240 238 241 239 mutex_lock(&dp->lock); ··· 246 244 return status; 247 245 } 248 246 249 - static void cdn_dp_connector_destroy(struct drm_connector *connector) 247 + static const struct drm_edid * 248 + cdn_dp_bridge_edid_read(struct drm_bridge *bridge, struct drm_connector *connector) 250 249 { 251 - drm_connector_unregister(connector); 252 - drm_connector_cleanup(connector); 253 - } 254 - 255 - static const struct drm_connector_funcs cdn_dp_atomic_connector_funcs = { 256 - .detect = cdn_dp_connector_detect, 257 - .destroy = cdn_dp_connector_destroy, 258 - .fill_modes = drm_helper_probe_single_connector_modes, 259 - .reset = drm_atomic_helper_connector_reset, 260 - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 261 - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 262 - }; 263 - 264 - static int cdn_dp_connector_get_modes(struct drm_connector *connector) 265 - { 266 - struct cdn_dp_device *dp = connector_to_dp(connector); 267 - int ret = 0; 250 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 251 + const struct drm_edid *drm_edid; 268 252 269 253 mutex_lock(&dp->lock); 270 - 271 - ret = drm_edid_connector_add_modes(connector); 272 - 254 + drm_edid = drm_edid_read_custom(connector, cdn_dp_get_edid_block, dp); 273 255 mutex_unlock(&dp->lock); 274 256 275 - return ret; 257 + return drm_edid; 276 258 } 277 259 278 260 static enum drm_mode_status 279 - cdn_dp_connector_mode_valid(struct drm_connector *connector, 280 - const struct drm_display_mode *mode) 261 + cdn_dp_bridge_mode_valid(struct drm_bridge *bridge, 262 + const struct drm_display_info *display_info, 263 + const struct drm_display_mode *mode) 281 264 { 282 - struct cdn_dp_device *dp = connector_to_dp(connector); 283 - struct drm_display_info *display_info = &dp->connector.display_info; 265 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 284 266 u32 requested, actual, rate, sink_max, source_max = 0; 285 267 u8 lanes, bpc; 286 268 ··· 309 323 return MODE_OK; 310 324 } 311 325 312 - static struct drm_connector_helper_funcs cdn_dp_connector_helper_funcs = { 313 - .get_modes = cdn_dp_connector_get_modes, 314 - .mode_valid = cdn_dp_connector_mode_valid, 315 - }; 316 - 317 326 static int cdn_dp_firmware_init(struct cdn_dp_device *dp) 318 327 { 319 328 int ret; ··· 341 360 342 361 static int cdn_dp_get_sink_capability(struct cdn_dp_device *dp) 343 362 { 344 - const struct drm_display_info *info = &dp->connector.display_info; 345 363 int ret; 346 364 347 365 if (!cdn_dp_check_sink_connection(dp)) ··· 352 372 DRM_DEV_ERROR(dp->dev, "Failed to get caps %d\n", ret); 353 373 return ret; 354 374 } 355 - 356 - drm_edid_free(dp->drm_edid); 357 - dp->drm_edid = drm_edid_read_custom(&dp->connector, 358 - cdn_dp_get_edid_block, dp); 359 - drm_edid_connector_update(&dp->connector, dp->drm_edid); 360 - 361 - dp->sink_has_audio = info->has_audio; 362 - 363 - if (dp->drm_edid) 364 - DRM_DEV_DEBUG_KMS(dp->dev, "got edid: width[%d] x height[%d]\n", 365 - info->width_mm / 10, info->height_mm / 10); 366 375 367 376 return 0; 368 377 } ··· 457 488 dp->active = false; 458 489 dp->max_lanes = 0; 459 490 dp->max_rate = 0; 460 - if (!dp->connected) { 461 - drm_edid_free(dp->drm_edid); 462 - dp->drm_edid = NULL; 463 - } 464 491 465 492 return 0; 466 493 } ··· 511 546 return ret; 512 547 } 513 548 514 - static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder, 515 - struct drm_display_mode *mode, 516 - struct drm_display_mode *adjusted) 549 + static void cdn_dp_bridge_mode_set(struct drm_bridge *bridge, 550 + const struct drm_display_mode *mode, 551 + const struct drm_display_mode *adjusted) 517 552 { 518 - struct cdn_dp_device *dp = encoder_to_dp(encoder); 519 - struct drm_display_info *display_info = &dp->connector.display_info; 553 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 520 554 struct video_info *video = &dp->video_info; 521 - 522 - switch (display_info->bpc) { 523 - case 10: 524 - video->color_depth = 10; 525 - break; 526 - case 6: 527 - video->color_depth = 6; 528 - break; 529 - default: 530 - video->color_depth = 8; 531 - break; 532 - } 533 555 534 556 video->color_fmt = PXL_RGB; 535 557 video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); ··· 544 592 return drm_dp_channel_eq_ok(link_status, min(port->lanes, sink_lanes)); 545 593 } 546 594 547 - static void cdn_dp_audio_handle_plugged_change(struct cdn_dp_device *dp, 548 - bool plugged) 595 + static void cdn_dp_display_info_update(struct cdn_dp_device *dp, 596 + struct drm_display_info *display_info) 549 597 { 550 - if (dp->codec_dev) 551 - dp->plugged_cb(dp->codec_dev, plugged); 598 + struct video_info *video = &dp->video_info; 599 + 600 + switch (display_info->bpc) { 601 + case 10: 602 + video->color_depth = 10; 603 + break; 604 + case 6: 605 + video->color_depth = 6; 606 + break; 607 + default: 608 + video->color_depth = 8; 609 + break; 610 + } 552 611 } 553 612 554 - static void cdn_dp_encoder_enable(struct drm_encoder *encoder) 613 + static void cdn_dp_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_atomic_state *state) 555 614 { 556 - struct cdn_dp_device *dp = encoder_to_dp(encoder); 615 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 616 + struct drm_connector *connector; 557 617 int ret, val; 558 618 559 - ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); 619 + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); 620 + if (!connector) 621 + return; 622 + 623 + cdn_dp_display_info_update(dp, &connector->display_info); 624 + 625 + ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, &dp->encoder.encoder); 560 626 if (ret < 0) { 561 627 DRM_DEV_ERROR(dp->dev, "Could not get vop id, %d", ret); 562 628 return; ··· 595 625 596 626 ret = cdn_dp_enable(dp); 597 627 if (ret) { 598 - DRM_DEV_ERROR(dp->dev, "Failed to enable encoder %d\n", 628 + DRM_DEV_ERROR(dp->dev, "Failed to enable bridge %d\n", 599 629 ret); 600 630 goto out; 601 631 } ··· 625 655 goto out; 626 656 } 627 657 628 - cdn_dp_audio_handle_plugged_change(dp, true); 629 - 630 658 out: 631 659 mutex_unlock(&dp->lock); 632 660 } 633 661 634 - static void cdn_dp_encoder_disable(struct drm_encoder *encoder) 662 + static void cdn_dp_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_atomic_state *state) 635 663 { 636 - struct cdn_dp_device *dp = encoder_to_dp(encoder); 664 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 637 665 int ret; 638 666 639 667 mutex_lock(&dp->lock); 640 - cdn_dp_audio_handle_plugged_change(dp, false); 641 668 642 669 if (dp->active) { 643 670 ret = cdn_dp_disable(dp); 644 671 if (ret) { 645 - DRM_DEV_ERROR(dp->dev, "Failed to disable encoder %d\n", 672 + DRM_DEV_ERROR(dp->dev, "Failed to disable bridge %d\n", 646 673 ret); 647 674 } 648 675 } ··· 671 704 } 672 705 673 706 static const struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = { 674 - .mode_set = cdn_dp_encoder_mode_set, 675 - .enable = cdn_dp_encoder_enable, 676 - .disable = cdn_dp_encoder_disable, 677 707 .atomic_check = cdn_dp_encoder_atomic_check, 678 708 }; 679 709 ··· 743 779 return 0; 744 780 } 745 781 746 - static int cdn_dp_audio_hw_params(struct device *dev, void *data, 747 - struct hdmi_codec_daifmt *daifmt, 748 - struct hdmi_codec_params *params) 782 + static int cdn_dp_audio_prepare(struct drm_connector *connector, 783 + struct drm_bridge *bridge, 784 + struct hdmi_codec_daifmt *daifmt, 785 + struct hdmi_codec_params *params) 749 786 { 750 - struct cdn_dp_device *dp = dev_get_drvdata(dev); 787 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 751 788 struct audio_info audio = { 752 789 .sample_width = params->sample_width, 753 790 .sample_rate = params->sample_rate, ··· 770 805 audio.format = AFMT_SPDIF; 771 806 break; 772 807 default: 773 - DRM_DEV_ERROR(dev, "Invalid format %d\n", daifmt->fmt); 808 + drm_err(bridge->dev, "Invalid format %d\n", daifmt->fmt); 774 809 ret = -EINVAL; 775 810 goto out; 776 811 } ··· 784 819 return ret; 785 820 } 786 821 787 - static void cdn_dp_audio_shutdown(struct device *dev, void *data) 822 + static void cdn_dp_audio_shutdown(struct drm_connector *connector, 823 + struct drm_bridge *bridge) 788 824 { 789 - struct cdn_dp_device *dp = dev_get_drvdata(dev); 825 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 790 826 int ret; 791 827 792 828 mutex_lock(&dp->lock); ··· 801 835 mutex_unlock(&dp->lock); 802 836 } 803 837 804 - static int cdn_dp_audio_mute_stream(struct device *dev, void *data, 838 + static int cdn_dp_audio_mute_stream(struct drm_connector *connector, 839 + struct drm_bridge *bridge, 805 840 bool enable, int direction) 806 841 { 807 - struct cdn_dp_device *dp = dev_get_drvdata(dev); 842 + struct cdn_dp_device *dp = bridge_to_dp(bridge); 808 843 int ret; 809 844 810 845 mutex_lock(&dp->lock); ··· 821 854 return ret; 822 855 } 823 856 824 - static int cdn_dp_audio_get_eld(struct device *dev, void *data, 825 - u8 *buf, size_t len) 826 - { 827 - struct cdn_dp_device *dp = dev_get_drvdata(dev); 857 + static const struct drm_bridge_funcs cdn_dp_bridge_funcs = { 858 + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 859 + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 860 + .atomic_reset = drm_atomic_helper_bridge_reset, 861 + .detect = cdn_dp_bridge_detect, 862 + .edid_read = cdn_dp_bridge_edid_read, 863 + .atomic_enable = cdn_dp_bridge_atomic_enable, 864 + .atomic_disable = cdn_dp_bridge_atomic_disable, 865 + .mode_valid = cdn_dp_bridge_mode_valid, 866 + .mode_set = cdn_dp_bridge_mode_set, 828 867 829 - memcpy(buf, dp->connector.eld, min(sizeof(dp->connector.eld), len)); 830 - 831 - return 0; 832 - } 833 - 834 - static int cdn_dp_audio_hook_plugged_cb(struct device *dev, void *data, 835 - hdmi_codec_plugged_cb fn, 836 - struct device *codec_dev) 837 - { 838 - struct cdn_dp_device *dp = dev_get_drvdata(dev); 839 - 840 - mutex_lock(&dp->lock); 841 - dp->plugged_cb = fn; 842 - dp->codec_dev = codec_dev; 843 - cdn_dp_audio_handle_plugged_change(dp, dp->connected); 844 - mutex_unlock(&dp->lock); 845 - 846 - return 0; 847 - } 848 - 849 - static const struct hdmi_codec_ops audio_codec_ops = { 850 - .hw_params = cdn_dp_audio_hw_params, 851 - .audio_shutdown = cdn_dp_audio_shutdown, 852 - .mute_stream = cdn_dp_audio_mute_stream, 853 - .get_eld = cdn_dp_audio_get_eld, 854 - .hook_plugged_cb = cdn_dp_audio_hook_plugged_cb, 868 + .dp_audio_prepare = cdn_dp_audio_prepare, 869 + .dp_audio_mute_stream = cdn_dp_audio_mute_stream, 870 + .dp_audio_shutdown = cdn_dp_audio_shutdown, 855 871 }; 856 - 857 - static int cdn_dp_audio_codec_init(struct cdn_dp_device *dp, 858 - struct device *dev) 859 - { 860 - struct hdmi_codec_pdata codec_data = { 861 - .i2s = 1, 862 - .spdif = 1, 863 - .ops = &audio_codec_ops, 864 - .max_i2s_channels = 8, 865 - .no_capture_mute = 1, 866 - }; 867 - 868 - dp->audio_pdev = platform_device_register_data( 869 - dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, 870 - &codec_data, sizeof(codec_data)); 871 - 872 - return PTR_ERR_OR_ZERO(dp->audio_pdev); 873 - } 874 872 875 873 static int cdn_dp_request_firmware(struct cdn_dp_device *dp) 876 874 { ··· 938 1006 939 1007 out: 940 1008 mutex_unlock(&dp->lock); 941 - drm_connector_helper_hpd_irq_event(&dp->connector); 1009 + drm_bridge_hpd_notify(&dp->bridge, 1010 + dp->connected ? connector_status_connected 1011 + : connector_status_disconnected); 942 1012 } 943 1013 944 1014 static int cdn_dp_pd_event(struct notifier_block *nb, ··· 996 1062 997 1063 drm_encoder_helper_add(encoder, &cdn_dp_encoder_helper_funcs); 998 1064 999 - connector = &dp->connector; 1000 - connector->polled = DRM_CONNECTOR_POLL_HPD; 1001 - connector->dpms = DRM_MODE_DPMS_OFF; 1065 + dp->bridge.ops = 1066 + DRM_BRIDGE_OP_DETECT | 1067 + DRM_BRIDGE_OP_EDID | 1068 + DRM_BRIDGE_OP_HPD | 1069 + DRM_BRIDGE_OP_DP_AUDIO; 1070 + dp->bridge.of_node = dp->dev->of_node; 1071 + dp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; 1072 + dp->bridge.hdmi_audio_dev = dp->dev; 1073 + dp->bridge.hdmi_audio_max_i2s_playback_channels = 8; 1074 + dp->bridge.hdmi_audio_spdif_playback = 1; 1075 + dp->bridge.hdmi_audio_dai_port = -1; 1002 1076 1003 - ret = drm_connector_init(drm_dev, connector, 1004 - &cdn_dp_atomic_connector_funcs, 1005 - DRM_MODE_CONNECTOR_DisplayPort); 1006 - if (ret) { 1007 - DRM_ERROR("failed to initialize connector with drm\n"); 1008 - goto err_free_encoder; 1077 + ret = devm_drm_bridge_add(dev, &dp->bridge); 1078 + if (ret) 1079 + return ret; 1080 + 1081 + ret = drm_bridge_attach(encoder, &dp->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); 1082 + if (ret) 1083 + return ret; 1084 + 1085 + connector = drm_bridge_connector_init(drm_dev, encoder); 1086 + if (IS_ERR(connector)) { 1087 + ret = PTR_ERR(connector); 1088 + dev_err(dp->dev, "failed to init bridge connector: %d\n", ret); 1089 + return ret; 1009 1090 } 1010 1091 1011 - drm_connector_helper_add(connector, &cdn_dp_connector_helper_funcs); 1012 - 1013 - ret = drm_connector_attach_encoder(connector, encoder); 1014 - if (ret) { 1015 - DRM_ERROR("failed to attach connector and encoder\n"); 1016 - goto err_free_connector; 1017 - } 1092 + drm_connector_attach_encoder(connector, encoder); 1018 1093 1019 1094 for (i = 0; i < dp->ports; i++) { 1020 1095 port = dp->port[i]; ··· 1035 1092 if (ret) { 1036 1093 DRM_DEV_ERROR(dev, 1037 1094 "register EXTCON_DISP_DP notifier err\n"); 1038 - goto err_free_connector; 1095 + return ret; 1039 1096 } 1040 1097 } 1041 1098 ··· 1044 1101 schedule_work(&dp->event_work); 1045 1102 1046 1103 return 0; 1047 - 1048 - err_free_connector: 1049 - drm_connector_cleanup(connector); 1050 - err_free_encoder: 1051 - drm_encoder_cleanup(encoder); 1052 - return ret; 1053 1104 } 1054 1105 1055 1106 static void cdn_dp_unbind(struct device *dev, struct device *master, void *data) 1056 1107 { 1057 1108 struct cdn_dp_device *dp = dev_get_drvdata(dev); 1058 1109 struct drm_encoder *encoder = &dp->encoder.encoder; 1059 - struct drm_connector *connector = &dp->connector; 1060 1110 1061 1111 cancel_work_sync(&dp->event_work); 1062 - cdn_dp_encoder_disable(encoder); 1063 1112 encoder->funcs->destroy(encoder); 1064 - connector->funcs->destroy(connector); 1065 1113 1066 1114 pm_runtime_disable(dev); 1067 1115 if (dp->fw_loaded) 1068 1116 release_firmware(dp->fw); 1069 - drm_edid_free(dp->drm_edid); 1070 - dp->drm_edid = NULL; 1071 1117 } 1072 1118 1073 1119 static const struct component_ops cdn_dp_component_ops = { ··· 1103 1171 int ret; 1104 1172 int i; 1105 1173 1106 - dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); 1107 - if (!dp) 1108 - return -ENOMEM; 1174 + dp = devm_drm_bridge_alloc(dev, struct cdn_dp_device, bridge, 1175 + &cdn_dp_bridge_funcs); 1176 + if (IS_ERR(dp)) 1177 + return PTR_ERR(dp); 1109 1178 dp->dev = dev; 1110 1179 1111 1180 match = of_match_node(cdn_dp_dt_ids, pdev->dev.of_node); ··· 1142 1209 mutex_init(&dp->lock); 1143 1210 dev_set_drvdata(dev, dp); 1144 1211 1145 - ret = cdn_dp_audio_codec_init(dp, dev); 1212 + ret = component_add(dev, &cdn_dp_component_ops); 1146 1213 if (ret) 1147 1214 return ret; 1148 1215 1149 - ret = component_add(dev, &cdn_dp_component_ops); 1150 - if (ret) 1151 - goto err_audio_deinit; 1152 - 1153 1216 return 0; 1154 - 1155 - err_audio_deinit: 1156 - platform_device_unregister(dp->audio_pdev); 1157 - return ret; 1158 1217 } 1159 1218 1160 1219 static void cdn_dp_remove(struct platform_device *pdev)
+2 -6
drivers/gpu/drm/rockchip/cdn-dp-core.h
··· 8 8 #define _CDN_DP_CORE_H 9 9 10 10 #include <drm/display/drm_dp_helper.h> 11 + #include <drm/drm_bridge.h> 11 12 #include <drm/drm_panel.h> 12 13 #include <drm/drm_probe_helper.h> 13 14 #include <sound/hdmi-codec.h> ··· 66 65 struct cdn_dp_device { 67 66 struct device *dev; 68 67 struct drm_device *drm_dev; 69 - struct drm_connector connector; 68 + struct drm_bridge bridge; 70 69 struct rockchip_encoder encoder; 71 70 struct drm_display_mode mode; 72 71 struct platform_device *audio_pdev; 73 72 struct work_struct event_work; 74 - const struct drm_edid *drm_edid; 75 73 76 74 struct mutex lock; 77 75 bool connected; ··· 101 101 int active_port; 102 102 103 103 u8 dpcd[DP_RECEIVER_CAP_SIZE]; 104 - bool sink_has_audio; 105 - 106 - hdmi_codec_plugged_cb plugged_cb; 107 - struct device *codec_dev; 108 104 }; 109 105 #endif /* _CDN_DP_CORE_H */