2 * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include "drm/drm_edid.h"
18 struct edp_connector
{
19 struct drm_connector base
;
22 #define to_edp_connector(x) container_of(x, struct edp_connector, base)
24 static enum drm_connector_status
edp_connector_detect(
25 struct drm_connector
*connector
, bool force
)
27 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
28 struct msm_edp
*edp
= edp_connector
->edp
;
31 return msm_edp_ctrl_panel_connected(edp
->ctrl
) ?
32 connector_status_connected
: connector_status_disconnected
;
35 static void edp_connector_destroy(struct drm_connector
*connector
)
37 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
41 drm_connector_cleanup(connector
);
46 static int edp_connector_get_modes(struct drm_connector
*connector
)
48 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
49 struct msm_edp
*edp
= edp_connector
->edp
;
51 struct edid
*drm_edid
= NULL
;
55 ret
= msm_edp_ctrl_get_panel_info(edp
->ctrl
, connector
, &drm_edid
);
59 drm_mode_connector_update_edid_property(connector
, drm_edid
);
61 ret
= drm_add_edid_modes(connector
, drm_edid
);
66 static int edp_connector_mode_valid(struct drm_connector
*connector
,
67 struct drm_display_mode
*mode
)
69 struct edp_connector
*edp_connector
= to_edp_connector(connector
);
70 struct msm_edp
*edp
= edp_connector
->edp
;
71 struct msm_drm_private
*priv
= connector
->dev
->dev_private
;
72 struct msm_kms
*kms
= priv
->kms
;
73 long actual
, requested
;
75 requested
= 1000 * mode
->clock
;
76 actual
= kms
->funcs
->round_pixclk(kms
,
77 requested
, edp_connector
->edp
->encoder
);
79 DBG("requested=%ld, actual=%ld", requested
, actual
);
80 if (actual
!= requested
)
81 return MODE_CLOCK_RANGE
;
83 if (!msm_edp_ctrl_pixel_clock_valid(
84 edp
->ctrl
, mode
->clock
, NULL
, NULL
))
85 return MODE_CLOCK_RANGE
;
87 /* Invalidate all modes if color format is not supported */
88 if (connector
->display_info
.bpc
> 8)
94 static const struct drm_connector_funcs edp_connector_funcs
= {
95 .dpms
= drm_atomic_helper_connector_dpms
,
96 .detect
= edp_connector_detect
,
97 .fill_modes
= drm_helper_probe_single_connector_modes
,
98 .destroy
= edp_connector_destroy
,
99 .reset
= drm_atomic_helper_connector_reset
,
100 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
101 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
104 static const struct drm_connector_helper_funcs edp_connector_helper_funcs
= {
105 .get_modes
= edp_connector_get_modes
,
106 .mode_valid
= edp_connector_mode_valid
,
109 /* initialize connector */
110 struct drm_connector
*msm_edp_connector_init(struct msm_edp
*edp
)
112 struct drm_connector
*connector
= NULL
;
113 struct edp_connector
*edp_connector
;
116 edp_connector
= kzalloc(sizeof(*edp_connector
), GFP_KERNEL
);
118 return ERR_PTR(-ENOMEM
);
120 edp_connector
->edp
= edp
;
122 connector
= &edp_connector
->base
;
124 ret
= drm_connector_init(edp
->dev
, connector
, &edp_connector_funcs
,
125 DRM_MODE_CONNECTOR_eDP
);
129 drm_connector_helper_add(connector
, &edp_connector_helper_funcs
);
131 /* We don't support HPD, so only poll status until connected. */
132 connector
->polled
= DRM_CONNECTOR_POLL_CONNECT
;
134 /* Display driver doesn't support interlace now. */
135 connector
->interlace_allowed
= false;
136 connector
->doublescan_allowed
= false;
138 drm_mode_connector_attach_encoder(connector
, edp
->encoder
);