1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
6 #include <drm/drm_atomic_helper.h>
7 #include <drm/drm_atomic.h>
8 #include <drm/drm_crtc.h>
15 struct drm_connector base
;
16 struct msm_dp
*dp_display
;
18 #define to_dp_connector(x) container_of(x, struct dp_connector, base)
21 * dp_connector_detect - callback to determine if connector is connected
22 * @conn: Pointer to drm connector structure
23 * @force: Force detect setting from drm framework
24 * Returns: Connector 'is connected' status
26 static enum drm_connector_status
dp_connector_detect(struct drm_connector
*conn
,
31 dp
= to_dp_connector(conn
)->dp_display
;
33 DRM_DEBUG_DP("is_connected = %s\n",
34 (dp
->is_connected
) ? "true" : "false");
36 return (dp
->is_connected
) ? connector_status_connected
:
37 connector_status_disconnected
;
41 * dp_connector_get_modes - callback to add drm modes via drm_mode_probed_add()
42 * @connector: Pointer to drm connector structure
43 * Returns: Number of modes added
45 static int dp_connector_get_modes(struct drm_connector
*connector
)
49 struct dp_display_mode
*dp_mode
= NULL
;
50 struct drm_display_mode
*m
, drm_mode
;
55 dp
= to_dp_connector(connector
)->dp_display
;
57 dp_mode
= kzalloc(sizeof(*dp_mode
), GFP_KERNEL
);
61 /* pluggable case assumes EDID is read when HPD */
62 if (dp
->is_connected
) {
64 *The get_modes() function might return one mode that is stored
65 * in dp_mode when compliance test is in progress. If not, the
66 * return value is equal to the total number of modes supported
69 rc
= dp_display_get_modes(dp
, dp_mode
);
71 DRM_ERROR("failed to get DP sink modes, rc=%d\n", rc
);
75 if (dp_mode
->drm_mode
.clock
) { /* valid DP mode */
76 memset(&drm_mode
, 0x0, sizeof(drm_mode
));
77 drm_mode_copy(&drm_mode
, &dp_mode
->drm_mode
);
78 m
= drm_mode_duplicate(connector
->dev
, &drm_mode
);
80 DRM_ERROR("failed to add mode %ux%u\n",
86 drm_mode_probed_add(connector
, m
);
89 DRM_DEBUG_DP("No sink connected\n");
96 * dp_connector_mode_valid - callback to determine if specified mode is valid
97 * @connector: Pointer to drm connector structure
98 * @mode: Pointer to drm mode structure
99 * Returns: Validity status for specified mode
101 static enum drm_mode_status
dp_connector_mode_valid(
102 struct drm_connector
*connector
,
103 struct drm_display_mode
*mode
)
105 struct msm_dp
*dp_disp
;
107 dp_disp
= to_dp_connector(connector
)->dp_display
;
109 if ((dp_disp
->max_pclk_khz
<= 0) ||
110 (dp_disp
->max_pclk_khz
> DP_MAX_PIXEL_CLK_KHZ
) ||
111 (mode
->clock
> dp_disp
->max_pclk_khz
))
114 return dp_display_validate_mode(dp_disp
, mode
->clock
);
117 static const struct drm_connector_funcs dp_connector_funcs
= {
118 .detect
= dp_connector_detect
,
119 .fill_modes
= drm_helper_probe_single_connector_modes
,
120 .destroy
= drm_connector_cleanup
,
121 .reset
= drm_atomic_helper_connector_reset
,
122 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
123 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
126 static const struct drm_connector_helper_funcs dp_connector_helper_funcs
= {
127 .get_modes
= dp_connector_get_modes
,
128 .mode_valid
= dp_connector_mode_valid
,
131 /* connector initialization */
132 struct drm_connector
*dp_drm_connector_init(struct msm_dp
*dp_display
)
134 struct drm_connector
*connector
= NULL
;
135 struct dp_connector
*dp_connector
;
138 dp_connector
= devm_kzalloc(dp_display
->drm_dev
->dev
,
139 sizeof(*dp_connector
),
142 return ERR_PTR(-ENOMEM
);
144 dp_connector
->dp_display
= dp_display
;
146 connector
= &dp_connector
->base
;
148 ret
= drm_connector_init(dp_display
->drm_dev
, connector
,
150 DRM_MODE_CONNECTOR_DisplayPort
);
154 drm_connector_helper_add(connector
, &dp_connector_helper_funcs
);
157 * Enable HPD to let hpd event is handled when cable is connected.
159 connector
->polled
= DRM_CONNECTOR_POLL_HPD
;
161 drm_connector_attach_encoder(connector
, dp_display
->encoder
);