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

📄 pm3fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	switch (info->fix.visual) {	case FB_VISUAL_PSEUDOCOLOR:		fgx = image->fg_color;		bgx = image->bg_color;		break;	case FB_VISUAL_TRUECOLOR:	default:		fgx = par->palette[image->fg_color];		bgx = par->palette[image->bg_color];		break;	}	if (image->depth != 1) {		cfb_imageblit(info, image);		return;	}	if (info->var.bits_per_pixel == 8) {		fgx |= fgx << 8;		bgx |= bgx << 8;	}	if (info->var.bits_per_pixel <= 16) {		fgx |= fgx << 16;		bgx |= bgx << 16;	}	PM3_WAIT(par, 7);	PM3_WRITE_REG(par, PM3ForegroundColor, fgx);	PM3_WRITE_REG(par, PM3BackgroundColor, bgx);	/* ROP Ox3 is GXcopy */	PM3_WRITE_REG(par, PM3Config2D,			PM3Config2D_UserScissorEnable |			PM3Config2D_UseConstantSource |			PM3Config2D_ForegroundROPEnable |			PM3Config2D_ForegroundROP(0x3) |			PM3Config2D_OpaqueSpan |			PM3Config2D_FBWriteEnable);	PM3_WRITE_REG(par, PM3ScissorMinXY,			((image->dy & 0x0fff) << 16) | (image->dx & 0x0fff));	PM3_WRITE_REG(par, PM3ScissorMaxXY,			(((image->dy + image->height) & 0x0fff) << 16) |			((image->dx + image->width) & 0x0fff));	PM3_WRITE_REG(par, PM3RectanglePosition,			PM3RectanglePosition_XOffset(image->dx) |			PM3RectanglePosition_YOffset(image->dy));	PM3_WRITE_REG(par, PM3Render2D,			PM3Render2D_XPositive |			PM3Render2D_YPositive |			PM3Render2D_Operation_SyncOnBitMask |			PM3Render2D_SpanOperation |			PM3Render2D_Width(image->width) |			PM3Render2D_Height(image->height));	while (height--) {		int width = ((image->width + 7) >> 3)				+ info->pixmap.scan_align - 1;		width >>= 2;		while (width >= PM3_FIFO_SIZE) {			int i = PM3_FIFO_SIZE - 1;			PM3_WAIT(par, PM3_FIFO_SIZE);			while (i--) {				PM3_WRITE_REG(par, PM3BitMaskPattern, *src);				src++;			}			width -= PM3_FIFO_SIZE - 1;		}		PM3_WAIT(par, width + 1);		while (width--) {			PM3_WRITE_REG(par, PM3BitMaskPattern, *src);			src++;		}	}}/* end of acceleration functions *//* *	Hardware Cursor support. */static const u8 cursor_bits_lookup[16] = {	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55};static int pm3fb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct pm3_par *par = info->par;	u8 mode;	if (!hwcursor)		return -EINVAL;	/* just to force soft_cursor() call */	/* Too large of a cursor or wrong bpp :-( */	if (cursor->image.width > 64 ||	    cursor->image.height > 64 ||	    cursor->image.depth > 1)		return -EINVAL;	mode = PM3RD_CursorMode_TYPE_X;	if (cursor->enable)		 mode |= PM3RD_CursorMode_CURSOR_ENABLE;	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode, mode);	/*	 * If the cursor is not be changed this means either we want the	 * current cursor state (if enable is set) or we want to query what	 * we can do with the cursor (if enable is not set)	 */	if (!cursor->set)		return 0;	if (cursor->set & FB_CUR_SETPOS) {		int x = cursor->image.dx - info->var.xoffset;		int y = cursor->image.dy - info->var.yoffset;		PM3_WRITE_DAC_REG(par, PM3RD_CursorXLow, x & 0xff);		PM3_WRITE_DAC_REG(par, PM3RD_CursorXHigh, (x >> 8) & 0xf);		PM3_WRITE_DAC_REG(par, PM3RD_CursorYLow, y & 0xff);		PM3_WRITE_DAC_REG(par, PM3RD_CursorYHigh, (y >> 8) & 0xf);	}	if (cursor->set & FB_CUR_SETHOT) {		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotX,				  cursor->hot.x & 0x3f);		PM3_WRITE_DAC_REG(par, PM3RD_CursorHotSpotY,				  cursor->hot.y & 0x3f);	}	if (cursor->set & FB_CUR_SETCMAP) {		u32 fg_idx = cursor->image.fg_color;		u32 bg_idx = cursor->image.bg_color;		struct fb_cmap cmap = info->cmap;		/* the X11 driver says one should use these color registers */		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(39),				  cmap.red[fg_idx] >> 8 );		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(40),				  cmap.green[fg_idx] >> 8 );		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(41),				  cmap.blue[fg_idx] >> 8 );		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(42),				  cmap.red[bg_idx] >> 8 );		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(43),				  cmap.green[bg_idx] >> 8 );		PM3_WRITE_DAC_REG(par, PM3RD_CursorPalette(44),				  cmap.blue[bg_idx] >> 8 );	}	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {		u8 *bitmap = (u8 *)cursor->image.data;		u8 *mask = (u8 *)cursor->mask;		int i;		int pos = PM3RD_CursorPattern(0);		for (i = 0; i < cursor->image.height; i++) {			int j = (cursor->image.width + 7) >> 3;			int k = 8 - j;			for (; j > 0; j--) {				u8 data = *bitmap ^ *mask;				if (cursor->rop == ROP_COPY)					data = *mask & *bitmap;				/* Upper 4 bits of bitmap data */				PM3_WRITE_DAC_REG(par, pos++,					cursor_bits_lookup[data >> 4] |					(cursor_bits_lookup[*mask >> 4] << 1));				/* Lower 4 bits of bitmap */				PM3_WRITE_DAC_REG(par, pos++,					cursor_bits_lookup[data & 0xf] |					(cursor_bits_lookup[*mask & 0xf] << 1));				bitmap++;				mask++;			}			for (; k > 0; k--) {				PM3_WRITE_DAC_REG(par, pos++, 0);				PM3_WRITE_DAC_REG(par, pos++, 0);			}		}		while (pos < PM3RD_CursorPattern(1024))			PM3_WRITE_DAC_REG(par, pos++, 0);	}	return 0;}/* write the mode to registers */static void pm3fb_write_mode(struct fb_info *info){	struct pm3_par *par = info->par;	char tempsync = 0x00;	char tempmisc = 0x00;	const u32 hsstart = info->var.right_margin;	const u32 hsend = hsstart + info->var.hsync_len;	const u32 hbend = hsend + info->var.left_margin;	const u32 xres = (info->var.xres + 31) & ~31;	const u32 htotal = xres + hbend;	const u32 vsstart = info->var.lower_margin;	const u32 vsend = vsstart + info->var.vsync_len;	const u32 vbend = vsend + info->var.upper_margin;	const u32 vtotal = info->var.yres + vbend;	const u32 width = (info->var.xres_virtual + 7) & ~7;	const unsigned bpp = info->var.bits_per_pixel;	PM3_WAIT(par, 20);	PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);	PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);	PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);	PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);	PM3_WRITE_REG(par, PM3HTotal,			   pm3fb_shift_bpp(bpp, htotal - 1));	PM3_WRITE_REG(par, PM3HsEnd,			   pm3fb_shift_bpp(bpp, hsend));	PM3_WRITE_REG(par, PM3HsStart,			   pm3fb_shift_bpp(bpp, hsstart));	PM3_WRITE_REG(par, PM3HbEnd,			   pm3fb_shift_bpp(bpp, hbend));	PM3_WRITE_REG(par, PM3HgEnd,			   pm3fb_shift_bpp(bpp, hbend));	PM3_WRITE_REG(par, PM3ScreenStride,			   pm3fb_shift_bpp(bpp, width));	PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);	PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);	PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);	PM3_WRITE_REG(par, PM3VbEnd, vbend);	switch (bpp) {	case 8:		PM3_WRITE_REG(par, PM3ByAperture1Mode,				   PM3ByApertureMode_PIXELSIZE_8BIT);		PM3_WRITE_REG(par, PM3ByAperture2Mode,				   PM3ByApertureMode_PIXELSIZE_8BIT);		break;	case 16:#ifndef __BIG_ENDIAN		PM3_WRITE_REG(par, PM3ByAperture1Mode,				   PM3ByApertureMode_PIXELSIZE_16BIT);		PM3_WRITE_REG(par, PM3ByAperture2Mode,				   PM3ByApertureMode_PIXELSIZE_16BIT);#else		PM3_WRITE_REG(par, PM3ByAperture1Mode,				   PM3ByApertureMode_PIXELSIZE_16BIT |				   PM3ByApertureMode_BYTESWAP_BADC);		PM3_WRITE_REG(par, PM3ByAperture2Mode,				   PM3ByApertureMode_PIXELSIZE_16BIT |				   PM3ByApertureMode_BYTESWAP_BADC);#endif /* ! __BIG_ENDIAN */		break;	case 32:#ifndef __BIG_ENDIAN		PM3_WRITE_REG(par, PM3ByAperture1Mode,				   PM3ByApertureMode_PIXELSIZE_32BIT);		PM3_WRITE_REG(par, PM3ByAperture2Mode,				   PM3ByApertureMode_PIXELSIZE_32BIT);#else		PM3_WRITE_REG(par, PM3ByAperture1Mode,				   PM3ByApertureMode_PIXELSIZE_32BIT |				   PM3ByApertureMode_BYTESWAP_DCBA);		PM3_WRITE_REG(par, PM3ByAperture2Mode,				   PM3ByApertureMode_PIXELSIZE_32BIT |				   PM3ByApertureMode_BYTESWAP_DCBA);#endif /* ! __BIG_ENDIAN */		break;	default:		DPRINTK("Unsupported depth %d\n", bpp);		break;	}	/*	 * Oxygen VX1 - it appears that setting PM3VideoControl and	 * then PM3RD_SyncControl to the same SYNC settings undoes	 * any net change - they seem to xor together.  Only set the	 * sync options in PM3RD_SyncControl.  --rmk	 */	{		unsigned int video = par->video;		video &= ~(PM3VideoControl_HSYNC_MASK |			   PM3VideoControl_VSYNC_MASK);		video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |			 PM3VideoControl_VSYNC_ACTIVE_HIGH;		PM3_WRITE_REG(par, PM3VideoControl, video);	}	PM3_WRITE_REG(par, PM3VClkCtl,			   (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));	PM3_WRITE_REG(par, PM3ScreenBase, par->base);	PM3_WRITE_REG(par, PM3ChipConfig,			   (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));	wmb();	{		unsigned char uninitialized_var(m);	/* ClkPreScale */		unsigned char uninitialized_var(n);	/* ClkFeedBackScale */		unsigned char uninitialized_var(p);	/* ClkPostScale */		unsigned long pixclock = PICOS2KHZ(info->var.pixclock);		(void)pm3fb_calculate_clock(pixclock, &m, &n, &p);		DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",			pixclock, (int) m, (int) n, (int) p);		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);		PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);	}	/*	   PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);	 */	/*	   PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);	 */	if ((par->video & PM3VideoControl_HSYNC_MASK) ==	    PM3VideoControl_HSYNC_ACTIVE_HIGH)		tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;	if ((par->video & PM3VideoControl_VSYNC_MASK) ==	    PM3VideoControl_VSYNC_ACTIVE_HIGH)		tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;	PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);	DPRINTK("PM3RD_SyncControl: %d\n", tempsync);	PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);	switch (pm3fb_depth(&info->var)) {	case 8:		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,				  PM3RD_PixelSize_8_BIT_PIXELS);		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,				  PM3RD_ColorFormat_CI8_COLOR |				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);		tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;		break;	case 12:		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,				  PM3RD_PixelSize_16_BIT_PIXELS);		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,				  PM3RD_ColorFormat_4444_COLOR |				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;		break;	case 15:		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,				  PM3RD_PixelSize_16_BIT_PIXELS);		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,				  PM3RD_ColorFormat_5551_FRONT_COLOR |				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;		break;	case 16:		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,				  PM3RD_PixelSize_16_BIT_PIXELS);		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,				  PM3RD_ColorFormat_565_FRONT_COLOR |				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;		break;	case 32:		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,				  PM3RD_PixelSize_32_BIT_PIXELS);		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,				  PM3RD_ColorFormat_8888_COLOR |				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;		break;	}	PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);}/* * hardware independent functions */static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	u32 lpitch;	unsigned bpp = var->red.length + var->green.length			+ var->blue.length + var->transp.length;	if (bpp != var->bits_per_pixel) {		/* set predefined mode for bits_per_pixel settings */		switch (var->bits_per_pixel) {		case 8:			var->red.length = 8;			var->green.length = 8;			var->blue.length = 8;			var->red.offset = 0;			var->green.offset = 0;			var->blue.offset = 0;			var->transp.offset = 0;			var->transp.length = 0;			break;		case 16:			var->red.length = 5;			var->blue.length = 5;			var->green.length = 6;			var->transp.length = 0;			break;		case 32:			var->red.length = 8;			var->green.length = 8;			var->blue.length = 8;			var->transp.length = 8;			break;		default:			DPRINTK("depth not supported: %u\n",				var->bits_per_pixel);			return -EINVAL;		}	}	/* it is assumed BGRA order */	if (var->bits_per_pixel > 8 ) {		var->blue.offset = 0;		var->green.offset = var->blue.length;		var->red.offset = var->green.offset + var->green.length;		var->transp.offset = var->red.offset + var->red.length;	}	var->height = -1;	var->width = -1;	if (var->xres != var->xres_virtual) {		DPRINTK("virtual x resolution != "			"physical x resolution not supported\n");		return -EINVAL;	}	if (var->yres > var->yres_virtual) {		DPRINTK("virtual y resolution < "			"physical y resolution not possible\n");		return -EINVAL;	}	if (var->xoffset) {		DPRINTK("xoffset not supported\n");		return -EINVAL;	}	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		DPRINTK("interlace not supported\n");		return -EINVAL;	}	var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */	lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);	if (var->xres < 200 || var->xres > 2048) {		DPRINTK("width not supported: %u\n", var->xres);		return -EINVAL;	}	if (var->yres < 200 || var->yres > 4095) {		DPRINTK("height not supported: %u\n", var->yres);		return -EINVAL;	}	if (lpitch * var->yres_virtual > info->fix.smem_len) {		DPRINTK("no memory for screen (%ux%ux%u)\n",			var->xres, var->yres_virtual, var->bits_per_pixel);		return -EINVAL;	}	if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {		DPRINTK("pixclock too high (%ldKHz)\n",			PICOS2KHZ(var->pixclock));		return -EINVAL;	}	var->accel_flags = 0;	/* Can't mmap if this is on */	DPRINTK("Checking graphics mode at %dx%d depth %d\n",		var->xres, var->yres, var->bits_per_pixel);	return 0;}static int pm3fb_set_par(struct fb_info *info){	struct pm3_par *par = info->par;	const u32 xres = (info->var.xres + 31) & ~31;	const unsigned bpp = info->var.bits_per_pixel;	par->base = pm3fb_shift_bpp(bpp, (info->var.yoffset * xres)					+ info->var.xoffset);	par->video = 0;	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)		par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;	else		par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)		par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;	else		par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)		par->video |= PM3VideoControl_LINE_DOUBLE_ON;	if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)		par->video |= PM3VideoControl_ENABLE;	else		DPRINTK("PM3Video disabled\n");	switch (bpp) {	case 8:		par->video |= PM3VideoControl_PIXELSIZE_8BIT;		break;	case 16:		par->video |= PM3VideoControl_PIXELSIZE_16BIT;		break;	case 32:		par->video |= PM3VideoControl_PIXELSIZE_32BIT;		break;	default:		DPRINTK("Unsupported depth\n");		break;

⌨️ 快捷键说明

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