sstfb.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,724 行 · 第 1/4 页

C
1,724
字号
	u32 stride = info->fix.line_length;	if (!IS_VOODOO2(par))		return;   		sst_write(BLTCLIPX, info->var.xres);	sst_write(BLTCLIPY, info->var.yres);		sst_write(BLTDSTBASEADDR, 0);	sst_write(BLTCOLOR, rect->color);	sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);	sst_write(BLTXYSTRIDES, stride | (stride << 16));	sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));	sst_write(BLTSIZE, rect->width | (rect->height << 16));	sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT		 | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );	sst_wait_idle();}/*  * get lfb size  */static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize){	u_long fbbase_virt = (u_long) info->screen_base;	/* force memsize */	if ((mem >= 1 ) &&  (mem <= 4)) {		*memsize = (mem * 0x100000);		iprintk("supplied memsize: %#x\n", *memsize);		return 1;	}	writel(0xdeadbeef, fbbase_virt);	writel(0xdeadbeef, fbbase_virt+0x100000);	writel(0xdeadbeef, fbbase_virt+0x200000);	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),	           readl(fbbase_virt + 0x200000));	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: %dMB\n", *memsize >> 20);	return 1;}/*  * DAC detection routines  *//* fbi should be idle, and fifo emty and mem disabled *//* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */static int __devinit sst_detect_att(struct fb_info *info){	struct sstfb_par *par = (struct sstfb_par *) info->par;	int i, mir, dir;	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 __devinit sst_detect_ti(struct fb_info *info){	struct sstfb_par *par = (struct sstfb_par *) info->par;	int i, mir, dir;	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 __devinit sst_detect_ics(struct fb_info *info){	struct sstfb_par *par = (struct sstfb_par *) info->par;	int m_clk0_1, m_clk0_7, m_clk1_b;	int n_clk0_1, n_clk0_7, n_clk1_b;	int i;	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;}/* * gfx, video, pci fifo should be reset, dram refresh disabled * see detect_dac */static int sst_set_pll_att_ti(struct fb_info *info, 		const struct pll_timing *t, const int clock){	struct sstfb_par *par = (struct sstfb_par *) info->par;	u8 cr0, cc;	/* 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("%s: wrong clock code '%d'\n",		        __FUNCTION__, 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(struct fb_info *info,		const struct pll_timing *t, const int clock){	struct sstfb_par *par = (struct sstfb_par *) info->par;	u8 pll_ctrl;	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("%s: wrong clock code '%d'\n",		        __FUNCTION__, clock);		return 0;		}	udelay(300);	return 1;}static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp){	struct sstfb_par *par = (struct sstfb_par *) info->par;	u8 cr0;	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("%s: bad depth '%u'\n", __FUNCTION__, bpp);		break;	}}static void sst_set_vidmod_ics(struct fb_info *info, const int bpp){	struct sstfb_par *par = (struct sstfb_par *) info->par;	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:		dprintk("%s: bad depth '%u'\n", __FUNCTION__, bpp);		break;	}}/* * 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 struct dac_switch dacs[] __devinitdata = {	{	.name		= "TI TVP3409",		.detect		= sst_detect_ti,		.set_pll	= sst_set_pll_att_ti,		.set_vidmod	= sst_set_vidmod_att_ti },	{	.name		= "AT&T ATT20C409",		.detect		= sst_detect_att,		.set_pll	= sst_set_pll_att_ti,		.set_vidmod	= sst_set_vidmod_att_ti },	{	.name		= "ICS ICS5342",		.detect		= sst_detect_ics,		.set_pll	= sst_set_pll_ics,		.set_vidmod	= sst_set_vidmod_ics },};static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par){	int i, ret = 0;		for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {		ret = dacs[i].detect(info);		if (ret) break;	}	if (!ret)		return 0;	f_dprintk("%s found %s\n", __FUNCTION__, dacs[i].name);	par->dac_sw = dacs[i];	return 1;}/* * Internal Routines */static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par){	u32 fbiinit0, fbiinit1, fbiinit4;	struct pci_dev *dev = par->dev;	struct pll_timing gfx_timings;	struct sst_spec *spec;	int Fout;	spec = &voodoo_spec[par->type];	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "	           " fbiinit6\n");	f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",	            sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),	            sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));	/* disable video clock */	pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);	/* enable writing to init registers, disable pci fifo */	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);	/* reset video */	sst_set_bits(FBIINIT1, VIDEO_RESET);	sst_wait_idle();	/* reset gfx + pci fifo */	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_wait_idle();	/* unreset fifo */	/*sst_unset_bits(FBIINIT0, FIFO_RESET);	sst_wait_idle();*/	/* unreset FBI */	/*sst_unset_bits(FBIINIT0, FBI_RESET);	sst_wait_idle();*/	/* disable dram refresh */	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);	sst_wait_idle();	/* remap fbinit2/3 to dac */	pci_write_config_dword(dev, PCI_INIT_ENABLE,				PCI_EN_INIT_WR | PCI_REMAP_DAC );	/* detect dac type */	if (!sst_detect_dactype(info, par)) {		eprintk("Unknown dac type\n");		//FIXME watch it: we are not in a safe state, bad bad bad.		return 0;	}	/* set graphic clock */	par->gfx_clock = spec->default_gfx_clock;	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {		iprintk("Using supplied graphic freq : %dMHz\n", gfxclk);		 par->gfx_clock = gfxclk *1000;	} else if (gfxclk) {		wprintk ("%dMhz is way out of spec! Using default\n", gfxclk);	}	sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);	/* disable fbiinit remap */	pci_write_config_dword(dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR| PCI_EN_FIFO_WR );	/* defaults init registers */	/* FbiInit0: unreset gfx, unreset fifo */	fbiinit0 = FBIINIT0_DEFAULT;	fbiinit1 = FBIINIT1_DEFAULT;	fbiinit4 = FBIINIT4_DEFAULT;	if (vgapass)		fbiinit0 &= ~EN_VGA_PASSTHROUGH;	else		fbiinit0 |= EN_VGA_PASSTHROUGH;	if (slowpci) {		fbiinit1 |= SLOW_PCI_WRITES;		fbiinit4 |= SLOW_PCI_READS;	} else {		fbiinit1 &= ~SLOW_PCI_WRITES;		fbiinit4 &= ~SLOW_PCI_READS;	}	sst_write(FBIINIT0, fbiinit0);

⌨️ 快捷键说明

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