i810_main.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,063 行 · 第 1/4 页

C
2,063
字号
	case 32:		if (info->var.nonstd)			fix->visual = FB_VISUAL_DIRECTCOLOR;		else			fix->visual = FB_VISUAL_TRUECOLOR;	    	break;	default:		return -EINVAL;	}    	fix->ywrapstep = 0;	fix->line_length = par->pitch;	fix->mmio_start = par->mmio_start_phys;	fix->mmio_len = MMIO_SIZE;	fix->accel = FB_ACCEL_I810;	return 0;}/** * decode_var - modify par according to contents of var * @var: pointer to fb_var_screeninfo * @par: pointer to i810fb_par * * DESCRIPTION: * Based on the contents of @var, @par will be dynamically filled up. * @par contains all information necessary to modify the hardware. */static void decode_var(const struct fb_var_screeninfo *var, 		       struct i810fb_par *par){	u32 xres, yres, vxres, vyres;	xres = var->xres;	yres = var->yres;	vxres = var->xres_virtual;	vyres = var->yres_virtual;	switch (var->bits_per_pixel) {	case 8:		par->pixconf = PIXCONF8;		par->bltcntl = 0;		par->depth = 1;		par->blit_bpp = BPP8;		break;	case 16:		if (var->green.length == 5)			par->pixconf = PIXCONF15;		else			par->pixconf = PIXCONF16;		par->bltcntl = 16;		par->depth = 2;		par->blit_bpp = BPP16;		break;	case 24:		par->pixconf = PIXCONF24;		par->bltcntl = 32;		par->depth = 3;		par->blit_bpp = BPP24;		break;	case 32:		par->pixconf = PIXCONF32;		par->bltcntl = 0;		par->depth = 4;		par->blit_bpp = 3 << 24;		break;	}	if (var->nonstd && var->bits_per_pixel != 8)		par->pixconf |= 1 << 27;	i810_calc_dclk(var->pixclock, &par->regs.M, 		       &par->regs.N, &par->regs.P);	i810fb_encode_registers(var, par, xres, yres);	par->watermark = i810_get_watermark(var, par);	par->pitch = get_line_length(par, vxres, var->bits_per_pixel);}	/** * i810fb_getcolreg - gets red, green and blue values of the hardware DAC * @regno: DAC index * @red: red * @green: green * @blue: blue * @transp: transparency (alpha) * @info: pointer to fb_info * * DESCRIPTION: * Gets the red, green and blue values of the hardware DAC as pointed by @regno * and writes them to @red, @green and @blue respectively */static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 			    u8 *transp, struct fb_info *info){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u8 *mmio = par->mmio_start_virtual, temp;	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {		if ((info->var.green.length == 5 && regno > 31) ||		    (info->var.green.length == 6 && regno > 63))			return 1;	}	temp = i810_readb(PIXCONF1, mmio);	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 	    info->var.green.length == 5) 		i810_read_dac(regno * 8, red, green, blue, mmio);	else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 		 info->var.green.length == 6) {		u8 tmp;		i810_read_dac(regno * 8, red, &tmp, blue, mmio);		i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);	}	else 		i810_read_dac(regno, red, green, blue, mmio);    	*transp = 0;	i810_writeb(PIXCONF1, mmio, temp);    	return 0;}/******************************************************************  *           Framebuffer device-specific hooks                    * ******************************************************************/static int i810fb_open(struct fb_info *info, int user){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u32 count = atomic_read(&par->use_count);		if (count == 0) {		memset(&par->state, 0, sizeof(struct vgastate));		par->state.flags = VGA_SAVE_CMAP;		par->state.vgabase = (caddr_t) par->mmio_start_virtual;		save_vga(&par->state);		i810_save_vga_state(par);	}	atomic_inc(&par->use_count);		return 0;}static int i810fb_release(struct fb_info *info, int user){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u32 count;		count = atomic_read(&par->use_count);	if (count == 0)		return -EINVAL;	if (count == 1) {		i810_restore_vga_state(par);		restore_vga(&par->state);	}	atomic_dec(&par->use_count);		return 0;}static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, 			    unsigned blue, unsigned transp, 			    struct fb_info *info){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u8 *mmio = par->mmio_start_virtual, temp;	int i; 	if (regno > 255) return 1;	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {		if ((info->var.green.length == 5 && regno > 31) ||		    (info->var.green.length == 6 && regno > 63))			return 1;	}	if (info->var.grayscale)		red = green = blue = (19595 * red + 38470 * green +				      7471 * blue) >> 16;	temp = i810_readb(PIXCONF1, mmio);	i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 	    info->var.green.length == 5) {		for (i = 0; i < 8; i++) 			i810_write_dac((u8) (regno * 8) + i, (u8) red, 				       (u8) green, (u8) blue, mmio);	} else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 		 info->var.green.length == 6) {		u8 r, g, b;		if (regno < 32) {			for (i = 0; i < 8; i++) 				i810_write_dac((u8) (regno * 8) + i,					       (u8) red, (u8) green, 					       (u8) blue, mmio);		}		i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);		for (i = 0; i < 4; i++) 			i810_write_dac((u8) (regno*4) + i, r, (u8) green, 				       b, mmio);	} else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {		i810_write_dac((u8) regno, (u8) red, (u8) green,			       (u8) blue, mmio);	}	i810_writeb(PIXCONF1, mmio, temp);	if (regno < 16) {		switch (info->var.bits_per_pixel) {		case 16:				if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {				if (info->var.green.length == 5) 					((u32 *)info->pseudo_palette)[regno] = 						(regno << 10) | (regno << 5) |						regno;				else					((u32 *)info->pseudo_palette)[regno] = 						(regno << 11) | (regno << 5) |						regno;			} else {				if (info->var.green.length == 5) {					/* RGB 555 */					((u32 *)info->pseudo_palette)[regno] = 						((red & 0xf800) >> 1) |						((green & 0xf800) >> 6) |						((blue & 0xf800) >> 11);				} else {					/* RGB 565 */					((u32 *)info->pseudo_palette)[regno] =						(red & 0xf800) |						((green & 0xf800) >> 5) |						((blue & 0xf800) >> 11);				}			}			break;		case 24:	/* RGB 888 */		case 32:	/* RGBA 8888 */			if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 				((u32 *)info->pseudo_palette)[regno] = 					(regno << 16) | (regno << 8) |					regno;			else 				((u32 *)info->pseudo_palette)[regno] = 					((red & 0xff00) << 8) |					(green & 0xff00) |					((blue & 0xff00) >> 8);			break;		}	}	return 0;}static int i810fb_pan_display(struct fb_var_screeninfo *var, 			      struct fb_info *info){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u32 total;		total = var->xoffset * par->depth + 		var->yoffset * info->fix.line_length;	i810fb_load_front(total, info);	return 0;}static int i810fb_blank (int blank_mode, struct fb_info *info){	struct i810fb_par *par = (struct i810fb_par *) info->par;	u8 *mmio = par->mmio_start_virtual;	int mode = 0, pwr, scr_off = 0;		pwr = i810_readl(PWR_CLKC, mmio);	switch(blank_mode) {	case VESA_NO_BLANKING:		mode = POWERON;		pwr |= 1;		scr_off = ON;		break;	case VESA_VSYNC_SUSPEND:		mode = STANDBY;		pwr |= 1;		scr_off = OFF;		break;	case VESA_HSYNC_SUSPEND:		mode = SUSPEND;		pwr |= 1;		scr_off = OFF;		break;	case VESA_POWERDOWN:		mode = POWERDOWN;		pwr &= ~1;		scr_off = OFF;		break;	default:		return -EINVAL; 	}	i810_screen_off(mmio, scr_off);	i810_writel(HVSYNC, mmio, mode);	i810_writel(PWR_CLKC, mmio, pwr);	return 0;}static int i810fb_set_par(struct fb_info *info){	struct i810fb_par *par = (struct i810fb_par *) info->par;	decode_var(&info->var, par);	i810_load_regs(par);	i810_init_cursor(par);	encode_fix(&info->fix, info);	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) 		info->pixmap.scan_align = 2;	else 		info->pixmap.scan_align = 1;		return 0;}static int i810fb_check_var(struct fb_var_screeninfo *var, 			    struct fb_info *info){	int err;	if (IS_DVT) {		var->vmode &= ~FB_VMODE_MASK;		var->vmode |= FB_VMODE_NONINTERLACED;	}	if (var->vmode & FB_VMODE_DOUBLE) {		var->vmode &= ~FB_VMODE_MASK;		var->vmode |= FB_VMODE_NONINTERLACED;	}	i810_round_off(var);	if ((err = i810_check_params(var, info)))		return err;	i810fb_fill_var_timings(var);	set_color_bitfields(var);	return 0;}static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct i810fb_par *par = (struct i810fb_par *)info->par;	u8 *mmio = par->mmio_start_virtual;		u8 data[64 * 8];		if (!info->var.accel_flags || par->dev_flags & LOCKUP) 		return soft_cursor(info, cursor);	if (cursor->image.width > 64 || cursor->image.height > 64)		return -ENXIO;	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)		i810_init_cursor(par);	i810_enable_cursor(mmio, OFF);	if (cursor->set & FB_CUR_SETHOT)		info->cursor.hot = cursor->hot;		if (cursor->set & FB_CUR_SETPOS) {		u32 tmp;		info->cursor.image.dx = cursor->image.dx;		info->cursor.image.dy = cursor->image.dy;				tmp = cursor->image.dx - info->var.xoffset;		tmp |= (cursor->image.dy - info->var.yoffset) << 16;	    		i810_writel(CURPOS, mmio, tmp);	}	if (cursor->set & FB_CUR_SETSIZE) {		info->cursor.image.height = cursor->image.height;		info->cursor.image.width = cursor->image.width;		i810_reset_cursor_image(par);	}	if (cursor->set & FB_CUR_SETCMAP) {		info->cursor.image.fg_color = cursor->image.fg_color;		info->cursor.image.bg_color = cursor->image.bg_color;		i810_load_cursor_colors(cursor->image.fg_color,					cursor->image.bg_color,					info);	}	if (cursor->set & FB_CUR_SETSHAPE) {		int size = ((info->cursor.image.width + 7) >> 3) * 			     info->cursor.image.height;		int i;		switch (info->cursor.rop) {		case ROP_XOR:			for (i = 0; i < size; i++)				data[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 			break;		case ROP_COPY:		default:			for (i = 0; i < size; i++)				data[i] = cursor->image.data[i] & info->cursor.mask[i]; 			break;		}		i810_load_cursor_image(info->cursor.image.width, 				       info->cursor.image.height, data,				       par);	}	if (info->cursor.enable)		i810_enable_cursor(mmio, ON);	return 0;}static struct fb_ops i810fb_ops __devinitdata = {	.owner =             THIS_MODULE,	.fb_open =           i810fb_open,	.fb_release =        i810fb_release,	.fb_check_var =      i810fb_check_var,	.fb_set_par =        i810fb_set_par,	.fb_setcolreg =      i810fb_setcolreg,	.fb_blank =          i810fb_blank,	.fb_pan_display =    i810fb_pan_display, 	.fb_fillrect =       i810fb_fillrect,	.fb_copyarea =       i810fb_copyarea,	.fb_imageblit =      i810fb_imageblit,	.fb_cursor =         i810fb_cursor,	.fb_sync =           i810fb_sync,};/*********************************************************************** *                         Power Management                            * ***********************************************************************/static int i810fb_suspend(struct pci_dev *dev, u32 state){	struct fb_info *info = pci_get_drvdata(dev);	struct i810fb_par *par = (struct i810fb_par *) info->par;	int blank = 0, prev_state = par->cur_state;	if (state == prev_state)		return 0;	par->cur_state = state;	switch (state) {	case 1:		blank = VESA_VSYNC_SUSPEND;		break;	case 2:		blank = VESA_HSYNC_SUSPEND;		break;	case 3:		blank = VESA_POWERDOWN;		break;	default:		return -EINVAL;	}	info->fbops->fb_blank(blank, info);	if (!prev_state) { 		par->drm_agp->unbind_memory(par->i810_gtt.i810_fb_memory);		par->drm_agp->unbind_memory(par->i810_gtt.i810_cursor_memory);		pci_disable_device(dev);	}	pci_save_state(dev, par->pci_state);	pci_set_power_state(dev, state);	return 0;}static int i810fb_resume(struct pci_dev *dev) {	struct fb_info *info = pci_get_drvdata(dev);	struct i810fb_par *par = (struct i810fb_par *) info->par;	if (par->cur_state == 0)		return 0;	pci_restore_state(dev, par->pci_state);	pci_set_power_state(dev, 0);	pci_enable_device(dev);	par->drm_agp->bind_memory(par->i810_gtt.i810_fb_memory, 				  par->fb.offset);	par->drm_agp->bind_memory(par->i810_gtt.i810_cursor_memory, 				  par->cursor_heap.offset);	info->fbops->fb_blank(VESA_NO_BLANKING, info);	par->cur_state = 0;	return 0;}/*********************************************************************** *                  AGP resource allocation                            * ***********************************************************************/  static void __devinit i810_fix_pointers(struct i810fb_par *par){      	par->fb.physical = par->aperture.physical+(par->fb.offset << 12);	par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);	par->iring.physical = par->aperture.physical + 		(par->iring.offset << 12);	par->iring.virtual = par->aperture.virtual + 		(par->iring.offset << 12);

⌨️ 快捷键说明

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