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