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

📄 sstfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* 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(struct sstfb_info * sst_info, 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, fbiinit5, fbiinit6=0;	int ntiles;	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);	if (!par->valid) {		BUG();		return -1;	}	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 << 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(sst_info, par->bpp);	/* set video clock */	sst_info->dac_sw.set_pll(sst_info, &par->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 (IS_VOODOO2(sst_info)) {		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 (IS_VOODOO2(sst_info)) {		sst_write(FBIINIT6, fbiinit6);		fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;		if (par->vmode & FB_VMODE_INTERLACED)			fbiinit5 |= INTERLACE;		if (par->vmode & FB_VMODE_DOUBLE )			fbiinit5 |= VDOUBLESCAN;		if (par->sync & FB_SYNC_HOR_HIGH_ACT)			fbiinit5 |= HSYNC_HIGH;		if (par->sync & FB_SYNC_VERT_HIGH_ACT)			fbiinit5 |= VSYNC_HIGH;		sst_write(FBIINIT5, fbiinit5);	}	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  */	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:		BUG();		return 0;	}#if defined(__BIG_ENDIAN)	/* enable byte-swizzle functionality in hardware */	lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR | 		     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );#endif	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);		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(struct sstfb_info * sst_info, 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:		BUG();	}}static void sst_set_vidmod_ics(struct sstfb_info * sst_info, 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:		BUG();	}}static int __devinit sst_init(struct sstfb_info *sst_info){	struct pll_timing gfx_timings;	struct sst_spec * spec;	struct pci_dev * sst_dev = sst_info->dev;	int Fout;	u32 fbiinit0, fbiinit1, fbiinit4;	spec = &voodoo_spec[sst_info->type];	f_dprintk("sst_init\n");	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(sst_dev, PCI_VCLK_DISABLE,0);	/* enable writing to init registers ,disable pci fifo*/	pci_write_config_dword(sst_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(sst_dev, PCI_INIT_ENABLE,	                               PCI_EN_INIT_WR | PCI_REMAP_DAC );	/* detect dac type */	if (!sst_detect_dactype(sst_info)) {		eprintk("Unknown dac type\n");		//FIXME watch it : we are not in a safe state , bad bad bad .		return 0;	}	/* set graphic clock */	sst_info->gfx_clock = spec->default_gfx_clock;	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {		iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk);		 sst_info->gfx_clock = gfxclk *1000;	} else if (gfxclk) {		wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk);	}	sst_calc_pll(sst_info->gfx_clock, &Fout, &gfx_timings);	sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);	/* disable fbiinit remap */	pci_write_config_dword(sst_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);	sst_wait_idle();	sst_write(FBIINIT1, fbiinit1);	sst_wait_idle();	sst_write(FBIINIT2, FBIINIT2_DEFAULT);	sst_wait_idle();	sst_write(FBIINIT3, FBIINIT3_DEFAULT);	sst_wait_idle();	sst_write(FBIINIT4, fbiinit4);	sst_wait_idle();	if (IS_VOODOO2(sst_info)) {		sst_write(FBIINIT6, FBIINIT6_DEFAULT);		sst_wait_idle();	}	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR );	pci_write_config_dword(sst_dev, PCI_VCLK_ENABLE, 0);	return 1;}static void  __devexit sst_shutdown(struct sstfb_info *sst_info){	struct pci_dev * sst_dev = sst_info->dev;	struct pll_timing gfx_timings;	int Fout;	f_dprintk("sst_shutdown\n");	/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);	sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);	sst_wait_idle();	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,	                       PCI_EN_INIT_WR | PCI_REMAP_DAC );	/*set 20Mhz gfx clock */	sst_calc_pll(20000, &Fout, &gfx_timings);	sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK);

⌨️ 快捷键说明

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