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

📄 sstfb.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	writel (0xabcdef01, fbbase_virt);	f_ddprintk("0Mb: %#x, 1Mb: %#x, 2Mb: %#x\n",	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),	           readl(fbbase_virt + 0x200000));	/* checks for 4mb lfb , then 2, then defaults to 1*/	if (readl(fbbase_virt + 0x200000) == 0xdeadbeef) {		*memsize = 0x400000;	} else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef) {		*memsize = 0x200000;	} else {		*memsize = 0x100000;	}	f_ddprintk("detected memsize: %#lx\n", *memsize);	return 1;}/* * wait for the fbi chip. ASK: what happens if the fbi is stuck ? * * the FBI is supposed to be ready if we receive 5 time * in a row a "idle" answer to our requests */static int sst_wait_idle(void){	int count = 0;	f_ddprintk("sst_wait_idle\n");	while(1) {		if (sst_read(STATUS) & STATUS_FBI_BUSY) {			f_dddprintk("status: busy\n");/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; this is a small loop after all ...*/			count = 0;		} else {			count++;			f_dddprintk("status: idle(%d)\n", count);		}		if (count >= 5) return 1;	}}/* * detect dac type * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset, * dram refresh disabled, FbiInit remaped. * TODO: mmh.. maybe i shoud put the "prerequisite" in the func ... */static int __init sst_detect_dactype(void){	int ret=0,i;	f_dprintk("sst_detect_dactype\n");	for (i=0; i< sizeof(dacs)/sizeof(dacs[0]) ; i++) {		ret = dacs[i].detect();		if (ret) break;	}	if (!ret)		return 0;	f_dprintk("found %s\n", dacs[i].name);	fb_info.dac_sw=&dacs[i];	return 1;}/* fbi should be idle, and fifo emty and mem disabled *//* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */static int __init (sst_detect_att(void)){	int i, mir, dir;	f_dprintk("sst_detect_att\n");	for (i = 0; i<3; i++) {		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */		sst_dac_read(DACREG_RMR);		sst_dac_read(DACREG_RMR);		sst_dac_read(DACREG_RMR);		/* the fifth time,  CR0 is read */		sst_dac_read(DACREG_RMR);		/* the 6th, manufacturer id register */		mir = sst_dac_read(DACREG_RMR);		/*the 7th, device ID register */		dir = sst_dac_read(DACREG_RMR);		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);		if ((mir == DACREG_MIR_ATT ) && (dir == DACREG_DIR_ATT)) {			return 1;		}	}	return 0;}static int __init (sst_detect_ti(void)){	int i, mir, dir;	f_dprintk("sst_detect_ti\n");	for (i = 0; i<3; i++) {		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */		sst_dac_read(DACREG_RMR);		sst_dac_read(DACREG_RMR);		sst_dac_read(DACREG_RMR);		/* the fifth time,  CR0 is read */		sst_dac_read(DACREG_RMR);		/* the 6th, manufacturer id register */		mir = sst_dac_read(DACREG_RMR);		/*the 7th, device ID register */		dir = sst_dac_read(DACREG_RMR);		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);		if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) {			return 1;		}	}	return 0;}/* * try to detect ICS5342  ramdac * we get the 1st byte (M value) of preset f1,f7 and fB * why those 3 ? mmmh... for now, i'll do it the glide way... * and ask questions later. anyway, it seems that all the freq registers are * realy at their default state (cf specs) so i ask again, why those 3 regs ? * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be * touched... * is it realy safe ? how can i reset this ramdac ? geee... */static int __init sst_detect_ics(void){	int i;	int m_clk0_1, m_clk0_7, m_clk1_b;	int n_clk0_1, n_clk0_7, n_clk1_b;	f_dprintk("sst_detect_ics\n");	for (i = 0; i<5; i++ ) {		sst_dac_write(DACREG_ICS_PLLRMA, 0x1);	/* f1 */		m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);		n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);		sst_dac_write(DACREG_ICS_PLLRMA, 0x7);	/* f7 */		m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);		n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);		sst_dac_write(DACREG_ICS_PLLRMA, 0xb);	/* fB */		m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);		n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);		f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n",			m_clk0_1, m_clk0_7, m_clk1_b);		f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n",			n_clk0_1, n_clk0_7, n_clk1_b);		if ((   m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI)		    && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI)		    && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) {			return 1;		}	}	return 0;}/* compute the m,n,p  , returns the real freq * (ics datasheet :  N <-> N1 , P <-> N2) * * Fout= Fref * (M+2)/( 2^P * (N+2)) *  we try to get close to the asked freq *  with P as high, and M as low as possible * range: * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63 * ics    : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31 * we'll use the lowest limitation, should be precise enouth */static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t){	int m, m2, n, p, best_err, fout;	int best_n=-1;	int best_m=-1;	f_dprintk("sst_calc_pll(%dKhz)\n", freq);	best_err = freq;	p=3;	/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/	while (((1 << p) * freq > VCO_MAX) && (p >= 0))		p--;	if (p == -1)		return -EINVAL;	for (n = 1; n < 32; n++) {		/* calc 2 * m so we can round it later*/		m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;		m = (m2 % 2 ) ? m2/2+1 : m2/2 ;		if (m >= 128)			break;		fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));		if ((ABS(fout - freq) < best_err) && (m > 0)) {			best_n = n;			best_m = m;			best_err = ABS(fout - freq);			/* we get the lowest m , allowing 0.5% error in freq*/			if (200*best_err < freq) break;		}	}	if (best_n == -1)  /* unlikely, but who knows ? */		return -EINVAL;	t->p=p;	t->n=best_n;	t->m=best_m;	*freq_out=(DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));	f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",		  t->m, t->n, t->p, *freq_out);	return 0;}/* * gfx, video, pci fifo should be reset, dram refresh disabled * see detect_dac */static int sst_set_pll_att_ti(const struct pll_timing *t, const int clock){	u8 cr0, cc;	f_dprintk("sst_set_pll_att_ti\n");	/* enable indexed mode */	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */	sst_dac_read(DACREG_RMR);	/* 1 time:  RMR */	sst_dac_read(DACREG_RMR);	/* 2 RMR */	sst_dac_read(DACREG_RMR);	/* 3 //  */	sst_dac_read(DACREG_RMR);	/* 4 //  */	cr0 = sst_dac_read(DACREG_RMR);	/* 5 CR0 */	sst_dac_write(DACREG_WMA, 0);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_write(DACREG_RMR, (cr0 & 0xf0)	              | DACREG_CR0_EN_INDEXED	              | DACREG_CR0_8BIT	              | DACREG_CR0_PWDOWN );	/* so, now we are in indexed mode . dunno if its common, but	   i find this way of doing things a little bit weird :p */	udelay(300);	cc = dac_i_read(DACREG_CC_I);	switch (clock) {	case VID_CLOCK:		dac_i_write(DACREG_AC0_I, t->m);		dac_i_write(DACREG_AC1_I, t->p << 6 | t->n);		dac_i_write(DACREG_CC_I,		            (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C);		break;	case GFX_CLOCK:		dac_i_write(DACREG_BD0_I, t->m);		dac_i_write(DACREG_BD1_I, t->p << 6 | t->n);		dac_i_write(DACREG_CC_I,		            (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);		break;	default:		dprintk("bug line %d: wrong clock code '%d'\n",		        __LINE__,clock);		return 0;		}	udelay(300);	/* power up the dac & return to "normal" non-indexed mode */	dac_i_write(DACREG_CR0_I,	            cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED);	return 1;}static int sst_set_pll_ics(const struct pll_timing *t, const int clock){	u8 pll_ctrl;	f_dprintk("sst_set_pll_ics\n");	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);	pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);	switch(clock) {	case VID_CLOCK:		sst_dac_write(DACREG_ICS_PLLWMA, 0x0);	/* CLK0, f0 */		sst_dac_write(DACREG_ICS_PLLDATA, t->m);		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);		/* selects freq f0 for clock 0 */		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);		sst_dac_write(DACREG_ICS_PLLDATA,		              (pll_ctrl & 0xd8)		              | DACREG_ICS_CLK0		              | DACREG_ICS_CLK0_0);		break;	case GFX_CLOCK :		sst_dac_write(DACREG_ICS_PLLWMA, 0xa);	/* CLK1, fA */		sst_dac_write(DACREG_ICS_PLLDATA, t->m);		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);		/* selects freq fA for clock 1 */		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);		sst_dac_write(DACREG_ICS_PLLDATA,		              (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);		break;	default:		dprintk("bug line %d: wrong clock code '%d'\n",		        __LINE__, clock);		return 0;		}	udelay(300);	return 1;}static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_info){	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit6=0;	int ntiles;	struct pll_timing pll;	int fout;	struct pci_dev  * sst_dev = sst_info->dev;	f_dprintk("sst_set_par(%dx%d)\n", par->xDim, par->yDim);	f_ddprintk("hSyncOn hSyncOff vSyncOn vSyncOff\n");	f_ddprintk("%-7d %-8d %-7d %-8d\n",	           par->hSyncOn, par->hSyncOff,	           par->vSyncOn, par->vSyncOff);	f_ddprintk("hBackPorch vBackPorch xDim yDim Freq\n");	f_ddprintk("%-10d %-10d %-4d %-4d %-8d\n",	           par->hBackPorch, par->vBackPorch,	           par->xDim, par->yDim, par->freq);	sst_calc_pll (par->freq, &fout, &pll);	sst_write(NOPCMD, 0);	sst_wait_idle();	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);	sst_set_bits(FBIINIT1, VIDEO_RESET);	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);	sst_wait_idle();	/*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */	sst_write(BACKPORCH,       par->vBackPorch << 16 | (par->hBackPorch-2));	sst_write(VIDEODIMENSIONS, (par->yDim - 1) << 16 | (par->xDim - 1));	sst_write(HSYNC,         (par->hSyncOff-1) << 16 | (par->hSyncOn-1));	sst_write(VSYNC,             par->vSyncOff << 16 | par->vSyncOn);	fbiinit2=sst_read(FBIINIT2);	fbiinit3=sst_read(FBIINIT3);	/* everything is reset. we enable fbiinit2/3 remap : dac acces ok */	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR | PCI_REMAP_DAC );	sst_info->dac_sw->set_vidmod(par->bpp);	/* set video clock */	sst_info->dac_sw->set_pll(&pll, VID_CLOCK);	/* disable fbiinit2/3 remap */	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR);	/* restore fbiinit2/3 */	sst_write(FBIINIT2,fbiinit2);	sst_write(FBIINIT3,fbiinit3);	fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)	            | EN_DATA_OE	            | EN_BLANK_OE	            | EN_HVSYNC_OE	            | EN_DCLK_OE/*	            | (15 << TILES_IN_X_SHIFT)*/	            | SEL_INPUT_VCLK_2X/*	            | (2 << VCLK_2X_SEL_DEL_SHIFT)	            | (2 << VCLK_DEL_SHIFT)*/;/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28) in (near) future set them accordingly to revision + resolution (cf glide) first understand what it stands for :) FIXME: there are some artefacts... check for the vclk_in_delay lets try with 6ns delay in both vclk_out & in... doh... they're still there :\*/	ntiles = par->tiles_in_X;	if (sst_info->is_voodoo2) {		fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT		            | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ;/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),   and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just   write our value. BTW due to the dac unable to read odd number of tiles, this   field is always null ... */		fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;	}	else		fbiinit1 |= ntiles << TILES_IN_X_SHIFT;	switch(par->bpp) {	case 16:		fbiinit1 |=  SEL_SOURCE_VCLK_2X_SEL;		break;#ifdef EN_24_32_BPP	case 24:	case 32:/*	orig	sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP); */		fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP;		break;#endif	default:		dprintk("bug line %d: bad depth '%u'\n", __LINE__,			par->bpp );		return 0;		break;	}	sst_write(FBIINIT1, fbiinit1);	if (sst_info->is_voodoo2)		sst_write(FBIINIT6, fbiinit6);	sst_wait_idle();	sst_unset_bits(FBIINIT1, VIDEO_RESET);	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);/* disables fbiinit writes */	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);	/* set lfbmode : set mode + front buffer for reads/writes	   + disable pipeline + disable byte swapping */	switch(par->bpp) {	case 16:		lfbmode = LFB_565;		break;#ifdef EN_24_32_BPP	case 24:		lfbmode = LFB_888;		break;	case 32:		lfbmode = LFB_8888;		break;#endif	default:		dprintk("bug line %d: bad depth '%u'\n", __LINE__,			par->bpp );		return 0;		break;	}	if (clipping) {		sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);	/*	 * Set "clipping" dimensions. If clipping is disabled and	 * writes to offscreen areas of the framebuffer are performed,	 * the "behaviour is undefined" (_very_ undefined) - Urs	 */	/* btw, it requires enabling pixel pipeline in LFBMODE .	   off screen read/writes will just wrap and read/print pixels	   on screen. Ugly but not that dangerous */		f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",		            par->xDim-1, par->yDim-1);/* warning the fields are 9bits wide on voodoo1 , 11 (or 10) on voodoo2,   make sure we check the values before playing with the registers.. */		sst_write(CLIP_LEFT_RIGHT, par->xDim );		sst_write(CLIP_LOWY_HIGHY, par->yDim );		sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);	} else {		/* no clipping : direct access, no pipeline */		sst_write(LFBMODE, lfbmode );	}	sst_info->current_par = *par ;	return 1;}static void sst_set_vidmod_att_ti(const int bpp){	u8 cr0;	f_dprintk("sst_set_vidmod_att_ti(bpp: %d)\n", bpp);	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	/* the fifth time,  CR0 is read */	cr0 = sst_dac_read(DACREG_RMR);	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	sst_dac_read(DACREG_RMR);	/* cr0 */	switch(bpp) {	case 16:		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);		break;#ifdef EN_24_32_BPP	case 24:	case 32:		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_24BPP);		break;#endif	default:		dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);		break;	}}static void sst_set_vidmod_ics(const int bpp){	f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);	switch(bpp) {	case 16:		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);		break;#ifdef EN_24_32_BPP	case 24:	case 32:		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_24BPP);		break;#endif	default:

⌨️ 快捷键说明

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