1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
6 #include "drm/drm_edid.h"
10 struct edp_connector
{
11 struct drm_connector base
;
14 #define to_edp_connector(x) container_of(x, struct edp_connector, base)
16 static enum drm_connector_status
edp_connector_detect(
17 struct drm_connector
*connector
, bool force
)
19 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
20 struct msm_edp
*edp
= edp_connector
->edp
;
23 return msm_edp_ctrl_panel_connected(edp
->ctrl
) ?
24 connector_status_connected
: connector_status_disconnected
;
27 static void edp_connector_destroy(struct drm_connector
*connector
)
29 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
33 drm_connector_cleanup(connector
);
38 static int edp_connector_get_modes(struct drm_connector
*connector
)
40 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
41 struct msm_edp
*edp
= edp_connector
->edp
;
43 struct edid
*drm_edid
= NULL
;
47 ret
= msm_edp_ctrl_get_panel_info(edp
->ctrl
, connector
, &drm_edid
);
51 drm_connector_update_edid_property(connector
, drm_edid
);
53 ret
= drm_add_edid_modes(connector
, drm_edid
);
58 static int edp_connector_mode_valid(struct drm_connector
*connector
,
59 struct drm_display_mode
*mode
)
61 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
62 struct msm_edp
*edp
= edp_connector
->edp
;
63 struct msm_drm_private
*priv
= connector
->dev
->dev_private
;
64 struct msm_kms
*kms
= priv
->kms
;
65 long actual
, requested
;
67 requested
= 1000 * mode
->clock
;
68 actual
= kms
->funcs
->round_pixclk(kms
,
69 requested
, edp_connector
->edp
->encoder
);
71 DBG("requested=%ld, actual=%ld", requested
, actual
);
72 if (actual
!= requested
)
73 return MODE_CLOCK_RANGE
;
75 if (!msm_edp_ctrl_pixel_clock_valid(
76 edp
->ctrl
, mode
->clock
, NULL
, NULL
))
77 return MODE_CLOCK_RANGE
;
79 /* Invalidate all modes if color format is not supported */
80 if (connector
->display_info
.bpc
> 8)
86 static const struct drm_connector_funcs edp_connector_funcs
= {
87 .detect
= edp_connector_detect
,
88 .fill_modes
= drm_helper_probe_single_connector_modes
,
89 .destroy
= edp_connector_destroy
,
90 .reset
= drm_atomic_helper_connector_reset
,
91 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
92 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
95 static const struct drm_connector_helper_funcs edp_connector_helper_funcs
= {
96 .get_modes
= edp_connector_get_modes
,
97 .mode_valid
= edp_connector_mode_valid
,
100 /* initialize connector */
101 struct drm_connector
*msm_edp_connector_init(struct msm_edp
*edp
)
103 struct drm_connector
*connector
= NULL
;
104 struct edp_connector
*edp_connector
;
107 edp_connector
= kzalloc(sizeof(*edp_connector
), GFP_KERNEL
);
109 return ERR_PTR(-ENOMEM
);
111 edp_connector
->edp
= edp
;
113 connector
= &edp_connector
->base
;
115 ret
= drm_connector_init(edp
->dev
, connector
, &edp_connector_funcs
,
116 DRM_MODE_CONNECTOR_eDP
);
120 drm_connector_helper_add(connector
, &edp_connector_helper_funcs
);
122 /* We don't support HPD, so only poll status until connected. */
123 connector
->polled
= DRM_CONNECTOR_POLL_CONNECT
;
125 /* Display driver doesn't support interlace now. */
126 connector
->interlace_allowed
= false;
127 connector
->doublescan_allowed
= false;
129 drm_connector_attach_encoder(connector
, edp
->encoder
);