Rev 1126 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1123 | serge | 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.h" |
||
29 | #include "drm_crtc_helper.h" |
||
30 | #include "radeon_drm.h" |
||
31 | #include "radeon.h" |
||
32 | |||
33 | extern void |
||
34 | radeon_combios_connected_scratch_regs(struct drm_connector *connector, |
||
35 | struct drm_encoder *encoder, |
||
36 | bool connected); |
||
37 | extern void |
||
38 | radeon_atombios_connected_scratch_regs(struct drm_connector *connector, |
||
39 | struct drm_encoder *encoder, |
||
40 | bool connected); |
||
41 | |||
42 | static void |
||
43 | radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) |
||
44 | { |
||
45 | struct drm_device *dev = connector->dev; |
||
46 | struct radeon_device *rdev = dev->dev_private; |
||
47 | struct drm_encoder *best_encoder = NULL; |
||
48 | struct drm_encoder *encoder = NULL; |
||
49 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; |
||
50 | struct drm_mode_object *obj; |
||
51 | bool connected; |
||
52 | int i; |
||
53 | |||
54 | best_encoder = connector_funcs->best_encoder(connector); |
||
55 | |||
56 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
||
57 | if (connector->encoder_ids[i] == 0) |
||
58 | break; |
||
59 | |||
60 | obj = drm_mode_object_find(connector->dev, |
||
61 | connector->encoder_ids[i], |
||
62 | DRM_MODE_OBJECT_ENCODER); |
||
63 | if (!obj) |
||
64 | continue; |
||
65 | |||
66 | encoder = obj_to_encoder(obj); |
||
67 | |||
68 | if ((encoder == best_encoder) && (status == connector_status_connected)) |
||
69 | connected = true; |
||
70 | else |
||
71 | connected = false; |
||
72 | |||
73 | if (rdev->is_atom_bios) |
||
74 | radeon_atombios_connected_scratch_regs(connector, encoder, connected); |
||
75 | else |
||
76 | radeon_combios_connected_scratch_regs(connector, encoder, connected); |
||
77 | |||
78 | } |
||
79 | } |
||
80 | |||
81 | struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) |
||
82 | { |
||
83 | int enc_id = connector->encoder_ids[0]; |
||
84 | struct drm_mode_object *obj; |
||
85 | struct drm_encoder *encoder; |
||
86 | |||
87 | /* pick the encoder ids */ |
||
88 | if (enc_id) { |
||
89 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
||
90 | if (!obj) |
||
91 | return NULL; |
||
92 | encoder = obj_to_encoder(obj); |
||
93 | return encoder; |
||
94 | } |
||
95 | return NULL; |
||
96 | } |
||
97 | |||
98 | static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) |
||
99 | { |
||
100 | struct drm_device *dev = encoder->dev; |
||
101 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
||
102 | struct drm_display_mode *mode = NULL; |
||
103 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; |
||
104 | |||
105 | if (native_mode->panel_xres != 0 && |
||
106 | native_mode->panel_yres != 0 && |
||
107 | native_mode->dotclock != 0) { |
||
108 | mode = drm_mode_create(dev); |
||
109 | |||
110 | mode->hdisplay = native_mode->panel_xres; |
||
111 | mode->vdisplay = native_mode->panel_yres; |
||
112 | |||
113 | mode->htotal = mode->hdisplay + native_mode->hblank; |
||
114 | mode->hsync_start = mode->hdisplay + native_mode->hoverplus; |
||
115 | mode->hsync_end = mode->hsync_start + native_mode->hsync_width; |
||
116 | mode->vtotal = mode->vdisplay + native_mode->vblank; |
||
117 | mode->vsync_start = mode->vdisplay + native_mode->voverplus; |
||
118 | mode->vsync_end = mode->vsync_start + native_mode->vsync_width; |
||
119 | mode->clock = native_mode->dotclock; |
||
120 | mode->flags = 0; |
||
121 | |||
122 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; |
||
123 | drm_mode_set_name(mode); |
||
124 | |||
125 | DRM_DEBUG("Adding native panel mode %s\n", mode->name); |
||
126 | } |
||
127 | return mode; |
||
128 | } |
||
129 | |||
130 | int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, |
||
131 | uint64_t val) |
||
132 | { |
||
133 | return 0; |
||
134 | } |
||
135 | |||
136 | |||
137 | static int radeon_lvds_get_modes(struct drm_connector *connector) |
||
138 | { |
||
139 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
140 | struct drm_encoder *encoder; |
||
141 | int ret = 0; |
||
142 | struct drm_display_mode *mode; |
||
143 | |||
144 | if (radeon_connector->ddc_bus) { |
||
145 | ret = radeon_ddc_get_modes(radeon_connector); |
||
146 | if (ret > 0) { |
||
147 | return ret; |
||
148 | } |
||
149 | } |
||
150 | |||
151 | encoder = radeon_best_single_encoder(connector); |
||
152 | if (!encoder) |
||
153 | return 0; |
||
154 | |||
155 | /* we have no EDID modes */ |
||
156 | mode = radeon_fp_native_mode(encoder); |
||
157 | if (mode) { |
||
158 | ret = 1; |
||
159 | drm_mode_probed_add(connector, mode); |
||
160 | } |
||
161 | return ret; |
||
162 | } |
||
163 | |||
164 | static int radeon_lvds_mode_valid(struct drm_connector *connector, |
||
165 | struct drm_display_mode *mode) |
||
166 | { |
||
167 | return MODE_OK; |
||
168 | } |
||
169 | |||
170 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) |
||
171 | { |
||
172 | enum drm_connector_status ret = connector_status_connected; |
||
173 | /* check acpi lid status ??? */ |
||
174 | radeon_connector_update_scratch_regs(connector, ret); |
||
175 | return ret; |
||
176 | } |
||
177 | |||
178 | static void radeon_connector_destroy(struct drm_connector *connector) |
||
179 | { |
||
180 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
181 | |||
182 | if (radeon_connector->ddc_bus) |
||
183 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
||
184 | kfree(radeon_connector->con_priv); |
||
185 | // drm_sysfs_connector_remove(connector); |
||
186 | drm_connector_cleanup(connector); |
||
187 | kfree(connector); |
||
188 | } |
||
189 | |||
190 | struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { |
||
191 | .get_modes = radeon_lvds_get_modes, |
||
192 | .mode_valid = radeon_lvds_mode_valid, |
||
193 | .best_encoder = radeon_best_single_encoder, |
||
194 | }; |
||
195 | |||
196 | struct drm_connector_funcs radeon_lvds_connector_funcs = { |
||
197 | .dpms = drm_helper_connector_dpms, |
||
198 | .detect = radeon_lvds_detect, |
||
199 | .fill_modes = drm_helper_probe_single_connector_modes, |
||
200 | .destroy = radeon_connector_destroy, |
||
201 | .set_property = radeon_connector_set_property, |
||
202 | }; |
||
203 | |||
204 | static int radeon_vga_get_modes(struct drm_connector *connector) |
||
205 | { |
||
206 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
207 | int ret; |
||
208 | |||
209 | ret = radeon_ddc_get_modes(radeon_connector); |
||
210 | |||
211 | return ret; |
||
212 | } |
||
213 | |||
214 | static int radeon_vga_mode_valid(struct drm_connector *connector, |
||
215 | struct drm_display_mode *mode) |
||
216 | { |
||
217 | |||
218 | return MODE_OK; |
||
219 | } |
||
220 | |||
221 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) |
||
222 | { |
||
223 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
224 | struct drm_encoder *encoder; |
||
225 | struct drm_encoder_helper_funcs *encoder_funcs; |
||
226 | bool dret; |
||
227 | enum drm_connector_status ret = connector_status_disconnected; |
||
228 | |||
229 | radeon_i2c_do_lock(radeon_connector, 1); |
||
230 | dret = radeon_ddc_probe(radeon_connector); |
||
231 | radeon_i2c_do_lock(radeon_connector, 0); |
||
232 | if (dret) |
||
233 | ret = connector_status_connected; |
||
234 | else { |
||
235 | /* if EDID fails to a load detect */ |
||
236 | encoder = radeon_best_single_encoder(connector); |
||
237 | if (!encoder) |
||
238 | ret = connector_status_disconnected; |
||
239 | else { |
||
240 | encoder_funcs = encoder->helper_private; |
||
241 | ret = encoder_funcs->detect(encoder, connector); |
||
242 | } |
||
243 | } |
||
244 | |||
245 | radeon_connector_update_scratch_regs(connector, ret); |
||
246 | return ret; |
||
247 | } |
||
248 | |||
249 | struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { |
||
250 | .get_modes = radeon_vga_get_modes, |
||
251 | .mode_valid = radeon_vga_mode_valid, |
||
252 | .best_encoder = radeon_best_single_encoder, |
||
253 | }; |
||
254 | |||
255 | struct drm_connector_funcs radeon_vga_connector_funcs = { |
||
256 | .dpms = drm_helper_connector_dpms, |
||
257 | .detect = radeon_vga_detect, |
||
258 | .fill_modes = drm_helper_probe_single_connector_modes, |
||
259 | .destroy = radeon_connector_destroy, |
||
260 | .set_property = radeon_connector_set_property, |
||
261 | }; |
||
262 | |||
263 | static int radeon_dvi_get_modes(struct drm_connector *connector) |
||
264 | { |
||
265 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
266 | int ret; |
||
267 | |||
268 | ret = radeon_ddc_get_modes(radeon_connector); |
||
269 | /* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */ |
||
270 | radeon_connector_update_scratch_regs(connector, connector_status_connected); |
||
271 | return ret; |
||
272 | } |
||
273 | |||
274 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) |
||
275 | { |
||
276 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
277 | struct drm_encoder *encoder; |
||
278 | struct drm_encoder_helper_funcs *encoder_funcs; |
||
279 | struct drm_mode_object *obj; |
||
280 | int i; |
||
281 | enum drm_connector_status ret = connector_status_disconnected; |
||
282 | bool dret; |
||
283 | |||
284 | radeon_i2c_do_lock(radeon_connector, 1); |
||
285 | dret = radeon_ddc_probe(radeon_connector); |
||
286 | radeon_i2c_do_lock(radeon_connector, 0); |
||
287 | if (dret) |
||
288 | ret = connector_status_connected; |
||
289 | else { |
||
290 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
||
291 | if (connector->encoder_ids[i] == 0) |
||
292 | break; |
||
293 | |||
294 | obj = drm_mode_object_find(connector->dev, |
||
295 | connector->encoder_ids[i], |
||
296 | DRM_MODE_OBJECT_ENCODER); |
||
297 | if (!obj) |
||
298 | continue; |
||
299 | |||
300 | encoder = obj_to_encoder(obj); |
||
301 | |||
302 | encoder_funcs = encoder->helper_private; |
||
303 | if (encoder_funcs->detect) { |
||
304 | ret = encoder_funcs->detect(encoder, connector); |
||
305 | if (ret == connector_status_connected) { |
||
306 | radeon_connector->use_digital = 0; |
||
307 | break; |
||
308 | } |
||
309 | } |
||
310 | } |
||
311 | } |
||
312 | |||
313 | /* updated in get modes as well since we need to know if it's analog or digital */ |
||
314 | radeon_connector_update_scratch_regs(connector, ret); |
||
315 | return ret; |
||
316 | } |
||
317 | |||
318 | /* okay need to be smart in here about which encoder to pick */ |
||
319 | struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) |
||
320 | { |
||
321 | int enc_id = connector->encoder_ids[0]; |
||
322 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
||
323 | struct drm_mode_object *obj; |
||
324 | struct drm_encoder *encoder; |
||
325 | int i; |
||
326 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
||
327 | if (connector->encoder_ids[i] == 0) |
||
328 | break; |
||
329 | |||
330 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); |
||
331 | if (!obj) |
||
332 | continue; |
||
333 | |||
334 | encoder = obj_to_encoder(obj); |
||
335 | |||
336 | if (radeon_connector->use_digital) { |
||
337 | if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) |
||
338 | return encoder; |
||
339 | } else { |
||
340 | if (encoder->encoder_type == DRM_MODE_ENCODER_DAC || |
||
341 | encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) |
||
342 | return encoder; |
||
343 | } |
||
344 | } |
||
345 | |||
346 | /* see if we have a default encoder TODO */ |
||
347 | |||
348 | /* then check use digitial */ |
||
349 | /* pick the first one */ |
||
350 | if (enc_id) { |
||
351 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); |
||
352 | if (!obj) |
||
353 | return NULL; |
||
354 | encoder = obj_to_encoder(obj); |
||
355 | return encoder; |
||
356 | } |
||
357 | return NULL; |
||
358 | } |
||
359 | |||
360 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { |
||
361 | .get_modes = radeon_dvi_get_modes, |
||
362 | .mode_valid = radeon_vga_mode_valid, |
||
363 | .best_encoder = radeon_dvi_encoder, |
||
364 | }; |
||
365 | |||
366 | struct drm_connector_funcs radeon_dvi_connector_funcs = { |
||
367 | .dpms = drm_helper_connector_dpms, |
||
368 | .detect = radeon_dvi_detect, |
||
369 | .fill_modes = drm_helper_probe_single_connector_modes, |
||
370 | .set_property = radeon_connector_set_property, |
||
371 | .destroy = radeon_connector_destroy, |
||
372 | }; |
||
373 | |||
374 | void |
||
375 | radeon_add_atom_connector(struct drm_device *dev, |
||
376 | uint32_t connector_id, |
||
377 | uint32_t supported_device, |
||
378 | int connector_type, |
||
379 | struct radeon_i2c_bus_rec *i2c_bus, |
||
380 | bool linkb, |
||
381 | uint32_t igp_lane_info) |
||
382 | { |
||
383 | struct drm_connector *connector; |
||
384 | struct radeon_connector *radeon_connector; |
||
385 | struct radeon_connector_atom_dig *radeon_dig_connector; |
||
386 | uint32_t subpixel_order = SubPixelNone; |
||
387 | |||
388 | /* fixme - tv/cv/din */ |
||
389 | if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || |
||
390 | (connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
||
391 | (connector_type == DRM_MODE_CONNECTOR_Composite) || |
||
392 | (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) |
||
393 | return; |
||
394 | |||
395 | /* see if we already added it */ |
||
396 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
||
397 | radeon_connector = to_radeon_connector(connector); |
||
398 | if (radeon_connector->connector_id == connector_id) { |
||
399 | radeon_connector->devices |= supported_device; |
||
400 | return; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
||
405 | if (!radeon_connector) |
||
406 | return; |
||
407 | |||
408 | connector = &radeon_connector->base; |
||
409 | |||
410 | radeon_connector->connector_id = connector_id; |
||
411 | radeon_connector->devices = supported_device; |
||
412 | switch (connector_type) { |
||
413 | case DRM_MODE_CONNECTOR_VGA: |
||
414 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
||
415 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
||
416 | if (i2c_bus->valid) { |
||
417 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
||
418 | if (!radeon_connector->ddc_bus) |
||
419 | goto failed; |
||
420 | } |
||
421 | break; |
||
422 | case DRM_MODE_CONNECTOR_DVIA: |
||
423 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
||
424 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
||
425 | if (i2c_bus->valid) { |
||
426 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
||
427 | if (!radeon_connector->ddc_bus) |
||
428 | goto failed; |
||
429 | } |
||
430 | break; |
||
431 | case DRM_MODE_CONNECTOR_DVII: |
||
432 | case DRM_MODE_CONNECTOR_DVID: |
||
433 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
||
434 | if (!radeon_dig_connector) |
||
435 | goto failed; |
||
436 | radeon_dig_connector->linkb = linkb; |
||
437 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
||
438 | radeon_connector->con_priv = radeon_dig_connector; |
||
439 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
||
440 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
||
441 | if (i2c_bus->valid) { |
||
442 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
||
443 | if (!radeon_connector->ddc_bus) |
||
444 | goto failed; |
||
445 | } |
||
446 | subpixel_order = SubPixelHorizontalRGB; |
||
447 | break; |
||
448 | case DRM_MODE_CONNECTOR_HDMIA: |
||
449 | case DRM_MODE_CONNECTOR_HDMIB: |
||
450 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
||
451 | if (!radeon_dig_connector) |
||
452 | goto failed; |
||
453 | radeon_dig_connector->linkb = linkb; |
||
454 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
||
455 | radeon_connector->con_priv = radeon_dig_connector; |
||
456 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
||
457 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
||
458 | if (i2c_bus->valid) { |
||
459 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); |
||
460 | if (!radeon_connector->ddc_bus) |
||
461 | goto failed; |
||
462 | } |
||
463 | subpixel_order = SubPixelHorizontalRGB; |
||
464 | break; |
||
465 | case DRM_MODE_CONNECTOR_DisplayPort: |
||
466 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
||
467 | if (!radeon_dig_connector) |
||
468 | goto failed; |
||
469 | radeon_dig_connector->linkb = linkb; |
||
470 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
||
471 | radeon_connector->con_priv = radeon_dig_connector; |
||
472 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
||
473 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
||
474 | if (i2c_bus->valid) { |
||
475 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); |
||
476 | if (!radeon_connector->ddc_bus) |
||
477 | goto failed; |
||
478 | } |
||
479 | subpixel_order = SubPixelHorizontalRGB; |
||
480 | break; |
||
481 | case DRM_MODE_CONNECTOR_SVIDEO: |
||
482 | case DRM_MODE_CONNECTOR_Composite: |
||
483 | case DRM_MODE_CONNECTOR_9PinDIN: |
||
484 | break; |
||
485 | case DRM_MODE_CONNECTOR_LVDS: |
||
486 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); |
||
487 | if (!radeon_dig_connector) |
||
488 | goto failed; |
||
489 | radeon_dig_connector->linkb = linkb; |
||
490 | radeon_dig_connector->igp_lane_info = igp_lane_info; |
||
491 | radeon_connector->con_priv = radeon_dig_connector; |
||
492 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
||
493 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
||
494 | if (i2c_bus->valid) { |
||
495 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
||
496 | if (!radeon_connector->ddc_bus) |
||
497 | goto failed; |
||
498 | } |
||
499 | subpixel_order = SubPixelHorizontalRGB; |
||
500 | break; |
||
501 | } |
||
502 | |||
503 | connector->display_info.subpixel_order = subpixel_order; |
||
504 | // drm_sysfs_connector_add(connector); |
||
505 | return; |
||
506 | |||
507 | failed: |
||
508 | if (radeon_connector->ddc_bus) |
||
509 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
||
510 | drm_connector_cleanup(connector); |
||
511 | kfree(connector); |
||
512 | } |
||
513 | |||
514 | void |
||
515 | radeon_add_legacy_connector(struct drm_device *dev, |
||
516 | uint32_t connector_id, |
||
517 | uint32_t supported_device, |
||
518 | int connector_type, |
||
519 | struct radeon_i2c_bus_rec *i2c_bus) |
||
520 | { |
||
521 | struct drm_connector *connector; |
||
522 | struct radeon_connector *radeon_connector; |
||
523 | uint32_t subpixel_order = SubPixelNone; |
||
524 | |||
525 | /* fixme - tv/cv/din */ |
||
526 | if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || |
||
527 | (connector_type == DRM_MODE_CONNECTOR_SVIDEO) || |
||
528 | (connector_type == DRM_MODE_CONNECTOR_Composite) || |
||
529 | (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) |
||
530 | return; |
||
531 | |||
532 | /* see if we already added it */ |
||
533 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
||
534 | radeon_connector = to_radeon_connector(connector); |
||
535 | if (radeon_connector->connector_id == connector_id) { |
||
536 | radeon_connector->devices |= supported_device; |
||
537 | return; |
||
538 | } |
||
539 | } |
||
540 | |||
541 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); |
||
542 | if (!radeon_connector) |
||
543 | return; |
||
544 | |||
545 | connector = &radeon_connector->base; |
||
546 | |||
547 | radeon_connector->connector_id = connector_id; |
||
548 | radeon_connector->devices = supported_device; |
||
549 | switch (connector_type) { |
||
550 | case DRM_MODE_CONNECTOR_VGA: |
||
551 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
||
552 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
||
553 | if (i2c_bus->valid) { |
||
554 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); |
||
555 | if (!radeon_connector->ddc_bus) |
||
556 | goto failed; |
||
557 | } |
||
558 | break; |
||
559 | case DRM_MODE_CONNECTOR_DVIA: |
||
560 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); |
||
561 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); |
||
562 | if (i2c_bus->valid) { |
||
563 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
||
564 | if (!radeon_connector->ddc_bus) |
||
565 | goto failed; |
||
566 | } |
||
567 | break; |
||
568 | case DRM_MODE_CONNECTOR_DVII: |
||
569 | case DRM_MODE_CONNECTOR_DVID: |
||
570 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); |
||
571 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); |
||
572 | if (i2c_bus->valid) { |
||
573 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); |
||
574 | if (!radeon_connector->ddc_bus) |
||
575 | goto failed; |
||
576 | } |
||
577 | subpixel_order = SubPixelHorizontalRGB; |
||
578 | break; |
||
579 | case DRM_MODE_CONNECTOR_SVIDEO: |
||
580 | case DRM_MODE_CONNECTOR_Composite: |
||
581 | case DRM_MODE_CONNECTOR_9PinDIN: |
||
582 | break; |
||
583 | case DRM_MODE_CONNECTOR_LVDS: |
||
584 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); |
||
585 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); |
||
586 | if (i2c_bus->valid) { |
||
587 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); |
||
588 | if (!radeon_connector->ddc_bus) |
||
589 | goto failed; |
||
590 | } |
||
591 | subpixel_order = SubPixelHorizontalRGB; |
||
592 | break; |
||
593 | } |
||
594 | |||
595 | connector->display_info.subpixel_order = subpixel_order; |
||
596 | // drm_sysfs_connector_add(connector); |
||
597 | return; |
||
598 | |||
599 | failed: |
||
600 | if (radeon_connector->ddc_bus) |
||
601 | radeon_i2c_destroy(radeon_connector->ddc_bus); |
||
602 | drm_connector_cleanup(connector); |
||
603 | kfree(connector); |
||
604 | }>>> |