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

📄 sstfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		display->ywrapstep = 0;		display->line_length = (var->bits_per_pixel==16) ? 2048 : 4096;		display->inverse = 0;		switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB16		case 16:			display->dispsw = &fbcon_cfb16;			display->dispsw_data = sst_info->fbcon_cmap.cfb16;			break;#endif#ifdef EN_24_32_BPP#if defined (FBCON_HAS_CFB24) || defined (FBCON_HAS_CFB32 )		case 24: /*24bpp non packed <=> 32 bpp */		case 32:			display->dispsw = &fbcon_cfb32;			display->dispsw_data = sst_info->fbcon_cmap.cfb32;			break;#endif#endif		default:			display->dispsw = &fbcon_dummy;			break;		}		display->scrollmode = SCROLL_YREDRAW;		if (sst_info->info.changevar) {			v_dprintk("fb_info.changevar(con: %d)\n", con);			(*sst_info->info.changevar)(con);			v_dprintk("fb_info.changevar: done \n");		} else {			v_dprintk("fb_info.changevar() == NULL . \n");		}	}	if ((con == -1) || (con==sst_info->currcon)) {		sstfb_set_par (&par, sst_info);	}	print_var(var, "var");	print_var(&display->var, "&display->var");	if (old_bpp != var->bits_per_pixel) {	    if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))		return err;	    sstfb_install_cmap(con, info);	}	return 0;#undef sst_info}static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,                          int con, struct fb_info *info){#define sst_info	((struct sstfb_info *) info)	struct display *d = (con<0) ? info->disp : fb_display + con;	f_dprintk("sstfb_set_cmap\n");	f_ddprintk("con: %d, currcon: %d, d->cmap.len %d\n",		 con, sst_info->currcon, d->cmap.len);	if (d->cmap.len != 16 ) {	/* or test if cmap.len == 0 ? */		int err;		err = fb_alloc_cmap(&d->cmap, 16, 0); /* cmap size=16 */		if (err) return err;	}	if (con == sst_info->currcon) {		return fb_set_cmap(cmap, kspc, sstfb_setcolreg, info);	} else {		fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);	}	return 0;#undef sst_info}static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,                          int con, struct fb_info *info){#define sst_info	((struct sstfb_info *) info)	f_dprintk("sstfb_get_cmap\n");	f_ddprintk("con %d, curcon %d, cmap.len %d\n",		 con, sst_info->currcon, fb_display[con].cmap.len);	/* FIXME: check if con = -1 ? cf sstfb_set_cmap...  */	if (con == sst_info->currcon)		return fb_get_cmap(cmap, kspc, sstfb_getcolreg, info);	else if (fb_display[con].cmap.len)		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);	else		fb_copy_cmap(			fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),			cmap, kspc ? 0 : 2);	return 0;#undef sst_info}/* TODO */static int sstfb_pan_display(struct fb_var_screeninfo *var,                             int con, struct fb_info *info){	f_dprintk("sstfb_pan_display\n");	return -EINVAL;}static int sstfb_ioctl(struct inode *inode, struct file *file,                       u_int cmd, u_long arg, int con,                       struct fb_info *info){#define sst_info	((struct sstfb_info *) info)	int i;	u_long p;	u32 tmp, val;	u32 fbiinit0;	struct pci_dev * sst_dev = sst_info->dev;	f_dprintk("sstfb_ioctl(%x)\n", cmd);		switch (cmd) {		#if (SST_DEBUG_VAR >0)	/* tmp ioctl : dumps fb_display[0-5] */	case _IO('F', 0xdb):		/* 0x46db */		f_dprintk("dumping fb_display[0-5].var\n");		for (i = 0 ; i< 6 ; i++) {			print_var(&fb_display[i].var, "var(%d)", i);		}		return 0;#endif /* (SST_DEBUG_VAR >0) */	/* fills the lfb up to given count of pixels */	case _IOW('F', 0xdc, u32):	/* 0x46dc */		if (copy_from_user(&val, (void *) arg, sizeof(val)))			return -EFAULT;		if (val > 0x400000 )			val = 0x400000;		f_dprintk("filling %#x \n", val);		for (p = 0 ; p < val; p+=2)			writew( p >> 6 , sst_info->video.vbase + p);		return 0;			/* enable/disable VGA pass_through */	case _IOW('F', 0xdd, u32):	/* 0x46dd */		if (copy_from_user(&val, (void *) arg, sizeof(val)))			return -EFAULT;		f_dprintk("switch VGA pass-through\n");		pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,				       tmp | PCI_EN_INIT_WR );		fbiinit0 = sst_read (FBIINIT0);		if (val) {			sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);			iprintk ( "Disabling VGA pass-through\n");		} else {			sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);			iprintk ( "Enabling VGA pass-through\n");		}		pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);		return 0;	/* display test pattern */	case _IO('F', 0xde):		/* 0x46de */		f_dprintk("test color display\n");		f_ddprintk("currcon: %d, bpp %d\n", sst_info->currcon,			  sst_info->current_par.bpp);		memset_io(sst_info->video.vbase, 0, sst_info->video.len);		switch (sst_info->current_par.bpp) {	       	case 16:			sstfb_test16(sst_info);			break;#ifdef EN_24_32_BPP		case 24:		case 32:			sstfb_test32(sst_info);			break;#endif		default:			return -EFAULT;		}		return 0;	}		return -EINVAL;#undef sst_info}/* * Low level routines *//* get lfb size */static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize){	u_long fbbase_virt = sst_info->video.vbase;	f_dprintk("sst_get_memsize\n");	/* force memsize */	if ((mem >= 1 ) &&  (mem <= 4)) {		*memsize = (mem * 0x100000);		iprintk("supplied memsize: %#lx\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: %#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(u_long vbase){	int count = 0;	f_ddprintk("sst_wait_idle\n");	while(1) {		if (__sst_read(vbase, 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;//XXX  do something to avoid hanging the machine if the voodoo is out	}}/* * 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 __devinit sst_detect_dactype(struct sstfb_info * sst_info){	int ret=0,i;	f_dprintk("sst_detect_dactype\n");	for (i=0; i< sizeof(dacs)/sizeof(dacs[0]) ; i++) {		ret = dacs[i].detect(sst_info);		if (ret) break;	}	if (!ret)		return 0;	f_dprintk("found %s\n", dacs[i].name);	sst_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 __devinit sst_detect_att(struct sstfb_info * sst_info){	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 __devinit sst_detect_ti(struct sstfb_info * sst_info){	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 __devinit sst_detect_ics(struct sstfb_info * sst_info){	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(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock){	u8 cr0, cc;	f_dprintk("sst_set_pll_att_ti\n");

⌨️ 快捷键说明

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