32f969ab611262dbcbd01a1b22f29ff0a85e4d11
[platform/upstream/libdrm.git] / linux-core / radeon_connectors.c
1 /*
2  * Copyright 2007-8 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: Dave Airlie
24  *          Alex Deucher
25  */
26 #include "drmP.h"
27 #include "drm_edid.h"
28 #include "drm_crtc_helper.h"
29 #include "radeon_drm.h"
30 #include "radeon_drv.h"
31
32 static int radeon_lvds_get_modes(struct drm_connector *connector)
33 {
34         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
35         struct drm_encoder *lvds_encoder;
36         int ret = 0;
37         struct edid *edid;
38
39         radeon_i2c_do_lock(radeon_connector, 1);
40         edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
41         radeon_i2c_do_lock(radeon_connector, 0);
42         if (edid) {
43                 drm_mode_connector_update_edid_property(&radeon_connector->base, edid);
44                 ret = drm_add_edid_modes(&radeon_connector->base, edid);
45                 kfree(edid);
46                 return ret;
47         }
48
49 #if 0
50         lvds_encoder = radeon_best_single_encoder(connector);
51
52         if (!lvds_encoder)
53                 return ret;
54
55         radeon_encoder_update_panel_size(lvds_encoder, connector);
56 #endif
57         return ret;
58 }
59
60 static int radeon_lvds_mode_valid(struct drm_connector *connector,
61                                   struct drm_display_mode *mode)
62 {
63
64         return MODE_OK;
65 }
66
67 static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
68 {
69         return connector_status_connected;
70 }
71
72
73
74 struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
75 {
76         int enc_id = connector->encoder_ids[0];
77         struct drm_mode_object *obj;
78         struct drm_encoder *encoder;
79
80         /* pick the encoder ids */
81         if (enc_id) {
82                 obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
83                 if (!obj)
84                         return NULL;
85                 encoder = obj_to_encoder(obj);
86                 return encoder;
87         }
88         return NULL;
89 }
90
91 static void radeon_connector_destroy(struct drm_connector *connector)
92 {
93         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
94
95         if (radeon_connector->ddc_bus)
96                 radeon_i2c_destroy(radeon_connector->ddc_bus);
97         drm_sysfs_connector_remove(connector);
98         drm_connector_cleanup(connector);
99         kfree(connector);
100 }
101
102 struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
103         .get_modes = radeon_lvds_get_modes,
104         .mode_valid = radeon_lvds_mode_valid,
105         .best_encoder = radeon_best_single_encoder,
106 };
107
108 struct drm_connector_funcs radeon_lvds_connector_funcs = {
109         .detect = radeon_lvds_detect,
110         .fill_modes = drm_helper_probe_single_connector_modes,
111         .destroy = radeon_connector_destroy,
112 };
113
114 static int radeon_vga_get_modes(struct drm_connector *connector)
115 {
116         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
117         int ret;
118
119         ret = radeon_ddc_get_modes(radeon_connector);
120
121         return ret;
122 }
123
124 static int radeon_vga_mode_valid(struct drm_connector *connector,
125                                   struct drm_display_mode *mode)
126 {
127
128         return MODE_OK;
129 }
130
131 static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector)
132 {
133         struct edid *edid;
134         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
135         struct drm_encoder *encoder;
136         struct drm_encoder_helper_funcs *encoder_funcs;
137
138         radeon_i2c_do_lock(radeon_connector, 1);
139         edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
140         radeon_i2c_do_lock(radeon_connector, 0);
141         if (edid) {
142                 kfree(edid);
143                 return connector_status_connected;
144         }
145
146         /* if EDID fails to a load detect */
147         encoder = radeon_best_single_encoder(connector);
148         if (!encoder)
149                 return connector_status_disconnected;
150
151         encoder_funcs = encoder->helper_private;
152         return encoder_funcs->detect(encoder, connector);
153 }
154
155 struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = {
156         .get_modes = radeon_vga_get_modes,
157         .mode_valid = radeon_vga_mode_valid,
158         .best_encoder = radeon_best_single_encoder,
159 };
160
161 struct drm_connector_funcs radeon_vga_connector_funcs = {
162         .detect = radeon_vga_detect,
163         .fill_modes = drm_helper_probe_single_connector_modes,
164         .destroy = radeon_connector_destroy,
165 };
166
167
168 static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
169 {
170         struct edid *edid;
171         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
172         struct drm_encoder *encoder;
173         struct drm_encoder_helper_funcs *encoder_funcs;
174         struct drm_mode_object *obj;
175         int i;
176         enum drm_connector_status ret;
177
178         radeon_i2c_do_lock(radeon_connector, 1);
179         edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
180         radeon_i2c_do_lock(radeon_connector, 0);
181         if (edid) {
182                 /* if the monitor is digital - set the bits */
183                 if (edid->digital)
184                         radeon_connector->use_digital = 1;
185                 else
186                         radeon_connector->use_digital = 0;
187
188                 kfree(edid);
189                 return connector_status_connected;
190         }
191
192         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
193                 if (connector->encoder_ids[i] == 0)
194                         break;
195
196                 obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
197                 if (!obj)
198                         continue;
199
200                 encoder = obj_to_encoder(obj);
201
202                 encoder_funcs = encoder->helper_private;
203                 if (encoder_funcs->detect) {
204                         ret = encoder_funcs->detect(encoder, connector);
205                         if (ret == connector_status_connected) {
206                                 radeon_connector->use_digital = 0;
207                                 return ret;
208                         }
209                 }
210         }
211         return connector_status_disconnected;
212 }
213
214 /* okay need to be smart in here about which encoder to pick */
215 struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
216 {
217         int enc_id = connector->encoder_ids[0];
218         struct radeon_connector *radeon_connector = to_radeon_connector(connector);
219         struct drm_mode_object *obj;
220         struct drm_encoder *encoder;
221         int i;
222         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
223                 if (connector->encoder_ids[i] == 0)
224                         break;
225
226                 obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
227                 if (!obj)
228                         continue;
229
230                 encoder = obj_to_encoder(obj);
231
232                 if (radeon_connector->use_digital) {
233                         if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
234                                 return encoder;
235                 } else {
236                         if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
237                             encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
238                                 return encoder;
239                 }
240         }
241
242         /* see if we have a default encoder  TODO */
243         
244         /* then check use digitial */
245         /* pick the first one */
246         if (enc_id) {
247                 obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
248                 if (!obj)
249                         return NULL;
250                 encoder = obj_to_encoder(obj);
251                 return encoder;
252         }
253         return NULL;
254 }
255
256 struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
257         .get_modes = radeon_vga_get_modes,
258         .mode_valid = radeon_vga_mode_valid,
259         .best_encoder = radeon_dvi_encoder,
260 };
261
262 struct drm_connector_funcs radeon_dvi_connector_funcs = {
263         .detect = radeon_dvi_detect,
264         .fill_modes = drm_helper_probe_single_connector_modes,
265         .destroy = radeon_connector_destroy,
266 };
267
268
269 static struct connector_funcs {
270         int conn_id;
271         struct drm_connector_funcs *connector_funcs;
272         struct drm_connector_helper_funcs *helper_funcs;
273         int conn_type;
274         char *i2c_id;
275 } connector_fns[] = {
276         { CONNECTOR_NONE, NULL, NULL, DRM_MODE_CONNECTOR_Unknown },
277         { CONNECTOR_VGA, &radeon_vga_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA , "VGA"},
278         { CONNECTOR_LVDS, &radeon_lvds_connector_funcs, &radeon_lvds_connector_helper_funcs, DRM_MODE_CONNECTOR_LVDS, "LVDS" },
279         { CONNECTOR_DVI_A, &radeon_vga_connector_funcs, &radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_DVIA, "DVI" },
280         { CONNECTOR_DVI_I, &radeon_dvi_connector_funcs, &radeon_dvi_connector_helper_funcs, DRM_MODE_CONNECTOR_DVII, "DVI" },
281
282 #if 0
283         { CONNECTOR_DVI_D, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
284
285         { CONNECTOR_STV, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
286         { CONNECTOR_CTV, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
287         { CONNECTOR_DIGITAL, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
288         { CONNECTOR_SCART, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
289
290         { CONNECTOR_HDMI_TYPE_A, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
291         { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
292         { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
293         { CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
294         { CONNECTOR_DIN, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
295         { CONNECTOR_DISPLAY_PORT, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
296 #endif
297 };
298
299 struct drm_connector *radeon_connector_add(struct drm_device *dev, int bios_index)
300 {
301         struct radeon_connector *radeon_connector;
302         struct drm_radeon_private *dev_priv = dev->dev_private;
303         struct radeon_mode_info *mode_info = &dev_priv->mode_info;
304         struct drm_connector *connector;
305         int table_idx;
306
307         for (table_idx = 0; table_idx < ARRAY_SIZE(connector_fns); table_idx++) {
308                 if (connector_fns[table_idx].conn_id == mode_info->bios_connector[bios_index].connector_type)
309                         break;
310         }
311
312         if (table_idx == ARRAY_SIZE(connector_fns))
313                 return NULL;
314
315         radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
316         if (!radeon_connector) {
317                 return NULL;
318         }
319
320         connector = &radeon_connector->base;
321
322         drm_connector_init(dev, &radeon_connector->base, connector_fns[table_idx].connector_funcs,
323                            connector_fns[table_idx].conn_type);
324
325         drm_connector_helper_add(&radeon_connector->base, connector_fns[table_idx].helper_funcs);
326
327         if (mode_info->bios_connector[bios_index].ddc_i2c.valid) {
328                 radeon_connector->ddc_bus = radeon_i2c_create(dev, &mode_info->bios_connector[bios_index].ddc_i2c,
329                                                               connector_fns[table_idx].i2c_id);
330                 if (!radeon_connector->ddc_bus)
331                         goto failed;
332         }
333
334         drm_sysfs_connector_add(connector);
335         return connector;
336
337
338 failed:
339         if (radeon_connector->ddc_bus)
340                 radeon_i2c_destroy(radeon_connector->ddc_bus);
341         drm_connector_cleanup(connector);
342         kfree(connector);
343         return NULL;
344 }