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