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

📄 sstfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");	f_ddprintk("%-7d %-8d %-7d %-8d\n",	           info->var.hsync_len, par->hSyncOff,	           par->vSyncOn, par->vSyncOff);	f_ddprintk("left_margin upper_margin xres yres Freq\n");	f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",	           info->var.left_margin, info->var.upper_margin,	           info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));	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 | (info->var.left_margin - 2));	sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));	sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 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 );	par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);	/* set video clock */	par->dac_sw.set_pll(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(par)) {		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 (info->var.bits_per_pixel) {	case 16:		fbiinit1 |=  SEL_SOURCE_VCLK_2X_SEL;		break;	default:		return -EINVAL;	}	sst_write(FBIINIT1, fbiinit1);	if (IS_VOODOO2(par)) {		sst_write(FBIINIT6, fbiinit6);		fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;		if (info->var.vmode & FB_VMODE_INTERLACED)			fbiinit5 |= INTERLACE;		if (info->var.vmode & FB_VMODE_DOUBLE)			fbiinit5 |= VDOUBLESCAN;		if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)			fbiinit5 |= HSYNC_HIGH;		if (info->var.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 (info->var.bits_per_pixel) {	case 16:		lfbmode = LFB_565;		break;	default:		return -EINVAL;	}#if defined(__BIG_ENDIAN)	/* Enable byte-swizzle functionality in hardware.	 * With this enabled, all our read- and write-accesses to	 * the voodoo framebuffer can be done in native format, and	 * the hardware will automatically convert it to little-endian.	 * - tested on HP-PARISC, Helge Deller <deller@gmx.de> */	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",		            info->var.xres - 1, par->yDim - 1);		sst_write(CLIP_LEFT_RIGHT, info->var.xres);		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);	}	return 0;}/** *      sstfb_setcolreg - Optional function. Sets a color register. *      @regno: hardware colormap register *      @red: frame buffer colormap structure *      @green: The green value which can be up to 16 bits wide *      @blue:  The blue value which can be up to 16 bits wide. *      @transp: If supported the alpha value which can be up to 16 bits wide. *      @info: frame buffer info structure */static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,                           u_int transp, struct fb_info *info){	struct sstfb_par *par = info->par;	u32 col;	f_dddprintk("sstfb_setcolreg\n");	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",	            regno, red, green, blue, transp);	if (regno > 15)		return 0;	red    >>= (16 - info->var.red.length);	green  >>= (16 - info->var.green.length);	blue   >>= (16 - info->var.blue.length);	transp >>= (16 - info->var.transp.length);	col = (red << info->var.red.offset)	    | (green << info->var.green.offset)	    | (blue  << info->var.blue.offset)	    | (transp << info->var.transp.offset);		par->palette[regno] = col;	return 0;}static void sstfb_setvgapass( struct fb_info *info, int enable ){	struct sstfb_par *par = info->par;	struct pci_dev *sst_dev = par->dev;	u32 fbiinit0, tmp;	enable = enable ? 1:0;	if (par->vgapass == enable)		return;	par->vgapass = enable;	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 (par->vgapass) {		sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);		printk(KERN_INFO "fb%d: Enabling VGA pass-through\n", info->node );	} else {		sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);		printk(KERN_INFO "fb%d: Disabling VGA pass-through\n", info->node );	}	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);}static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,			const char *buf, size_t count){	struct fb_info *info = dev_get_drvdata(device);	char ** last = NULL;	int val;	val = simple_strtoul(buf, last, 0);	sstfb_setvgapass(info, val);	return count;}static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,			char *buf){	struct fb_info *info = dev_get_drvdata(device);	struct sstfb_par *par = info->par;	return snprintf(buf, PAGE_SIZE, "%d\n", par->vgapass);}static struct device_attribute device_attrs[] = {	__ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)	};static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,			unsigned long arg){	struct sstfb_par *par;	u32 val;	switch (cmd) {	/* set/get VGA pass_through mode */	case SSTFB_SET_VGAPASS:		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))			return -EFAULT;		sstfb_setvgapass(info, val);		return 0;	case SSTFB_GET_VGAPASS:		par = info->par;		val = par->vgapass;		if (copy_to_user((void __user *)arg, &val, sizeof(val)))			return -EFAULT;		return 0;	}	return -EINVAL;}/* * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only */#if 0static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area){	struct sstfb_par *par = info->par;	u32 stride = info->fix.line_length;   	if (!IS_VOODOO2(par))		return;	sst_write(BLTSRCBASEADDR, 0);	sst_write(BLTDSTBASEADDR, 0);	sst_write(BLTROP, BLTROP_COPY);	sst_write(BLTXYSTRIDES, stride | (stride << 16));	sst_write(BLTSRCXY, area->sx | (area->sy << 16));	sst_write(BLTDSTXY, area->dx | (area->dy << 16));	sst_write(BLTSIZE, area->width | (area->height << 16));	sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |		(BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) );	sst_wait_idle();}#endif/* * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only */#if 0static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) {	struct sstfb_par *par = info->par;	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();}#endif/*  * get lfb size  */static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize){	u8 __iomem *fbbase_virt = info->screen_base;	/* force memsize */	if (mem >= 1  && mem <= 4) {		*memsize = (mem * 0x100000);		printk(KERN_INFO "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 = 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 = 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 = 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 = 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",		        __func__, 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){

⌨️ 快捷键说明

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