xref: /haiku/src/add-ons/accelerants/radeon/monitor_detection.c (revision 1b8f7f13a3dc70e0e903cb94248220b40b732204)
1 /*
2  * Copyright 2002-2004, Thomas Kurschel. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*!
7 	Radeon monitor detection
8 */
9 
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "radeon_accelerant.h"
14 #include "mmio.h"
15 #include "crtc_regs.h"
16 #include "dac_regs.h"
17 #include "pll_regs.h"
18 #include "tv_out_regs.h"
19 #include "config_regs.h"
20 #include "ddc_regs.h"
21 #include "gpiopad_regs.h"
22 #include "fp_regs.h"
23 #include "pll_access.h"
24 #include "theatre_regs.h"
25 #include "set_mode.h"
26 #include "ddc.h"
27 
28 
29 typedef struct {
30 	accelerator_info *ai;
31 	uint32 port;
32 } ddc_port_info;
33 
34 
35 //! Get I2C signals
36 static status_t
37 get_signals(void *cookie, int *clk, int *data)
38 {
39 	ddc_port_info *info = (ddc_port_info *)cookie;
40 	vuint8 *regs = info->ai->regs;
41 	uint32 value;
42 
43 	value = INREG(regs, info->port);
44 	*clk = (value >> RADEON_GPIO_Y_SHIFT_1) & 1;
45 	*data = (value >> RADEON_GPIO_Y_SHIFT_0) & 1;
46 
47 	return B_OK;
48 }
49 
50 
51 //! Set I2C signals
52 static status_t
53 set_signals(void *cookie, int clk, int data)
54 {
55 	ddc_port_info *info = (ddc_port_info *)cookie;
56 	vuint8 *regs = info->ai->regs;
57 	uint32 value;
58 
59 	value = INREG(regs, info->port);
60 	value &= ~(RADEON_GPIO_A_1 | RADEON_GPIO_A_0);
61 	value &= ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1);
62 	value |= ((1-clk) << RADEON_GPIO_EN_SHIFT_1)
63 		| ((1-data) << RADEON_GPIO_EN_SHIFT_0);
64 
65 	OUTREG(regs, info->port, value);
66 	return B_OK;
67 }
68 
69 
70 /*! Read EDID information from monitor
71 	ddc_port - register to use for DDC2 communication
72 */
73 bool
74 Radeon_ReadEDID(accelerator_info *ai, uint32 ddcPort, edid1_info *edid)
75 {
76 	i2c_bus bus;
77 	ddc_port_info info;
78 	void *vdif;
79 	size_t vdifLength;
80 
81 	info.ai = ai;
82 	info.port = ddcPort;
83 
84 	ddc2_init_timing(&bus);
85 	bus.cookie = &info;
86 	bus.set_signals = &set_signals;
87 	bus.get_signals = &get_signals;
88 
89 	if (ddc2_read_edid1(&bus, edid, &vdif, &vdifLength) != B_OK)
90 		return false;
91 
92 	SHOW_FLOW(2, "Found DDC-capable monitor @0x%04x", ddcPort);
93 
94 	free(vdif);
95 	return true;
96 }
97 
98 
99 // search for display connect to CRT DAC
100 // colour - true, if only a colour monitor is to be accepted
101 static bool
102 Radeon_DetectCRTInt(accelerator_info *ai, bool colour)
103 {
104 	vuint8 *regs = ai->regs;
105 	uint32 old_crtc_ext_cntl, old_dac_ext_cntl, old_dac_cntl, value;
106 	bool found;
107 
108 	// makes sure there is a signal
109 	old_crtc_ext_cntl = INREG(regs, RADEON_CRTC_EXT_CNTL);
110 
111 	value = old_crtc_ext_cntl | RADEON_CRTC_CRT_ON;
112 	OUTREG(regs, RADEON_CRTC_EXT_CNTL, value);
113 
114 	// force DAC to output constant voltage
115 	// for colour monitors, RGB is tested, for B/W only G
116 	old_dac_ext_cntl = INREG(regs, RADEON_DAC_EXT_CNTL);
117 
118 	value = RADEON_DAC_FORCE_BLANK_OFF_EN | RADEON_DAC_FORCE_DATA_EN
119 		| (colour ? RADEON_DAC_FORCE_DATA_SEL_RGB : RADEON_DAC_FORCE_DATA_SEL_G)
120 		| (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
121 	OUTREG(regs, RADEON_DAC_EXT_CNTL, value);
122 
123 	// enable DAC and tell it to use VGA signals
124 	old_dac_cntl = INREG(regs, RADEON_DAC_CNTL);
125 
126 	value = old_dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
127 	value |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
128 	OUTREG(regs, RADEON_DAC_CNTL, value);
129 
130 	// specs says that we should wait 1µs before checking but sample
131 	// code uses 2 ms; we use long delay to be on safe side
132 	// (though we don't want to make it too long as the monitor
133 	// gets no sync signal now)
134 	snooze(2000);
135 
136 	// let's see whether there is some
137 	found = (INREG(regs, RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) != 0;
138 	if (found) {
139 		SHOW_INFO(2, "Found %s CRT connected to CRT-DAC",
140 			colour ? "colour" : "b/w");
141 	}
142 
143 	OUTREG(regs, RADEON_DAC_CNTL, old_dac_cntl);
144 	OUTREG(regs, RADEON_DAC_EXT_CNTL, old_dac_ext_cntl);
145 	OUTREG(regs, RADEON_CRTC_EXT_CNTL, old_crtc_ext_cntl);
146 
147 	return found;
148 }
149 
150 
151 //! Check whethere there is a CRT connected to CRT DAC
152 static bool
153 Radeon_DetectCRT(accelerator_info *ai)
154 {
155 	vuint32 old_vclk_ecp_cntl, value;
156 	bool found;
157 
158 	// enforce clock so the DAC gets activated
159 	old_vclk_ecp_cntl = Radeon_INPLL(ai->regs, ai->si->asic,
160 		RADEON_VCLK_ECP_CNTL);
161 
162 	value = old_vclk_ecp_cntl
163 		& ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
164 	Radeon_OUTPLL(ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL, value);
165 
166 	// search first for colour, then for B/W monitor
167 	found = Radeon_DetectCRTInt(ai, true) || Radeon_DetectCRTInt(ai, false);
168 
169 	Radeon_OUTPLL(ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL,
170 		old_vclk_ecp_cntl);
171 
172 	return found;
173 }
174 
175 
176 //! CRT on TV-DAC detection for rv200 and below checked for rv200
177 static bool
178 Radeon_DetectTVCRT_RV200(accelerator_info *ai)
179 {
180 	vuint8 *regs = ai->regs;
181 	uint32 old_crtc2_gen_cntl, old_tv_dac_cntl, old_dac_cntl2, value;
182 	bool found;
183 
184 	// enable CRTC2, setting 8 bpp (we just pick any valid value)
185 	old_crtc2_gen_cntl = INREG(regs, RADEON_CRTC2_GEN_CNTL);
186 
187 	value = old_crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
188 	value |= RADEON_CRTC2_CRT2_ON | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
189 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, value);
190 
191 	// enable TV-DAC, choosing VGA signal level
192 	old_tv_dac_cntl = INREG(regs, RADEON_TV_DAC_CNTL);
193 
194 	value = RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD
195 		| RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_STD_PS2;
196 	OUTREG(regs, RADEON_TV_DAC_CNTL, value);
197 
198 	// enforce constant DAC output voltage on RGB
199 	value = RADEON_DAC2_FORCE_BLANK_OFF_EN | RADEON_DAC2_FORCE_DATA_EN
200 		| RADEON_DAC_FORCE_DATA_SEL_RGB
201 		| (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
202 	OUTREG(regs, RADEON_DAC_EXT_CNTL, value);
203 
204 	old_dac_cntl2 = INREG(regs, RADEON_DAC_CNTL2);
205 
206 	// set DAC in CRT mode and enable detection
207 	// TODO: make sure we really use CRTC2 - this is ASIC dependant
208 	value = old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT | RADEON_DAC2_CMP_EN;
209 	OUTREG(regs, RADEON_DAC_CNTL2, value);
210 
211 	snooze(10000);
212 
213 	// let's see what we've got!
214 	found = (INREG(regs, RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) != 0;
215 	if (found)
216 		SHOW_INFO0(2, "Found CRT connected to TV-DAC, i.e. DVI port");
217 
218 	OUTREG(regs, RADEON_DAC_CNTL2, old_dac_cntl2);
219 	OUTREG(regs, RADEON_DAC_EXT_CNTL, 0);
220 	OUTREG(regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl);
221 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl);
222 
223 	return found;
224 }
225 
226 
227 //! CRT on TV-DAC detection for r300 checked for r300
228 static bool
229 Radeon_DetectTVCRT_R300(accelerator_info *ai)
230 {
231 	vuint8 *regs = ai->regs;
232 	uint32 old_crtc2_gen_cntl, old_tv_dac_cntl, old_dac_cntl2, value;
233 	uint32 old_radeon_gpiopad_a;
234 	bool found;
235 
236 	old_radeon_gpiopad_a = INREG(regs, RADEON_GPIOPAD_A);
237 
238 	// whatever these flags mean - let's pray they won't get changed
239 	OUTREGP(regs, RADEON_GPIOPAD_EN, 1, ~1);
240 	OUTREGP(regs, RADEON_GPIOPAD_MASK, 1, ~1);
241 	OUTREGP(regs, RADEON_GPIOPAD_A, 1, ~1);
242 
243 	old_crtc2_gen_cntl = INREG(regs, RADEON_CRTC2_GEN_CNTL);
244 
245 	// enable DAC, choose valid pixel format and enable DPMS
246 	// as usual, the code doesn't take into account whether the TV-DAC
247 	// does really use CRTC2
248 	value = old_crtc2_gen_cntl;
249 	value &= ~RADEON_CRTC2_PIX_WIDTH_MASK;
250 	value |= (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT) | RADEON_CRTC2_CRT2_ON
251 		| RADEON_CRTC2_VSYNC_TRISTAT;
252 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, value);
253 
254 	old_tv_dac_cntl = INREG(regs, RADEON_TV_DAC_CNTL);
255 
256 	// enable TV-DAC
257 	OUTREG(regs, RADEON_TV_DAC_CNTL, RADEON_TV_DAC_CNTL_NBLANK
258 		| RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_DETECT
259 		| RADEON_TV_DAC_CNTL_STD_PS2);
260 
261 	// force constant voltage output of DAC for impedance test
262 	OUTREG(regs, RADEON_DAC_EXT_CNTL, RADEON_DAC2_FORCE_BLANK_OFF_EN
263 		| RADEON_DAC2_FORCE_DATA_EN | RADEON_DAC_FORCE_DATA_SEL_RGB
264 		| (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT));
265 
266 	old_dac_cntl2 = INREG(regs, RADEON_DAC_CNTL2);
267 
268 	// enable CRT mode of TV-DAC and enable comparator
269 	OUTREG(regs, RADEON_DAC_CNTL2, old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT
270 		| RADEON_DAC2_CMP_EN);
271 
272 	snooze(10000);
273 
274 	// check connection of blue data signal to see whether there is a CRT
275 	found = (INREG(regs, RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) != 0;
276 
277 	// clean up the mess
278 	OUTREG(regs, RADEON_DAC_CNTL2, old_dac_cntl2);
279 	OUTREG(regs, RADEON_DAC_EXT_CNTL, 0);
280 	OUTREG(regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl);
281 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl);
282 
283 	OUTREGP(regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1);
284 
285 	return found;
286 }
287 
288 
289 //! Check whether there is a CRT connected to TV-DAC
290 static bool
291 Radeon_DetectTVCRT(accelerator_info *ai)
292 {
293 	if (ai->si->is_mobility)
294 		return dd_none;
295 
296 	switch (ai->si->asic) {
297 		case rt_r100:
298 			// original Radeons have pure DVI only and mobility chips
299 			// have no DVI connector
300 			// TBD: can they have a docking station for CRT on TV-DAC?
301 			return dd_none;
302 
303 		case rt_rv100:
304 		case rt_rv200:
305 		case rt_rv250:
306 		case rt_rv280:
307 		// IGP is guessed
308 		case rt_rs100:
309 		case rt_rs200:
310 		case rt_rs300:
311 			return Radeon_DetectTVCRT_RV200(ai);
312 
313 		case rt_r300:
314 		case rt_r350:
315 		case rt_rv350:
316 		case rt_rv380:
317 		case rt_r420:
318 			return Radeon_DetectTVCRT_R300(ai);
319 
320 		case rt_r200:
321 			// r200 has no built-in TV-out and thus no TV-DAC to use for
322 			// second CRT
323 			return dd_none;
324 	}
325 
326 	return dd_none;
327 }
328 
329 
330 //! TV detection for rv200 and below should work for M6 and RV200
331 static display_device_e
332 Radeon_DetectTV_RV200(accelerator_info *ai, bool tv_crt_found)
333 {
334 	vuint8 *regs = ai->regs;
335 	uint32 value, old_dac_cntl2, old_crtc_ext_cntl, old_crtc2_gen_cntl;
336 	uint32 old_tv_master_cntl, old_tv_dac_cntl, old_pre_dac_mux_cntl;
337 	uint32 config_cntl;
338 	display_device_e displays = dd_none;
339 
340 	// give up if there is a CRT connected to TV-DAC
341 	if (tv_crt_found)
342 		return dd_none;
343 
344 	// enable TV mode
345 	old_dac_cntl2 = INREG(regs, RADEON_DAC_CNTL2);
346 	value = old_dac_cntl2 & ~RADEON_DAC2_CLK_SEL_CRT;
347 	OUTREG(regs, RADEON_DAC_CNTL2, value);
348 
349 	old_crtc_ext_cntl = INREG(regs, RADEON_CRTC_EXT_CNTL);
350 	old_crtc2_gen_cntl = INREG(regs, RADEON_CRTC2_GEN_CNTL);
351 	old_tv_master_cntl = INREG(regs, RADEON_TV_MASTER_CNTL);
352 
353 	// enable TV output
354 	value = old_tv_master_cntl | RADEON_TV_MASTER_CNTL_TV_ON;
355 	value &= ~(
356 		RADEON_TV_MASTER_CNTL_TV_ASYNC_RST |
357 		RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX |
358 		RADEON_TV_MASTER_CNTL_CRT_FIFO_CE_EN |
359 		RADEON_TV_MASTER_CNTL_TV_FIFO_CE_EN |
360 		RADEON_TV_MASTER_CNTL_RE_SYNC_NOW_SEL_MASK);
361 	value |=
362 		RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST |
363 		RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST;
364 	OUTREG(regs, RADEON_TV_MASTER_CNTL, value);
365 
366 	old_tv_dac_cntl = INREG(regs, RADEON_TV_DAC_CNTL);
367 
368 	config_cntl = INREG(regs, RADEON_CONFIG_CNTL);
369 
370 	// unlock TV DAC
371 	value =
372 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |
373 		RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_STD_NTSC |
374 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
375 		((((config_cntl & RADEON_CFG_ATI_REV_ID_MASK) == 0) ? 8 : 4) << RADEON_TV_DAC_CNTL_DACADJ_SHIFT);
376 	OUTREG(regs, RADEON_TV_DAC_CNTL, value);
377 
378 	old_pre_dac_mux_cntl = INREG(regs, RADEON_TV_PRE_DAC_MUX_CNTL);
379 
380 	// force constant DAC output voltage
381 	value =
382 		RADEON_TV_PRE_DAC_MUX_CNTL_C_GRN_EN | RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |
383 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT) |
384 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_GRN_MX_SHIFT) |
385 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT) |
386 		(0x109 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT);
387 	OUTREG(regs, RADEON_TV_PRE_DAC_MUX_CNTL, value);
388 
389 	// let things settle a bit
390 	snooze(3000);
391 
392 	// now see which wires are connected
393 	value = INREG(regs, RADEON_TV_DAC_CNTL);
394 	if ((value & RADEON_TV_DAC_CNTL_GDACDET) != 0) {
395 		displays |= dd_stv;
396 		SHOW_INFO0(2, "S-Video TV-Out is connected");
397 	}
398 
399 	if ((value & RADEON_TV_DAC_CNTL_BDACDET) != 0) {
400 		displays |= dd_ctv;
401 		SHOW_INFO0(2, "Composite TV-Out is connected");
402 	}
403 
404 	OUTREG(regs, RADEON_TV_PRE_DAC_MUX_CNTL, old_pre_dac_mux_cntl);
405 	OUTREG(regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl);
406 	OUTREG(regs, RADEON_TV_MASTER_CNTL, old_tv_master_cntl);
407 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl);
408 	OUTREG(regs, RADEON_CRTC_EXT_CNTL, old_crtc_ext_cntl);
409 	OUTREG(regs, RADEON_DAC_CNTL2, old_dac_cntl2);
410 
411 	return displays;
412 }
413 
414 
415 // TV detection for r300 series
416 // should work for R300
417 static display_device_e Radeon_DetectTV_R300(accelerator_info *ai)
418 {
419 	vuint8 *regs = ai->regs;
420 	display_device_e displays = dd_none;
421 	uint32 tmp, old_dac_cntl2, old_crtc2_gen_cntl, old_dac_ext_cntl, old_tv_dac_cntl;
422 	uint32 old_radeon_gpiopad_a;
423 
424 	old_radeon_gpiopad_a = INREG(regs, RADEON_GPIOPAD_A);
425 
426 	// whatever these flags mean - let's pray they won't get changed
427 	OUTREGP(regs, RADEON_GPIOPAD_EN, 1, ~1);
428 	OUTREGP(regs, RADEON_GPIOPAD_MASK, 1, ~1);
429 	OUTREGP(regs, RADEON_GPIOPAD_A, 0, ~1);
430 
431 	old_dac_cntl2 = INREG(regs, RADEON_DAC_CNTL2);
432 
433 	// set CRT mode (!) of TV-DAC
434 	OUTREG(regs, RADEON_DAC_CNTL2, RADEON_DAC2_CLK_SEL_CRT);
435 
436 	old_crtc2_gen_cntl = INREG(regs, RADEON_CRTC2_GEN_CNTL);
437 
438 	// enable TV-Out output, but set DPMS mode
439 	// (this seems to be not correct if TV-Out is connected to CRTC1,
440 	//  but it doesn't really hurt having wrong DPMS mode)
441 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL,
442 		RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
443 
444 	old_dac_ext_cntl = INREG(regs, RADEON_DAC_EXT_CNTL);
445 
446 	// force constant voltage output of DAC for impedance test
447 	OUTREG(regs, RADEON_DAC_EXT_CNTL,
448 		RADEON_DAC2_FORCE_BLANK_OFF_EN | RADEON_DAC2_FORCE_DATA_EN |
449     	RADEON_DAC_FORCE_DATA_SEL_RGB |
450     	(0xec << RADEON_DAC_FORCE_DATA_SHIFT));
451 
452 	old_tv_dac_cntl = INREG(regs, RADEON_TV_DAC_CNTL);
453 
454 	// get TV-DAC running (or something...)
455 	OUTREG(regs, RADEON_TV_DAC_CNTL,
456 		RADEON_TV_DAC_CNTL_STD_NTSC |
457 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
458 		(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT));
459 
460 	(void)INREG(regs, RADEON_TV_DAC_CNTL);
461 
462 	snooze(4000);
463 
464 	OUTREG(regs, RADEON_TV_DAC_CNTL,
465 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |
466 		RADEON_TV_DAC_CNTL_DETECT |
467 		RADEON_TV_DAC_CNTL_STD_NTSC |
468 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
469 		(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT));
470 
471 	(void)INREG(regs, RADEON_TV_DAC_CNTL);
472 
473 	snooze(6000);
474 
475 	// now see which wires are connected
476 	tmp = INREG(regs, RADEON_TV_DAC_CNTL);
477 	if ((tmp & RADEON_TV_DAC_CNTL_GDACDET) != 0) {
478 		displays |= dd_stv;
479 		SHOW_INFO0(2, "S-Video TV-Out is connected");
480 	}
481 
482 	if ((tmp & RADEON_TV_DAC_CNTL_BDACDET) != 0) {
483 		displays |= dd_ctv;
484 		SHOW_INFO0(2, "Composite TV-Out is connected");
485 	}
486 
487 	// clean up the mess we did
488 	OUTREG(regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl);
489 	OUTREG(regs, RADEON_DAC_EXT_CNTL, old_dac_ext_cntl);
490 	OUTREG(regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl);
491 	OUTREG(regs, RADEON_DAC_CNTL2, old_dac_cntl2);
492 
493 	OUTREGP(regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1);
494 
495 	return displays;
496 }
497 
498 
499 // save readout of TV detection comparators
500 static bool readTVDetect(accelerator_info *ai)
501 {
502 	uint32 tmp;
503 	int i;
504 	bigtime_t start_time;
505 	bool detect;
506 
507 	// make output constant
508 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
509 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK);
510 
511 	// check detection result
512 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp);
513 	detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
514 
515 	//SHOW_FLOW(2, "detect=%d", detect);
516 
517 	start_time = system_time();
518 
519 	do {
520 		// wait for stable detect signal
521 		for (i = 0; i < 5; ++i) {
522 			bool cur_detect;
523 
524 			Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
525 				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |
526 				RADEON_TV_DAC_CNTL_NHOLD);
527 			Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
528 				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK);
529 
530 			Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp);
531 			cur_detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
532 
533 			//SHOW_FLOW(2, "cur_detect=%d", cur_detect);
534 
535 			if (cur_detect != detect)
536 				break;
537 
538 			detect = cur_detect;
539 		}
540 
541 		if (i == 5) {
542 			//SHOW_FLOW(2, "return %d", detect);
543 			return detect;
544 		}
545 
546 		// don't wait forever - give up after 1 second
547 	} while (system_time() - start_time < 1000000);
548 
549 	SHOW_FLOW0(2, "timeout");
550 	return false;
551 }
552 
553 
554 //! Detect TV connected to external Theatre-Out
555 static display_device_e
556 Radeon_DetectTV_Theatre(accelerator_info *ai)
557 {
558 	uint32 old_tv_dac_cntl, old_pre_dac_mux_cntl, old_modulator_cntl1;
559 	uint32 old_master_cntl;
560 	uint32 uv_adr, old_last_fifo_entry, old_mid_fifo_entry, last_fifo_addr;
561 	display_device_e displays = dd_none;
562 
563 	if (ai->si->tv_chip != tc_external_rt1)
564 		return dd_none;
565 
566 	// save previous values (TV-Out may be running)
567 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
568 		&old_tv_dac_cntl);
569 
570 	// enable DAC and comparators
571 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
572 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT
573 		| RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_NBLANK);
574 
575 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
576 		&old_pre_dac_mux_cntl);
577 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,
578 		&old_modulator_cntl1);
579 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
580 		&old_master_cntl);
581 
582 	// save output timing
583 	Radeon_VIPRead(ai, ai->si->theatre_channel, THEATRE_VIP_UV_ADR, &uv_adr);
584 
585 	last_fifo_addr = (uv_adr & RADEON_TV_UV_ADR_MAX_UV_ADR_MASK) * 2 + 1;
586 
587 	old_last_fifo_entry = Radeon_TheatreReadFIFO(ai, last_fifo_addr);
588 	old_mid_fifo_entry = Radeon_TheatreReadFIFO(ai, 0x18f);
589 
590 	Radeon_TheatreWriteFIFO(ai, last_fifo_addr, 0x20208);
591 	Radeon_TheatreWriteFIFO(ai, 0x18f, 0x3ff2608);
592 
593 	// stop TV-Out to savely program it
594 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
595 		RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST
596 		| RADEON_TV_MASTER_CNTL_TV_ASYNC_RST);
597 
598 	// set constant base level
599 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,
600 		(0x2c << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT)
601 		| (0x2c << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT));
602 
603 	// enable output
604 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
605 		RADEON_TV_MASTER_CNTL_TV_ASYNC_RST);
606 
607 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, 0);
608 
609 	// set constant Composite output
610 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
611 		RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN
612 		| RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN
613 		| (9 << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT)
614 		| (0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT));
615 
616 	// check for S-Video connection
617 	if (readTVDetect(ai)) {
618 		SHOW_FLOW0(2, "Composite-Out of Rage Theatre is connected");
619 		displays |= dd_ctv;
620 	}
621 
622 	// enable output changes
623 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
624 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT
625 		| RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD);
626 
627 	// set constant Y-output of S-Video adapter
628 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
629 		RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN
630 		| RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN
631 		| (9 << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT)
632 		| (0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT));
633 
634 	// check for composite connection
635 	if (readTVDetect(ai)) {
636 		SHOW_FLOW0(2, "S-Video-Out of Rage Theatre is connected");
637 		displays |= dd_stv;
638 	}
639 
640 	// restore everything
641 	Radeon_TheatreWriteFIFO(ai, last_fifo_addr, old_last_fifo_entry);
642 	Radeon_TheatreWriteFIFO(ai, 0x18f, old_mid_fifo_entry);
643 
644 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
645 		old_master_cntl);
646 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,
647 		old_modulator_cntl1);
648 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
649 		old_pre_dac_mux_cntl);
650 	Radeon_VIPWrite(ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
651 		old_tv_dac_cntl);
652 
653 	return displays;
654 }
655 
656 
657 /*!
658 	Check whether there is a TV connected to TV-DAC
659 	returns bit set, i.e. there can be S-Video or composite or both
660 */
661 static display_device_e
662 Radeon_DetectTV(accelerator_info *ai, bool tv_crt_found)
663 {
664 	switch (ai->si->asic) {
665 		case rt_r100:
666 		case rt_r200:
667 			return Radeon_DetectTV_Theatre(ai);
668 
669 		case rt_rv100:
670 		case rt_rv200:
671 		case rt_rv250:
672 		case rt_rv280:
673 		// IGP method is guessed
674 		case rt_rs100:
675 		case rt_rs200:
676 		case rt_rs300:
677 			return Radeon_DetectTV_RV200(ai, tv_crt_found);
678 
679 		case rt_r300:
680 		case rt_r350:
681 		case rt_rv350:
682 		case rt_rv380:
683 		case rt_r420:
684 			return Radeon_DetectTV_R300(ai);
685 	}
686 
687 	return dd_none;
688 }
689 
690 
691 //! Get native monitor timing, using Detailed Monitor Description
692 static void
693 Radeon_FindFPTiming_DetailedMonitorDesc(const edid1_info *edid, fp_info *fp,
694 	uint32 *max_hsize, uint32 *max_vsize)
695 {
696 	int i;
697 
698 	for (i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i) {
699 		if (edid->detailed_monitor[i].monitor_desc_type == EDID1_IS_DETAILED_TIMING) {
700 			const edid1_detailed_timing *timing = &edid->detailed_monitor[i].data.detailed_timing;
701 
702 			SHOW_FLOW(2, "Found detailed timing for mode %dx%d in DDC data",
703 				(int)timing->h_active, (int)timing->v_active);
704 
705 			if (timing->h_active > *max_hsize && timing->v_active > *max_vsize) {
706 				*max_hsize = timing->h_active;
707 				*max_vsize = timing->v_active;
708 
709 				// copy it to timing specification
710 				fp->panel_xres = timing->h_active;
711 				fp->h_blank = timing->h_blank;
712 				fp->h_over_plus = timing->h_sync_off;
713 				fp->h_sync_width = timing->h_sync_width;
714 
715 				fp->panel_yres = timing->v_active;
716 				fp->v_blank = timing->v_blank;
717 				fp->v_over_plus = timing->v_sync_off;
718 				fp->v_sync_width = timing->v_sync_width;
719 
720 				// BeOS uses kHz, but the timing is in 10 kHz
721 				fp->dot_clock = timing->pixel_clock * 10;
722 			}
723 		}
724 	}
725 }
726 
727 
728 /*!	Get native monitor timing, using Standard Timing table;
729 	this table doesn't contain the actual timing, so we try to find a
730 	appropriate VESA modes for the resolutions given in the table
731 */
732 static void
733 Radeon_FindFPTiming_StandardTiming(const edid1_info *edid, fp_info *fp,
734 	uint32 *max_hsize, uint32 *max_vsize)
735 {
736 	int i;
737 
738 	for (i = 0; i < EDID1_NUM_STD_TIMING; ++i) {
739 		const edid1_std_timing *std_timing = &edid->std_timing[i];
740 		int best_fit = -1;
741 		int best_refresh_deviation = 10000;
742 		int j;
743 
744 		if (std_timing->h_size <= 256)
745 			continue;
746 
747 		for (j = 0; j < (int)vesa_mode_list_count; ++j) {
748 			int refresh_rate, cur_refresh_deviation;
749 
750 			if (vesa_mode_list[j].h_display != std_timing->h_size
751 				|| vesa_mode_list[j].v_display != std_timing->v_size)
752 				continue;
753 
754 			// take pixel_clock times 1000 because is is in kHz
755 			// further, take it times 1000 again, to get 1/1000 frames
756 			// as refresh rate
757 			refresh_rate = (int64)vesa_mode_list[j].pixel_clock * 1000*1000
758 				/ (vesa_mode_list[j].h_total * vesa_mode_list[j].v_total);
759 
760 			// standard timing is in frames, so multiple by it to get 1/1000 frames
761 			// result is scaled by 100 to get difference in percentage;
762 			cur_refresh_deviation = (100 * (refresh_rate - std_timing->refresh
763 				* 1000)) / refresh_rate;
764 
765 			if (cur_refresh_deviation < 0)
766 				cur_refresh_deviation = -cur_refresh_deviation;
767 
768 			// less then 1 percent difference is (hopefully) OK,
769 			// if there are multiple, we take best one
770 			// (if the screen is that picky, it should have defined an enhanced timing)
771 			if (cur_refresh_deviation < 1
772 				&& cur_refresh_deviation < best_refresh_deviation) {
773 				best_fit = j;
774 				best_refresh_deviation = cur_refresh_deviation;
775 			}
776 		}
777 
778 		if (best_fit < 0) {
779 			SHOW_FLOW(2, "Unsupported standard mode %dx%d@%dHz (not VESA)",
780 				std_timing->h_size, std_timing->v_size, std_timing->refresh);
781 			continue;
782 		}
783 
784 		if (std_timing->h_size > *max_hsize && std_timing->h_size > *max_vsize) {
785 			const display_timing *timing = &vesa_mode_list[best_fit];
786 
787 			SHOW_FLOW(2, "Found DDC data for standard mode %dx%d",
788 				(int)timing->h_display, (int)timing->v_display);
789 
790 			*max_hsize = timing->h_display;
791 			*max_vsize = timing->h_display;
792 
793 			// copy it to timing specification
794 			fp->panel_xres = timing->h_display;
795 			fp->h_blank = timing->h_total - timing->h_display;
796 			fp->h_over_plus = timing->h_sync_start - timing->h_display;
797 			fp->h_sync_width = timing->h_sync_end - timing->h_sync_start;
798 
799 			fp->panel_yres = timing->v_display;
800 			fp->v_blank = timing->v_total - timing->v_display;
801 			fp->v_over_plus = timing->v_sync_start - timing->v_display;
802 			fp->v_sync_width = timing->v_sync_end - timing->v_sync_start;
803 
804 			fp->dot_clock = timing->pixel_clock;
805 		}
806 	}
807 }
808 
809 
810 //! Read edid data of flat panel and setup its timing accordingly
811 static status_t
812 Radeon_StoreFPEDID(accelerator_info *ai, int port, const edid1_info *edid)
813 {
814 	fp_info *fp = &ai->si->flatpanels[port];
815 	uint32 max_hsize, max_vsize;
816 
817 	//SHOW_FLOW0(2, "EDID data read from DVI port via DDC2:");
818 	//edid_dump(edid);
819 
820 	// find detailed timing with maximum resolution
821 	max_hsize = max_vsize = 0;
822 	Radeon_FindFPTiming_DetailedMonitorDesc(edid, fp, &max_hsize, &max_vsize);
823 
824 	if (max_hsize == 0) {
825 		SHOW_FLOW0(2, "Timing is not explicitely defined in DDC - checking standard modes");
826 
827 		Radeon_FindFPTiming_StandardTiming(edid, fp, &max_hsize, &max_vsize);
828 		if (max_hsize == 0) {
829 			SHOW_FLOW0(2, "Still found no valid native mode, disabling DVI");
830 			return B_ERROR;
831 		}
832 	}
833 
834 	SHOW_INFO(2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
835 		fp->panel_xres, fp->h_blank, fp->h_over_plus, fp->h_sync_width);
836 	SHOW_INFO(2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
837 		fp->panel_yres, fp->v_blank, fp->v_over_plus, fp->v_sync_width);
838 	SHOW_INFO(2, "pixel_clock=%d kHz", fp->dot_clock);
839 
840 	return B_OK;
841 }
842 
843 
844 static void
845 Radeon_ConnectorInfo(accelerator_info *ai, int port, disp_entity* ptr_entity)
846 {
847 	const char* mon;
848 	const char* ddc = ptr_entity->port_info[port].ddc_type == ddc_none_detected
849 		? "None" : ptr_entity->port_info[port].ddc_type == ddc_monid
850 		? "Mon ID" : ptr_entity->port_info[port].ddc_type == ddc_dvi
851 		? "DVI DDC" : ptr_entity->port_info[port].ddc_type == ddc_vga
852 		? "VGA DDC" : ptr_entity->port_info[port].ddc_type == ddc_crt2
853 		? "CRT2 DDC" : "Error";
854 	const char* tmds = ptr_entity->port_info[port].tmds_type == tmds_unknown
855 		? "None" : ptr_entity->port_info[port].tmds_type == tmds_int
856 		? "Internal" : ptr_entity->port_info[port].tmds_type == tmds_ext
857 		? "External" : "??? ";
858 	const char* dac = ptr_entity->port_info[port].dac_type == dac_unknown
859 		? "Unknown" : ptr_entity->port_info[port].dac_type == dac_primary
860 		? "Primary" : ptr_entity->port_info[port].dac_type == dac_tvdac
861 		? "TV / External" : "Error";
862 	const char* con;
863 
864 	if (ai->si->is_atombios) {
865 		con = ptr_entity->port_info[port].connector_type == connector_none_atom
866 			? "None" : ptr_entity->port_info[port].connector_type == connector_vga_atom
867 			? "VGA" : ptr_entity->port_info[port].connector_type == connector_dvi_i_atom
868 			? "DVI-I" : ptr_entity->port_info[port].connector_type == connector_dvi_d_atom
869 			? "DVI-D" : ptr_entity->port_info[port].connector_type == connector_dvi_a_atom
870 			? "DVI-A" : ptr_entity->port_info[port].connector_type == connector_stv_atom
871 			? "S-Video TV" : ptr_entity->port_info[port].connector_type == connector_ctv_atom
872 			? "Composite TV" : ptr_entity->port_info[port].connector_type == connector_lvds_atom
873 			? "LVDS" : ptr_entity->port_info[port].connector_type == connector_digital_atom
874 			? "Digital" : ptr_entity->port_info[port].connector_type == connector_unsupported_atom
875 			? "N/A  " : "Err  ";
876 	} else {
877 		con = ptr_entity->port_info[port].connector_type == connector_none
878 			? "None" : ptr_entity->port_info[port].connector_type == connector_crt
879 			? "VGA" : ptr_entity->port_info[port].connector_type == connector_dvi_i
880 			? "DVI-I" : ptr_entity->port_info[port].connector_type == connector_dvi_d
881 			? "DVI-D" : ptr_entity->port_info[port].connector_type == connector_proprietary
882 			? "Proprietary" : ptr_entity->port_info[port].connector_type == connector_stv
883 			? "S-Video TV" : ptr_entity->port_info[port].connector_type == connector_ctv
884 			? "Composite TV" : ptr_entity->port_info[port].connector_type == connector_unsupported
885 			? "N/A" : "Err";
886 	}
887 
888 	mon = ptr_entity->port_info[port].mon_type == mt_unknown ? "???"
889 		: ptr_entity->port_info[port].mon_type == mt_none ? "None"
890 		: ptr_entity->port_info[port].mon_type == mt_crt ? "CRT "
891 		: ptr_entity->port_info[port].mon_type == mt_lcd ? "LCD "
892 		: ptr_entity->port_info[port].mon_type == mt_dfp ? "DVI "
893 		: ptr_entity->port_info[port].mon_type == mt_ctv ? "Composite TV"
894 		: ptr_entity->port_info[port].mon_type == mt_stv ? "S-Video TV"
895 		: "Err ?";
896 
897 	SHOW_INFO(2, "Port %d:- \nMonitor:    %s\nConn Type:  %s\nDDC Port:   %s\nTMDS Type:  %s\nDAC Type:   %s",
898 		port, mon, con, ddc, tmds, dac);
899 }
900 
901 
902 /*!
903 	Detect connected displays devices
904 	whished_num_heads - how many heads the requested display mode needs
905 */
906 void
907 Radeon_DetectDisplays(accelerator_info *ai)
908 {
909 	shared_info *si = ai->si;
910 
911 	disp_entity* routes = &si->routing;
912 	display_device_e displays = 0;
913 	display_device_e controlled_displays = ai->vc->controlled_displays;
914 	int i;
915 
916 	uint32 edid_regs[] = {
917 		0,
918 		RADEON_GPIO_MONID,
919 		RADEON_GPIO_DVI_DDC,
920 		RADEON_GPIO_VGA_DDC,
921 		RADEON_GPIO_CRT2_DDC
922 	};
923 
924 	// lock hardware so noone bothers us
925 	Radeon_WaitForIdle(ai, true);
926 
927 	// alwats make TMDS_INT port first
928 	if (routes->port_info[1].tmds_type == tmds_int) {
929 		radeon_connector swap_entity;
930 		swap_entity = routes->port_info[0];
931 		routes->port_info[0] = routes->port_info[1];
932 		routes->port_info[1] = swap_entity;
933 		SHOW_FLOW0(2, "Swapping TMDS_INT to first port");
934 	} else if (routes->port_info[0].tmds_type != tmds_int
935 		&& routes->port_info[1].tmds_type != tmds_int) {
936 		// no TMDS_INT port, make primary DAC port first
937 		// On my Inspiron 8600 both internal and external ports are
938 		// marked DAC_PRIMARY in BIOS. So be extra careful - only
939 		// swap when the first port is not DAC_PRIMARY
940 		if (routes->port_info[1].dac_type == dac_primary
941 			&& routes->port_info[0].dac_type != dac_primary) {
942 			radeon_connector swap_entity;
943 			swap_entity = routes->port_info[0];
944 			routes->port_info[0] = routes->port_info[1];
945 			routes->port_info[1] = swap_entity;
946 			SHOW_FLOW0(2, "Swapping Primary Dac to front");
947 		}
948 	}
949 
950 	if (si->asic == rt_rs300) {
951 		// RS300 only has single Dac of TV type
952 		// For RS300/RS350/RS400 chips, there is no primary DAC.
953 		// Force VGA port to use TVDAC
954 		if (routes->port_info[0].connector_type == connector_crt) {
955 			routes->port_info[0].dac_type = dac_tvdac;
956 			routes->port_info[1].dac_type = dac_primary;
957 		} else {
958 			routes->port_info[1].dac_type = dac_primary;
959 			routes->port_info[0].dac_type = dac_tvdac;
960 		}
961 	} else if (si->num_crtc == 1) {
962 		routes->port_info[0].dac_type = dac_primary;
963 	}
964 
965 	// use DDC to detect monitors - if we can read DDC, there must be
966 	// a monitor
967 	for (i = 0; i < 2; i++) {
968 		//TODO could skip edid reading instead if we already have it, but what
969 		//if monitors have been hot swapped?  Also rely on edid for DVI-D detection
970 		//if (routes->port_info[i].mon_type != mt_unknown) {
971 		//	SHOW_FLOW0(2, "known type, skpping detection");
972 		//	continue;
973 		//}
974 		memset(&routes->port_info[i].edid , 0, sizeof(edid1_info));
975 		switch (routes->port_info[i].ddc_type) {
976 			case ddc_monid:
977 			case ddc_dvi:
978 			case ddc_vga:
979 			case ddc_crt2:
980 				if (Radeon_ReadEDID(ai,
981 						edid_regs[routes->port_info[i].ddc_type],
982 						&routes->port_info[i].edid)) {
983 					routes->port_info[i].edid_valid = true;
984 					SHOW_FLOW(2, "Edid Data for CRTC %d on line %d", i, routes->port_info[i].ddc_type);
985 					edid_dump(&routes->port_info[i].edid);
986 				} else {
987 					routes->port_info[i].mon_type = mt_none;
988 				}
989 				break;
990 
991 			default:
992 				SHOW_FLOW(2, "No Edid Pin Assigned to CRTC %d ", i);
993 				routes->port_info[i].mon_type = mt_none;
994 		}
995 
996 		if (routes->port_info[i].edid_valid) {
997 			if (routes->port_info[i].edid.display.input_type == 1) {
998 				SHOW_FLOW0(2, "Must be a DVI monitor");
999 
1000 				// Note some laptops have a DVI output that uses internal TMDS,
1001 				// when its DVI is enabled by hotkey, LVDS panel is not used.
1002 				// In this case, the laptop is configured as DVI+VGA as a normal
1003 				// desktop card.
1004 				// Also for laptop, when X starts with lid closed (no DVI connection)
1005 				// both LDVS and TMDS are disable, we still need to treat it as a LVDS panel.
1006 				if (routes->port_info[i].tmds_type == tmds_ext){
1007 					// store info about DVI-connected flat-panel
1008 					if (Radeon_StoreFPEDID(ai, i, &routes->port_info[i].edid) == B_OK) {
1009 						SHOW_INFO0(2, "Found Ext Laptop DVI");
1010 						routes->port_info[i].mon_type = mt_dfp;
1011 						ai->si->flatpanels[i].is_fp2 = true;
1012 						displays |= dd_dvi_ext;
1013 					} else {
1014 						SHOW_ERROR0(2, "Disabled Ext DVI - invalid EDID");
1015 					}
1016 				} else {
1017 					if (INREG(ai->regs, RADEON_FP_GEN_CNTL) & (1 << 7) || (!si->is_mobility)) {
1018 						// store info about DVI-connected flat-panel
1019 						if (Radeon_StoreFPEDID(ai, i, &routes->port_info[i].edid) == B_OK) {
1020 							SHOW_INFO0(2, "Found DVI");
1021 							routes->port_info[i].mon_type = mt_dfp;
1022 							displays |= dd_dvi;
1023 						} else {
1024 							SHOW_ERROR0(2, "Disabled DVI - invalid EDID");
1025 						}
1026 					} else {
1027 						SHOW_INFO0(2, "Laptop Panel Found");
1028 						routes->port_info[i].mon_type = mt_lcd;
1029 						displays |= dd_lvds;
1030 					}
1031 					ai->si->flatpanels[1].is_fp2 = FALSE;
1032 				}
1033 			} else {
1034 				// must be the analog portion of DVI
1035 				// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?
1036 				// anyway - if there are two CRTC, analog portion must be connected
1037 				// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC
1038 				if (si->num_crtc > 1) {
1039 					SHOW_FLOW0(2, "Must be an analog monitor on DVI port");
1040 					routes->port_info[i].mon_type = mt_crt;
1041 					displays |= dd_tv_crt;
1042 				} else {
1043 					SHOW_FLOW0(2, "Seems to be a CRT on VGA port!?");
1044 					routes->port_info[i].mon_type = mt_crt;
1045 					displays |= dd_crt;
1046 				}
1047 			}
1048 		}
1049 	}
1050 
1051 	if (!routes->port_info[0].edid_valid) {
1052 		SHOW_INFO0(2, "Searching port 0");
1053 		if (si->is_mobility && (INREG(ai->regs, RADEON_BIOS_4_SCRATCH) & 4)) {
1054 			SHOW_INFO0(2, "Found Laptop Panel");
1055 			routes->port_info[0].mon_type = mt_lcd;
1056 			displays |= dd_lvds;
1057 		}
1058 	}
1059 
1060 	if (!routes->port_info[1].edid_valid) {
1061 		if (si->is_mobility && (INREG(ai->regs, RADEON_FP2_GEN_CNTL) & RADEON_FP2_FPON)) {
1062 			SHOW_INFO0(2, "Found Ext Laptop DVI");
1063 			routes->port_info[1].mon_type = mt_dfp;
1064 			displays |= dd_dvi_ext;
1065 		}
1066 	}
1067 
1068 	if (routes->port_info[0].mon_type == mt_none) {
1069 		if (routes->port_info[1].mon_type == mt_none) {
1070 			routes->port_info[0].mon_type = mt_crt;
1071 		} else {
1072 			radeon_connector swap_entity;
1073 			swap_entity = routes->port_info[0];
1074 			routes->port_info[0] = routes->port_info[1];
1075 			routes->port_info[1] = swap_entity;
1076 			SHOW_ERROR0(2, "swapping active port 2 to free port 1");
1077 		}
1078 
1079 	}
1080 
1081 	routes->reversed_DAC = false;
1082 	if (routes->port_info[1].dac_type == dac_tvdac) {
1083 		SHOW_ERROR0(2, "Reversed dac detected (not impl. yet)");
1084 		routes->reversed_DAC = true;
1085 	}
1086 
1087 	// we may have overseen monitors if they don't support DDC or
1088 	// have broken DDC data (like mine);
1089 	// time to do a physical wire test; this test is more reliable, but it
1090 	// leads to distortions on screen, which is not very nice to look at
1091 
1092 	// for DVI, there is no mercy if no DDC data is there - we wouldn't
1093 	// even know the native resolution of the panel!
1094 
1095 	// all versions have a standard VGA port
1096 	if ((displays & dd_crt) == 0 && (controlled_displays & dd_crt) != 0
1097 		&& Radeon_DetectCRT(ai))
1098 		displays |= dd_crt;
1099 
1100 	// check VGA signal routed to DVI port
1101 	// (the detection code checks whether there is hardware for that)
1102 	if ((displays & dd_tv_crt) == 0
1103 		&& (controlled_displays & dd_tv_crt) != 0
1104 		&& Radeon_DetectTVCRT(ai))
1105 		displays |= dd_tv_crt;
1106 
1107 	// check TV-out connector
1108 	if ((controlled_displays && (dd_ctv | dd_stv)) != 0)
1109 		displays |= Radeon_DetectTV(ai, (displays & dd_tv_crt) != 0);
1110 
1111 	SHOW_INFO(0, "Detected monitors: 0x%x", displays);
1112 
1113 	displays &= controlled_displays;
1114 
1115 	// if no monitor found, we define to have a CRT connected to CRT-DAC
1116 	if (displays == 0)
1117 		displays = dd_crt;
1118 
1119 	Radeon_ConnectorInfo(ai, 0, routes);
1120 	Radeon_ConnectorInfo(ai, 1, routes);
1121 
1122 	ai->vc->connected_displays = displays;
1123 
1124 	RELEASE_BEN(si->cp.lock);
1125 }
1126