2 * Copyright (C) 2014 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
4 * Author: Vinay Simha <vinaysimha@inforcecomputing.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/gpio.h>
23 struct mdp4_lvds_connector
{
24 struct drm_connector base
;
25 struct drm_encoder
*encoder
;
26 struct drm_panel
*panel
;
28 #define to_mdp4_lvds_connector(x) container_of(x, struct mdp4_lvds_connector, base)
30 static enum drm_connector_status
mdp4_lvds_connector_detect(
31 struct drm_connector
*connector
, bool force
)
33 struct mdp4_lvds_connector
*mdp4_lvds_connector
=
34 to_mdp4_lvds_connector(connector
);
36 return mdp4_lvds_connector
->panel
?
37 connector_status_connected
:
38 connector_status_disconnected
;
41 static void mdp4_lvds_connector_destroy(struct drm_connector
*connector
)
43 struct mdp4_lvds_connector
*mdp4_lvds_connector
=
44 to_mdp4_lvds_connector(connector
);
45 struct drm_panel
*panel
= mdp4_lvds_connector
->panel
;
48 drm_panel_detach(panel
);
50 drm_connector_unregister(connector
);
51 drm_connector_cleanup(connector
);
53 kfree(mdp4_lvds_connector
);
56 static int mdp4_lvds_connector_get_modes(struct drm_connector
*connector
)
58 struct mdp4_lvds_connector
*mdp4_lvds_connector
=
59 to_mdp4_lvds_connector(connector
);
60 struct drm_panel
*panel
= mdp4_lvds_connector
->panel
;
64 ret
= panel
->funcs
->get_modes(panel
);
69 static int mdp4_lvds_connector_mode_valid(struct drm_connector
*connector
,
70 struct drm_display_mode
*mode
)
72 struct mdp4_lvds_connector
*mdp4_lvds_connector
=
73 to_mdp4_lvds_connector(connector
);
74 struct drm_encoder
*encoder
= mdp4_lvds_connector
->encoder
;
75 long actual
, requested
;
77 requested
= 1000 * mode
->clock
;
78 actual
= mdp4_lcdc_round_pixclk(encoder
, requested
);
80 DBG("requested=%ld, actual=%ld", requested
, actual
);
82 if (actual
!= requested
)
83 return MODE_CLOCK_RANGE
;
88 static struct drm_encoder
*
89 mdp4_lvds_connector_best_encoder(struct drm_connector
*connector
)
91 struct mdp4_lvds_connector
*mdp4_lvds_connector
=
92 to_mdp4_lvds_connector(connector
);
93 return mdp4_lvds_connector
->encoder
;
96 static const struct drm_connector_funcs mdp4_lvds_connector_funcs
= {
97 .dpms
= drm_atomic_helper_connector_dpms
,
98 .detect
= mdp4_lvds_connector_detect
,
99 .fill_modes
= drm_helper_probe_single_connector_modes
,
100 .destroy
= mdp4_lvds_connector_destroy
,
101 .reset
= drm_atomic_helper_connector_reset
,
102 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
103 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
106 static const struct drm_connector_helper_funcs mdp4_lvds_connector_helper_funcs
= {
107 .get_modes
= mdp4_lvds_connector_get_modes
,
108 .mode_valid
= mdp4_lvds_connector_mode_valid
,
109 .best_encoder
= mdp4_lvds_connector_best_encoder
,
112 /* initialize connector */
113 struct drm_connector
*mdp4_lvds_connector_init(struct drm_device
*dev
,
114 struct drm_panel
*panel
, struct drm_encoder
*encoder
)
116 struct drm_connector
*connector
= NULL
;
117 struct mdp4_lvds_connector
*mdp4_lvds_connector
;
120 mdp4_lvds_connector
= kzalloc(sizeof(*mdp4_lvds_connector
), GFP_KERNEL
);
121 if (!mdp4_lvds_connector
) {
126 mdp4_lvds_connector
->encoder
= encoder
;
127 mdp4_lvds_connector
->panel
= panel
;
129 connector
= &mdp4_lvds_connector
->base
;
131 drm_connector_init(dev
, connector
, &mdp4_lvds_connector_funcs
,
132 DRM_MODE_CONNECTOR_LVDS
);
133 drm_connector_helper_add(connector
, &mdp4_lvds_connector_helper_funcs
);
135 connector
->polled
= 0;
137 connector
->interlace_allowed
= 0;
138 connector
->doublescan_allowed
= 0;
140 drm_connector_register(connector
);
142 drm_mode_connector_attach_encoder(connector
, encoder
);
145 drm_panel_attach(panel
, connector
);
151 mdp4_lvds_connector_destroy(connector
);