1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <drm/drm_atomic_helper.h> 7 #include <drm/drm_atomic.h> 8 #include <drm/drm_bridge.h> 9 #include <drm/drm_bridge_connector.h> 10 #include <drm/drm_crtc.h> 11 12 #include "msm_drv.h" 13 #include "msm_kms.h" 14 #include "dp_drm.h" 15 16 /** 17 * dp_bridge_detect - callback to determine if connector is connected 18 * @bridge: Pointer to drm bridge structure 19 * Returns: Bridge's 'is connected' status 20 */ 21 static enum drm_connector_status dp_bridge_detect(struct drm_bridge *bridge) 22 { 23 struct msm_dp *dp; 24 25 dp = to_dp_bridge(bridge)->dp_display; 26 27 drm_dbg_dp(dp->drm_dev, "is_connected = %s\n", 28 (dp->is_connected) ? "true" : "false"); 29 30 return (dp->is_connected) ? connector_status_connected : 31 connector_status_disconnected; 32 } 33 34 /** 35 * dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add() 36 * @bridge: Poiner to drm bridge 37 * @connector: Pointer to drm connector structure 38 * Returns: Number of modes added 39 */ 40 static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *connector) 41 { 42 int rc = 0; 43 struct msm_dp *dp; 44 45 if (!connector) 46 return 0; 47 48 dp = to_dp_bridge(bridge)->dp_display; 49 50 /* pluggable case assumes EDID is read when HPD */ 51 if (dp->is_connected) { 52 rc = dp_display_get_modes(dp); 53 if (rc <= 0) { 54 DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc); 55 return rc; 56 } 57 } else { 58 drm_dbg_dp(connector->dev, "No sink connected\n"); 59 } 60 return rc; 61 } 62 63 static const struct drm_bridge_funcs dp_bridge_ops = { 64 .enable = dp_bridge_enable, 65 .disable = dp_bridge_disable, 66 .post_disable = dp_bridge_post_disable, 67 .mode_set = dp_bridge_mode_set, 68 .mode_valid = dp_bridge_mode_valid, 69 .get_modes = dp_bridge_get_modes, 70 .detect = dp_bridge_detect, 71 }; 72 73 struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev, 74 struct drm_encoder *encoder) 75 { 76 int rc; 77 struct msm_dp_bridge *dp_bridge; 78 struct drm_bridge *bridge; 79 80 dp_bridge = devm_kzalloc(dev->dev, sizeof(*dp_bridge), GFP_KERNEL); 81 if (!dp_bridge) 82 return ERR_PTR(-ENOMEM); 83 84 dp_bridge->dp_display = dp_display; 85 86 bridge = &dp_bridge->bridge; 87 bridge->funcs = &dp_bridge_ops; 88 bridge->type = dp_display->connector_type; 89 90 /* 91 * Many ops only make sense for DP. Why? 92 * - Detect/HPD are used by DRM to know if a display is _physically_ 93 * there, not whether the display is powered on / finished initting. 94 * On eDP we assume the display is always there because you can't 95 * know until power is applied. If we don't implement the ops DRM will 96 * assume our display is always there. 97 * - Currently eDP mode reading is driven by the panel driver. This 98 * allows the panel driver to properly power itself on to read the 99 * modes. 100 */ 101 if (!dp_display->is_edp) { 102 bridge->ops = 103 DRM_BRIDGE_OP_DETECT | 104 DRM_BRIDGE_OP_HPD | 105 DRM_BRIDGE_OP_MODES; 106 } 107 108 drm_bridge_add(bridge); 109 110 rc = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); 111 if (rc) { 112 DRM_ERROR("failed to attach bridge, rc=%d\n", rc); 113 drm_bridge_remove(bridge); 114 115 return ERR_PTR(rc); 116 } 117 118 if (dp_display->next_bridge) { 119 rc = drm_bridge_attach(dp_display->encoder, 120 dp_display->next_bridge, bridge, 121 DRM_BRIDGE_ATTACH_NO_CONNECTOR); 122 if (rc < 0) { 123 DRM_ERROR("failed to attach panel bridge: %d\n", rc); 124 drm_bridge_remove(bridge); 125 return ERR_PTR(rc); 126 } 127 } 128 129 return bridge; 130 } 131 132 /* connector initialization */ 133 struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display) 134 { 135 struct drm_connector *connector = NULL; 136 137 connector = drm_bridge_connector_init(dp_display->drm_dev, dp_display->encoder); 138 if (IS_ERR(connector)) 139 return connector; 140 141 drm_connector_attach_encoder(connector, dp_display->encoder); 142 143 return connector; 144 } 145