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
26void 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
80void 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
419void 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
544static 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
650void 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