blob: 04ecb11ebb8cb0b966aa6b435579dd5f7034611f [file] [log] [blame]
Jerome Glisse771fe6b2009-06-05 14:42:42 +02001/*
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.h"
Alex Deucher923f6842009-09-10 17:53:39 -040031#include "atom.h"
Jerome Glisse771fe6b2009-06-05 14:42:42 +020032
33extern void
34radeon_combios_connected_scratch_regs(struct drm_connector *connector,
35 struct drm_encoder *encoder,
36 bool connected);
37extern void
38radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
39 struct drm_encoder *encoder,
40 bool connected);
41
42static void
43radeon_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
81struct 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
Dave Airlie4ce001a2009-08-13 16:32:14 +100098
99/*
100 * radeon_connector_analog_encoder_conflict_solve
101 * - search for other connectors sharing this encoder
102 * if priority is true, then set them disconnected if this is connected
103 * if priority is false, set us disconnected if they are connected
104 */
105static enum drm_connector_status
106radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
107 struct drm_encoder *encoder,
108 enum drm_connector_status current_status,
109 bool priority)
110{
111 struct drm_device *dev = connector->dev;
112 struct drm_connector *conflict;
113 int i;
114
115 list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
116 if (conflict == connector)
117 continue;
118
119 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
120 if (conflict->encoder_ids[i] == 0)
121 break;
122
123 /* if the IDs match */
124 if (conflict->encoder_ids[i] == encoder->base.id) {
125 if (conflict->status != connector_status_connected)
126 continue;
127
128 if (priority == true) {
129 DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict));
130 DRM_INFO("in favor of %s\n", drm_get_connector_name(connector));
131 conflict->status = connector_status_disconnected;
132 radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
133 } else {
134 DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector));
135 DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict));
136 current_status = connector_status_disconnected;
137 }
138 break;
139 }
140 }
141 }
142 return current_status;
143
144}
145
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200146static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
147{
148 struct drm_device *dev = encoder->dev;
149 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
150 struct drm_display_mode *mode = NULL;
151 struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
152
153 if (native_mode->panel_xres != 0 &&
154 native_mode->panel_yres != 0 &&
155 native_mode->dotclock != 0) {
156 mode = drm_mode_create(dev);
157
158 mode->hdisplay = native_mode->panel_xres;
159 mode->vdisplay = native_mode->panel_yres;
160
161 mode->htotal = mode->hdisplay + native_mode->hblank;
162 mode->hsync_start = mode->hdisplay + native_mode->hoverplus;
163 mode->hsync_end = mode->hsync_start + native_mode->hsync_width;
164 mode->vtotal = mode->vdisplay + native_mode->vblank;
165 mode->vsync_start = mode->vdisplay + native_mode->voverplus;
166 mode->vsync_end = mode->vsync_start + native_mode->vsync_width;
167 mode->clock = native_mode->dotclock;
168 mode->flags = 0;
169
170 mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
171 drm_mode_set_name(mode);
172
173 DRM_DEBUG("Adding native panel mode %s\n", mode->name);
174 }
175 return mode;
176}
177
Alex Deucher923f6842009-09-10 17:53:39 -0400178static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector)
179{
180 struct drm_device *dev = encoder->dev;
181 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
182 struct drm_display_mode *mode = NULL;
183 struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
184 int i;
185 struct mode_size {
186 int w;
187 int h;
188 } common_modes[17] = {
189 { 640, 480},
190 { 720, 480},
191 { 800, 600},
192 { 848, 480},
193 {1024, 768},
194 {1152, 768},
195 {1280, 720},
196 {1280, 800},
197 {1280, 854},
198 {1280, 960},
199 {1280, 1024},
200 {1440, 900},
201 {1400, 1050},
202 {1680, 1050},
203 {1600, 1200},
204 {1920, 1080},
205 {1920, 1200}
206 };
207
208 for (i = 0; i < 17; i++) {
209 if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
210 if (common_modes[i].w >= native_mode->panel_xres &&
211 common_modes[i].h >= native_mode->panel_yres)
212 continue;
213 }
214 if (common_modes[i].w < 320 || common_modes[i].h < 200)
215 continue;
216
217 mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false);
218 drm_mode_probed_add(connector, mode);
219 }
220}
221
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200222int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
223 uint64_t val)
224{
225 return 0;
226}
227
228
229static int radeon_lvds_get_modes(struct drm_connector *connector)
230{
231 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
232 struct drm_encoder *encoder;
233 int ret = 0;
234 struct drm_display_mode *mode;
235
236 if (radeon_connector->ddc_bus) {
237 ret = radeon_ddc_get_modes(radeon_connector);
238 if (ret > 0) {
Alex Deucher7747b712009-09-11 11:15:43 -0400239 encoder = radeon_best_single_encoder(connector);
240 if (encoder)
241 /* add scaled modes */
242 radeon_add_common_modes(encoder, connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200243 return ret;
244 }
245 }
246
247 encoder = radeon_best_single_encoder(connector);
248 if (!encoder)
249 return 0;
250
251 /* we have no EDID modes */
252 mode = radeon_fp_native_mode(encoder);
253 if (mode) {
254 ret = 1;
255 drm_mode_probed_add(connector, mode);
Alex Deucher7747b712009-09-11 11:15:43 -0400256 /* add scaled modes */
257 radeon_add_common_modes(encoder, connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200258 }
Alex Deucher923f6842009-09-10 17:53:39 -0400259
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200260 return ret;
261}
262
263static int radeon_lvds_mode_valid(struct drm_connector *connector,
264 struct drm_display_mode *mode)
265{
266 return MODE_OK;
267}
268
269static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
270{
271 enum drm_connector_status ret = connector_status_connected;
272 /* check acpi lid status ??? */
273 radeon_connector_update_scratch_regs(connector, ret);
274 return ret;
275}
276
277static void radeon_connector_destroy(struct drm_connector *connector)
278{
279 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
280
281 if (radeon_connector->ddc_bus)
282 radeon_i2c_destroy(radeon_connector->ddc_bus);
283 kfree(radeon_connector->con_priv);
284 drm_sysfs_connector_remove(connector);
285 drm_connector_cleanup(connector);
286 kfree(connector);
287}
288
289struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
290 .get_modes = radeon_lvds_get_modes,
291 .mode_valid = radeon_lvds_mode_valid,
292 .best_encoder = radeon_best_single_encoder,
293};
294
295struct drm_connector_funcs radeon_lvds_connector_funcs = {
296 .dpms = drm_helper_connector_dpms,
297 .detect = radeon_lvds_detect,
298 .fill_modes = drm_helper_probe_single_connector_modes,
299 .destroy = radeon_connector_destroy,
300 .set_property = radeon_connector_set_property,
301};
302
303static int radeon_vga_get_modes(struct drm_connector *connector)
304{
305 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
306 int ret;
307
308 ret = radeon_ddc_get_modes(radeon_connector);
309
310 return ret;
311}
312
313static int radeon_vga_mode_valid(struct drm_connector *connector,
314 struct drm_display_mode *mode)
315{
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200316 return MODE_OK;
317}
318
319static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector)
320{
321 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
322 struct drm_encoder *encoder;
323 struct drm_encoder_helper_funcs *encoder_funcs;
324 bool dret;
325 enum drm_connector_status ret = connector_status_disconnected;
326
Dave Airlie4ce001a2009-08-13 16:32:14 +1000327 encoder = radeon_best_single_encoder(connector);
328 if (!encoder)
329 ret = connector_status_disconnected;
330
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200331 radeon_i2c_do_lock(radeon_connector, 1);
332 dret = radeon_ddc_probe(radeon_connector);
333 radeon_i2c_do_lock(radeon_connector, 0);
334 if (dret)
335 ret = connector_status_connected;
336 else {
Dave Airlie4ce001a2009-08-13 16:32:14 +1000337 encoder_funcs = encoder->helper_private;
338 ret = encoder_funcs->detect(encoder, connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200339 }
340
Dave Airlie4ce001a2009-08-13 16:32:14 +1000341 if (ret == connector_status_connected)
342 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200343 radeon_connector_update_scratch_regs(connector, ret);
344 return ret;
345}
346
347struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = {
348 .get_modes = radeon_vga_get_modes,
349 .mode_valid = radeon_vga_mode_valid,
350 .best_encoder = radeon_best_single_encoder,
351};
352
353struct drm_connector_funcs radeon_vga_connector_funcs = {
354 .dpms = drm_helper_connector_dpms,
355 .detect = radeon_vga_detect,
356 .fill_modes = drm_helper_probe_single_connector_modes,
357 .destroy = radeon_connector_destroy,
358 .set_property = radeon_connector_set_property,
359};
360
Dave Airlie4ce001a2009-08-13 16:32:14 +1000361static int radeon_tv_get_modes(struct drm_connector *connector)
362{
363 struct drm_device *dev = connector->dev;
Alex Deucher923f6842009-09-10 17:53:39 -0400364 struct radeon_device *rdev = dev->dev_private;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000365 struct drm_display_mode *tv_mode;
Alex Deucher923f6842009-09-10 17:53:39 -0400366 struct drm_encoder *encoder;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000367
Alex Deucher923f6842009-09-10 17:53:39 -0400368 encoder = radeon_best_single_encoder(connector);
369 if (!encoder)
370 return 0;
Dave Airlie4ce001a2009-08-13 16:32:14 +1000371
Alex Deucher923f6842009-09-10 17:53:39 -0400372 /* avivo chips can scale any mode */
373 if (rdev->family >= CHIP_RS600)
374 /* add scaled modes */
375 radeon_add_common_modes(encoder, connector);
376 else {
377 /* only 800x600 is supported right now on pre-avivo chips */
378 tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false);
379 tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
380 drm_mode_probed_add(connector, tv_mode);
381 }
Dave Airlie4ce001a2009-08-13 16:32:14 +1000382 return 1;
383}
384
385static int radeon_tv_mode_valid(struct drm_connector *connector,
386 struct drm_display_mode *mode)
387{
388 return MODE_OK;
389}
390
391static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
392{
393 struct drm_encoder *encoder;
394 struct drm_encoder_helper_funcs *encoder_funcs;
395 int ret;
396
397 encoder = radeon_best_single_encoder(connector);
398 if (!encoder)
399 ret = connector_status_disconnected;
400 else {
401 encoder_funcs = encoder->helper_private;
402 ret = encoder_funcs->detect(encoder, connector);
403 }
404 if (ret == connector_status_connected)
405 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
406 radeon_connector_update_scratch_regs(connector, ret);
407 return ret;
408}
409
410struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
411 .get_modes = radeon_tv_get_modes,
412 .mode_valid = radeon_tv_mode_valid,
413 .best_encoder = radeon_best_single_encoder,
414};
415
416struct drm_connector_funcs radeon_tv_connector_funcs = {
417 .dpms = drm_helper_connector_dpms,
418 .detect = radeon_tv_detect,
419 .fill_modes = drm_helper_probe_single_connector_modes,
420 .destroy = radeon_connector_destroy,
421 .set_property = radeon_connector_set_property,
422};
423
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200424static int radeon_dvi_get_modes(struct drm_connector *connector)
425{
426 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
427 int ret;
428
429 ret = radeon_ddc_get_modes(radeon_connector);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200430 return ret;
431}
432
Dave Airlie4ce001a2009-08-13 16:32:14 +1000433/*
434 * DVI is complicated
435 * Do a DDC probe, if DDC probe passes, get the full EDID so
436 * we can do analog/digital monitor detection at this point.
437 * If the monitor is an analog monitor or we got no DDC,
438 * we need to find the DAC encoder object for this connector.
439 * If we got no DDC, we do load detection on the DAC encoder object.
440 * If we got analog DDC or load detection passes on the DAC encoder
441 * we have to check if this analog encoder is shared with anyone else (TV)
442 * if its shared we have to set the other connector to disconnected.
443 */
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200444static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
445{
446 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000447 struct drm_encoder *encoder = NULL;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200448 struct drm_encoder_helper_funcs *encoder_funcs;
449 struct drm_mode_object *obj;
450 int i;
451 enum drm_connector_status ret = connector_status_disconnected;
452 bool dret;
453
454 radeon_i2c_do_lock(radeon_connector, 1);
455 dret = radeon_ddc_probe(radeon_connector);
456 radeon_i2c_do_lock(radeon_connector, 0);
Dave Airlie4ce001a2009-08-13 16:32:14 +1000457 if (dret) {
458 radeon_i2c_do_lock(radeon_connector, 1);
459 radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
460 radeon_i2c_do_lock(radeon_connector, 0);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200461
Dave Airlie4ce001a2009-08-13 16:32:14 +1000462 if (!radeon_connector->edid) {
463 DRM_ERROR("DDC responded but not EDID found for %s\n",
464 drm_get_connector_name(connector));
465 } else {
466 radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200467
Dave Airlie4ce001a2009-08-13 16:32:14 +1000468 /* if this isn't a digital monitor
469 then we need to make sure we don't have any
470 TV conflicts */
471 ret = connector_status_connected;
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200472 }
473 }
474
Dave Airlie4ce001a2009-08-13 16:32:14 +1000475 if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
476 goto out;
477
478 /* find analog encoder */
479 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
480 if (connector->encoder_ids[i] == 0)
481 break;
482
483 obj = drm_mode_object_find(connector->dev,
484 connector->encoder_ids[i],
485 DRM_MODE_OBJECT_ENCODER);
486 if (!obj)
487 continue;
488
489 encoder = obj_to_encoder(obj);
490
491 encoder_funcs = encoder->helper_private;
492 if (encoder_funcs->detect) {
493 if (ret != connector_status_connected) {
494 ret = encoder_funcs->detect(encoder, connector);
495 if (ret == connector_status_connected) {
496 radeon_connector->use_digital = false;
497 }
498 }
499 break;
500 }
501 }
502
503 if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
504 encoder) {
505 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
506 }
507
508out:
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200509 /* updated in get modes as well since we need to know if it's analog or digital */
510 radeon_connector_update_scratch_regs(connector, ret);
511 return ret;
512}
513
514/* okay need to be smart in here about which encoder to pick */
515struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
516{
517 int enc_id = connector->encoder_ids[0];
518 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
519 struct drm_mode_object *obj;
520 struct drm_encoder *encoder;
521 int i;
522 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
523 if (connector->encoder_ids[i] == 0)
524 break;
525
526 obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
527 if (!obj)
528 continue;
529
530 encoder = obj_to_encoder(obj);
531
Dave Airlie4ce001a2009-08-13 16:32:14 +1000532 if (radeon_connector->use_digital == true) {
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200533 if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
534 return encoder;
535 } else {
536 if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
537 encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
538 return encoder;
539 }
540 }
541
542 /* see if we have a default encoder TODO */
543
544 /* then check use digitial */
545 /* pick the first one */
546 if (enc_id) {
547 obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
548 if (!obj)
549 return NULL;
550 encoder = obj_to_encoder(obj);
551 return encoder;
552 }
553 return NULL;
554}
555
556struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = {
557 .get_modes = radeon_dvi_get_modes,
558 .mode_valid = radeon_vga_mode_valid,
559 .best_encoder = radeon_dvi_encoder,
560};
561
562struct drm_connector_funcs radeon_dvi_connector_funcs = {
563 .dpms = drm_helper_connector_dpms,
564 .detect = radeon_dvi_detect,
565 .fill_modes = drm_helper_probe_single_connector_modes,
566 .set_property = radeon_connector_set_property,
567 .destroy = radeon_connector_destroy,
568};
569
570void
571radeon_add_atom_connector(struct drm_device *dev,
572 uint32_t connector_id,
573 uint32_t supported_device,
574 int connector_type,
575 struct radeon_i2c_bus_rec *i2c_bus,
576 bool linkb,
577 uint32_t igp_lane_info)
578{
579 struct drm_connector *connector;
580 struct radeon_connector *radeon_connector;
581 struct radeon_connector_atom_dig *radeon_dig_connector;
582 uint32_t subpixel_order = SubPixelNone;
583
584 /* fixme - tv/cv/din */
Dave Airlie4ce001a2009-08-13 16:32:14 +1000585 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200586 return;
587
588 /* see if we already added it */
589 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
590 radeon_connector = to_radeon_connector(connector);
591 if (radeon_connector->connector_id == connector_id) {
592 radeon_connector->devices |= supported_device;
593 return;
594 }
595 }
596
597 radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
598 if (!radeon_connector)
599 return;
600
601 connector = &radeon_connector->base;
602
603 radeon_connector->connector_id = connector_id;
604 radeon_connector->devices = supported_device;
605 switch (connector_type) {
606 case DRM_MODE_CONNECTOR_VGA:
607 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
608 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
609 if (i2c_bus->valid) {
610 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
611 if (!radeon_connector->ddc_bus)
612 goto failed;
613 }
614 break;
615 case DRM_MODE_CONNECTOR_DVIA:
616 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
617 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
618 if (i2c_bus->valid) {
619 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
620 if (!radeon_connector->ddc_bus)
621 goto failed;
622 }
623 break;
624 case DRM_MODE_CONNECTOR_DVII:
625 case DRM_MODE_CONNECTOR_DVID:
626 radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
627 if (!radeon_dig_connector)
628 goto failed;
629 radeon_dig_connector->linkb = linkb;
630 radeon_dig_connector->igp_lane_info = igp_lane_info;
631 radeon_connector->con_priv = radeon_dig_connector;
632 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
633 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
634 if (i2c_bus->valid) {
635 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
636 if (!radeon_connector->ddc_bus)
637 goto failed;
638 }
639 subpixel_order = SubPixelHorizontalRGB;
640 break;
641 case DRM_MODE_CONNECTOR_HDMIA:
642 case DRM_MODE_CONNECTOR_HDMIB:
643 radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
644 if (!radeon_dig_connector)
645 goto failed;
646 radeon_dig_connector->linkb = linkb;
647 radeon_dig_connector->igp_lane_info = igp_lane_info;
648 radeon_connector->con_priv = radeon_dig_connector;
649 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
650 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
651 if (i2c_bus->valid) {
652 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
653 if (!radeon_connector->ddc_bus)
654 goto failed;
655 }
656 subpixel_order = SubPixelHorizontalRGB;
657 break;
658 case DRM_MODE_CONNECTOR_DisplayPort:
659 radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
660 if (!radeon_dig_connector)
661 goto failed;
662 radeon_dig_connector->linkb = linkb;
663 radeon_dig_connector->igp_lane_info = igp_lane_info;
664 radeon_connector->con_priv = radeon_dig_connector;
665 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
666 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
667 if (i2c_bus->valid) {
668 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
669 if (!radeon_connector->ddc_bus)
670 goto failed;
671 }
672 subpixel_order = SubPixelHorizontalRGB;
673 break;
674 case DRM_MODE_CONNECTOR_SVIDEO:
675 case DRM_MODE_CONNECTOR_Composite:
676 case DRM_MODE_CONNECTOR_9PinDIN:
Dave Airlie4ce001a2009-08-13 16:32:14 +1000677 if (radeon_tv == 1) {
678 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
679 drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
680 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200681 break;
682 case DRM_MODE_CONNECTOR_LVDS:
683 radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
684 if (!radeon_dig_connector)
685 goto failed;
686 radeon_dig_connector->linkb = linkb;
687 radeon_dig_connector->igp_lane_info = igp_lane_info;
688 radeon_connector->con_priv = radeon_dig_connector;
689 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
690 drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
691 if (i2c_bus->valid) {
692 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
693 if (!radeon_connector->ddc_bus)
694 goto failed;
695 }
696 subpixel_order = SubPixelHorizontalRGB;
697 break;
698 }
699
700 connector->display_info.subpixel_order = subpixel_order;
701 drm_sysfs_connector_add(connector);
702 return;
703
704failed:
705 if (radeon_connector->ddc_bus)
706 radeon_i2c_destroy(radeon_connector->ddc_bus);
707 drm_connector_cleanup(connector);
708 kfree(connector);
709}
710
711void
712radeon_add_legacy_connector(struct drm_device *dev,
713 uint32_t connector_id,
714 uint32_t supported_device,
715 int connector_type,
716 struct radeon_i2c_bus_rec *i2c_bus)
717{
718 struct drm_connector *connector;
719 struct radeon_connector *radeon_connector;
720 uint32_t subpixel_order = SubPixelNone;
721
722 /* fixme - tv/cv/din */
Dave Airlie4ce001a2009-08-13 16:32:14 +1000723 if (connector_type == DRM_MODE_CONNECTOR_Unknown)
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200724 return;
725
726 /* see if we already added it */
727 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
728 radeon_connector = to_radeon_connector(connector);
729 if (radeon_connector->connector_id == connector_id) {
730 radeon_connector->devices |= supported_device;
731 return;
732 }
733 }
734
735 radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
736 if (!radeon_connector)
737 return;
738
739 connector = &radeon_connector->base;
740
741 radeon_connector->connector_id = connector_id;
742 radeon_connector->devices = supported_device;
743 switch (connector_type) {
744 case DRM_MODE_CONNECTOR_VGA:
745 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
746 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
747 if (i2c_bus->valid) {
748 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
749 if (!radeon_connector->ddc_bus)
750 goto failed;
751 }
752 break;
753 case DRM_MODE_CONNECTOR_DVIA:
754 drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
755 drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
756 if (i2c_bus->valid) {
757 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
758 if (!radeon_connector->ddc_bus)
759 goto failed;
760 }
761 break;
762 case DRM_MODE_CONNECTOR_DVII:
763 case DRM_MODE_CONNECTOR_DVID:
764 drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
765 drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
766 if (i2c_bus->valid) {
767 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
768 if (!radeon_connector->ddc_bus)
769 goto failed;
770 }
771 subpixel_order = SubPixelHorizontalRGB;
772 break;
773 case DRM_MODE_CONNECTOR_SVIDEO:
774 case DRM_MODE_CONNECTOR_Composite:
775 case DRM_MODE_CONNECTOR_9PinDIN:
Dave Airlie4ce001a2009-08-13 16:32:14 +1000776 if (radeon_tv == 1) {
777 drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
778 drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
779 }
Jerome Glisse771fe6b2009-06-05 14:42:42 +0200780 break;
781 case DRM_MODE_CONNECTOR_LVDS:
782 drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
783 drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
784 if (i2c_bus->valid) {
785 radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
786 if (!radeon_connector->ddc_bus)
787 goto failed;
788 }
789 subpixel_order = SubPixelHorizontalRGB;
790 break;
791 }
792
793 connector->display_info.subpixel_order = subpixel_order;
794 drm_sysfs_connector_add(connector);
795 return;
796
797failed:
798 if (radeon_connector->ddc_bus)
799 radeon_i2c_destroy(radeon_connector->ddc_bus);
800 drm_connector_cleanup(connector);
801 kfree(connector);
802}