xref: /haiku/src/add-ons/accelerants/radeon/monitor_routing.c (revision 5412911f7f8ca41340b0f5cb928ed9726322ab44)
1 /*
2 	Copyright (c) 2002-04, Thomas Kurschel
3 
4 
5 	Part of Radeon accelerant
6 
7 	CRTC <-> display routing
8 
9 	This stuff is highly ASIC dependant and is probably the most ASIC-specific
10 	code of the entire project.
11 */
12 
13 #include "radeon_accelerant.h"
14 #include "mmio.h"
15 #include "dac_regs.h"
16 #include "fp_regs.h"
17 #include "crtc_regs.h"
18 #include "tv_out_regs.h"
19 #include "pll_regs.h"
20 #include "gpiopad_regs.h"
21 #include "pll_access.h"
22 #include "set_mode.h"
23 
24 
25 // read regs needed for display device routing
26 void Radeon_ReadMonitorRoutingRegs(
27 	accelerator_info *ai, routing_regs *values )
28 {
29 	vuint8 *regs = ai->regs;
30 
31 	values->dac_cntl = INREG( regs, RADEON_DAC_CNTL );
32 	values->dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 );
33 	values->crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL );
34 	values->crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
35 	values->disp_output_cntl = INREG( regs, RADEON_DISP_OUTPUT_CNTL );
36 	values->pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL );
37 	values->vclk_ecp_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL );
38 
39 	switch( ai->si->asic ) {
40 	case rt_ve:
41 	case rt_m6:
42 	case rt_rv200:
43 	case rt_m7:
44 	case rt_rv250:
45 	case rt_m9:
46 	case rt_rv280:
47 	case rt_m9plus:
48 	case rt_rs100:
49 	case rt_rs200:
50 		values->disp_hw_debug = INREG( regs, RADEON_DISP_HW_DEBUG );
51 		break;
52 
53 	case rt_r200:
54 		values->disp_tv_out_cntl = INREG( regs, RADEON_DISP_TV_OUT_CNTL );
55 		break;
56 
57 	case rt_r300:
58 	case rt_r300_4p:
59 	case rt_rv350:
60 	case rt_m10:
61 	case rt_rv360:
62 	case rt_r350:
63 	case rt_r360:
64 		values->gpiopad_a = INREG( regs, RADEON_GPIOPAD_A );
65 		break;
66 
67 	case rt_r100:
68 		break;
69 	}
70 
71 	if( ai->si->asic > rt_r100 ) {
72 		// register introduced after R100
73 		values->tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
74 	}
75 
76 	if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
77 		values->tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL );
78 
79 	values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
80 	values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
81 }
82 
83 
84 // setup register contents to proper CRTC <-> display device mapping
85 void Radeon_CalcMonitorRouting(
86 	accelerator_info *ai, const impactv_params *tv_parameters, routing_regs *values )
87 {
88 	display_device_e display_devices[2], total_devices, controlled_devices;
89 
90 	if( ai->vc->used_crtc[0] )
91 		display_devices[0] = ai->si->crtc[0].chosen_displays;
92 	else
93 		display_devices[0] = dd_none;
94 
95 	if( ai->vc->used_crtc[1] )
96 		display_devices[1] = ai->si->crtc[1].chosen_displays;
97 	else
98 		display_devices[1] = dd_none;
99 
100 	total_devices = display_devices[0] | display_devices[1];
101 	controlled_devices = ai->vc->controlled_displays;
102 
103 	// enable 8 bit DAC
104 	// (could be moved to boot initialization)
105 	values->dac_cntl |=
106 		RADEON_DAC_MASK_ALL | RADEON_DAC_VGA_ADR_EN | RADEON_DAC_8BIT_EN;
107 
108 	// enable frame buffer access and extended CRTC counter
109 	// (again: something for boot init.)
110 	values->crtc_ext_cntl =
111 		RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN;
112 
113 	// set VGA signal style (not sure whether this affects
114 	// CRTC1 or CRT-DAC, so we better always set it)
115 	values->dac_cntl &= ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING);
116 	values->dac_cntl |= RADEON_DAC_RANGE_CNTL_PS2;
117 
118 	// disable all the magic CRTC shadowing
119 	values->fp_gen_cntl &=
120 		~(RADEON_FP_RMX_HVSYNC_CONTROL_EN |
121 		  RADEON_FP_DFP_SYNC_SEL |
122 		  RADEON_FP_CRT_SYNC_SEL |
123 		  RADEON_FP_CRTC_LOCK_8DOT |
124 		  RADEON_FP_USE_SHADOW_EN |
125 		  RADEON_FP_CRTC_USE_SHADOW_VEND |
126 		  RADEON_FP_CRT_SYNC_ALT);
127 	values->fp_gen_cntl |=
128 		RADEON_FP_CRTC_DONT_SHADOW_VPAR |
129 		RADEON_FP_CRTC_DONT_SHADOW_HEND;
130 
131 	// route VGA-DAC
132 	if( (total_devices & dd_crt) != 0 ) {
133 		int crtc_idx = (display_devices[1] & dd_crt) != 0;
134 
135 		// the CRT_ON flag seems to directly affect the CRT-DAC, _not_ the CRTC1 signal
136 		values->crtc_ext_cntl |= RADEON_CRTC_CRT_ON;
137 
138 		switch( ai->si->asic ) {
139 		case rt_ve:
140 		case rt_m6:
141 		case rt_rv200:
142 		case rt_m7:
143 		case rt_rv250:
144 		case rt_m9:
145 		case rt_rv280:
146 		case rt_m9plus:
147 		case rt_rs100:
148 		case rt_rs200:
149 			values->dac_cntl2 &= ~RADEON_DAC_CLK_SEL_MASK;
150 			values->dac_cntl2 |= crtc_idx == 0 ? 0 : RADEON_DAC_CLK_SEL_CRTC2;
151 			break;
152 
153 		case rt_r200:
154 		case rt_r300:
155 		case rt_r300_4p:
156 		case rt_rv350:
157 		case rt_m10:
158 		case rt_rv360:
159 		case rt_r350:
160 		case rt_r360:
161 			values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
162 			values->disp_output_cntl |=
163 				(crtc_idx == 0 ? 0 : RADEON_DISP_DAC_SOURCE_CRTC2);
164 			break;
165 
166 		case rt_r100:
167 			break;
168 		}
169 
170 	} else if( (controlled_devices & dd_crt) != 0 ) {
171 		values->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
172 	}
173 
174 
175 	if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) {
176 		// power down TV-DAC
177 		// (but only if TV-Out _and_ TV-CRT is controlled by us)
178 		// this will be undone if needed
179 		values->tv_dac_cntl |=
180 			RADEON_TV_DAC_CNTL_RDACPD |
181 			RADEON_TV_DAC_CNTL_GDACPD |
182 			RADEON_TV_DAC_CNTL_BDACPD;
183 	}
184 
185 
186 	// set CRT mode of TV-DAC if needed
187 	// (doesn't work on r200, but there is no TV-DAC used for CRT anyway)
188 	if( (total_devices & dd_tv_crt) != 0 ) {
189 		// enable CRT via TV-DAC (ignored if TV-DAC is in TV-Out mode)
190 		values->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
191 
192 		values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK;
193 		values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_CRT;
194 
195 		// enable TV-DAC and set PS2 signal level
196 		values->tv_dac_cntl =
197 			RADEON_TV_DAC_CNTL_NBLANK |
198 			RADEON_TV_DAC_CNTL_NHOLD |
199 			RADEON_TV_DAC_CNTL_STD_PS2 |
200 			(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |
201 			(2 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT);
202 
203 		// at least r300 needs magic bit set to switch between TV-CRT and TV-Out
204 		switch( ai->si->asic ) {
205 			case rt_r200:
206 			case rt_r300:
207 			case rt_r300_4p:
208 			case rt_rv350:
209 			case rt_m10:
210 			case rt_rv360:
211 			case rt_r350:
212 			case rt_r360:
213 				values->gpiopad_a |= 1;
214 				break;
215 			default:
216 				;
217 		}
218 
219 	} else if( (controlled_devices & dd_tv_crt) != 0 ) {
220 		values->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
221 	}
222 
223 	values->skip_tv_dac = false;
224 
225 
226 	// disable forwarding data to TV-Out unit
227 	// (will be enabled on demand later on)
228 	if( (controlled_devices & (dd_ctv | dd_stv)) != 0 )
229 		values->dac_cntl &= ~RADEON_DAC_TVO_EN;
230 
231 
232 	// set TV mode of TV-DAC if needed
233 	if( (total_devices & (dd_ctv | dd_stv)) != 0 ) {
234 		// see above
235 		values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK;
236 		values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_TV;
237 
238 		// at least r300 needs magic bit set to switch between TV-CRT and TV-Out
239 		switch( ai->si->asic ) {
240 			case rt_r200:
241 			case rt_r300:
242 			case rt_r300_4p:
243 			case rt_rv350:
244 			case rt_rv360:
245 			case rt_m10:
246 			case rt_r350:
247 			case rt_r360:
248 				values->gpiopad_a &= ~1;
249 				break;
250 			default:
251 				;
252 		}
253 
254 		// the TV-DAC itself is under control of the TV-Out code
255 		values->skip_tv_dac = true;
256 
257 		if( !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
258 			// tell DAC to forward data to external chip
259 			values->dac_cntl |= RADEON_DAC_TVO_EN;
260 
261 			// set Output Linear Transform Unit as source
262 			// (TODO: is this unit initialized properly?)
263 			// disable overlay sync (could be a good idea to enable it)
264 			// set 8 BPP mode
265 			values->disp_output_cntl &=
266 				~(RADEON_DISP_TV_SOURCE |
267 				RADEON_DISP_TV_MODE_MASK |
268 				RADEON_DISP_TV_YG_DITH_EN |
269 				RADEON_DISP_TV_CBB_CRR_DITH_EN |
270 				RADEON_DISP_TV_BIT_WIDTH |
271 				RADEON_DISP_TV_SYNC_MODE_MASK |
272 				RADEON_DISP_TV_SYNC_COLOR_MASK);
273 
274 			// enable dithering
275 			values->disp_output_cntl |=
276 				RADEON_DISP_TV_YG_DITH_EN |
277 				RADEON_DISP_TV_CBB_CRR_DITH_EN;
278 
279 			// set output data format
280 			values->disp_output_cntl |= tv_parameters->mode888 ?
281 				RADEON_DISP_TV_MODE_888 : RADEON_DISP_TV_MODE_565;
282 
283 			switch( ai->si->asic ) {
284 			case rt_r200:
285 				// disable downfiltering and scaling, set RGB mode,
286 				// don't transmit overlay indicator;
287 				// I don't really know whether this is a good choice
288 				values->disp_tv_out_cntl &=
289 					(RADEON_DISP_TV_OUT_YG_FILTER_MASK |
290 					 RADEON_DISP_TV_OUT_YG_SAMPLE |
291 					 RADEON_DISP_TV_OUT_CrR_FILTER_MASK |
292 					 RADEON_DISP_TV_OUT_CrR_SAMPLE |
293 					 RADEON_DISP_TV_OUT_CbB_FILTER_MASK |
294 					 RADEON_DISP_TV_OUT_CbB_SAMPLE |
295 					 RADEON_DISP_TV_SUBSAMPLE_CNTL_MASK |
296 					 RADEON_DISP_TV_H_DOWNSCALE |
297 					 RADEON_DISP_TV_COLOR_SPACE |
298 					 RADEON_DISP_TV_DITH_MODE |
299 					 RADEON_DISP_TV_DATA_ZERO_SEL |
300 					 RADEON_DISP_TV_CLKO_SEL |
301 					 RADEON_DISP_TV_CLKO_OUT_EN |
302 					 RADEON_DISP_TV_DOWNSCALE_CNTL);
303 
304 				// enable TVOCLKO (is this needed?)
305 				values->disp_tv_out_cntl |= RADEON_DISP_TV_CLKO_OUT_EN;
306 				break;
307 
308 			default:
309 				;
310 			}
311 		}
312 
313 	} else if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) {
314 		if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) {
315 			// disable clock of TV-out units
316 			values->tv_master_cntl =
317 				RADEON_TV_MASTER_CNTL_TV_ASYNC_RST |
318 				RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST |
319 				RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST |
320 				RADEON_TV_MASTER_CNTL_TVCLK_ALWAYS_ONb;
321 		}
322 	}
323 
324 	// choose CRTC for TV-DAC
325 	if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) {
326 		int crtc_idx = (display_devices[1] & (dd_tv_crt | dd_ctv | dd_stv)) != 0;
327 
328 		switch( ai->si->asic ) {
329 		case rt_ve:
330 		case rt_m6:
331 		case rt_rv200:
332 		case rt_m7:
333 		case rt_rv250:
334 		case rt_m9:
335 		case rt_rv280:
336 		case rt_m9plus:
337 		case rt_rs100:
338 		case rt_rs200:
339 			values->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
340 			// warning: meaning is wrong way around - 0 means crtc2, 1 means crtc1
341 			values->disp_hw_debug |= crtc_idx == 0 ? RADEON_CRT2_DISP1_SEL : 0;
342 			break;
343 
344 		case rt_r200:
345 			// TV-Out data comes directly from CRTC (i.e. with Linear Transform Unit)
346 			values->disp_output_cntl |= RADEON_DISP_TV_SOURCE;
347 			// choose CRTC
348 			values->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC;
349 			values->disp_tv_out_cntl |= crtc_idx == 0 ? 0 : RADEON_DISP_TV_PATH_SRC;
350 			break;
351 
352 		case rt_r300:
353 		case rt_r300_4p:
354 		case rt_rv350:
355 		case rt_m10:
356 		case rt_rv360:
357 		case rt_r350:
358 		case rt_r360:
359 			values->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
360 			values->disp_output_cntl |=
361 				crtc_idx == 0 ? 0 : RADEON_DISP_TVDAC_SOURCE_CRTC2;
362 			break;
363 
364 		case rt_r100:
365 			break;
366 		}
367 	}
368 
369 	// choose clock source for (internal) TV-out unit
370 	if( (total_devices & (dd_ctv | dd_stv)) != 0 ) {
371 		int crtc_idx = (display_devices[1] & (dd_ctv | dd_stv)) != 0;
372 
373 		values->pixclks_cntl &= ~RADEON_PIXCLK_TV_SRC_SEL_MASK;
374 		values->pixclks_cntl |= crtc_idx == 0 ?
375 			RADEON_PIXCLK_TV_SRC_SEL_PIXCLK : RADEON_PIXCLK_TV_SRC_SEL_PIX2CLK;
376 	}
377 
378 	// choose CRTC clock source;
379 	// normally, CRTC1 uses PLL1 and CRTC2 uses PLL2, but if an external TV-Out
380 	// chip is used, the clock is retrieved from this chip to stay in perfect sync
381 	if( (display_devices[0] & (dd_ctv | dd_stv)) != 0
382 		&& !IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
383 	{
384 		// select BYTCLK input pin as pixel src
385 		values->vclk_ecp_cntl &=
386 			~(RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_MASK | RADEON_VCLK_SRC_SEL_MASK);
387 
388 		values->vclk_ecp_cntl |= RADEON_VCLK_SRC_BYTE_CLK;
389 		values->vclk_ecp_cntl |= 0 << RADEON_VCLK_ECP_CNTL_BYTE_CLK_POST_DIV_SHIFT;
390 
391 		// disable clock if pixel format in CRTC_GEN_CNTL is zero;
392 		// disable (DAC?) during blank
393 		values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb;
394 
395 	} else {
396 		// select PLL as pixel clock
397 		values->vclk_ecp_cntl &= ~RADEON_VCLK_SRC_SEL_MASK;
398 		values->vclk_ecp_cntl |= RADEON_VCLK_SRC_PPLL_CLK;
399 
400 		// disable clock if pixel format in CRTC_GEN_CNTL is zero
401 		values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb;
402 	}
403 
404 	values->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
405 	if( (display_devices[1] & (dd_ctv | dd_stv)) != 0
406 		&& !IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
407 	{
408 		// r200 spec misses everything regarding second CRTC, so
409 		// this is guessing
410 		values->pixclks_cntl |= 2;
411 	} else
412 		values->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLL_CLK;
413 
414 	// choose CRTC for flat panel
415 	if( (total_devices & (dd_lvds | dd_dvi)) != 0 ) {
416 		int crtc_idx = (display_devices[1] & (dd_lvds | dd_dvi)) != 0;
417 
418 		values->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
419 		values->fp_gen_cntl |= crtc_idx == 0 ? 0 : RADEON_FP_SEL_CRTC2;
420 	}
421 
422 	// enable/disable RMX for crtc1 if there is a flat panel
423 	// (TODO: this doesn't seem to work)
424 	// !!! makes trouble on Radeon 9200 Mobility !??
425 	if( (display_devices[1] & (dd_lvds | dd_dvi)) != 0 ) {
426 		values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK;
427 		values->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_RMX;
428 	}
429 
430 
431 	// choose CRTC for secondary flat panel
432 	if( (total_devices & dd_dvi_ext) != 0 ) {
433 		int crtc_idx = (display_devices[1] & (dd_dvi_ext)) != 0;
434 
435 		// TODO: this list looks a bit magic/wrong for me; I reckon ATI moved the
436 		// bit starting with ASIC xxx, but I have no specs to verify that
437 		switch( ai->si->asic ) {
438 		case rt_r200:
439 		case rt_r300:
440 		case rt_r350:
441 		case rt_rv350:
442 		case rt_m10:
443 			values->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_CRTC2;
444 		    values->fp2_gen_cntl |=
445 		    	crtc_idx == 0 ? 0 : RADEON_FP2_SOURCE_SEL_CRTC2;
446 		    break;
447 
448 		default:
449 			values->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2;
450 			values->fp2_gen_cntl |=
451 				crtc_idx == 0 ? 0 : RADEON_FP2_SRC_SEL_CRTC2;
452 		}
453 	}
454 }
455 
456 void Radeon_ProgramMonitorRouting(
457 	accelerator_info *ai, routing_regs *values )
458 {
459 	vuint8 *regs = ai->regs;
460 
461 	OUTREG( regs, RADEON_DAC_CNTL, values->dac_cntl );
462 	OUTREG( regs, RADEON_DAC_CNTL2, values->dac_cntl2 );
463 	OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, values->crtc2_gen_cntl,
464 		~RADEON_CRTC2_CRT2_ON );
465 	OUTREG( regs, RADEON_DISP_OUTPUT_CNTL, values->disp_output_cntl );
466 
467 	switch( ai->si->asic ) {
468 	case rt_ve:
469 	case rt_m6:
470 	case rt_rv200:
471 	case rt_m7:
472 	case rt_rv250:
473 	case rt_m9:
474 	case rt_rv280:
475 	case rt_m9plus:
476 	case rt_rs100:
477 	case rt_rs200:
478 		OUTREG( regs, RADEON_DISP_HW_DEBUG, values->disp_hw_debug );
479 		break;
480 
481 	case rt_r200:
482 		OUTREG( regs, RADEON_DISP_TV_OUT_CNTL, values->disp_tv_out_cntl );
483 		break;
484 
485 	case rt_r300:
486 	case rt_r300_4p:
487 	case rt_rv350:
488 	case rt_m10:
489 	case rt_rv360:
490 	case rt_r350:
491 	case rt_r360:
492 		OUTREGP( regs, RADEON_GPIOPAD_A, values->gpiopad_a, ~1 );
493 		break;
494 
495 	case rt_r100:
496 		break;
497 	}
498 
499 	if( ai->si->asic > rt_r100 ) {
500 		// register introduced after R100;
501 		// only set it when necessary (more precisely: if TV-Out is used,
502 		// this register is set by the TV-Out code)
503 		if( !values->skip_tv_dac )
504 			OUTREG( regs, RADEON_TV_DAC_CNTL, values->tv_dac_cntl );
505 	}
506 
507 	if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
508 		OUTREG( regs, RADEON_TV_MASTER_CNTL, values->tv_master_cntl );
509 
510 	OUTREGP( regs, RADEON_FP_GEN_CNTL, values->fp_gen_cntl, ~(
511 		RADEON_FP_SEL_CRTC2 |
512 		RADEON_FP_RMX_HVSYNC_CONTROL_EN |
513 		RADEON_FP_DFP_SYNC_SEL |
514 		RADEON_FP_CRT_SYNC_SEL |
515 		RADEON_FP_CRTC_LOCK_8DOT |
516 		RADEON_FP_USE_SHADOW_EN |
517 		RADEON_FP_CRTC_USE_SHADOW_VEND |
518 		RADEON_FP_CRT_SYNC_ALT |
519 		RADEON_FP_CRTC_DONT_SHADOW_VPAR |
520 		RADEON_FP_CRTC_DONT_SHADOW_HEND ));
521 
522 
523 	OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
524 		~(RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 ));
525 
526 	if( ai->vc->used_crtc[0] ) {
527 		Radeon_OUTPLLP( ai->regs, ai->si->asic,
528 			RADEON_VCLK_ECP_CNTL, values->vclk_ecp_cntl,
529 			~RADEON_VCLK_SRC_SEL_MASK );
530 	}
531 
532 	if( ai->vc->used_crtc[1] ) {
533 		Radeon_OUTPLLP( ai->regs, ai->si->asic,
534 			RADEON_PIXCLKS_CNTL, values->pixclks_cntl,
535 			~RADEON_PIX2CLK_SRC_SEL_MASK );
536 	}
537 
538 	Radeon_OUTPLLP( ai->regs, ai->si->asic,
539 		RADEON_PIXCLKS_CNTL, values->pixclks_cntl,
540 		~RADEON_PIXCLK_TV_SRC_SEL_MASK );
541 
542 	// enable/disable CRTC1
543 	if( ai->vc->assigned_crtc[0] ) {
544 		uint32 crtc_gen_cntl;
545 
546 		crtc_gen_cntl = INREG( regs, RADEON_CRTC_GEN_CNTL );
547 
548 		if( ai->vc->used_crtc[0] ) {
549 			crtc_gen_cntl |= RADEON_CRTC_EN;
550 		} else {
551 			crtc_gen_cntl &= ~RADEON_CRTC_EN;
552 			crtc_gen_cntl &= ~RADEON_CRTC_PIX_WIDTH_MASK;
553 		}
554 
555 		OUTREGP( regs, RADEON_CRTC_GEN_CNTL, crtc_gen_cntl,
556 			~(RADEON_CRTC_PIX_WIDTH_MASK | RADEON_CRTC_EN) );
557 	}
558 
559 	// enable/disable CRTC2
560 	if( ai->vc->assigned_crtc[1] ) {
561 		uint32 crtc2_gen_cntl;
562 
563 		crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
564 
565 		if( ai->vc->used_crtc[1] ) {
566 			crtc2_gen_cntl |= RADEON_CRTC2_EN;
567 		} else {
568 			crtc2_gen_cntl &= ~RADEON_CRTC2_EN;
569 			crtc2_gen_cntl &= ~RADEON_CRTC2_PIX_WIDTH_MASK;
570 		}
571 
572 		OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl,
573 			~(RADEON_CRTC2_PIX_WIDTH_MASK | RADEON_CRTC2_EN) );
574 	}
575 
576 	// XFree says that crtc_ext_cntl must be restored after CRTC2 in dual-screen mode
577 	OUTREGP( regs, RADEON_CRTC_EXT_CNTL, values->crtc_ext_cntl,
578 		RADEON_CRTC_VSYNC_DIS |
579 		RADEON_CRTC_HSYNC_DIS |
580 		RADEON_CRTC_DISPLAY_DIS );
581 }
582 
583 
584 // internal version of SetupDefaultMonitorRouting;
585 // input and output are written to local variables
586 void assignDefaultMonitorRoute(
587 	accelerator_info *ai,
588 	display_device_e display_devices, int whished_num_heads, bool use_laptop_panel,
589 	display_device_e *crtc1, display_device_e *crtc2 )
590 {
591 	virtual_card *vc = ai->vc;
592 	display_device_e crtc1_displays = 0, crtc2_displays = 0;
593 
594 	SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d",
595 		display_devices, whished_num_heads );
596 
597 	// restrict to allowed devices
598 	display_devices &= ai->vc->controlled_displays;
599 
600 	// if CRTC1 is not ours, we cannot use flat panels
601 	if( !ai->vc->assigned_crtc[0] ) {
602 		display_devices &= ~(dd_lvds | dd_dvi);
603 	}
604 
605 	SHOW_FLOW( 2, "after restriction: %x", display_devices );
606 
607 	// flat panels get always connected to CRTC1 because its RMX unit
608 	if( (display_devices & dd_lvds) != 0 ) {
609 		// if user requests it, laptop panels are always used
610 		if( use_laptop_panel ) {
611 			crtc1_displays |= dd_lvds;
612 
613 		} else {
614 			// if he doesn't request it, we try to not use it
615 			display_device_e tmp_crtc1, tmp_crtc2;
616 			int effective_num_heads;
617 
618 			// determine routing with laptop panel ignored
619 			assignDefaultMonitorRoute( ai, display_devices & ~dd_lvds,
620 				whished_num_heads, use_laptop_panel, &tmp_crtc1, &tmp_crtc2 );
621 
622 			effective_num_heads = (tmp_crtc1 != 0) + (tmp_crtc2 != 0);
623 
624 			// only use laptop panel if we cannot satisfy the requested
625 			// number of heads without it
626 			if( effective_num_heads < whished_num_heads )
627 				crtc1_displays |= dd_lvds;
628 		}
629 
630 	} else if( (display_devices & dd_dvi) != 0 )
631 		crtc1_displays |= dd_dvi;
632 
633 	// TV-Out gets always connected to crtc2...
634 	if( (display_devices & dd_stv) != 0 )
635 		crtc2_displays |= dd_stv;
636 	else if( (display_devices & dd_ctv) != 0 )
637 		crtc2_displays |= dd_ctv;
638 
639 	// ...but if there is no crtc2, they win on crtc1;
640 	// if the user connects both a flat panel and a TV, he usually
641 	// wants to use the TV
642 	if( !vc->assigned_crtc[1] && crtc2_displays != 0 ) {
643 		crtc1_displays = crtc2_displays;
644 		crtc2_displays = dd_none;
645 	}
646 
647 	// if internal TV-Out is used, the DAC cannot drive a CRT at the same time
648 	if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ) && (display_devices & (dd_stv | dd_ctv)) != 0 )
649 		display_devices &= ~dd_tv_crt;
650 
651 	// CRT on CRT-DAC gets any spare CRTC;
652 	// if there is none, it can share CRTC with TV-Out;
653 	// this sharing may be dangerous as TV-Out uses strange timings, so
654 	// we should perhaps forbid sharing
655 	if( (display_devices & dd_crt) != 0 ) {
656 		if( crtc1_displays == 0 && vc->assigned_crtc[0] )
657 			crtc1_displays |= dd_crt;
658 		else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] )
659 			crtc2_displays |= dd_crt;
660 		else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] )
661 			crtc1_displays |= dd_crt;
662 		else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] )
663 			crtc2_displays |= dd_crt;
664 	}
665 
666 	// same applies to CRT on TV-DAC;
667 	// if we cannot find a CRTC, we could clone the content of the CRT-DAC,
668 	// but I doubt that you really want two CRTs showing the same
669 	if( (display_devices & dd_tv_crt) != 0 ) {
670 		if( crtc1_displays == 0 && vc->assigned_crtc[0] )
671 			crtc1_displays |= dd_tv_crt;
672 		else if( ai->si->num_crtc > 1 && crtc2_displays == 0 && vc->assigned_crtc[1] )
673 			crtc2_displays |= dd_tv_crt;
674 		else if( (crtc1_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[0] )
675 			crtc1_displays |= dd_tv_crt;
676 		else if( ai->si->num_crtc > 1 && (crtc2_displays & ~(dd_stv | dd_ctv)) == 0 && vc->assigned_crtc[1] )
677 			crtc2_displays |= dd_tv_crt;
678 	}
679 
680 	SHOW_FLOW( 3, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
681 
682 	*crtc1 = crtc1_displays;
683 	*crtc2 = crtc2_displays;
684 }
685 
686 // Setup sensible default monitor routing
687 // whished_num_heads - number of independant heads current display mode would need
688 // use_laptop_panel - if true, always use laptop panel
689 void Radeon_SetupDefaultMonitorRouting(
690 	accelerator_info *ai, int whished_num_heads, bool use_laptop_panel )
691 {
692 	virtual_card *vc = ai->vc;
693 	shared_info *si = ai->si;
694 	display_device_e display_devices = vc->connected_displays;
695 
696 	SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d, use_laptop_panel=%d",
697 		display_devices, whished_num_heads, use_laptop_panel );
698 
699 	// ignore TV if standard is set to "off"
700 	if( vc->tv_standard == ts_off )
701 		display_devices &= ~(dd_ctv | dd_stv);
702 
703 	assignDefaultMonitorRoute(
704 		ai, display_devices, whished_num_heads, use_laptop_panel,
705 		&si->crtc[0].chosen_displays, &si->crtc[1].chosen_displays );
706 
707 /*	si->crtc[0].chosen_displays = dd_none;
708 	si->crtc[1].chosen_displays = dd_tv_crt;*/
709 
710 	/*vc->used_crtc[0] = si->crtc[0].chosen_displays != dd_none;
711 	vc->used_crtc[1] = si->crtc[1].chosen_displays != dd_none;*/
712 
713 	SHOW_FLOW( 2, "num_crtc: %d, CRTC1 (%s): 0x%x, CRTC2 (%s): 0x%x",
714 		si->num_crtc,
715 		vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[0].chosen_displays,
716 		vc->assigned_crtc[0] ? "assigned" : "not assigned", si->crtc[1].chosen_displays );
717 }
718