⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 impactv.c

📁 ati driver
💻 C
📖 第 1 页 / 共 2 页
字号:
// as a result, you must not call Radeon_CalcPLLRegisters() afterwards// TBD: what's special in terms of PLL in TV-Out mode?void Radeon_CalcImpacTVRegisters( 	accelerator_info *ai, display_mode *mode, 	impactv_params *params, impactv_regs *values, int crtc_idx, 	bool internal_encoder, tv_standard_e tv_format, display_device_e display_device ){	const tv_timing *timing = &params->timing;		SHOW_FLOW0( 2, "" );		if( tv_format < ts_ntsc || tv_format > ts_max )		tv_format = ts_ntsc;		values->tv_ftotal = timing->f_total;		// RE: UV_THINNER should affect sharpness only, but the only effect is that	// the colour fades out, so I leave it zero	values->tv_vscaler_cntl1 = RADEON_TV_VSCALER_CNTL1_Y_W_EN;		values->tv_vscaler_cntl1 = 		(values->tv_vscaler_cntl1 & 0xe3ff0000) |		params->uv_inc;			if( internal_encoder ) {		// RE: was on - update: disabling it breaks restart		values->tv_vscaler_cntl1 |= RADEON_TV_VSCALER_CNTL1_RESTART_FIELD;		if( mode->timing.h_display == 1024 )			values->tv_vscaler_cntl1 |= 4 << RADEON_TV_VSCALER_CNTL1_Y_DEL_W_SIG_SHIFT;		else			values->tv_vscaler_cntl1 |= 2 << RADEON_TV_VSCALER_CNTL1_Y_DEL_W_SIG_SHIFT;	} else {		values->tv_vscaler_cntl1 |= 2 << RADEON_TV_VSCALER_CNTL1_Y_DEL_W_SIG_SHIFT;	}		values->tv_y_saw_tooth_cntl =		params->y_saw_tooth_amp |		(params->y_saw_tooth_slope << RADEON_TV_Y_SAW_TOOTH_CNTL_SLOPE_SHIFT);		values->tv_y_fall_cntl =		params->y_fall_accum_init |		RADEON_TV_Y_FALL_CNTL_Y_FALL_PING_PONG |		(params->y_coeff_enable ? RADEON_TV_Y_FALL_CNTL_Y_COEFF_EN : 0) |		(params->y_coeff_value << RADEON_TV_Y_FALL_CNTL_Y_COEFF_VALUE_SHIFT);			values->tv_y_rise_cntl = 		params->y_rise_accum_init |		RADEON_TV_Y_RISE_CNTL_Y_RISE_PING_PONG;	// RE: all dither flags/values were zero	values->tv_vscaler_cntl2 =		(values->tv_vscaler_cntl2 & 0x00fffff0) | 		(params->uv_accum_init << RADEON_TV_VSCALER_CNTL2_UV_ACCUM_INIT_SHIFT);			if( internal_encoder ) {		values->tv_vscaler_cntl2 |= 			RADEON_TV_VSCALER_CNTL2_DITHER_MODE |			RADEON_TV_VSCALER_CNTL2_Y_OUTPUT_DITHER_EN |			RADEON_TV_VSCALER_CNTL2_UV_OUTPUT_DITHER_EN |			RADEON_TV_VSCALER_CNTL2_UV_TO_BUF_DITHER_EN;	}	values->tv_hrestart = params->h_restart;	values->tv_vrestart = params->v_restart;	values->tv_frestart = params->f_restart;		values->tv_tv_pll_cntl = 		(params->tv_dividers.ref & RADEON_TV_PLL_CNTL_TV_M0_LO_MASK) |		((params->tv_dividers.feedback & RADEON_TV_PLL_CNTL_TV_N0_LO_MASK) 			<< RADEON_TV_PLL_CNTL_TV_N0_LO_SHIFT) |		((params->tv_dividers.ref >> RADEON_TV_PLL_CNTL_TV_M0_LO_BITS) 			<< RADEON_TV_PLL_CNTL_TV_M0_HI_SHIFT) |		((params->tv_dividers.feedback >> RADEON_TV_PLL_CNTL_TV_N0_LO_BITS) 			<< RADEON_TV_PLL_CNTL_TV_N0_HI_SHIFT) |		// RE: was on		//RADEON_TV_PLL_CNTL_TV_SLIP_EN |		(params->tv_dividers.post << RADEON_TV_PLL_CNTL_TV_P_SHIFT); //|		// RE: was on		//RADEON_TV_PLL_CNTL_TV_DTO_EN;	values->tv_crt_pll_cntl = 		(params->crt_dividers.ref & RADEON_TV_CRT_PLL_CNTL_M0_LO_MASK) |		((params->crt_dividers.feedback & RADEON_TV_CRT_PLL_CNTL_N0_LO_MASK) 			<< RADEON_TV_CRT_PLL_CNTL_N0_LO_SHIFT) |		((params->crt_dividers.ref >> RADEON_TV_CRT_PLL_CNTL_M0_LO_BITS) 			<< RADEON_TV_CRT_PLL_CNTL_M0_HI_SHIFT) |		((params->crt_dividers.feedback >> RADEON_TV_CRT_PLL_CNTL_N0_LO_BITS) 			<< RADEON_TV_CRT_PLL_CNTL_N0_HI_SHIFT) |		(params->crt_dividers.extra_post == 2 ? RADEON_TV_CRT_PLL_CNTL_CLKBY2 : 0);	// TK: from Gatos	// in terms of byte clock devider, I have no clue how that works, 	// but leaving it 1 seems to be save	values->tv_clock_sel_cntl = 		0x33 |		((/*params->crt_dividers.post_code - 1*/0) << RADEON_TV_CLOCK_SEL_CNTL_BYTCLK_SHIFT) |		(1 << RADEON_TV_CLOCK_SEL_CNTL_BYTCLKD_SHIFT);        values->tv_clkout_cntl = 0x09;    if( !internal_encoder )    	values->tv_clkout_cntl |= 1 << 5;	values->tv_htotal = mode->timing.h_total - 1;	values->tv_hsize = mode->timing.h_display;	values->tv_hdisp = mode->timing.h_display - 1;	values->tv_hstart =		// TK: was -12, but this cuts off the left border of the image		internal_encoder ? 		values->tv_hdisp + 1 - params->mode888 + 12 :		values->tv_hdisp + 1 - params->mode888 + 12;			values->tv_vtotal = mode->timing.v_total - 1;	values->tv_vdisp = mode->timing.v_display - 1;	values->tv_sync_size = mode->timing.h_display + 8;	values->tv_timing_cntl = 		(values->tv_timing_cntl & 0xfffff000) |		params->h_inc;		if( ai->si->asic >= rt_r300 ) {		// this is a hack to fix improper UV scaling		// (at least this is what the sample code says)		values->tv_timing_cntl =			(values->tv_timing_cntl & 0x00ffffff) |			((0x72 * 640 / mode->timing.h_display) 				<< RADEON_TV_TIMING_CNTL_UV_OUTPUT_POST_SCALE_SHIFT);	}		if( internal_encoder ) {		// tell TV-DAC to generate proper NTSC/PAL signal		values->tv_dac_cntl =			RADEON_TV_DAC_CNTL_NBLANK |			RADEON_TV_DAC_CNTL_NHOLD |			(8 << RADEON_TV_DAC_CNTL_BGADJ_SHIFT) |			(6 << RADEON_TV_DAC_CNTL_DACADJ_SHIFT);					switch( tv_format ) {		case ts_ntsc:			values->tv_dac_cntl |= RADEON_TV_DAC_CNTL_STD_NTSC;			break;					case ts_pal_bdghi:		case ts_pal_m:		case ts_pal_nc:		case ts_scart_pal:		case ts_pal_60:			values->tv_dac_cntl |= RADEON_TV_DAC_CNTL_STD_PAL;			break;		default:		}				// enable composite or S-Video DAC		values->tv_dac_cntl |=			RADEON_TV_DAC_CNTL_RDACPD |			RADEON_TV_DAC_CNTL_GDACPD |			RADEON_TV_DAC_CNTL_BDACPD;					if( (display_device & dd_ctv) != 0 ) {			values->tv_dac_cntl &=				~RADEON_TV_DAC_CNTL_BDACPD;		}				if( (display_device & dd_stv) != 0 ) {			values->tv_dac_cntl &= 				~(RADEON_TV_DAC_CNTL_RDACPD |				  RADEON_TV_DAC_CNTL_GDACPD);		}	} else {		values->tv_dac_cntl =			(values->tv_dac_cntl & ~(RADEON_TV_DAC_CNTL_STD_NTSC | 0x88 | 				RADEON_TV_DAC_CNTL_BGSLEEP | RADEON_TV_DAC_CNTL_PEDESTAL)) |			RADEON_TV_DAC_CNTL_DETECT | 			RADEON_TV_DAC_CNTL_NBLANK |			RADEON_TV_DAC_CNTL_NHOLD;	}	values->tv_modulator_cntl1 &= ~(		RADEON_TV_MODULATOR_CNTL1_ALT_PHASE_EN | 		RADEON_TV_MODULATOR_CNTL1_SYNC_TIP_LEVEL | 		RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_MASK | 		RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_MASK);				switch( tv_format ) {	case ts_ntsc:		// RE: typo?		//values->tv_dac_cntl |=		values->tv_modulator_cntl1 |= 			RADEON_TV_MODULATOR_CNTL1_SYNC_TIP_LEVEL |			(0x46 << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT) |			(0x3b << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT);		values->tv_modulator_cntl2 = 			(-111 & TV_MODULATOR_CNTL2_U_BURST_LEVEL_MASK) |			((0 & TV_MODULATOR_CNTL2_V_BURST_LEVEL_MASK) << TV_MODULATOR_CNTL2_V_BURST_LEVEL_SHIFT);		break;			case ts_pal_bdghi:		values->tv_modulator_cntl1 |= 			RADEON_TV_MODULATOR_CNTL1_ALT_PHASE_EN |			RADEON_TV_MODULATOR_CNTL1_SYNC_TIP_LEVEL |			(0x3b << RADEON_TV_MODULATOR_CNTL1_SET_UP_LEVEL_SHIFT) |			(0x3b << RADEON_TV_MODULATOR_CNTL1_BLANK_LEVEL_SHIFT);		values->tv_modulator_cntl2 = 			(-78 & TV_MODULATOR_CNTL2_U_BURST_LEVEL_MASK) |			((62 & TV_MODULATOR_CNTL2_V_BURST_LEVEL_MASK) << TV_MODULATOR_CNTL2_V_BURST_LEVEL_SHIFT);		break;			case ts_scart_pal:		// from register spec		values->tv_modulator_cntl1 |= 			RADEON_TV_MODULATOR_CNTL1_ALT_PHASE_EN |			RADEON_TV_MODULATOR_CNTL1_SYNC_TIP_LEVEL;		values->tv_modulator_cntl2 = 			(0 & TV_MODULATOR_CNTL2_U_BURST_LEVEL_MASK) |			((0 & TV_MODULATOR_CNTL2_V_BURST_LEVEL_MASK) << TV_MODULATOR_CNTL2_V_BURST_LEVEL_SHIFT);		break;		    default:		// there are many formats missing, sigh...    }        // RE:    values->tv_modulator_cntl1 |=    	RADEON_TV_MODULATOR_CNTL1_YFLT_EN |    	RADEON_TV_MODULATOR_CNTL1_UVFLT_EN |    	RADEON_TV_MODULATOR_CNTL1_SLEW_RATE_LIMIT |    	(2 << RADEON_TV_MODULATOR_CNTL1_CY_FILT_BLEND_SHIFT);	if( internal_encoder ) {		values->tv_data_delay_a = 0x0b0c0a06;		values->tv_data_delay_b = 0x070a0a0c;	} else {		values->tv_data_delay_a = 0x07080604;		values->tv_data_delay_b = 0x03070607;	}		values->tv_frame_lock_cntl = internal_encoder ? 0 : 0xf0f;	if( internal_encoder ) {		values->tv_pll_cntl1 = 			(4 << RADEON_TV_PLL_CNTL1_TVPCP_SHIFT) |			(4 << RADEON_TV_PLL_CNTL1_TVPVG_SHIFT) |			// RE: was 2			(1 << RADEON_TV_PLL_CNTL1_TVPDC_SHIFT) |			RADEON_TV_PLL_CNTL1_TVCLK_SRC_SEL_TVPLLCLK |			RADEON_TV_PLL_CNTL1_TVPLL_TEST;					values->tv_rgb_cntl = 			((crtc_idx == 1 ? 2 : 0) << RADEON_TV_RGB_CNTL_RGB_SRC_SEL_SHIFT) |			RADEON_TV_RGB_CNTL_RGB_DITHER_EN |			(0xb << RADEON_TV_RGB_CNTL_UVRAM_READ_MARGIN_SHIFT) |			(7 << RADEON_TV_RGB_CNTL_FIFORAM_FIFOMACRO_READ_MARGIN_SHIFT);					// RE:		values->tv_rgb_cntl |= 0x4000000;					values->tv_pre_dac_mux_cntl = 			RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_C_GRN_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN;				// RE:			/* |			(0x2c << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT);*/	} else {		// this register seems to have completely different meaning on Theatre chip		values->tv_pll_cntl1 =			(1 << 3) | (1 << 4) | (4 << 8) | (1 << 11)		    | (5 << 13) | (4 << 16) | (1 << 19) | (5 << 21);		    		// this one too		values->tv_rgb_cntl = params->mode888;				values->tv_pre_dac_mux_cntl = 			RADEON_TV_PRE_DAC_MUX_CNTL_Y_RED_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_C_GRN_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_CMP_BLU_EN |			RADEON_TV_PRE_DAC_MUX_CNTL_DAC_DITHER_EN;			// RE:			/*(0xaf << RADEON_TV_PRE_DAC_MUX_CNTL_FORCE_DAC_DATA_SHIFT);*/	}		values->tv_pll_fine_cntl = 0;		// TBD: this is certainly broken 	// (they do an ((orig & 0xe0) & 0x600) which is constant zero)	values->tv_master_cntl = 		RADEON_TV_MASTER_CNTL_CRT_FIFO_CE_EN |		RADEON_TV_MASTER_CNTL_TV_FIFO_CE_EN;	if( tv_format == ts_ntsc )		values->tv_master_cntl |= RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX;	else		values->tv_master_cntl &= ~RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX;			// this is missing in the sample code	if( internal_encoder )		values->tv_master_cntl |= RADEON_TV_MASTER_CNTL_TV_ON;	else		values->tv_master_cntl |= 			RADEON_TV_MASTER_CNTL_RESTART_PHASE_FIX | // RE: guessed						RADEON_TV_MASTER_CNTL_VIN_ASYNC_RST |			RADEON_TV_MASTER_CNTL_AUD_ASYNC_RST |			RADEON_TV_MASTER_CNTL_DVS_ASYNC_RST;		values->tv_gain_limit_settings = 0x017f05ff;	values->tv_linear_gain_settings = 0x01000100;	values->tv_upsamp_and_gain_cntl = 0x00000005;	values->tv_crc_cntl = 0;		SHOW_FLOW( 2, "tv_master_cntl=%x", values->tv_master_cntl );	memcpy( values->tv_upsample_filter_coeff, std_upsample_filter_coeff, 		RADEON_TV_UPSAMP_COEFF_NUM * sizeof( uint32 ));	// setup output timing		memcpy( values->tv_hor_timing, hor_timings[tv_format-1], 		RADEON_TV_TIMING_SIZE * sizeof( uint16 ));	memcpy( values->tv_vert_timing, vert_timings[tv_format-1], 		RADEON_TV_TIMING_SIZE * sizeof( uint16 ) );		// arbitrary position of vertical timing table in FIFO	values->tv_uv_adr = TV_UV_ADR_INI;}// get address of horizontal timing table in FIFO static uint16 getHorTimingTableAddr( 	impactv_regs *values, bool internal_encoder ){	switch( (values->tv_uv_adr & RADEON_TV_UV_ADR_HCODE_TABLE_SEL_MASK) 		>> RADEON_TV_UV_ADR_HCODE_TABLE_SEL_SHIFT ) 	{	case 0:		return internal_encoder ? RADEON_TV_MAX_FIFO_ADDR_INTERN : RADEON_TV_MAX_FIFO_ADDR;			case 1:		return ((values->tv_uv_adr & RADEON_TV_UV_ADR_TABLE1_BOT_ADR_MASK) 			>> RADEON_TV_UV_ADR_TABLE1_BOT_ADR_SHIFT) * 2;	case 2:		return ((values->tv_uv_adr & RADEON_TV_UV_ADR_TABLE3_TOP_ADR_MASK) 			>> RADEON_TV_UV_ADR_TABLE3_TOP_ADR_SHIFT) * 2;				default:		return 0;	}}// get address of vertical timing table in FIFO static uint16 getVertTimingTableAddr( 	impactv_regs *values ){	switch( (values->tv_uv_adr & RADEON_TV_UV_ADR_VCODE_TABLE_SEL_MASK) 		>> RADEON_TV_UV_ADR_VCODE_TABLE_SEL_SHIFT )	{	case 0:		return ((values->tv_uv_adr & RADEON_TV_UV_ADR_MAX_UV_ADR_MASK) 			>> RADEON_TV_UV_ADR_MAX_UV_ADR_SHIFT) * 2 + 1;		case 1:		return ((values->tv_uv_adr & RADEON_TV_UV_ADR_TABLE1_BOT_ADR_MASK) 			>> RADEON_TV_UV_ADR_TABLE1_BOT_ADR_SHIFT) * 2 + 1;		case 2:		return ((values->tv_uv_adr & RADEON_TV_UV_ADR_TABLE3_TOP_ADR_MASK) 			>> RADEON_TV_UV_ADR_TABLE3_TOP_ADR_SHIFT) * 2 + 1;		default:		return 0;	}}// write horizontal timing tablevoid Radeon_ImpacTVwriteHorTimingTable( 	accelerator_info *ai, impactv_write_FIFO write, impactv_regs *values, bool internal_encoder ){	uint16 addr = getHorTimingTableAddr( values, internal_encoder );	int i;		for( i = 0; i < RADEON_TV_TIMING_SIZE; i += 2, --addr ) {		uint32 value = 			((uint32)values->tv_hor_timing[i] << 14) | 			values->tv_hor_timing[i + 1];					write( ai, addr, value );		if( values->tv_hor_timing[i] == 0 ||			values->tv_hor_timing[i + 1] == 0 )			break;	}}// write vertical timing tablevoid Radeon_ImpacTVwriteVertTimingTable( 	accelerator_info *ai, impactv_write_FIFO write, impactv_regs *values ){	uint16 addr = getVertTimingTableAddr( values );	int i;	for( i = 0; i < RADEON_TV_TIMING_SIZE; i += 2 , ++addr ) {		uint32 value =			((uint32)values->tv_vert_timing[i + 1] << 14) | 			values->tv_vert_timing[i];		write( ai, addr, value );		if( values->tv_vert_timing[i + 1] == 0 ||			values->tv_vert_timing[i] == 0 )			break;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -