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

📄 lxfb_ops.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Set default watermark values */	rdmsrl(MSR_LX_SPARE_MSR, msrval);	msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO			| MSR_LX_SPARE_MSR_VFIFO_ARB_SEL			| MSR_LX_SPARE_MSR_LOAD_WM_LPEN_M			| MSR_LX_SPARE_MSR_WM_LPEN_OVRD);	msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM |			MSR_LX_SPARE_MSR_DIS_INIT_V_PRI;	wrmsrl(MSR_LX_SPARE_MSR, msrval);	gcfg = DC_GENERAL_CFG_DFLE;   /* Display fifo enable */	gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */			(0xb << DC_GENERAL_CFG_DFHPEL_SHIFT);	gcfg |= DC_GENERAL_CFG_FDTY;  /* Set the frame dirty mode */	dcfg  = DC_DISPLAY_CFG_VDEN;  /* Enable video data */	dcfg |= DC_DISPLAY_CFG_GDEN;  /* Enable graphics */	dcfg |= DC_DISPLAY_CFG_TGEN;  /* Turn on the timing generator */	dcfg |= DC_DISPLAY_CFG_TRUP;  /* Update timings immediately */	dcfg |= DC_DISPLAY_CFG_PALB;  /* Palette bypass in > 8 bpp modes */	dcfg |= DC_DISPLAY_CFG_VISL;	dcfg |= DC_DISPLAY_CFG_DCEN;  /* Always center the display */	/* Set the current BPP mode */	switch (info->var.bits_per_pixel) {	case 8:		dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;		break;	case 16:		dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;		break;	case 32:	case 24:		dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;		break;	}	/* Now - set up the timings */	hactive = info->var.xres;	hblankstart = hactive;	hsyncstart = hblankstart + info->var.right_margin;	hsyncend =  hsyncstart + info->var.hsync_len;	hblankend = hsyncend + info->var.left_margin;	htotal = hblankend;	vactive = info->var.yres;	vblankstart = vactive;	vsyncstart = vblankstart + info->var.lower_margin;	vsyncend =  vsyncstart + info->var.vsync_len;	vblankend = vsyncend + info->var.upper_margin;	vtotal = vblankend;	write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1) | ((htotal - 1) << 16));	write_dc(par, DC_H_BLANK_TIMING,			(hblankstart - 1) | ((hblankend - 1) << 16));	write_dc(par, DC_H_SYNC_TIMING,			(hsyncstart - 1) | ((hsyncend - 1) << 16));	write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1) | ((vtotal - 1) << 16));	write_dc(par, DC_V_BLANK_TIMING,			(vblankstart - 1) | ((vblankend - 1) << 16));	write_dc(par, DC_V_SYNC_TIMING,			(vsyncstart - 1) | ((vsyncend - 1) << 16));	write_dc(par, DC_FB_ACTIVE,			(info->var.xres - 1) << 16 | (info->var.yres - 1));	/* And re-enable the graphics output */	lx_graphics_enable(info);	/* Write the two main configuration registers */	write_dc(par, DC_DISPLAY_CFG, dcfg);	write_dc(par, DC_ARB_CFG, 0);	write_dc(par, DC_GENERAL_CFG, gcfg);	/* Lock the DC registers */	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);}void lx_set_palette_reg(struct fb_info *info, unsigned regno,			unsigned red, unsigned green, unsigned blue){	struct lxfb_par *par = info->par;	int val;	/* Hardware palette is in RGB 8-8-8 format. */	val  = (red   << 8) & 0xff0000;	val |= (green)      & 0x00ff00;	val |= (blue  >> 8) & 0x0000ff;	write_dc(par, DC_PAL_ADDRESS, regno);	write_dc(par, DC_PAL_DATA, val);}int lx_blank_display(struct fb_info *info, int blank_mode){	struct lxfb_par *par = info->par;	u32 dcfg, misc, fp_pm;	int blank, hsync, vsync;	/* CRT power saving modes. */	switch (blank_mode) {	case FB_BLANK_UNBLANK:		blank = 0; hsync = 1; vsync = 1;		break;	case FB_BLANK_NORMAL:		blank = 1; hsync = 1; vsync = 1;		break;	case FB_BLANK_VSYNC_SUSPEND:		blank = 1; hsync = 1; vsync = 0;		break;	case FB_BLANK_HSYNC_SUSPEND:		blank = 1; hsync = 0; vsync = 1;		break;	case FB_BLANK_POWERDOWN:		blank = 1; hsync = 0; vsync = 0;		break;	default:		return -EINVAL;	}	dcfg = read_vp(par, VP_DCFG);	dcfg &= ~(VP_DCFG_DAC_BL_EN | VP_DCFG_HSYNC_EN | VP_DCFG_VSYNC_EN |			VP_DCFG_CRT_EN);	if (!blank)		dcfg |= VP_DCFG_DAC_BL_EN | VP_DCFG_CRT_EN;	if (hsync)		dcfg |= VP_DCFG_HSYNC_EN;	if (vsync)		dcfg |= VP_DCFG_VSYNC_EN;	write_vp(par, VP_DCFG, dcfg);	misc = read_vp(par, VP_MISC);	if (vsync && hsync)		misc &= ~VP_MISC_DACPWRDN;	else		misc |= VP_MISC_DACPWRDN;	write_vp(par, VP_MISC, misc);	/* Power on/off flat panel */	if (par->output & OUTPUT_PANEL) {		fp_pm = read_fp(par, FP_PM);		if (blank_mode == FB_BLANK_POWERDOWN)			fp_pm &= ~FP_PM_P;		else			fp_pm |= FP_PM_P;		write_fp(par, FP_PM, fp_pm);	}	return 0;}#ifdef CONFIG_PMstatic void lx_save_regs(struct lxfb_par *par){	uint32_t filt;	int i;	/* wait for the BLT engine to stop being busy */	do {		i = read_gp(par, GP_BLT_STATUS);	} while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE));	/* save MSRs */	rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);	rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll);	rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);	rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);	write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);	/* save registers */	memcpy(par->gp, par->gp_regs, sizeof(par->gp));	memcpy(par->dc, par->dc_regs, sizeof(par->dc));	memcpy(par->vp, par->vp_regs, sizeof(par->vp));	memcpy(par->fp, par->vp_regs + VP_FP_START, sizeof(par->fp));	/* save the palette */	write_dc(par, DC_PAL_ADDRESS, 0);	for (i = 0; i < ARRAY_SIZE(par->pal); i++)		par->pal[i] = read_dc(par, DC_PAL_DATA);	/* save the horizontal filter coefficients */	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);		par->hcoeff[i] = read_dc(par, DC_FILT_COEFF1);		par->hcoeff[i + 1] = read_dc(par, DC_FILT_COEFF2);	}	/* save the vertical filter coefficients */	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);		par->vcoeff[i] = read_dc(par, DC_FILT_COEFF1);	}	/* save video coeff ram */	memcpy(par->vp_coeff, par->vp_regs + VP_VCR, sizeof(par->vp_coeff));}static void lx_restore_gfx_proc(struct lxfb_par *par){	int i;	/* a bunch of registers require GP_RASTER_MODE to be set first */	write_gp(par, GP_RASTER_MODE, par->gp[GP_RASTER_MODE]);	for (i = 0; i < ARRAY_SIZE(par->gp); i++) {		switch (i) {		case GP_RASTER_MODE:		case GP_VECTOR_MODE:		case GP_BLT_MODE:		case GP_BLT_STATUS:		case GP_HST_SRC:			/* FIXME: restore LUT data */		case GP_LUT_INDEX:		case GP_LUT_DATA:			/* don't restore these registers */			break;		default:			write_gp(par, i, par->gp[i]);		}	}}static void lx_restore_display_ctlr(struct lxfb_par *par){	uint32_t filt;	int i;	wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare);	for (i = 0; i < ARRAY_SIZE(par->dc); i++) {		switch (i) {		case DC_UNLOCK:			/* unlock the DC; runs first */			write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);			break;		case DC_GENERAL_CFG:		case DC_DISPLAY_CFG:			/* disable all while restoring */			write_dc(par, i, 0);			break;		case DC_DV_CTL:			/* set all ram to dirty */			write_dc(par, i, par->dc[i] | DC_DV_CTL_CLEAR_DV_RAM);		case DC_RSVD_1:		case DC_RSVD_2:		case DC_RSVD_3:		case DC_LINE_CNT:		case DC_PAL_ADDRESS:		case DC_PAL_DATA:		case DC_DFIFO_DIAG:		case DC_CFIFO_DIAG:		case DC_FILT_COEFF1:		case DC_FILT_COEFF2:		case DC_RSVD_4:		case DC_RSVD_5:			/* don't restore these registers */			break;		default:			write_dc(par, i, par->dc[i]);		}	}	/* restore the palette */	write_dc(par, DC_PAL_ADDRESS, 0);	for (i = 0; i < ARRAY_SIZE(par->pal); i++)		write_dc(par, DC_PAL_DATA, par->pal[i]);	/* restore the horizontal filter coefficients */	filt = par->dc[DC_IRQ_FILT_CTL] | DC_IRQ_FILT_CTL_H_FILT_SEL;	for (i = 0; i < ARRAY_SIZE(par->hcoeff); i += 2) {		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);		write_dc(par, DC_FILT_COEFF1, par->hcoeff[i]);		write_dc(par, DC_FILT_COEFF2, par->hcoeff[i + 1]);	}	/* restore the vertical filter coefficients */	filt &= ~DC_IRQ_FILT_CTL_H_FILT_SEL;	for (i = 0; i < ARRAY_SIZE(par->vcoeff); i++) {		write_dc(par, DC_IRQ_FILT_CTL, (filt & 0xffffff00) | i);		write_dc(par, DC_FILT_COEFF1, par->vcoeff[i]);	}}static void lx_restore_video_proc(struct lxfb_par *par){	int i;	wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg);	wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel);	for (i = 0; i < ARRAY_SIZE(par->vp); i++) {		switch (i) {		case VP_VCFG:		case VP_DCFG:		case VP_PAR:		case VP_PDR:		case VP_CCS:		case VP_RSVD_0:		/* case VP_VDC: */ /* why should this not be restored? */		case VP_RSVD_1:		case VP_CRC32:			/* don't restore these registers */			break;		default:			write_vp(par, i, par->vp[i]);		}	}	/* restore video coeff ram */	memcpy(par->vp_regs + VP_VCR, par->vp_coeff, sizeof(par->vp_coeff));}static void lx_restore_regs(struct lxfb_par *par){	int i;	lx_set_dotpll((u32) (par->msr.dotpll >> 32));	lx_restore_gfx_proc(par);	lx_restore_display_ctlr(par);	lx_restore_video_proc(par);	/* Flat Panel */	for (i = 0; i < ARRAY_SIZE(par->fp); i++) {		switch (i) {		case FP_PM:		case FP_RSVD_0:		case FP_RSVD_1:		case FP_RSVD_2:		case FP_RSVD_3:		case FP_RSVD_4:			/* don't restore these registers */			break;		default:			write_fp(par, i, par->fp[i]);		}	}	/* control the panel */	if (par->fp[FP_PM] & FP_PM_P) {		/* power on the panel if not already power{ed,ing} on */		if (!(read_fp(par, FP_PM) &				(FP_PM_PANEL_ON|FP_PM_PANEL_PWR_UP)))			write_fp(par, FP_PM, par->fp[FP_PM]);	} else {		/* power down the panel if not already power{ed,ing} down */		if (!(read_fp(par, FP_PM) &				(FP_PM_PANEL_OFF|FP_PM_PANEL_PWR_DOWN)))			write_fp(par, FP_PM, par->fp[FP_PM]);	}	/* turn everything on */	write_vp(par, VP_VCFG, par->vp[VP_VCFG]);	write_vp(par, VP_DCFG, par->vp[VP_DCFG]);	write_dc(par, DC_DISPLAY_CFG, par->dc[DC_DISPLAY_CFG]);	/* do this last; it will enable the FIFO load */	write_dc(par, DC_GENERAL_CFG, par->dc[DC_GENERAL_CFG]);	/* lock the door behind us */	write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);}int lx_powerdown(struct fb_info *info){	struct lxfb_par *par = info->par;	if (par->powered_down)		return 0;	lx_save_regs(par);	lx_graphics_disable(info);	par->powered_down = 1;	return 0;}int lx_powerup(struct fb_info *info){	struct lxfb_par *par = info->par;	if (!par->powered_down)		return 0;	lx_restore_regs(par);	par->powered_down = 0;	return 0;}#endif

⌨️ 快捷键说明

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