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
29typedef struct {
30	accelerator_info *ai;
31	uint32 port;
32} ddc_port_info;
33
34
35//! Get I2C signals
36static status_t
37get_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
52static status_t
53set_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*/
73bool
74Radeon_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
101static bool
102Radeon_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
152static bool
153Radeon_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
177static bool
178Radeon_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
228static bool
229Radeon_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
290static bool
291Radeon_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
331static display_device_e
332Radeon_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
417static 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
500static 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
555static display_device_e
556Radeon_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*/
661static display_device_e
662Radeon_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
692static void
693Radeon_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*/
732static void
733Radeon_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
811static status_t
812Radeon_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
844static void
845Radeon_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*/
906void
907Radeon_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 portSwapEntity;
1073			fp_info panelInfoSwapEntity;
1074
1075			portSwapEntity = routes->port_info[0];
1076			routes->port_info[0] = routes->port_info[1];
1077			routes->port_info[1] = portSwapEntity;
1078
1079			panelInfoSwapEntity = ai->si->flatpanels[0];
1080			ai->si->flatpanels[0] = ai->si->flatpanels[1];
1081			ai->si->flatpanels[1] = panelInfoSwapEntity;
1082
1083			SHOW_ERROR0(2, "swapping active port 2 to free port 1");
1084		}
1085
1086	}
1087
1088	routes->reversed_DAC = false;
1089	if (routes->port_info[1].dac_type == dac_tvdac) {
1090		SHOW_ERROR0(2, "Reversed dac detected (not impl. yet)");
1091		routes->reversed_DAC = true;
1092	}
1093
1094	// we may have overseen monitors if they don't support DDC or
1095	// have broken DDC data (like mine);
1096	// time to do a physical wire test; this test is more reliable, but it
1097	// leads to distortions on screen, which is not very nice to look at
1098
1099	// for DVI, there is no mercy if no DDC data is there - we wouldn't
1100	// even know the native resolution of the panel!
1101
1102	// all versions have a standard VGA port
1103	if ((displays & dd_crt) == 0 && (controlled_displays & dd_crt) != 0
1104		&& Radeon_DetectCRT(ai))
1105		displays |= dd_crt;
1106
1107	// check VGA signal routed to DVI port
1108	// (the detection code checks whether there is hardware for that)
1109	if ((displays & dd_tv_crt) == 0
1110		&& (controlled_displays & dd_tv_crt) != 0
1111		&& Radeon_DetectTVCRT(ai))
1112		displays |= dd_tv_crt;
1113
1114	// check TV-out connector
1115	if ((controlled_displays & (dd_ctv | dd_stv)) != 0)
1116		displays |= Radeon_DetectTV(ai, (displays & dd_tv_crt) != 0);
1117
1118	SHOW_INFO(0, "Detected monitors: 0x%x", displays);
1119
1120	displays &= controlled_displays;
1121
1122	// if no monitor found, we define to have a CRT connected to CRT-DAC
1123	if (displays == 0)
1124		displays = dd_crt;
1125
1126	Radeon_ConnectorInfo(ai, 0, routes);
1127	Radeon_ConnectorInfo(ai, 1, routes);
1128
1129	ai->vc->connected_displays = displays;
1130
1131	RELEASE_BEN(si->cp.lock);
1132}
1133