vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / accelerants / radeon / monitor_routing.c
blob08be63afe33e6541c889934703dc8066bc29f66f
1 /*
2 Copyright (c) 2002-04, Thomas Kurschel
5 Part of Radeon accelerant
7 CRTC <-> display routing
9 This stuff is highly ASIC dependant and is probably the most ASIC-specific
10 code of the entire project.
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"
25 // read regs needed for display device routing
26 void Radeon_ReadMonitorRoutingRegs(
27 accelerator_info *ai, routing_regs *values )
29 vuint8 *regs = ai->regs;
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 );
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;
50 case rt_r200:
51 values->disp_tv_out_cntl = INREG( regs, RADEON_DISP_TV_OUT_CNTL );
52 break;
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;
62 case rt_r100:
63 break;
66 if( ai->si->asic > rt_r100 ) {
67 // register introduced after R100
68 values->tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL );
71 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
72 values->tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL );
74 values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL );
75 values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );
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 )
83 display_device_e display_devices[2], total_devices, controlled_devices;
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;
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;
95 total_devices = display_devices[0] | display_devices[1];
96 controlled_devices = ai->vc->controlled_displays;
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;
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;
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;
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;
126 // route VGA-DAC
127 if( (total_devices & dd_crt) != 0 ) {
128 int crtc_idx = (display_devices[1] & dd_crt) != 0;
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;
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;
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;
156 case rt_r100:
157 break;
160 } else if( (controlled_devices & dd_crt) != 0 ) {
161 values->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON;
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;
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;
182 values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK;
183 values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_CRT;
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);
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;
197 } else if( (controlled_devices & dd_tv_crt) != 0 ) {
198 values->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
201 values->skip_tv_dac = false;
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;
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;
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;
221 // the TV-DAC itself is under control of the TV-Out code
222 values->skip_tv_dac = true;
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;
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);
241 // enable dithering
242 values->disp_output_cntl |=
243 RADEON_DISP_TV_YG_DITH_EN |
244 RADEON_DISP_TV_CBB_CRR_DITH_EN;
246 // set output data format
247 values->disp_output_cntl |= tv_parameters->mode888 ?
248 RADEON_DISP_TV_MODE_888 : RADEON_DISP_TV_MODE_565;
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);
271 // enable TVOCLKO (is this needed?)
272 values->disp_tv_out_cntl |= RADEON_DISP_TV_CLKO_OUT_EN;
273 break;
275 default:
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;
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;
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;
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;
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;
326 case rt_r100:
327 break;
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;
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;
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 ))
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);
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;
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;
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;
362 // disable clock if pixel format in CRTC_GEN_CNTL is zero
363 values->vclk_ecp_cntl |= RADEON_PIXCLK_ALWAYS_ONb;
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 ))
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;
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;
380 values->fp_gen_cntl &= ~RADEON_FP_SEL_CRTC2;
381 values->fp_gen_cntl |= crtc_idx == 0 ? 0 : RADEON_FP_SEL_CRTC2;
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;
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;
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;
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;
419 void Radeon_ProgramMonitorRouting(
420 accelerator_info *ai, routing_regs *values )
422 vuint8 *regs = ai->regs;
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 );
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;
441 case rt_r200:
442 OUTREG( regs, RADEON_DISP_TV_OUT_CNTL, values->disp_tv_out_cntl );
443 break;
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;
453 case rt_r100:
454 break;
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 );
465 if( IS_INTERNAL_TV_OUT( ai->si->tv_chip ))
466 OUTREG( regs, RADEON_TV_MASTER_CNTL, values->tv_master_cntl );
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 ));
481 OUTREGP( regs, RADEON_FP2_GEN_CNTL, values->fp2_gen_cntl,
482 ~(RADEON_FP2_SOURCE_SEL_CRTC2 | RADEON_FP2_SRC_SEL_CRTC2 ));
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 );
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 );
496 Radeon_OUTPLLP( ai->regs, ai->si->asic,
497 RADEON_PIXCLKS_CNTL, values->pixclks_cntl,
498 ~RADEON_PIXCLK_TV_SRC_SEL_MASK );
500 // enable/disable CRTC1
501 if( ai->vc->assigned_crtc[0] ) {
502 uint32 crtc_gen_cntl;
504 crtc_gen_cntl = INREG( regs, RADEON_CRTC_GEN_CNTL );
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;
513 OUTREGP( regs, RADEON_CRTC_GEN_CNTL, crtc_gen_cntl,
514 ~(RADEON_CRTC_PIX_WIDTH_MASK | RADEON_CRTC_EN) );
517 // enable/disable CRTC2
518 if( ai->vc->assigned_crtc[1] ) {
519 uint32 crtc2_gen_cntl;
521 crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL );
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;
530 OUTREGP( regs, RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl,
531 ~(RADEON_CRTC2_PIX_WIDTH_MASK | RADEON_CRTC2_EN) );
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 );
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 )
549 virtual_card *vc = ai->vc;
550 display_device_e crtc1_displays = 0, crtc2_displays = 0;
552 SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d",
553 display_devices, whished_num_heads );
555 // restrict to allowed devices
556 display_devices &= ai->vc->controlled_displays;
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);
563 SHOW_FLOW( 2, "after restriction: %x", display_devices );
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;
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;
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 );
580 effective_num_heads = (tmp_crtc1 != 0) + (tmp_crtc2 != 0);
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;
588 } else if( (display_devices & dd_dvi) != 0 )
589 crtc1_displays |= dd_dvi;
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;
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;
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;
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;
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;
638 if( (display_devices & dd_dvi_ext) != 0 )
639 crtc2_displays |= dd_dvi_ext;
641 SHOW_FLOW( 2, "CRTC1: 0x%x, CRTC2: 0x%x", crtc1_displays, crtc2_displays );
643 *crtc1 = crtc1_displays;
644 *crtc2 = crtc2_displays;
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 )
653 virtual_card *vc = ai->vc;
654 shared_info *si = ai->si;
655 display_device_e display_devices = vc->connected_displays;
657 if (ai->si->settings.force_lcd) {
658 use_laptop_panel = true;
659 SHOW_FLOW0( 2, "LCD Forced Used by Kernel Settings");
662 SHOW_FLOW( 2, "display_devices=%x, whished_num_heads=%d, use_laptop_panel=%d",
663 display_devices, whished_num_heads, use_laptop_panel );
665 // ignore TV if standard is set to "off"
666 if( vc->tv_standard == ts_off )
667 display_devices &= ~(dd_ctv | dd_stv);
669 assignDefaultMonitorRoute(
670 ai, display_devices, whished_num_heads, use_laptop_panel,
671 &si->crtc[0].chosen_displays, &si->crtc[1].chosen_displays );
673 /* si->crtc[0].chosen_displays = dd_none;
674 si->crtc[1].chosen_displays = dd_tv_crt;*/
676 /*vc->used_crtc[0] = si->crtc[0].chosen_displays != dd_none;
677 vc->used_crtc[1] = si->crtc[1].chosen_displays != dd_none;*/
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 );