cirrusfb.c

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

C
2,329
字号
			.red		= { .length = 8 },			.green		= { .length = 8 },			.blue		= { .length = 8 },			.width		= -1,			.height		= -1,			.pixclock	= 20000,			.left_margin	= 128,			.right_margin	= 16,			.upper_margin	= 24,			.lower_margin	= 2,			.hsync_len	= 96,			.vsync_len	= 6,			.vmode		= FB_VMODE_NONINTERLACED		 }	}, {		/*		 * Modeline from XF86Config:		 * Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805		 */		/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */		.name	= "1024x768",		.var	= {			.xres		= 1024,			.yres		= 768,			.xres_virtual	= 1024,			.yres_virtual	= 768,			.bits_per_pixel	= 8,			.red		= { .length = 8 },			.green		= { .length = 8 },			.blue		= { .length = 8 },			.width		= -1,			.height		= -1,			.pixclock	= 12500,			.left_margin	= 144,			.right_margin	= 32,			.upper_margin	= 30,			.lower_margin	= 2,			.hsync_len	= 192,			.vsync_len	= 6,			.vmode		= FB_VMODE_NONINTERLACED		}	}};#define NUM_TOTAL_MODES    ARRAY_SIZE(cirrusfb_predefined)/****************************************************************************//**** BEGIN PROTOTYPES ******************************************************//*--- Interface used by the world ------------------------------------------*/int cirrusfb_init (void);int cirrusfb_setup (char *options);int cirrusfb_open (struct fb_info *info, int user);int cirrusfb_release (struct fb_info *info, int user);int cirrusfb_setcolreg (unsigned regno, unsigned red, unsigned green,			unsigned blue, unsigned transp,			struct fb_info *info);int cirrusfb_check_var (struct fb_var_screeninfo *var,			struct fb_info *info);int cirrusfb_set_par (struct fb_info *info);int cirrusfb_pan_display (struct fb_var_screeninfo *var,			  struct fb_info *info);int cirrusfb_blank (int blank_mode, struct fb_info *info);void cirrusfb_fillrect (struct fb_info *info, const struct fb_fillrect *region);void cirrusfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);void cirrusfb_imageblit(struct fb_info *info, const struct fb_image *image);/* function table of the above functions */static struct fb_ops cirrusfb_ops = {	.owner		= THIS_MODULE,	.fb_open	= cirrusfb_open,	.fb_release	= cirrusfb_release,	.fb_setcolreg	= cirrusfb_setcolreg,	.fb_check_var	= cirrusfb_check_var,	.fb_set_par	= cirrusfb_set_par,	.fb_pan_display = cirrusfb_pan_display,	.fb_blank	= cirrusfb_blank,	.fb_fillrect	= cirrusfb_fillrect,	.fb_copyarea	= cirrusfb_copyarea,	.fb_imageblit	= cirrusfb_imageblit,	.fb_cursor	= soft_cursor,};/*--- Hardware Specific Routines -------------------------------------------*/static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,				struct cirrusfb_regs *regs,				const struct fb_info *info);/*--- Internal routines ----------------------------------------------------*/static void init_vgachip (struct cirrusfb_info *cinfo);static void switch_monitor (struct cirrusfb_info *cinfo, int on);static void WGen (const struct cirrusfb_info *cinfo,		  int regnum, unsigned char val);static unsigned char RGen (const struct cirrusfb_info *cinfo, int regnum);static void AttrOn (const struct cirrusfb_info *cinfo);static void WHDR (const struct cirrusfb_info *cinfo, unsigned char val);static void WSFR (struct cirrusfb_info *cinfo, unsigned char val);static void WSFR2 (struct cirrusfb_info *cinfo, unsigned char val);static void WClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,		   unsigned char green,		   unsigned char blue);#if 0static void RClut (struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,		   unsigned char *green,		   unsigned char *blue);#endifstatic void cirrusfb_WaitBLT (caddr_t regbase);static void cirrusfb_BitBLT (caddr_t regbase, int bits_per_pixel,			     u_short curx, u_short cury,			     u_short destx, u_short desty,			     u_short width, u_short height,			     u_short line_length);static void cirrusfb_RectFill (caddr_t regbase, int bits_per_pixel,			       u_short x, u_short y,			       u_short width, u_short height,			       u_char color, u_short line_length);static void bestclock (long freq, long *best,		       long *nom, long *den,		       long *div, long maxfreq);#ifdef CIRRUSFB_DEBUGstatic void cirrusfb_dump (void);static void cirrusfb_dbg_reg_dump (caddr_t regbase);static void cirrusfb_dbg_print_regs (caddr_t regbase, cirrusfb_dbg_reg_class_t reg_class,...);static void cirrusfb_dbg_print_byte (const char *name, unsigned char val);#endif /* CIRRUSFB_DEBUG *//*** END   PROTOTYPES ********************************************************//*****************************************************************************//*** BEGIN Interface Used by the World ***************************************/static int opencount = 0;/*--- Open /dev/fbx ---------------------------------------------------------*/int cirrusfb_open (struct fb_info *info, int user){	if (opencount++ == 0)		switch_monitor (info->par, 1);	return 0;}/*--- Close /dev/fbx --------------------------------------------------------*/int cirrusfb_release (struct fb_info *info, int user){	if (--opencount == 0)		switch_monitor (info->par, 0);	return 0;}/**** END   Interface used by the World *************************************//****************************************************************************//**** BEGIN Hardware specific Routines **************************************//* Get a good MCLK value */static long cirrusfb_get_mclk (long freq, int bpp, long *div){	long mclk;	assert (div != NULL);	/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.	 * Assume a 64-bit data path for now.  The formula is:	 * ((B * PCLK * 2)/W) * 1.2	 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */	mclk = ((bpp / 8) * freq * 2) / 4;	mclk = (mclk * 12) / 10;	if (mclk < 50000)		mclk = 50000;	DPRINTK ("Use MCLK of %ld kHz\n", mclk);	/* Calculate value for SR1F.  Multiply by 2 so we can round up. */	mclk = ((mclk * 16) / 14318);	mclk = (mclk + 1) / 2;	DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);	/* Determine if we should use MCLK instead of VCLK, and if so, what we	   * should divide it by to get VCLK */	switch (freq) {	case 24751 ... 25249:		*div = 2;		DPRINTK ("Using VCLK = MCLK/2\n");		break;	case 49501 ... 50499:		*div = 1;		DPRINTK ("Using VCLK = MCLK\n");		break;	default:		*div = 0;		break;	}	return mclk;}int cirrusfb_check_var(struct fb_var_screeninfo *var,		       struct fb_info *info){	struct cirrusfb_info *cinfo = info->par;	int nom, den;		/* translyting from pixels->bytes */	int yres, i;	static struct { int xres, yres; } modes[] =	{ { 1600, 1280 },	  { 1280, 1024 },	  { 1024, 768 },	  { 800, 600 },	  { 640, 480 },	  { -1, -1 } };	switch (var->bits_per_pixel) {	case 0 ... 1:		var->bits_per_pixel = 1;		nom = 4;		den = 8;		break;		/* 8 pixel per byte, only 1/4th of mem usable */	case 2 ... 8:		var->bits_per_pixel = 8;		nom = 1;		den = 1;		break;		/* 1 pixel == 1 byte */	case 9 ... 16:		var->bits_per_pixel = 16;		nom = 2;		den = 1;		break;		/* 2 bytes per pixel */	case 17 ... 24:		var->bits_per_pixel = 24;		nom = 3;		den = 1;		break;		/* 3 bytes per pixel */	case 25 ... 32:		var->bits_per_pixel = 32;		nom = 4;		den = 1;		break;		/* 4 bytes per pixel */	default:		printk ("cirrusfb: mode %dx%dx%d rejected...color depth not supported.\n",			var->xres, var->yres, var->bits_per_pixel);		DPRINTK ("EXIT - EINVAL error\n");		return -EINVAL;	}	if (var->xres * nom / den * var->yres > cinfo->size) {		printk ("cirrusfb: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",			var->xres, var->yres, var->bits_per_pixel);		DPRINTK ("EXIT - EINVAL error\n");		return -EINVAL;	}	/* use highest possible virtual resolution */	if (var->xres_virtual == -1 &&	    var->yres_virtual == -1) {		printk ("cirrusfb: using maximum available virtual resolution\n");		for (i = 0; modes[i].xres != -1; i++) {			if (modes[i].xres * nom / den * modes[i].yres < cinfo->size / 2)				break;		}		if (modes[i].xres == -1) {			printk ("cirrusfb: could not find a virtual resolution that fits into video memory!!\n");			DPRINTK ("EXIT - EINVAL error\n");			return -EINVAL;		}		var->xres_virtual = modes[i].xres;		var->yres_virtual = modes[i].yres;		printk ("cirrusfb: virtual resolution set to maximum of %dx%d\n",			var->xres_virtual, var->yres_virtual);	}	if (var->xres_virtual < var->xres)		var->xres_virtual = var->xres;	if (var->yres_virtual < var->yres)		var->yres_virtual = var->yres;	if (var->xoffset < 0)		var->xoffset = 0;	if (var->yoffset < 0)		var->yoffset = 0;	/* truncate xoffset and yoffset to maximum if too high */	if (var->xoffset > var->xres_virtual - var->xres)		var->xoffset = var->xres_virtual - var->xres - 1;	if (var->yoffset > var->yres_virtual - var->yres)		var->yoffset = var->yres_virtual - var->yres - 1;	switch (var->bits_per_pixel) {	case 1:		var->red.offset = 0;		var->red.length = 1;		var->green.offset = 0;		var->green.length = 1;		var->blue.offset = 0;		var->blue.length = 1;		break;	case 8:		var->red.offset = 0;		var->red.length = 6;		var->green.offset = 0;		var->green.length = 6;		var->blue.offset = 0;		var->blue.length = 6;		break;	case 16:		if(isPReP) {			var->red.offset = 2;			var->green.offset = -3;			var->blue.offset = 8;		} else {			var->red.offset = 10;			var->green.offset = 5;			var->blue.offset = 0;		}		var->red.length = 5;		var->green.length = 5;		var->blue.length = 5;		break;	case 24:		if(isPReP) {			var->red.offset = 8;			var->green.offset = 16;			var->blue.offset = 24;		} else {			var->red.offset = 16;			var->green.offset = 8;			var->blue.offset = 0;		}		var->red.length = 8;		var->green.length = 8;		var->blue.length = 8;		break;	case 32:		if(isPReP) {			var->red.offset = 8;			var->green.offset = 16;			var->blue.offset = 24;		} else {			var->red.offset = 16;			var->green.offset = 8;			var->blue.offset = 0;		}		var->red.length = 8;		var->green.length = 8;		var->blue.length = 8;		break;	default:		DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);		assert (FALSE);		/* should never occur */		break;	}	var->red.msb_right =	    var->green.msb_right =	    var->blue.msb_right =	    var->transp.offset =	    var->transp.length =	    var->transp.msb_right = 0;	yres = var->yres;	if (var->vmode & FB_VMODE_DOUBLE)		yres *= 2;	else if (var->vmode & FB_VMODE_INTERLACED)		yres = (yres + 1) / 2;	if (yres >= 1280) {		printk (KERN_WARNING "cirrusfb: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");		DPRINTK ("EXIT - EINVAL error\n");		return -EINVAL;	}	return 0;}static int cirrusfb_decode_var (const struct fb_var_screeninfo *var,				struct cirrusfb_regs *regs,				const struct fb_info *info){	long freq;	long maxclock;	int maxclockidx = 0;	struct cirrusfb_info *cinfo = info->par;	int xres, hfront, hsync, hback;	int yres, vfront, vsync, vback;	switch(var->bits_per_pixel) {	case 1:		regs->line_length = var->xres_virtual / 8;		regs->visual = FB_VISUAL_MONO10;		maxclockidx = 0;		break;	case 8:		regs->line_length = var->xres_virtual;		regs->visual = FB_VISUAL_PSEUDOCOLOR;		maxclockidx = 1;		break;	case 16:		regs->line_length = var->xres_virtual * 2;		regs->visual = FB_VISUAL_DIRECTCOLOR;		maxclockidx = 2;		break;	case 24:		regs->line_length = var->xres_virtual * 3;		regs->visual = FB_VISUAL_DIRECTCOLOR;		maxclockidx = 3;		break;	case 32:		regs->line_length = var->xres_virtual * 4;		regs->visual = FB_VISUAL_DIRECTCOLOR;		maxclockidx = 4;		break;	default:		DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel);		assert (FALSE);		/* should never occur */		break;	}	regs->type = FB_TYPE_PACKED_PIXELS;	/* convert from ps to kHz */	freq = 1000000000 / var->pixclock;	DPRINTK ("desired pixclock: %ld kHz\n", freq);	maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];	regs->multiplexing = 0;	/* If the frequency is greater than we can support, we might be able	 * to use multiplexing for the video mode */	if (freq > maxclock) {		switch (cinfo->btype) {		case BT_ALPINE:		case BT_GD5480:			regs->multiplexing = 1;			break;		default:			printk (KERN_WARNING "cirrusfb: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);			DPRINTK ("EXIT - return -EINVAL\n");			return -EINVAL;		}	}#if 0	/* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where	 * the VCLK is double the pixel clock. */	switch (var->bits_per_pixel) {	case 16:	case 32:		if (regs->HorizRes <= 800)			freq /= 2;	/* Xbh has this type of clock for 32-bit */		break;	}#endif	bestclock (freq, &regs->freq, &regs->nom, &regs->den, &regs->div,

⌨️ 快捷键说明

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