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