xref: /haiku/src/add-ons/accelerants/radeon/monitor_detection.c (revision 55b40aa53a835472ec7952b138ae4256203d02e4)
1 /*
2 	Copyright (c) 2002-2004 Thomas Kurschel
3 
4 
5 	Part of Radeon accelerant
6 
7 	Monitor detection
8 */
9 
10 #include "radeon_accelerant.h"
11 #include "mmio.h"
12 #include "crtc_regs.h"
13 #include "dac_regs.h"
14 #include "pll_regs.h"
15 #include "tv_out_regs.h"
16 #include "config_regs.h"
17 #include "ddc_regs.h"
18 #include "gpiopad_regs.h"
19 #include "pll_access.h"
20 #include "theatre_regs.h"
21 #include "set_mode.h"
22 #include "ddc.h"
23 #include <malloc.h>
24 
25 typedef struct {
26 	accelerator_info *ai;
27 	uint32 port;
28 } ddc_port_info;
29 
30 
31 // get I2C signals
32 static status_t get_signals( void *cookie, int *clk, int *data )
33 {
34 	ddc_port_info *info = (ddc_port_info *)cookie;
35 	vuint8 *regs = info->ai->regs;
36 	uint32 value;
37 
38 	value = INREG( regs, info->port );
39 
40 	*clk = (value >> RADEON_GPIO_Y_SHIFT_1) & 1;
41 	*data = (value >> RADEON_GPIO_Y_SHIFT_0) & 1;
42 
43 	return B_OK;
44 }
45 
46 
47 // set I2C signals
48 static status_t set_signals( void *cookie, int clk, int data )
49 {
50 	ddc_port_info *info = (ddc_port_info *)cookie;
51 	vuint8 *regs = info->ai->regs;
52 	uint32 value;
53 
54 	value = INREG( regs, info->port );
55 	value &= ~(RADEON_GPIO_A_1 | RADEON_GPIO_A_0);
56 	value &= ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1);
57 	value |= ((1-clk) << RADEON_GPIO_EN_SHIFT_1) | ((1-data) << RADEON_GPIO_EN_SHIFT_0);
58 
59 	OUTREG( regs, info->port, value );
60 
61 	return B_OK;
62 }
63 
64 
65 // read EDID information from monitor
66 // ddc_port - register to use for DDC2 communication
67 bool Radeon_ReadEDID( accelerator_info *ai, uint32 ddc_port, edid1_info *edid )
68 {
69 	i2c_bus bus;
70 	ddc_port_info info;
71 	void *vdif;
72 	size_t vdif_len;
73 	status_t res;
74 
75 	info.ai = ai;
76 	info.port = ddc_port;
77 
78 	bus.cookie = &info;
79 	bus.set_signals = &set_signals;
80 	bus.get_signals = &get_signals;
81 
82 	res = ddc2_read_edid1( &bus, edid, &vdif, &vdif_len );
83 	if( res != B_OK )
84 		return false;
85 
86 	SHOW_FLOW( 2, "Found DDC-capable monitor @0x%04x", ddc_port );
87 
88 	if( vdif != NULL )
89 		free( vdif );
90 
91 	return true;
92 }
93 
94 
95 // search for display connect to CRT DAC
96 // colour - true, if only a colour monitor is to be accepted
97 static bool Radeon_DetectCRTInt( accelerator_info *ai, bool colour )
98 {
99 	vuint8 *regs = ai->regs;
100 	uint32 old_crtc_ext_cntl, old_dac_ext_cntl, old_dac_cntl, tmp;
101 	bool found;
102 
103 	// makes sure there is a signal
104 	old_crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL );
105 
106 	tmp = old_crtc_ext_cntl | RADEON_CRTC_CRT_ON;
107 	OUTREG( regs, RADEON_CRTC_EXT_CNTL, tmp );
108 
109 	// force DAC to output constant voltage
110 	// for colour monitors, RGB is tested, for B/W only G
111 	old_dac_ext_cntl = INREG( regs, RADEON_DAC_EXT_CNTL );
112 
113 	tmp =
114 		RADEON_DAC_FORCE_BLANK_OFF_EN |
115 		RADEON_DAC_FORCE_DATA_EN |
116 		(colour ? RADEON_DAC_FORCE_DATA_SEL_RGB : RADEON_DAC_FORCE_DATA_SEL_G) |
117 		(0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
118 	OUTREG( regs, RADEON_DAC_EXT_CNTL, tmp );
119 
120 	// enable DAC and tell is to use VGA signals
121 	old_dac_cntl = INREG( regs, RADEON_DAC_CNTL );
122 
123 	tmp = old_dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN);
124 	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
125 	OUTREG( regs, RADEON_DAC_CNTL, tmp );
126 
127 	// specs says that we should wait 1µs before checking but sample
128 	// code uses 2 ms; we use long delay to be on safe side
129 	// (though we don't want to make it too long as the monitor
130 	// gets no sync signal now)
131 	snooze( 2000 );
132 
133 	// let's see whether there is some
134 	found = (INREG( regs, RADEON_DAC_CNTL ) & RADEON_DAC_CMP_OUTPUT) != 0;
135 
136 	if( found )
137 		SHOW_INFO( 2, "Found %s CRT connected to CRT-DAC", colour ? "colour" : "b/w" );
138 
139 	OUTREG( regs, RADEON_DAC_CNTL, old_dac_cntl );
140 	OUTREG( regs, RADEON_DAC_EXT_CNTL, old_dac_ext_cntl );
141 	OUTREG( regs, RADEON_CRTC_EXT_CNTL, old_crtc_ext_cntl );
142 
143 	return found;
144 }
145 
146 
147 // check whethere there is a CRT connected to CRT DAC
148 static bool Radeon_DetectCRT( accelerator_info *ai )
149 {
150 	vuint32 old_vclk_ecp_cntl, tmp;
151 	bool found;
152 
153 	// enforce clock so the DAC gets activated
154 	old_vclk_ecp_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL );
155 
156 	tmp = old_vclk_ecp_cntl &
157 		~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb);
158 	Radeon_OUTPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL, tmp );
159 
160 	// search first for colour, then for B/W monitor
161 	found = Radeon_DetectCRTInt( ai, true ) || Radeon_DetectCRTInt( ai, false );
162 
163 	Radeon_OUTPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL, old_vclk_ecp_cntl );
164 
165 	return found;
166 }
167 
168 
169 // CRT on TV-DAC detection for rv200 and below
170 // checked for rv200
171 static bool Radeon_DetectTVCRT_RV200( accelerator_info *ai )
172 {
173 	vuint8 *regs = ai->regs;
174 	uint32 old_crtc2_gen_cntl, old_tv_dac_cntl, old_dac_cntl2, tmp;
175 	bool found;
176 
177 	// enable CRTC2, setting 8 bpp (we just pick any valid value)
178 	old_crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
179 
180 	tmp = old_crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
181 	tmp |=
182 		RADEON_CRTC2_CRT2_ON |
183 		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
184 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, tmp );
185 
186 	// enable TV-DAC, choosing VGA signal level
187 	old_tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
188 
189 	tmp =
190 		RADEON_TV_DAC_CNTL_NBLANK |
191 		RADEON_TV_DAC_CNTL_NHOLD |
192 		RADEON_TV_DAC_CNTL_DETECT |
193 		RADEON_TV_DAC_CNTL_STD_PS2;
194 	OUTREG( regs, RADEON_TV_DAC_CNTL, tmp );
195 
196 	// enforce constant DAC output voltage on RGB
197 	tmp =
198 		RADEON_DAC2_FORCE_BLANK_OFF_EN |
199 		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, tmp );
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 	tmp = old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT | RADEON_DAC2_CMP_EN;
209 	OUTREG( regs, RADEON_DAC_CNTL2, tmp );
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 
216 	if( found )
217 		SHOW_INFO0( 2, "Found CRT connected to TV-DAC, i.e. DVI port" );
218 
219 	OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
220 	OUTREG( regs, RADEON_DAC_EXT_CNTL, 0 );
221 	OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
222 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
223 
224 	return found;
225 }
226 
227 // CRT on TV-DAC detection for r300
228 // checked for r300
229 static bool 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, tmp;
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 	tmp = old_crtc2_gen_cntl;
249 	tmp &= ~RADEON_CRTC2_PIX_WIDTH_MASK;
250 	tmp |=
251 		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT) |
252 		RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT;
253 
254 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, tmp );
255 
256 	old_tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
257 
258 	// enable TV-DAC
259 	OUTREG( regs, RADEON_TV_DAC_CNTL,
260 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |
261 		RADEON_TV_DAC_CNTL_DETECT |
262 		RADEON_TV_DAC_CNTL_STD_PS2 );
263 
264 	// force constant voltage output of DAC for impedance test
265 	OUTREG( regs, RADEON_DAC_EXT_CNTL,
266 		RADEON_DAC2_FORCE_BLANK_OFF_EN | RADEON_DAC2_FORCE_DATA_EN |
267     	RADEON_DAC_FORCE_DATA_SEL_RGB |
268     	(0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT ));
269 
270     old_dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
271 
272 	// enable CRT mode of TV-DAC and enable comparator
273     tmp = old_dac_cntl2 | RADEON_DAC2_CLK_SEL_CRT | RADEON_DAC2_CMP_EN;
274 
275     OUTREG( regs, RADEON_DAC_CNTL2, tmp );
276 
277     snooze( 10000 );
278 
279     // check connection of blue data signal to see whether there is a CRT
280 	found = (INREG( regs, RADEON_DAC_CNTL2 ) & RADEON_DAC2_CMP_OUT_B) != 0;
281 
282     // clean up the mess
283 	OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
284 	OUTREG( regs, RADEON_DAC_EXT_CNTL, 0 );
285 	OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
286 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
287 
288 	OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );
289 
290     return found;
291 }
292 
293 
294 // check whether there is a CRT connected to TV-DAC
295 static bool Radeon_DetectTVCRT( accelerator_info *ai )
296 {
297 	switch( ai->si->asic ) {
298 	case rt_r100:
299 	case rt_m6:
300 	case rt_m7:
301 	case rt_m9:
302 	case rt_m9plus:
303 	case rt_m10:
304 		// original Radeons have pure DVI only and mobility chips
305 		// have no DVI connector
306 		// TBD: can they have a docking station for CRT on TV-DAC?
307 		return dd_none;
308 
309 	case rt_ve:
310 	case rt_rv200:
311 	case rt_rv250:
312 	case rt_rv280:
313 	// IGP is guessed
314 	case rt_rs100:
315 	case rt_rs200:
316 		return Radeon_DetectTVCRT_RV200( ai );
317 
318 	case rt_r300:
319 	case rt_r300_4p:
320 	case rt_rv350:
321 	case rt_rv360:
322 	case rt_r350:
323 	case rt_r360:
324 	case rt_m11:
325 		return Radeon_DetectTVCRT_R300( ai );
326 
327 	case rt_r200:
328 		// r200 has no built-in TV-out and thus no TV-DAC to use for
329 		// second CRT
330 		return dd_none;
331 	}
332 
333 	return dd_none;
334 }
335 
336 
337 // TV detection for rv200 and below
338 // should work for M6 and RV200
339 static display_device_e Radeon_DetectTV_RV200( accelerator_info *ai, bool tv_crt_found )
340 {
341 	vuint8 *regs = ai->regs;
342 	uint32
343 		tmp, old_dac_cntl2, old_crtc_ext_cntl, old_crtc2_gen_cntl, old_tv_master_cntl,
344 		old_tv_dac_cntl, old_pre_dac_mux_cntl, config_cntl;
345 	display_device_e displays = dd_none;
346 
347 	// give up if there is a CRT connected to TV-DAC
348 	if( tv_crt_found )
349 		return dd_none;
350 
351 	// enable TV mode
352 	old_dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
353 	tmp = old_dac_cntl2 & ~RADEON_DAC2_CLK_SEL_CRT;
354 	OUTREG( regs, RADEON_DAC_CNTL2, tmp );
355 
356 	old_crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL );
357 	old_crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
358 	old_tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL );
359 
360 	// enable TV output
361 	tmp = old_tv_master_cntl | RADEON_TV_MASTER_CNTL_TV_ON;
362 	tmp &= ~(
363 		RADEON_TV_MASTER_CNTL_TV_ASYNC_RST |
364 		RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX |
365 		RADEON_TV_MASTER_CNTL_CRT_FIFO_CE_EN |
366 		RADEON_TV_MASTER_CNTL_TV_FIFO_CE_EN |
367 		RADEON_TV_MASTER_CNTL_RE_SYNC_NOW_SEL_MASK);
368 	tmp |=
369 		RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST |
370 		RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST;
371 	OUTREG( regs, RADEON_TV_MASTER_CNTL, tmp );
372 
373 	old_tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
374 
375 	config_cntl = INREG( regs, RADEON_CONFIG_CNTL );
376 
377 	// unlock TV DAC
378 	tmp =
379 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |
380 		RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_STD_NTSC |
381 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
382 		((((config_cntl & RADEON_CFG_ATI_REV_ID_MASK) == 0) ? 8 : 4) << RADEON_TV_DAC_CNTL_DACADJ_SHIFT);
383 	OUTREG( regs, RADEON_TV_DAC_CNTL, tmp );
384 
385 	old_pre_dac_mux_cntl = INREG( regs, RADEON_TV_PRE_DAC_MUX_CNTL );
386 
387 	// force constant DAC output voltage
388 	tmp =
389 		RADEON_TV_PRE_DAC_MUX_CNTL_C_GRN_EN | RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |
390 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT) |
391 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_GRN_MX_SHIFT) |
392 		(RADEON_TV_MUX_FORCE_DAC_DATA << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT) |
393 		(0x109 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT);
394 	OUTREG( regs, RADEON_TV_PRE_DAC_MUX_CNTL, tmp );
395 
396 	// let things settle a bit
397 	snooze( 3000 );
398 
399 	// now see which wires are connected
400 	tmp = INREG( regs, RADEON_TV_DAC_CNTL );
401 	if( (tmp & RADEON_TV_DAC_CNTL_GDACDET) != 0 ) {
402 		displays |= dd_stv;
403 		SHOW_INFO0( 2, "S-Video TV-Out is connected" );
404 	}
405 
406 	if( (tmp & RADEON_TV_DAC_CNTL_BDACDET) != 0 ) {
407 		displays |= dd_ctv;
408 		SHOW_INFO0( 2, "Composite TV-Out is connected" );
409 	}
410 
411 	OUTREG( regs, RADEON_TV_PRE_DAC_MUX_CNTL, old_pre_dac_mux_cntl );
412 	OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
413 	OUTREG( regs, RADEON_TV_MASTER_CNTL, old_tv_master_cntl );
414 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
415 	OUTREG( regs, RADEON_CRTC_EXT_CNTL, old_crtc_ext_cntl );
416 	OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
417 
418 	return displays;
419 }
420 
421 
422 // TV detection for r300 series
423 // should work for R300
424 static display_device_e Radeon_DetectTV_R300( accelerator_info *ai )
425 {
426 	vuint8 *regs = ai->regs;
427 	display_device_e displays = dd_none;
428 	uint32 tmp, old_dac_cntl2, old_crtc2_gen_cntl, old_dac_ext_cntl, old_tv_dac_cntl;
429 	uint32 old_radeon_gpiopad_a;
430 
431 	old_radeon_gpiopad_a = INREG( regs, RADEON_GPIOPAD_A );
432 
433 	// whatever these flags mean - let's pray they won't get changed
434 	OUTREGP( regs, RADEON_GPIOPAD_EN, 1, ~1 );
435 	OUTREGP( regs, RADEON_GPIOPAD_MASK, 1, ~1 );
436 	OUTREGP( regs, RADEON_GPIOPAD_A, 0, ~1 );
437 
438 	old_dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
439 
440 	// set CRT mode (!) of TV-DAC
441 	OUTREG( regs, RADEON_DAC_CNTL2, RADEON_DAC2_CLK_SEL_CRT );
442 
443 	old_crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
444 
445 	// enable TV-Out output, but set DPMS mode
446 	// (this seems to be not correct if TV-Out is connected to CRTC1,
447 	//  but it doesn't really hurt having wrong DPMS mode)
448 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL,
449 		RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT );
450 
451 	old_dac_ext_cntl = INREG( regs, RADEON_DAC_EXT_CNTL );
452 
453 	// force constant voltage output of DAC for impedance test
454 	OUTREG( regs, RADEON_DAC_EXT_CNTL,
455 		RADEON_DAC2_FORCE_BLANK_OFF_EN | RADEON_DAC2_FORCE_DATA_EN |
456     	RADEON_DAC_FORCE_DATA_SEL_RGB |
457     	(0xec << RADEON_DAC_FORCE_DATA_SHIFT ));
458 
459 	old_tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
460 
461 	// get TV-DAC running (or something...)
462 	OUTREG( regs, RADEON_TV_DAC_CNTL,
463 		RADEON_TV_DAC_CNTL_STD_NTSC |
464 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
465 		(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT ));
466 
467 	(void)INREG( regs, RADEON_TV_DAC_CNTL );
468 
469 	snooze( 4000 );
470 
471 	OUTREG( regs, RADEON_TV_DAC_CNTL,
472 		RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD |
473 		RADEON_TV_DAC_CNTL_DETECT |
474 		RADEON_TV_DAC_CNTL_STD_NTSC |
475 		(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
476 		(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT ));
477 
478 	(void)INREG( regs, RADEON_TV_DAC_CNTL );
479 
480 	snooze( 6000 );
481 
482 	// now see which wires are connected
483 	tmp = INREG( regs, RADEON_TV_DAC_CNTL );
484 	if( (tmp & RADEON_TV_DAC_CNTL_GDACDET) != 0 ) {
485 		displays |= dd_stv;
486 		SHOW_INFO0( 2, "S-Video TV-Out is connected" );
487 	}
488 
489 	if( (tmp & RADEON_TV_DAC_CNTL_BDACDET) != 0 ) {
490 		displays |= dd_ctv;
491 		SHOW_INFO0( 2, "Composite TV-Out is connected" );
492 	}
493 
494 	// clean up the mess we did
495 	OUTREG( regs, RADEON_TV_DAC_CNTL, old_tv_dac_cntl );
496 	OUTREG( regs, RADEON_DAC_EXT_CNTL, old_dac_ext_cntl );
497 	OUTREG( regs, RADEON_CRTC2_GEN_CNTL, old_crtc2_gen_cntl );
498 	OUTREG( regs, RADEON_DAC_CNTL2, old_dac_cntl2 );
499 
500 	OUTREGP( regs, RADEON_GPIOPAD_A, old_radeon_gpiopad_a, ~1 );
501 
502 	return displays;
503 }
504 
505 
506 // save readout of TV detection comparators
507 static bool readTVDetect( accelerator_info *ai )
508 {
509 	uint32 tmp;
510 	int i;
511 	bigtime_t start_time;
512 	bool detect;
513 
514 	// make output constant
515 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
516 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );
517 
518 	// check detection result
519 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );
520 	detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
521 
522 	//SHOW_FLOW( 2, "detect=%d", detect );
523 
524 	start_time = system_time();
525 
526 	do {
527 		// wait for stable detect signal
528 		for( i = 0; i < 5; ++i ) {
529 			bool cur_detect;
530 
531 			Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
532 				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |
533 				RADEON_TV_DAC_CNTL_NHOLD );
534 			Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
535 				RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK );
536 
537 			Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &tmp );
538 			cur_detect = (tmp & RADEON_TV_DAC_CNTL_CMPOUT) != 0;
539 
540 			//SHOW_FLOW( 2, "cur_detect=%d", cur_detect );
541 
542 			if( cur_detect != detect )
543 				break;
544 
545 			detect = cur_detect;
546 		}
547 
548 		if( i == 5 ) {
549 			//SHOW_FLOW( 2, "return %d", detect );
550 			return detect;
551 		}
552 
553 		// don't wait forever - give up after 1 second
554 	} while( system_time() - start_time < 1000000 );
555 
556 	SHOW_FLOW0( 2, "timeout" );
557 
558 	return false;
559 }
560 
561 
562 // detect TV connected to external Theatre-Out
563 static display_device_e Radeon_DetectTV_Theatre( accelerator_info *ai )
564 {
565 	uint32
566 		old_tv_dac_cntl, old_pre_dac_mux_cntl, old_modulator_cntl1, old_master_cntl;
567 	uint32
568 		uv_adr, old_last_fifo_entry, old_mid_fifo_entry, last_fifo_addr;
569 	display_device_e displays = dd_none;
570 
571 	if( ai->si->tv_chip != tc_external_rt1 )
572 		return dd_none;
573 
574 	// save previous values (TV-Out may be running)
575 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, &old_tv_dac_cntl );
576 
577 	// enable DAC and comparators
578 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
579 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT |
580 		RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_NBLANK );
581 
582 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, &old_pre_dac_mux_cntl );
583 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, &old_modulator_cntl1 );
584 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, &old_master_cntl );
585 
586 	// save output timing
587 	Radeon_VIPRead( ai, ai->si->theatre_channel, THEATRE_VIP_UV_ADR, &uv_adr );
588 
589 	last_fifo_addr = (uv_adr & RADEON_TV_UV_ADR_MAX_UV_ADR_MASK) * 2 + 1;
590 
591 	old_last_fifo_entry = Radeon_TheatreReadFIFO( ai, last_fifo_addr );
592 	old_mid_fifo_entry = Radeon_TheatreReadFIFO( ai, 0x18f );
593 
594 	Radeon_TheatreWriteFIFO( ai, last_fifo_addr, 0x20208 );
595 	Radeon_TheatreWriteFIFO( ai, 0x18f, 0x3ff2608 );
596 
597 	// stop TV-Out to savely program it
598 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
599 		RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST | RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );
600 
601 	// set constant base level
602 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1,
603 		(0x2c << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT) |
604 		(0x2c << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT) );
605 
606 	// enable output
607 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
608 		RADEON_TV_MASTER_CNTL_TV_ASYNC_RST );
609 
610 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL,
611 		0 );
612 
613 	// set constant Composite output
614 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
615 		RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |
616 		RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN |
617 		(9 << RADEON_TV_PRE_DAC_MUX_CNTL_BLU_MX_SHIFT) |
618 		(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );
619 
620 	// check for S-Video connection
621 	if( readTVDetect( ai )) {
622 		SHOW_FLOW0( 2, "Composite-Out of Rage Theatre is connected" );
623 		displays |= dd_ctv;
624 	}
625 
626 	// enable output changes
627 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL,
628 		RADEON_TV_DAC_CNTL_STD_NTSC | RADEON_TV_DAC_CNTL_DETECT | RADEON_TV_DAC_CNTL_NBLANK |
629 		RADEON_TV_DAC_CNTL_NHOLD );
630 
631 	// set constant Y-output of S-Video adapter
632 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL,
633 		RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN |
634 		RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN |
635 		(9 << RADEON_TV_PRE_DAC_MUX_CNTL_RED_MX_SHIFT) |
636 		(0xa8 << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT) );
637 
638 	// check for composite connection
639 	if( readTVDetect( ai )) {
640 		SHOW_FLOW0( 2, "S-Video-Out of Rage Theatre is connected" );
641 		displays |= dd_stv;
642 	}
643 
644 	// restore everything
645 	Radeon_TheatreWriteFIFO( ai, last_fifo_addr, old_last_fifo_entry );
646 	Radeon_TheatreWriteFIFO( ai, 0x18f, old_mid_fifo_entry );
647 
648 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MASTER_CNTL, old_master_cntl );
649 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_MODULATOR_CNTL1, old_modulator_cntl1 );
650 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_PRE_DAC_MUX_CNTL, old_pre_dac_mux_cntl );
651 	Radeon_VIPWrite( ai, ai->si->theatre_channel, THEATRE_VIP_TV_DAC_CNTL, old_tv_dac_cntl );
652 
653 	return displays;
654 }
655 
656 // check whether there is a TV connected to TV-DAC
657 // returns bit set, i.e. there can be S-Video or composite or both
658 static display_device_e Radeon_DetectTV( accelerator_info *ai, bool tv_crt_found )
659 {
660 	switch( ai->si->asic ) {
661 	case rt_r100:
662 	case rt_r200:
663 		return Radeon_DetectTV_Theatre( ai );
664 
665 	case rt_ve:
666 	case rt_m6:
667 	case rt_rv200:
668 	case rt_m7:
669 	case rt_rv250:
670 	case rt_m9:
671 	case rt_rv280:
672 	case rt_m9plus:
673 	// IGP method is guessed
674 	case rt_rs100:
675 	case rt_rs200:
676 		return Radeon_DetectTV_RV200( ai, tv_crt_found );
677 
678 	case rt_r300:
679 	case rt_r300_4p:
680 	case rt_rv350:
681 	case rt_rv360:
682 	case rt_m10:
683 	case rt_m11:
684 	case rt_r350:
685 	case rt_r360:
686 		return Radeon_DetectTV_R300( ai );
687 	}
688 
689 	return dd_none;
690 }
691 
692 
693 // get native monitor timing, using Detailed Monitor Description
694 static void Radeon_FindFPTiming_DetailedMonitorDesc(
695 	const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize )
696 {
697 	int i;
698 
699 	for( i = 0; i < EDID1_NUM_DETAILED_MONITOR_DESC; ++i ) {
700 		if( edid->detailed_monitor[i].monitor_desc_type == edid1_is_detailed_timing ) {
701 			const edid1_detailed_timing *timing = &edid->detailed_monitor[i].data.detailed_timing;
702 
703 			SHOW_FLOW( 2, "Found detailed timing for mode %dx%d in DDC data",
704 				(int)timing->h_active, (int)timing->v_active );
705 
706 			if( timing->h_active > *max_hsize && timing->v_active > *max_vsize ) {
707 				*max_hsize = timing->h_active;
708 				*max_vsize = timing->v_active;
709 
710 				// copy it to timing specification
711 				fp->panel_xres = timing->h_active;
712 				fp->h_blank = timing->h_blank;
713 				fp->h_over_plus = timing->h_sync_off;
714 				fp->h_sync_width = timing->h_sync_width;
715 
716 				fp->panel_yres = timing->v_active;
717 				fp->v_blank = timing->v_blank;
718 				fp->v_over_plus = timing->v_sync_off;
719 				fp->v_sync_width = timing->v_sync_width;
720 
721 				// BeOS uses kHz, but the timing is in 10 kHz
722 				fp->dot_clock = timing->pixel_clock * 10;
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 static void Radeon_FindFPTiming_StandardTiming(
732 	const edid1_info *edid, fp_info *fp, uint32 *max_hsize, uint32 *max_vsize )
733 {
734 	int i;
735 
736 	for( i = 0; i < EDID1_NUM_STD_TIMING; ++i ) {
737 		const edid1_std_timing *std_timing = &edid->std_timing[i];
738 
739 		int best_fit = -1;
740 		int best_refresh_deviation = 10000;
741 		int j;
742 
743 		if( std_timing->h_size <= 256 )
744 			continue;
745 
746 		for( j = 0; j < (int)vesa_mode_list_count; ++j ) {
747 			int refresh_rate, cur_refresh_deviation;
748 
749 			if( vesa_mode_list[j].h_display != std_timing->h_size ||
750 				vesa_mode_list[j].v_display != std_timing->v_size )
751 				continue;
752 
753 			// take pixel_clock times 1000 because is is in kHz
754 			// further, take it times 1000 again, to get 1/1000 frames
755 			// as refresh rate
756 			refresh_rate = (int64)vesa_mode_list[j].pixel_clock * 1000*1000 /
757 				(vesa_mode_list[j].h_total * vesa_mode_list[j].v_total);
758 
759 			// standard timing is in frames, so multiple by it to get 1/1000 frames
760 			// result is scaled by 100 to get difference in percentage;
761 			cur_refresh_deviation =
762 				(100 * (refresh_rate - std_timing->refresh * 1000)) / refresh_rate;
763 
764 			if( cur_refresh_deviation < 0 )
765 				cur_refresh_deviation = -cur_refresh_deviation;
766 
767 			// less then 1 percent difference is (hopefully) OK,
768 			// if there are multiple, we take best one
769 			// (if the screen is that picky, it should have defined an enhanced timing)
770 			if( cur_refresh_deviation < 1 &&
771 				cur_refresh_deviation < best_refresh_deviation )
772 			{
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 // read edid data of flat panel and setup its timing accordingly
810 static status_t Radeon_StoreFPEDID( accelerator_info *ai, const edid1_info *edid )
811 {
812 	fp_info *fp = &ai->si->flatpanels[0];
813 	uint32 max_hsize, max_vsize;
814 
815 	SHOW_FLOW0( 2, "EDID data read from DVI port via DDC2:" );
816 	edid_dump( edid );
817 
818 	// find detailed timing with maximum resolution
819 	max_hsize = max_vsize = 0;
820 
821 	Radeon_FindFPTiming_DetailedMonitorDesc( edid, fp, &max_hsize, &max_vsize );
822 
823 	if( max_hsize == 0 ) {
824 		SHOW_FLOW0( 2, "Timing is not explicitely defined in DDC - checking standard modes" );
825 
826 		Radeon_FindFPTiming_StandardTiming(
827 			edid, fp, &max_hsize, &max_vsize );
828 
829 		if( max_hsize == 0 ) {
830 			SHOW_FLOW0( 2, "Still found no valid native mode, disabling DVI" );
831 			return B_ERROR;
832 		}
833 	}
834 
835 	SHOW_INFO( 2, "h_disp=%d, h_blank=%d, h_over_plus=%d, h_sync_width=%d",
836 		fp->panel_xres, fp->h_blank, fp->h_over_plus, fp->h_sync_width );
837 	SHOW_INFO( 2, "v_disp=%d, v_blank=%d, v_over_plus=%d, v_sync_width=%d",
838 		fp->panel_yres, fp->v_blank, fp->v_over_plus, fp->v_sync_width );
839 	SHOW_INFO( 2, "pixel_clock=%d kHz", fp->dot_clock );
840 
841 	return B_OK;
842 }
843 
844 
845 // detect connected displays devices
846 // whished_num_heads - how many heads the requested display mode needs
847 void Radeon_DetectDisplays( accelerator_info *ai )
848 {
849 	shared_info *si = ai->si;
850 	display_device_e displays = 0;
851 	display_device_e controlled_displays = ai->vc->controlled_displays;
852 	edid1_info edid;
853 
854 	// lock hardware so noone bothers us
855 	Radeon_WaitForIdle( ai, true );
856 
857 	// mobile chips are for use in laptops - there must be a laptop panel
858 	if( si->is_mobility )
859 		displays |= dd_lvds;
860 
861 	// use DDC to detect monitors - if we can read DDC, there must be a monitor
862 
863 	// all non-mobility versions have a DVI port
864 	if( (displays & dd_lvds) == 0 &&
865 		Radeon_ReadEDID( ai, RADEON_GPIO_DVI_DDC, &edid ))
866 	{
867 		SHOW_FLOW0( 2, "Found monitor on DVI DDC port" );
868 		// there may be an analog monitor connected to DVI-I;
869 		// we must check EDID to see whether it's really a digital monitor
870 		if( edid.display.input_type == 1 ) {
871 			SHOW_FLOW0( 2, "Must be a DVI monitor" );
872 
873 			// store info about DVI-connected flat-panel
874 			if( Radeon_StoreFPEDID( ai, &edid ) == B_OK ) {
875 				displays |= dd_dvi;
876 			} else {
877 				SHOW_ERROR0( 2, "Disabled DVI - invalid EDID" );
878 			}
879 		} else {
880 			// must be the analog portion of DVI
881 			// I'm not sure about Radeons with one CRTC - do they have DVI-I or DVI-D?
882 			// anyway - if there are two CRTC, analog portion must be connected
883 			// to TV-DAC; if there is one CRTC, it must be the normal VGA-DAC
884 			if( si->num_crtc > 1 ) {
885 				SHOW_FLOW0( 2, "Must be an analog monitor on DVI port" );
886 				displays |= dd_tv_crt;
887 			} else {
888 				SHOW_FLOW0( 2, "Seems to be a CRT on VGA port!?" );
889 				displays |= dd_crt;
890 			}
891 		}
892 	}
893 
894 	// all chips have a standard VGA port
895 	if( Radeon_ReadEDID( ai, RADEON_GPIO_VGA_DDC, &edid ))
896 		displays |= dd_crt;
897 
898 	// we may have overseen monitors if they don't support DDC or
899 	// have broken DDC data (like mine);
900 	// time to do a physical wire test; this test is more reliable, but it
901 	// leads to distortions on screen, which is not very nice to look at
902 
903 	// for DVI, there is no mercy if no DDC data is there - we wouldn't
904 	// even know the native resolution of the panel!
905 
906 	// all versions have a standard VGA port
907 	if( (displays & dd_crt) == 0 &&
908 		(controlled_displays && dd_crt) != 0 &&
909 		Radeon_DetectCRT( ai ))
910 		displays |= dd_crt;
911 
912 	// check VGA signal routed to DVI port
913 	// (the detection code checks whether there is hardware for that)
914 	if( (displays & dd_tv_crt) == 0 &&
915 		(controlled_displays && dd_tv_crt) != 0 &&
916 		Radeon_DetectTVCRT( ai ))
917 		displays |= dd_tv_crt;
918 
919 	// check TV-out connector
920 	if( (controlled_displays && (dd_ctv | dd_stv)) != 0 )
921 		displays |= Radeon_DetectTV( ai, (displays & dd_tv_crt) != 0 );
922 
923 	SHOW_INFO( 0, "Detected monitors: 0x%x", displays );
924 
925 	displays &= controlled_displays;
926 
927 	// if no monitor found, we define to have a CRT connected to CRT-DAC
928 	if( displays == 0 )
929 		displays = dd_crt;
930 
931 	ai->vc->connected_displays = displays;
932 
933 	RELEASE_BEN( si->cp.lock );
934 }
935