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

📄 radeon_base.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	radeon_fifo_wait(31);	for (i=0; i<10; i++)		OUTREG(common_regs[i].reg, common_regs[i].val);	/* Apply surface registers */	for (i=0; i<8; i++) {		OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]);		OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]);		OUTREG(SURFACE0_INFO + 0x10*i, mode->surf_info[i]);	}	OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);	OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,		~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));	OUTREG(CRTC_MORE_CNTL, mode->crtc_more_cntl);	OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);	OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);	OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);	OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);	OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);	OUTREG(CRTC_OFFSET, 0);	OUTREG(CRTC_OFFSET_CNTL, 0);	OUTREG(CRTC_PITCH, mode->crtc_pitch);	OUTREG(SURFACE_CNTL, mode->surface_cntl);	radeon_write_pll_regs(rinfo, mode);	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {		radeon_fifo_wait(10);		OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);		OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp);		OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid);		OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid);		OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch);		OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch);		OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl);		OUTREG(TMDS_CRC, mode->tmds_crc);		OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl);	}	if (!regs_only)		radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0);	radeon_fifo_wait(2);	OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);		return;}/* * Calculate the PLL values for a given mode */static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs,				 unsigned long freq){	const struct {		int divider;		int bitvalue;	} *post_div,	  post_divs[] = {		{ 1,  0 },		{ 2,  1 },		{ 4,  2 },		{ 8,  3 },		{ 3,  4 },		{ 16, 5 },		{ 6,  6 },		{ 12, 7 },		{ 0,  0 },	};	int fb_div, pll_output_freq = 0;	int uses_dvo = 0;	/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm	 * not sure which model starts having FP2_GEN_CNTL, I assume anything more	 * recent than an r(v)100...	 */#if 1	/* XXX I had reports of flicker happening with the cinema display	 * on TMDS1 that seem to be fixed if I also forbit odd dividers in	 * this case. This could just be a bandwidth calculation issue, I	 * haven't implemented the bandwidth code yet, but in the meantime,	 * forcing uses_dvo to 1 fixes it and shouln't have bad side effects,	 * I haven't seen a case were were absolutely needed an odd PLL	 * divider. I'll find a better fix once I have more infos on the	 * real cause of the problem.	 */	while (rinfo->has_CRTC2) {		u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);		u32 disp_output_cntl;		int source;		/* FP2 path not enabled */		if ((fp2_gen_cntl & FP2_ON) == 0)			break;		/* Not all chip revs have the same format for this register,		 * extract the source selection		 */		if (rinfo->family == CHIP_FAMILY_R200 ||		    rinfo->family == CHIP_FAMILY_R300 ||		    rinfo->family == CHIP_FAMILY_R350 ||		    rinfo->family == CHIP_FAMILY_RV350) {			source = (fp2_gen_cntl >> 10) & 0x3;			/* sourced from transform unit, check for transform unit			 * own source			 */			if (source == 3) {				disp_output_cntl = INREG(DISP_OUTPUT_CNTL);				source = (disp_output_cntl >> 12) & 0x3;			}		} else			source = (fp2_gen_cntl >> 13) & 0x1;		/* sourced from CRTC2 -> exit */		if (source == 1)			break;		/* so we end up on CRTC1, let's set uses_dvo to 1 now */		uses_dvo = 1;		break;	}#else	uses_dvo = 1;#endif	if (freq > rinfo->pll.ppll_max)		freq = rinfo->pll.ppll_max;	if (freq*12 < rinfo->pll.ppll_min)		freq = rinfo->pll.ppll_min / 12;	RTRACE("freq = %lu, PLL min = %u, PLL max = %u\n",	       freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);	for (post_div = &post_divs[0]; post_div->divider; ++post_div) {		pll_output_freq = post_div->divider * freq;		/* If we output to the DVO port (external TMDS), we don't allow an		 * odd PLL divider as those aren't supported on this path		 */		if (uses_dvo && (post_div->divider & 1))			continue;		if (pll_output_freq >= rinfo->pll.ppll_min  &&		    pll_output_freq <= rinfo->pll.ppll_max)			break;	}	/* If we fall through the bottom, try the "default value"	   given by the terminal post_div->bitvalue */	if ( !post_div->divider ) {		post_div = &post_divs[post_div->bitvalue];		pll_output_freq = post_div->divider * freq;	}	RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",	       rinfo->pll.ref_div, rinfo->pll.ref_clk,	       pll_output_freq);	/* If we fall through the bottom, try the "default value"	   given by the terminal post_div->bitvalue */	if ( !post_div->divider ) {		post_div = &post_divs[post_div->bitvalue];		pll_output_freq = post_div->divider * freq;	}	RTRACE("ref_div = %d, ref_clk = %d, output_freq = %d\n",	       rinfo->pll.ref_div, rinfo->pll.ref_clk,	       pll_output_freq);	fb_div = round_div(rinfo->pll.ref_div*pll_output_freq,				  rinfo->pll.ref_clk);	regs->ppll_ref_div = rinfo->pll.ref_div;	regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16);	RTRACE("post div = 0x%x\n", post_div->bitvalue);	RTRACE("fb_div = 0x%x\n", fb_div);	RTRACE("ppll_div_3 = 0x%x\n", regs->ppll_div_3);}static int radeonfb_set_par(struct fb_info *info){	struct radeonfb_info *rinfo = info->par;	struct fb_var_screeninfo *mode = &info->var;	struct radeon_regs *newmode;	int hTotal, vTotal, hSyncStart, hSyncEnd,	    hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;	u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};	u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};	u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock;	int i, freq;	int format = 0;	int nopllcalc = 0;	int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;	int primary_mon = PRIMARY_MONITOR(rinfo);	int depth = var_to_depth(mode);	int use_rmx = 0;	newmode = kmalloc(sizeof(struct radeon_regs), GFP_KERNEL);	if (!newmode)		return -ENOMEM;	/* We always want engine to be idle on a mode switch, even	 * if we won't actually change the mode	 */	radeon_engine_idle();	hSyncStart = mode->xres + mode->right_margin;	hSyncEnd = hSyncStart + mode->hsync_len;	hTotal = hSyncEnd + mode->left_margin;	vSyncStart = mode->yres + mode->lower_margin;	vSyncEnd = vSyncStart + mode->vsync_len;	vTotal = vSyncEnd + mode->upper_margin;	pixClock = mode->pixclock;	sync = mode->sync;	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;	if (primary_mon == MT_DFP || primary_mon == MT_LCD) {		if (rinfo->panel_info.xres < mode->xres)			mode->xres = rinfo->panel_info.xres;		if (rinfo->panel_info.yres < mode->yres)			mode->yres = rinfo->panel_info.yres;		hTotal = mode->xres + rinfo->panel_info.hblank;		hSyncStart = mode->xres + rinfo->panel_info.hOver_plus;		hSyncEnd = hSyncStart + rinfo->panel_info.hSync_width;		vTotal = mode->yres + rinfo->panel_info.vblank;		vSyncStart = mode->yres + rinfo->panel_info.vOver_plus;		vSyncEnd = vSyncStart + rinfo->panel_info.vSync_width;		h_sync_pol = !rinfo->panel_info.hAct_high;		v_sync_pol = !rinfo->panel_info.vAct_high;		pixClock = 100000000 / rinfo->panel_info.clock;		if (rinfo->panel_info.use_bios_dividers) {			nopllcalc = 1;			newmode->ppll_div_3 = rinfo->panel_info.fbk_divider |				(rinfo->panel_info.post_divider << 16);			newmode->ppll_ref_div = rinfo->panel_info.ref_divider;		}	}	dotClock = 1000000000 / pixClock;	freq = dotClock / 10; /* x100 */	RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",		hSyncStart, hSyncEnd, hTotal);	RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",		vSyncStart, vSyncEnd, vTotal);	hsync_wid = (hSyncEnd - hSyncStart) / 8;	vsync_wid = vSyncEnd - vSyncStart;	if (hsync_wid == 0)		hsync_wid = 1;	else if (hsync_wid > 0x3f)	/* max */		hsync_wid = 0x3f;	if (vsync_wid == 0)		vsync_wid = 1;	else if (vsync_wid > 0x1f)	/* max */		vsync_wid = 0x1f;	hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;	vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;	cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;	format = radeon_get_dstbpp(depth);	bytpp = mode->bits_per_pixel >> 3;	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))		hsync_fudge = hsync_fudge_fp[format-1];	else		hsync_fudge = hsync_adj_tab[format-1];	hsync_start = hSyncStart - 8 + hsync_fudge;	newmode->crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |				(format << 8);	/* Clear auto-center etc... */	newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;	newmode->crtc_more_cntl &= 0xfffffff0;		if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;		if (mirror)			newmode->crtc_ext_cntl |= CRTC_CRT_ON;		newmode->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |					   CRTC_INTERLACE_EN);	} else {		newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |					CRTC_CRT_ON;	}	newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |			   DAC_8BIT_EN;	newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) |				     (((mode->xres / 8) - 1) << 16));	newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) |					(hsync_wid << 16) | (h_sync_pol << 23));	newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) |				    ((mode->yres - 1) << 16);	newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |					 (vsync_wid << 16) | (v_sync_pol  << 23));	if (!(info->flags & FBINFO_HWACCEL_DISABLED)) {		/* We first calculate the engine pitch */		rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) 				& ~(0x3f)) >> 6;		/* Then, re-multiply it to get the CRTC pitch */		newmode->crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8);	} else		newmode->crtc_pitch = (mode->xres_virtual >> 3);	newmode->crtc_pitch |= (newmode->crtc_pitch << 16);	/*	 * It looks like recent chips have a problem with SURFACE_CNTL,	 * setting SURF_TRANSLATION_DIS completely disables the	 * swapper as well, so we leave it unset now.	 */	newmode->surface_cntl = 0;#if defined(__BIG_ENDIAN)	/* Setup swapping on both apertures, though we currently	 * only use aperture 0, enabling swapper on aperture 1	 * won't harm	 */	switch (mode->bits_per_pixel) {		case 16:			newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;			newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP;			break;		case 24:			case 32:			newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;			newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP;			break;	}#endif	/* Clear surface registers */	for (i=0; i<8; i++) {		newmode->surf_lower_bound[i] = 0;		newmode->surf_upper_bound[i] = 0x1f;		newmode->surf_info[i] = 0;	}	RTRACE("h_total_disp = 0x%x\t   hsync_strt_wid = 0x%x\n",		newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid);	RTRACE("v_total_disp = 0x%x\t   vsync_strt_wid = 0x%x\n",		newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid);	rinfo->bpp = mode->bits_per_pixel;	rinfo->depth = depth;	RTRACE("pixclock = %lu\n", (unsigned long)pixClock);	RTRACE("freq = %lu\n", (unsigned long)freq);	/* We use PPLL_DIV_3 */	newmode->clk_cntl_index = 0x300;	/* Calculate PPLL value if necessary */	if (!nopllcalc)		radeon_calc_pll_regs(rinfo, newmode, freq);	newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl;	if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {		unsigned int hRatio, vRatio;		if (mode->xres > rinfo->panel_info.xres)			mode->xres = rinfo->panel_info.xres;		if (mode->yres > rinfo->panel_info.yres)			mode->yres = rinfo->panel_info.yres;		newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1)					   << HORZ_PANEL_SHIFT);		newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1)					   << VERT_PANEL_SHIFT);		if (mode->xres != rinfo->panel_info.xres) {			hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,					   rinfo->panel_info.xres);			newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |						   (newmode->fp_horz_stretch &						    (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |						     HORZ_AUTO_RATIO_INC)));			newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND |						    HORZ_STRETCH_ENABLE);			use_rmx = 1;		}		newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO;		if (mode->yres != rinfo->panel_info.yres) {			vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,					   rinfo->panel_info.yres);			newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |						   (newmode->fp_vert_stretch &						   (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));			newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND |						    VERT_STRETCH_ENABLE);			use_rmx = 1;		}		newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;		newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)				       ~(FP_SEL_CRTC2 |					 FP_RMX_HVSYNC_CONTROL_EN |					 FP_DFP_SYNC_SEL |					 FP_CRT_SYNC_SEL |					 FP_CRTC_LOCK_8DOT |					 FP_USE_SHADOW_EN |					 FP_CRTC_USE_SHADOW_VEND |					 FP_CRT_SYNC_ALT));		newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR |					FP_CRTC_DONT_SHADOW_HEND |					FP_PANEL_FORMAT);		if (IS_R300_VARIANT(rinfo) ||		    (rinfo->family == CHIP_FAMILY_R200)) {			newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;			if (use_rmx)				newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;			else

⌨️ 快捷键说明

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