sstfb.c

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

C
1,724
字号
	   || (var->hsync_len <= 1)	   || (hSyncOff <= 1)	   || (var->left_margin <= 2)	   || (vSyncOn <= 0)	   || (vSyncOff <= 0)	   || (vBackPorch <= 0)) {		return -EINVAL;	}	if (IS_VOODOO2(par)) {		/* Voodoo 2 limits */		tiles_in_X = (var->xres + 63 ) / 64 * 2;				if (((var->xres - 1) >= POW2(11)) || (yDim >= POW2(11))) {			eprintk("Unsupported resolution %dx%d\n",			         var->xres, var->yres);			return -EINVAL;		}		if (((var->hsync_len-1) >= POW2(9))		   || ((hSyncOff-1) >= POW2(11))		   || ((var->left_margin - 2) >= POW2(9))		   || (vSyncOn >= POW2(13))		   || (vSyncOff >= POW2(13))		   || (vBackPorch >= POW2(9))		   || (tiles_in_X >= POW2(6))		   || (tiles_in_X <= 0)) {			eprintk("Unsupported Timings\n");			return -EINVAL;		}	} else {		/* Voodoo limits */		tiles_in_X = (var->xres + 63 ) / 64;		if (var->vmode) {			eprintk("Interlace/Doublescan not supported %#x\n",				var->vmode);			return -EINVAL;		}		if (((var->xres - 1) >= POW2(10)) || (var->yres >= POW2(10))) {			eprintk("Unsupported resolution %dx%d\n",			         var->xres, var->yres);			return -EINVAL;		}		if (((var->hsync_len - 1) >= POW2(8))		   || ((hSyncOff-1) >= POW2(10))		   || ((var->left_margin - 2) >= POW2(8))		   || (vSyncOn >= POW2(12))		   || (vSyncOff >= POW2(12))		   || (vBackPorch >= POW2(8))		   || (tiles_in_X >= POW2(4))		   || (tiles_in_X <= 0)) {			eprintk("Unsupported Timings\n");			return -EINVAL;		}	}	/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */	/* FIXME: i don't like this... looks wrong */	real_length = tiles_in_X  * (IS_VOODOO2(par) ? 32 : 64 )	              * ((var->bits_per_pixel == 16) ? 2 : 4);	if ((real_length * yDim) > info->fix.smem_len) {		eprintk("Not enough video memory\n");		return -ENOMEM;	}	var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);	var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);	var->xoffset = 0;	var->yoffset = 0;	var->height  = -1;	var->width   = -1;	/*	 * correct the color bit fields	 */	/* var->{red|green|blue}.msb_right = 0; */	switch (var->bits_per_pixel) {	case 16:	/* RGB 565  LfbMode 0 */		var->red.length    = 5;		var->green.length  = 6;		var->blue.length   = 5;		var->transp.length = 0;		var->red.offset    = 11;		var->green.offset  = 5;		var->blue.offset   = 0;		var->transp.offset = 0;		break;#ifdef EN_24_32_BPP	case 24:	/* RGB 888 LfbMode 4 */	case 32:	/* ARGB 8888 LfbMode 5 */		var->red.length    = 8;		var->green.length  = 8;		var->blue.length   = 8;		var->transp.length = 0;		var->red.offset    = 16;		var->green.offset  = 8;		var->blue.offset   = 0;		var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */		break;#endif	default:		return -EINVAL;	}	return 0;}/** *      sstfb_set_par - Optional function.  Alters the hardware state. *      @info: frame buffer structure that represents a single frame buffer */static int sstfb_set_par(struct fb_info *info){	struct sstfb_par *par = (struct sstfb_par *) info->par;	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;	struct pci_dev *sst_dev = par->dev;	unsigned int freq;	int ntiles;	par->hSyncOff	= info->var.xres + info->var.right_margin + info->var.left_margin;	par->yDim 	= info->var.yres;	par->vSyncOn 	= info->var.vsync_len;	par->vSyncOff	= info->var.yres + info->var.lower_margin + info->var.upper_margin;	par->vBackPorch = info->var.upper_margin;	/* We need par->pll */	sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);	if (info->var.vmode & FB_VMODE_INTERLACED)		par->vBackPorch += (par->vBackPorch % 2);	if (info->var.vmode & FB_VMODE_DOUBLE) {		par->vBackPorch <<= 1;		par->yDim <<=1;		par->vSyncOn <<=1;		par->vSyncOff <<=1;	}	if (IS_VOODOO2(par)) {		/* voodoo2 has 32 pixel wide tiles , BUT stange things		   happen with odd number of tiles */		par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;	} else {		/* voodoo1 has 64 pixels wide tiles. */		par->tiles_in_X = (info->var.xres + 63 ) / 64;	}	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;#ifdef EN_24_32_BPP	case 24:	case 32:		/* sst_set_bits(FBIINIT1, SEL_SOURCE_VCLK_2X_DIV2 | EN_24BPP);*/		fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL | EN_24BPP;		break;#endif	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;#ifdef EN_24_32_BPP	case 24:		lfbmode = LFB_888;		break;	case 32:		lfbmode = LFB_8888;		break;#endif	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){	u32 col;	f_dddprintk("sstfb_setcolreg\n");	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",	            regno, red, green, blue, transp);	if (regno >= 16)		return -EINVAL;	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);		((u32 *)info->pseudo_palette)[regno] = col;	return 0;}static int sstfb_ioctl(struct inode *inode, struct file *file,                       u_int cmd, u_long arg, struct fb_info *info ){	struct sstfb_par *par = (struct sstfb_par *) info->par;	struct pci_dev *sst_dev = par->dev;	u32 fbiinit0, tmp, val;	u_long p;	switch (cmd) {			/* dump current FBIINIT values to system log */	case _IO('F', 0xdb):            /* 0x46db */		return sstfb_dump_regs(info);			/* fills lfb with #arg pixels */	case _IOW('F', 0xdc, u32):	/* 0x46dc */		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))			return -EFAULT;		if (val > info->fix.smem_len)			val = info->fix.smem_len;		printk("filling %#x \n", val);		for (p=0 ; p<val; p+=2)			writew(p >> 6, info->screen_base + p);		return 0;			/* change VGA pass_through mode */	case _IOW('F', 0xdd, u32):	/* 0x46dd */		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))			return -EFAULT;		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;			/* draw test image  */	case _IO('F', 0xde):		/* 0x46de */		f_dprintk("test color display at %d bpp\n",					info->var.bits_per_pixel);		sstfb_drawdebugimage(info);		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 = (struct sstfb_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 */static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) {	struct sstfb_par *par = (struct sstfb_par *) info->par;

⌨️ 快捷键说明

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