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

📄 intelfbhw.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	hw->vsync_a = INREG(VSYNC_A);	hw->src_size_a = INREG(SRC_SIZE_A);	hw->bclrpat_a = INREG(BCLRPAT_A);	hw->htotal_b = INREG(HTOTAL_B);	hw->hblank_b = INREG(HBLANK_B);	hw->hsync_b = INREG(HSYNC_B);	hw->vtotal_b = INREG(VTOTAL_B);	hw->vblank_b = INREG(VBLANK_B);	hw->vsync_b = INREG(VSYNC_B);	hw->src_size_b = INREG(SRC_SIZE_B);	hw->bclrpat_b = INREG(BCLRPAT_B);	if (flag == 3)		return flag;	hw->adpa = INREG(ADPA);	hw->dvoa = INREG(DVOA);	hw->dvob = INREG(DVOB);	hw->dvoc = INREG(DVOC);	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);	hw->dvob_srcdim = INREG(DVOB_SRCDIM);	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);	hw->lvds = INREG(LVDS);	if (flag == 4)		return flag;	hw->pipe_a_conf = INREG(PIPEACONF);	hw->pipe_b_conf = INREG(PIPEBCONF);	hw->disp_arb = INREG(DISPARB);	if (flag == 5)		return flag;	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);	if (flag == 6)		return flag;	for (i = 0; i < 4; i++) {		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));	}	if (flag == 7)		return flag;	hw->cursor_size = INREG(CURSOR_SIZE);	if (flag == 8)		return flag;	hw->disp_a_ctrl = INREG(DSPACNTR);	hw->disp_b_ctrl = INREG(DSPBCNTR);	hw->disp_a_base = INREG(DSPABASE);	hw->disp_b_base = INREG(DSPBBASE);	hw->disp_a_stride = INREG(DSPASTRIDE);	hw->disp_b_stride = INREG(DSPBSTRIDE);	if (flag == 9)		return flag;	hw->vgacntrl = INREG(VGACNTRL);	if (flag == 10)		return flag;	hw->add_id = INREG(ADD_ID);	if (flag == 11)		return flag;	for (i = 0; i < 7; i++) {		hw->swf0x[i] = INREG(SWF00 + (i << 2));		hw->swf1x[i] = INREG(SWF10 + (i << 2));		if (i < 3)			hw->swf3x[i] = INREG(SWF30 + (i << 2));	}	for (i = 0; i < 8; i++)		hw->fence[i] = INREG(FENCE + (i << 2));	hw->instpm = INREG(INSTPM);	hw->mem_mode = INREG(MEM_MODE);	hw->fw_blc_0 = INREG(FW_BLC_0);	hw->fw_blc_1 = INREG(FW_BLC_1);	hw->hwstam = INREG16(HWSTAM);	hw->ier = INREG16(IER);	hw->iir = INREG16(IIR);	hw->imr = INREG16(IMR);	return 0;}static int calc_vclock3(int index, int m, int n, int p){	if (p == 0 || n == 0)		return 0;	return plls[index].ref_clk * m / n / p;}static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2,		       int lvds){	struct pll_min_max *pll = &plls[index];	u32 m, vco, p;	m = (5 * (m1 + 2)) + (m2 + 2);	n += 2;	vco = pll->ref_clk * m / n;	if (index == PLLS_I8xx)		p = ((p1 + 2) * (1 << (p2 + 1)));	else		p = ((p1) * (p2 ? 5 : 10));	return vco / p;}#if REGDUMPstatic void intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll,			       int *o_p1, int *o_p2){	int p1, p2;	if (IS_I9XX(dinfo)) {		if (dpll & DPLL_P1_FORCE_DIV2)			p1 = 1;		else			p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;		p1 = ffs(p1);		p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;	} else {		if (dpll & DPLL_P1_FORCE_DIV2)			p1 = 0;		else			p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;		p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;	}	*o_p1 = p1;	*o_p2 = p2;}#endifvoid intelfbhw_print_hw_state(struct intelfb_info *dinfo,			      struct intelfb_hwstate *hw){#if REGDUMP	int i, m1, m2, n, p1, p2;	int index = dinfo->pll_index;	DBG_MSG("intelfbhw_print_hw_state\n");	if (!hw)		return;	/* Read in as much of the HW state as possible. */	printk("hw state dump start\n");	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);	printk("	VGAPD:			0x%08x\n", hw->vga_pd);	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",	       m1, m2, n, p1, p2);	printk("	VGA0: clock is %d\n",	       calc_vclock(index, m1, m2, n, p1, p2, 0));	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",	       m1, m2, n, p1, p2);	printk("	VGA1: clock is %d\n",	       calc_vclock(index, m1, m2, n, p1, p2, 0));	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);	printk("	FPA0:			0x%08x\n", hw->fpa0);	printk("	FPA1:			0x%08x\n", hw->fpa1);	printk("	FPB0:			0x%08x\n", hw->fpb0);	printk("	FPB1:			0x%08x\n", hw->fpb1);	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",	       m1, m2, n, p1, p2);	printk("	PLLA0: clock is %d\n",	       calc_vclock(index, m1, m2, n, p1, p2, 0));	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",	       m1, m2, n, p1, p2);	printk("	PLLA1: clock is %d\n",	       calc_vclock(index, m1, m2, n, p1, p2, 0));#if 0	printk("	PALETTE_A:\n");	for (i = 0; i < PALETTE_8_ENTRIES)		printk("	%3d:	0x%08x\n", i, hw->palette_a[i]);	printk("	PALETTE_B:\n");	for (i = 0; i < PALETTE_8_ENTRIES)		printk("	%3d:	0x%08x\n", i, hw->palette_b[i]);#endif	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);	printk("	SRC_SIZE_A:		0x%08x\n", hw->src_size_a);	printk("	BCLRPAT_A:		0x%08x\n", hw->bclrpat_a);	printk("	HTOTAL_B:		0x%08x\n", hw->htotal_b);	printk("	HBLANK_B:		0x%08x\n", hw->hblank_b);	printk("	HSYNC_B:		0x%08x\n", hw->hsync_b);	printk("	VTOTAL_B:		0x%08x\n", hw->vtotal_b);	printk("	VBLANK_B:		0x%08x\n", hw->vblank_b);	printk("	VSYNC_B:		0x%08x\n", hw->vsync_b);	printk("	SRC_SIZE_B:		0x%08x\n", hw->src_size_b);	printk("	BCLRPAT_B:		0x%08x\n", hw->bclrpat_b);	printk("	ADPA:			0x%08x\n", hw->adpa);	printk("	DVOA:			0x%08x\n", hw->dvoa);	printk("	DVOB:			0x%08x\n", hw->dvob);	printk("	DVOC:			0x%08x\n", hw->dvoc);	printk("	DVOA_SRCDIM:		0x%08x\n", hw->dvoa_srcdim);	printk("	DVOB_SRCDIM:		0x%08x\n", hw->dvob_srcdim);	printk("	DVOC_SRCDIM:		0x%08x\n", hw->dvoc_srcdim);	printk("	LVDS:			0x%08x\n", hw->lvds);	printk("	PIPEACONF:		0x%08x\n", hw->pipe_a_conf);	printk("	PIPEBCONF:		0x%08x\n", hw->pipe_b_conf);	printk("	DISPARB:		0x%08x\n", hw->disp_arb);	printk("	CURSOR_A_CONTROL:	0x%08x\n", hw->cursor_a_control);	printk("	CURSOR_B_CONTROL:	0x%08x\n", hw->cursor_b_control);	printk("	CURSOR_A_BASEADDR:	0x%08x\n", hw->cursor_a_base);	printk("	CURSOR_B_BASEADDR:	0x%08x\n", hw->cursor_b_base);	printk("	CURSOR_A_PALETTE:	");	for (i = 0; i < 4; i++) {		printk("0x%08x", hw->cursor_a_palette[i]);		if (i < 3)			printk(", ");	}	printk("\n");	printk("	CURSOR_B_PALETTE:	");	for (i = 0; i < 4; i++) {		printk("0x%08x", hw->cursor_b_palette[i]);		if (i < 3)			printk(", ");	}	printk("\n");	printk("	CURSOR_SIZE:		0x%08x\n", hw->cursor_size);	printk("	DSPACNTR:		0x%08x\n", hw->disp_a_ctrl);	printk("	DSPBCNTR:		0x%08x\n", hw->disp_b_ctrl);	printk("	DSPABASE:		0x%08x\n", hw->disp_a_base);	printk("	DSPBBASE:		0x%08x\n", hw->disp_b_base);	printk("	DSPASTRIDE:		0x%08x\n", hw->disp_a_stride);	printk("	DSPBSTRIDE:		0x%08x\n", hw->disp_b_stride);	printk("	VGACNTRL:		0x%08x\n", hw->vgacntrl);	printk("	ADD_ID:			0x%08x\n", hw->add_id);	for (i = 0; i < 7; i++) {		printk("	SWF0%d			0x%08x\n", i,			hw->swf0x[i]);	}	for (i = 0; i < 7; i++) {		printk("	SWF1%d			0x%08x\n", i,			hw->swf1x[i]);	}	for (i = 0; i < 3; i++) {		printk("	SWF3%d			0x%08x\n", i,		       hw->swf3x[i]);	}	for (i = 0; i < 8; i++)		printk("	FENCE%d			0x%08x\n", i,		       hw->fence[i]);	printk("	INSTPM			0x%08x\n", hw->instpm);	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);	printk("	FW_BLC_0		0x%08x\n", hw->fw_blc_0);	printk("	FW_BLC_1		0x%08x\n", hw->fw_blc_1);	printk("	HWSTAM			0x%04x\n", hw->hwstam);	printk("	IER			0x%04x\n", hw->ier);	printk("	IIR			0x%04x\n", hw->iir);	printk("	IMR			0x%04x\n", hw->imr);	printk("hw state dump end\n");#endif}/* Split the M parameter into M1 and M2. */static int splitm(int index, unsigned int m, unsigned int *retm1,		  unsigned int *retm2){	int m1, m2;	int testm;	struct pll_min_max *pll = &plls[index];	/* no point optimising too much - brute force m */	for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {		for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {			testm = (5 * (m1 + 2)) + (m2 + 2);			if (testm == m) {				*retm1 = (unsigned int)m1;				*retm2 = (unsigned int)m2;				return 0;			}		}	}	return 1;}/* Split the P parameter into P1 and P2. */static int splitp(int index, unsigned int p, unsigned int *retp1,		  unsigned int *retp2){	int p1, p2;	struct pll_min_max *pll = &plls[index];	if (index == PLLS_I9xx) {		p2 = (p % 10) ? 1 : 0;		p1 = p / (p2 ? 5 : 10);		*retp1 = (unsigned int)p1;		*retp2 = (unsigned int)p2;		return 0;	}	if (p % 4 == 0)		p2 = 1;	else		p2 = 0;	p1 = (p / (1 << (p2 + 1))) - 2;	if (p % 4 == 0 && p1 < pll->min_p1) {		p2 = 0;		p1 = (p / (1 << (p2 + 1))) - 2;	}	if (p1 < pll->min_p1 || p1 > pll->max_p1 ||	    (p1 + 2) * (1 << (p2 + 1)) != p) {		return 1;	} else {		*retp1 = (unsigned int)p1;		*retp2 = (unsigned int)p2;		return 0;	}}static int calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2,			   u32 *retn, u32 *retp1, u32 *retp2, u32 *retclock){	u32 m1, m2, n, p1, p2, n1, testm;	u32 f_vco, p, p_best = 0, m, f_out = 0;	u32 err_max, err_target, err_best = 10000000;	u32 n_best = 0, m_best = 0, f_best, f_err;	u32 p_min, p_max, p_inc, div_max;	struct pll_min_max *pll = &plls[index];	/* Accept 0.5% difference, but aim for 0.1% */	err_max = 5 * clock / 1000;	err_target = clock / 1000;	DBG_MSG("Clock is %d\n", clock);	div_max = pll->max_vco / clock;	p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;	p_min = p_inc;	p_max = ROUND_DOWN_TO(div_max, p_inc);	if (p_min < pll->min_p)		p_min = pll->min_p;	if (p_max > pll->max_p)		p_max = pll->max_p;	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);	p = p_min;	do {		if (splitp(index, p, &p1, &p2)) {			WRN_MSG("cannot split p = %d\n", p);			p += p_inc;			continue;		}		n = pll->min_n;		f_vco = clock * p;		do {			m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;			if (m < pll->min_m)				m = pll->min_m + 1;			if (m > pll->max_m)				m = pll->max_m - 1;			for (testm = m - 1; testm <= m; testm++) {				f_out = calc_vclock3(index, testm, n, p);				if (splitm(index, testm, &m1, &m2)) {					WRN_MSG("cannot split m = %d\n",						testm);					continue;				}				if (clock > f_out)					f_err = clock - f_out;				else/* slightly bias the error for bigger clocks */					f_err = f_out - clock + 1;				if (f_err < err_best) {					m_best = testm;					n_best = n;					p_best = p;					f_best = f_out;					err_best = f_err;				}			}			n++;		} while ((n <= pll->max_n) && (f_out >= clock));		p += p_inc;	} while ((p <= p_max));	if (!m_best) {		WRN_MSG("cannot find parameters for clock %d\n", clock);		return 1;	}	m = m_best;	n = n_best;	p = p_best;	splitm(index, m, &m1, &m2);	splitp(index, p, &p1, &p2);	n1 = n - 2;	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "		"f: %d (%d), VCO: %d\n",		m, m1, m2, n, n1, p, p1, p2,		calc_vclock3(index, m, n, p),		calc_vclock(index, m1, m2, n1, p1, p2, 0),		calc_vclock3(index, m, n, p) * p);	*retm1 = m1;	*retm2 = m2;	*retn = n1;	*retp1 = p1;	*retp2 = p2;	*retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);	return 0;}static __inline__ int check_overflow(u32 value, u32 limit,				     const char *description){	if (value > limit) {		WRN_MSG("%s value %d exceeds limit %d\n",			description, value, limit);		return 1;	}	return 0;}/* It is assumed that hw is filled in with the initial state information. */int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,			 struct intelfb_hwstate *hw,			 struct fb_var_screeninfo *var){	int pipe = PIPE_A;	u32 *dpll, *fp0, *fp1;	u32 m1, m2, n, p1, p2, clock_target, clock;	u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;	u32 vsync_pol, hsync_pol;	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;	u32 stride_alignment;	DBG_MSG("intelfbhw_mode_to_hw\n");	/* Disable VGA */	hw->vgacntrl |= VGA_DISABLE;	/* Check whether pipe A or pipe B is enabled. */	if (hw->pipe_a_conf & PIPECONF_ENABLE)		pipe = PIPE_A;	else if (hw->pipe_b_conf & PIPECONF_ENABLE)		pipe = PIPE_B;	/* Set which pipe's registers will be set. */	if (pipe == PIPE_B) {		dpll = &hw->dpll_b;		fp0 = &hw->fpb0;		fp1 = &hw->fpb1;		hs = &hw->hsync_b;		hb = &hw->hblank_b;		ht = &hw->htotal_b;		vs = &hw->vsync_b;		vb = &hw->vblank_b;		vt = &hw->vtotal_b;		ss = &hw->src_size_b;		pipe_conf = &hw->pipe_b_conf;	} else {		dpll = &hw->dpll_a;		fp0 = &hw->fpa0;		fp1 = &hw->fpa1;		hs = &hw->hsync_a;

⌨️ 快捷键说明

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