📄 monitor_routing.c
字号:
/* Copyright (c) 2002-04, Thomas Kurschel Part of Radeon accelerant CRTC <-> display routing This stuff is highly ASIC dependant and is probably the most ASIC-specific code of the entire project.*/#include "radeon_accelerant.h"#include "../shared/mmio.h"#include "../regs/dac_regs.h"#include "../regs/fp_regs.h"#include "../regs/crtc_regs.h"#include "../regs/tv_out_regs.h"#include "../regs/pll_regs.h"#include "../regs/gpiopad_regs.h"#include "../shared/pll_access.h"#include "set_mode.h"// read regs needed for display device routingvoid Radeon_ReadMonitorRoutingRegs( accelerator_info *ai, routing_regs *values ){ vuint8 *regs = ai->regs; values->dac_cntl = INREG( regs, RADEON_DAC_CNTL ); values->dac_cntl2 = INREG( regs, RADEON_DAC_CNTL2 ); values->crtc_ext_cntl = INREG( regs, RADEON_CRTC_EXT_CNTL ); values->crtc2_gen_cntl = INREG( regs, RADEON_CRTC2_GEN_CNTL ); values->disp_output_cntl = INREG( regs, RADEON_DISP_OUTPUT_CNTL ); values->pixclks_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_PIXCLKS_CNTL ); values->vclk_ecp_cntl = Radeon_INPLL( ai->regs, ai->si->asic, RADEON_VCLK_ECP_CNTL ); switch( ai->si->asic ) { case rt_ve: case rt_m6: case rt_rv200: case rt_m7: case rt_rv250: case rt_m9: case rt_rv280: case rt_m9plus: case rt_rs100: case rt_rs200: values->disp_hw_debug = INREG( regs, RADEON_DISP_HW_DEBUG ); break; case rt_r200: values->disp_tv_out_cntl = INREG( regs, RADEON_DISP_TV_OUT_CNTL ); break; case rt_r300: case rt_r300_4p: case rt_rv350: case rt_m10: case rt_rv360: case rt_r350: case rt_r360: values->gpiopad_a = INREG( regs, RADEON_GPIOPAD_A ); break; case rt_r100: break; } if( ai->si->asic > rt_r100 ) { // register introduced after R100 values->tv_dac_cntl = INREG( regs, RADEON_TV_DAC_CNTL ); } if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) values->tv_master_cntl = INREG( regs, RADEON_TV_MASTER_CNTL ); values->fp_gen_cntl = INREG( regs, RADEON_FP_GEN_CNTL ); values->fp2_gen_cntl = INREG( regs, RADEON_FP2_GEN_CNTL );}// setup register contents to proper CRTC <-> display device mappingvoid Radeon_CalcMonitorRouting( accelerator_info *ai, const impactv_params *tv_parameters, routing_regs *values ){ display_device_e display_devices[2], total_devices, controlled_devices; if( ai->vc->used_crtc[0] ) display_devices[0] = ai->si->crtc[0].chosen_displays; else display_devices[0] = dd_none; if( ai->vc->used_crtc[1] ) display_devices[1] = ai->si->crtc[1].chosen_displays; else display_devices[1] = dd_none; total_devices = display_devices[0] | display_devices[1]; controlled_devices = ai->vc->controlled_displays; // enable 8 bit DAC // (could be moved to boot initialization) values->dac_cntl |= RADEON_DAC_MASK_ALL | RADEON_DAC_VGA_ADR_EN | RADEON_DAC_8BIT_EN; // enable frame buffer access and extended CRTC counter // (again: something for boot init.) values->crtc_ext_cntl = RADEON_VGA_ATI_LINEAR | RADEON_XCRT_CNT_EN; // set VGA signal style (not sure whether this affects // CRTC1 or CRT-DAC, so we better always set it) values->dac_cntl &= ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_BLANKING); values->dac_cntl |= RADEON_DAC_RANGE_CNTL_PS2; // disable all the magic CRTC shadowing values->fp_gen_cntl &= ~(RADEON_FP_RMX_HVSYNC_CONTROL_EN | RADEON_FP_DFP_SYNC_SEL | RADEON_FP_CRT_SYNC_SEL | RADEON_FP_CRTC_LOCK_8DOT | RADEON_FP_USE_SHADOW_EN | RADEON_FP_CRTC_USE_SHADOW_VEND | RADEON_FP_CRT_SYNC_ALT); values->fp_gen_cntl |= RADEON_FP_CRTC_DONT_SHADOW_VPAR | RADEON_FP_CRTC_DONT_SHADOW_HEND; // route VGA-DAC if( (total_devices & dd_crt) != 0 ) { int crtc_idx = (display_devices[1] & dd_crt) != 0; // the CRT_ON flag seems to directly affect the CRT-DAC, _not_ the CRTC1 signal values->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; switch( ai->si->asic ) { case rt_ve: case rt_m6: case rt_rv200: case rt_m7: case rt_rv250: case rt_m9: case rt_rv280: case rt_m9plus: case rt_rs100: case rt_rs200: values->dac_cntl2 &= ~RADEON_DAC_CLK_SEL_MASK; values->dac_cntl2 |= crtc_idx == 0 ? 0 : RADEON_DAC_CLK_SEL_CRTC2; break; case rt_r200: case rt_r300: case rt_r300_4p: case rt_rv350: case rt_m10: case rt_rv360: case rt_r350: case rt_r360: values->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; values->disp_output_cntl |= (crtc_idx == 0 ? 0 : RADEON_DISP_DAC_SOURCE_CRTC2); break; case rt_r100: break; } } else if( (controlled_devices & dd_crt) != 0 ) { values->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; } if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) { // power down TV-DAC // (but only if TV-Out _and_ TV-CRT is controlled by us) // this will be undone if needed values->tv_dac_cntl |= RADEON_TV_DAC_CNTL_RDACPD | RADEON_TV_DAC_CNTL_GDACPD | RADEON_TV_DAC_CNTL_BDACPD; } // set CRT mode of TV-DAC if needed // (doesn't work on r200, but there is no TV-DAC used for CRT anyway) if( (total_devices & dd_tv_crt) != 0 ) { // enable CRT via TV-DAC (ignored if TV-DAC is in TV-Out mode) values->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK; values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_CRT; // enable TV-DAC and set PS2 signal level values->tv_dac_cntl = RADEON_TV_DAC_CNTL_NBLANK | RADEON_TV_DAC_CNTL_NHOLD | RADEON_TV_DAC_CNTL_STD_PS2 | (8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) | (2 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT); // at least r300 needs magic bit set to switch between TV-CRT and TV-Out switch( ai->si->asic ) { case rt_r200: case rt_r300: case rt_r300_4p: case rt_rv350: case rt_m10: case rt_rv360: case rt_r350: case rt_r360: values->gpiopad_a |= 1; break; default: ; } } else if( (controlled_devices & dd_tv_crt) != 0 ) { values->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; } values->skip_tv_dac = false; // disable forwarding data to TV-Out unit // (will be enabled on demand later on) if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) values->dac_cntl &= ~RADEON_DAC_TVO_EN; // set TV mode of TV-DAC if needed if( (total_devices & (dd_ctv | dd_stv)) != 0 ) { // see above values->dac_cntl2 &= ~RADEON_DAC2_CLK_SEL_MASK; values->dac_cntl2 |= RADEON_DAC2_CLK_SEL_TV; // at least r300 needs magic bit set to switch between TV-CRT and TV-Out switch( ai->si->asic ) { case rt_r200: case rt_r300: case rt_r300_4p: case rt_rv350: case rt_rv360: case rt_m10: case rt_r350: case rt_r360: values->gpiopad_a &= ~1; break; default: ; } // the TV-DAC itself is under control of the TV-Out code values->skip_tv_dac = true; if( !IS_INTERNAL_TV_OUT( ai->si->tv_chip )) { // tell DAC to forward data to external chip values->dac_cntl |= RADEON_DAC_TVO_EN; // set Output Linear Transform Unit as source // (TODO: is this unit initialized properly?) // disable overlay sync (could be a good idea to enable it) // set 8 BPP mode values->disp_output_cntl &= ~(RADEON_DISP_TV_SOURCE | RADEON_DISP_TV_MODE_MASK | RADEON_DISP_TV_YG_DITH_EN | RADEON_DISP_TV_CBB_CRR_DITH_EN | RADEON_DISP_TV_BIT_WIDTH | RADEON_DISP_TV_SYNC_MODE_MASK | RADEON_DISP_TV_SYNC_COLOR_MASK); // enable dithering values->disp_output_cntl |= RADEON_DISP_TV_YG_DITH_EN | RADEON_DISP_TV_CBB_CRR_DITH_EN; // set output data format values->disp_output_cntl |= tv_parameters->mode888 ? RADEON_DISP_TV_MODE_888 : RADEON_DISP_TV_MODE_565; switch( ai->si->asic ) { case rt_r200: // disable downfiltering and scaling, set RGB mode, // don't transmit overlay indicator; // I don't really know whether this is a good choice values->disp_tv_out_cntl &= (RADEON_DISP_TV_OUT_YG_FILTER_MASK | RADEON_DISP_TV_OUT_YG_SAMPLE | RADEON_DISP_TV_OUT_CrR_FILTER_MASK | RADEON_DISP_TV_OUT_CrR_SAMPLE | RADEON_DISP_TV_OUT_CbB_FILTER_MASK | RADEON_DISP_TV_OUT_CbB_SAMPLE | RADEON_DISP_TV_SUBSAMPLE_CNTL_MASK | RADEON_DISP_TV_H_DOWNSCALE | RADEON_DISP_TV_COLOR_SPACE | RADEON_DISP_TV_DITH_MODE | RADEON_DISP_TV_DATA_ZERO_SEL | RADEON_DISP_TV_CLKO_SEL | RADEON_DISP_TV_CLKO_OUT_EN | RADEON_DISP_TV_DOWNSCALE_CNTL); // enable TVOCLKO (is this needed?) values->disp_tv_out_cntl |= RADEON_DISP_TV_CLKO_OUT_EN; break; default: ; } } } else if( (controlled_devices & (dd_ctv | dd_stv)) != 0 ) { if( IS_INTERNAL_TV_OUT( ai->si->tv_chip )) { // disable clock of TV-out units values->tv_master_cntl = RADEON_TV_MASTER_CNTL_TV_ASYNC_RST | RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST | RADEON_TV_MASTER_CNTL_TV_FIFO_ASYNC_RST | RADEON_TV_MASTER_CNTL_TVCLK_ALWAYS_ONb; } } // choose CRTC for TV-DAC if( (total_devices & (dd_tv_crt | dd_ctv | dd_stv)) != 0 ) { int crtc_idx = (display_devices[1] & (dd_tv_crt | dd_ctv | dd_stv)) != 0; switch( ai->si->asic ) { case rt_ve: case rt_m6: case rt_rv200: case rt_m7: case rt_rv250: case rt_m9: case rt_rv280: case rt_m9plus: case rt_rs100: case rt_rs200: values->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; // warning: meaning is wrong way around - 0 means crtc2, 1 means crtc1 values->disp_hw_debug |= crtc_idx == 0 ? RADEON_CRT2_DISP1_SEL : 0; break; case rt_r200: // TV-Out data comes directly from CRTC (i.e. with Linear Transform Unit) values->disp_output_cntl |= RADEON_DISP_TV_SOURCE; // choose CRTC values->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC; values->disp_tv_out_cntl |= crtc_idx == 0 ? 0 : RADEON_DISP_TV_PATH_SRC; break; case rt_r300: case rt_r300_4p: case rt_rv350: case rt_m10: case rt_rv360: case rt_r350: case rt_r360: values->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -