📄 internal_tv_out.c
字号:
/* Copyright (c) 2002/03, Thomas Kurschel Part of Radeon accelerant Programming of internal TV-out unit*/#include "radeon_interface.h"#include "radeon_accelerant.h"#include "../regs/tv_out_regs.h"#include "../shared/pll_access.h"#include "../shared/mmio.h"#include "utils.h"#include "set_mode.h"// mapping of offset in impactv_regs to register address typedef struct register_mapping { uint16 address; // register address uint16 offset; // offset in impactv_regs} register_mapping;// internal TV-encoder:// registers to write before programming PLLstatic const register_mapping intern_reg_mapping_before_pll[] = { { RADEON_TV_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) }, { RADEON_TV_HRESTART, offsetof( impactv_regs, tv_hrestart ) }, { RADEON_TV_VRESTART, offsetof( impactv_regs, tv_vrestart ) }, { RADEON_TV_FRESTART, offsetof( impactv_regs, tv_frestart ) }, { RADEON_TV_FTOTAL, offsetof( impactv_regs, tv_ftotal ) }, { 0, 0 }};// PLL registers to programstatic const register_mapping intern_reg_mapping_pll[] = { { RADEON_TV_PLL_CNTL, offsetof( impactv_regs, tv_tv_pll_cntl ) }, { RADEON_TV_PLL_CNTL1, offsetof( impactv_regs, tv_pll_cntl1 ) }, { RADEON_TV_PLL_FINE_CNTL, offsetof( impactv_regs, tv_pll_fine_cntl ) }, { 0, 0 }};// registers to write after programming of PLLstatic const register_mapping intern_reg_mapping_after_pll[] = { { RADEON_TV_HTOTAL, offsetof( impactv_regs, tv_htotal ) }, { RADEON_TV_HDISP, offsetof( impactv_regs, tv_hdisp ) }, { RADEON_TV_HSTART, offsetof( impactv_regs, tv_hstart ) }, { RADEON_TV_VTOTAL, offsetof( impactv_regs, tv_vtotal ) }, { RADEON_TV_VDISP, offsetof( impactv_regs, tv_vdisp ) }, { RADEON_TV_TIMING_CNTL, offsetof( impactv_regs, tv_timing_cntl ) }, { RADEON_TV_VSCALER_CNTL1, offsetof( impactv_regs, tv_vscaler_cntl1 ) }, { RADEON_TV_VSCALER_CNTL2, offsetof( impactv_regs, tv_vscaler_cntl2 ) }, { RADEON_TV_Y_SAW_TOOTH_CNTL, offsetof( impactv_regs, tv_y_saw_tooth_cntl ) }, { RADEON_TV_Y_RISE_CNTL, offsetof( impactv_regs, tv_y_rise_cntl ) }, { RADEON_TV_Y_FALL_CNTL, offsetof( impactv_regs, tv_y_fall_cntl ) }, { RADEON_TV_MODULATOR_CNTL1, offsetof( impactv_regs, tv_modulator_cntl1 ) }, { RADEON_TV_MODULATOR_CNTL2, offsetof( impactv_regs, tv_modulator_cntl2 ) }, { RADEON_TV_RGB_CNTL, offsetof( impactv_regs, tv_rgb_cntl ) }, { RADEON_TV_UV_ADR, offsetof( impactv_regs, tv_uv_adr ) }, { RADEON_TV_PRE_DAC_MUX_CNTL, offsetof( impactv_regs, tv_pre_dac_mux_cntl ) }, { RADEON_TV_CRC_CNTL, offsetof( impactv_regs, tv_crc_cntl ) }, { 0, 0 }};// registers to write when things settled downstatic const register_mapping intern_reg_mapping_finish[] = { { RADEON_TV_GAIN_LIMIT_SETTINGS, offsetof( impactv_regs, tv_gain_limit_settings ) }, { RADEON_TV_LINEAR_GAIN_SETTINGS, offsetof( impactv_regs, tv_linear_gain_settings ) }, { RADEON_TV_UPSAMP_AND_GAIN_CNTL, offsetof( impactv_regs, tv_upsamp_and_gain_cntl ) }, { RADEON_TV_DAC_CNTL, offsetof( impactv_regs, tv_dac_cntl ) }, { RADEON_TV_MASTER_CNTL, offsetof( impactv_regs, tv_master_cntl ) }, { 0, 0 }};// write list of MM I/O registersstatic void writeMMIORegList( accelerator_info *ai, impactv_regs *values, const register_mapping *mapping ){ vuint8 *regs = ai->regs; for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) { /*SHOW_FLOW( 2, "%x=%x", mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );*/ OUTREG( regs, mapping->address, *(uint32 *)((char *)(values) + mapping->offset) ); } //snooze( 1000000 );}// write list of PLL registersstatic void writePLLRegList( accelerator_info *ai, impactv_regs *values, const register_mapping *mapping ){ for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) { /*SHOW_FLOW( 2, "%x=%x", mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );*/ Radeon_OUTPLL( ai->regs, ai->si->asic, mapping->address, *(uint32 *)((char *)(values) + mapping->offset) ); } //snooze( 1000000 );}// read timing FIFOstatic uint32 Radeon_InternalTVOutReadFIFO( accelerator_info *ai, uint16 addr ){ vuint8 *regs = ai->regs; bigtime_t start_time; uint32 res = ~0; //SHOW_FLOW( 2, "addr=%d", addr ); OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_RD); start_time = system_time(); do { uint32 status; status = INREG( regs, RADEON_TV_HOST_RD_WT_CNTL ); if( (status & RADEON_TV_HOST_RD_WT_CNTL_RD_ACK) != 0 ) break; } while( system_time() - start_time < 2000000 ); OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, 0); res = INREG( regs, RADEON_TV_HOST_READ_DATA ); //SHOW_FLOW( 2, "res=%x %x", res >> 14, res & 0x3fff ); return res;}// write to timing FIFOstatic void Radeon_InternalTVOutWriteFIFO( accelerator_info *ai, uint16 addr, uint32 value ){ vuint8 *regs = ai->regs; bigtime_t start_time; //readFIFO( ai, addr, internal_encoder ); //SHOW_FLOW( 2, "addr=%d, value=%x %x", addr, value >> 14, value & 0x3fff ); OUTREG( regs, RADEON_TV_HOST_WRITE_DATA, value ); OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_TV_HOST_RD_WT_CNTL_WT ); start_time = system_time(); do { uint32 status; status = INREG( regs, RADEON_TV_HOST_RD_WT_CNTL ); if( (status & RADEON_TV_HOST_RD_WT_CNTL_WT_ACK) != 0 ) break; } while( system_time() - start_time < 2000000 ); OUTREG( regs, RADEON_TV_HOST_RD_WT_CNTL, 0 );}// program TV-Out registersvoid Radeon_InternalTVOutProgramRegisters( accelerator_info *ai, impactv_regs *values ){ uint32 orig_tv_master_cntl = values->tv_master_cntl; SHOW_FLOW0( 2, "" ); // disable TV-out when registers are setup // it gets enabled again when things have settled down 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_VIN_ASYNC_RST | RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST | RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST; writeMMIORegList( ai, values, intern_reg_mapping_before_pll ); writePLLRegList( ai, values, intern_reg_mapping_pll ); writeMMIORegList( ai, values, intern_reg_mapping_after_pll ); // un-reset FIFO to access timing table OUTREG( ai->regs, RADEON_TV_MASTER_CNTL, orig_tv_master_cntl | RADEON_TV_MASTER_CNTL_TV_ASYNC_RST | RADEON_TV_MASTER_CNTL_CRT_ASYNC_RST | RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST | RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST | RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST ); Radeon_ImpacTVwriteHorTimingTable( ai, Radeon_InternalTVOutWriteFIFO, values, true ); Radeon_ImpacTVwriteVertTimingTable( ai, Radeon_InternalTVOutWriteFIFO, values ); snooze( 50000 ); values->tv_master_cntl = orig_tv_master_cntl; writeMMIORegList( ai, values, intern_reg_mapping_finish );}// read list of MM I/O registersstatic void readMMIORegList( accelerator_info *ai, impactv_regs *values, const register_mapping *mapping ){ vuint8 *regs = ai->regs; for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) { *(uint32 *)((char *)(values) + mapping->offset) = INREG( regs, mapping->address ); /*SHOW_FLOW( 2, "%x=%x", mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );*/ } //snooze( 1000000 );}// read list of PLL registersstatic void readPLLRegList( accelerator_info *ai, impactv_regs *values, const register_mapping *mapping ){ for( ; mapping->address != 0 && mapping->offset != 0; ++mapping ) { *(uint32 *)((char *)(values) + mapping->offset) = Radeon_INPLL( ai->regs, ai->si->asic, mapping->address ); /*SHOW_FLOW( 2, "%x=%x", mapping->address, *(uint32 *)((char *)(values) + mapping->offset) );*/ } //snooze( 1000000 );}// read TV-Out registersvoid Radeon_InternalTVOutReadRegisters( accelerator_info *ai, impactv_regs *values ){ readMMIORegList( ai, values, intern_reg_mapping_before_pll ); readPLLRegList( ai, values, intern_reg_mapping_pll ); readMMIORegList( ai, values, intern_reg_mapping_after_pll ); readMMIORegList( ai, values, intern_reg_mapping_finish ); //snooze( 1000000 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -