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

📄 fbmon.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {		if (edid_is_serial_block(block)) {			copy_string(block, specs->serial_no);			DPRINTK("   Serial Number: %s\n", specs->serial_no);		} else if (edid_is_ascii_block(block)) {			copy_string(block, specs->ascii);			DPRINTK("   ASCII Block: %s\n", specs->ascii);		} else if (edid_is_monitor_block(block)) {			copy_string(block, specs->monitor);			DPRINTK("   Monitor Name: %s\n", specs->monitor);		}	}	DPRINTK("   Display Characteristics:\n");	get_monspecs(edid, specs);	specs->modedb = fb_create_modedb(edid, &specs->modedb_len);	/*	 * Workaround for buggy EDIDs that sets that the first	 * detailed timing is preferred but has not detailed	 * timing specified	 */	for (i = 0; i < specs->modedb_len; i++) {		if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {			found = 1;			break;		}	}	if (!found)		specs->misc &= ~FB_MISC_1ST_DETAIL;	DPRINTK("========================================\n");}/* * VESA Generalized Timing Formula (GTF) */#define FLYBACK                     550#define V_FRONTPORCH                1#define H_OFFSET                    40#define H_SCALEFACTOR               20#define H_BLANKSCALE                128#define H_GRADIENT                  600#define C_VAL                       30#define M_VAL                       300struct __fb_timings {	u32 dclk;	u32 hfreq;	u32 vfreq;	u32 hactive;	u32 vactive;	u32 hblank;	u32 vblank;	u32 htotal;	u32 vtotal;};/** * fb_get_vblank - get vertical blank time * @hfreq: horizontal freq * * DESCRIPTION: * vblank = right_margin + vsync_len + left_margin * *    given: right_margin = 1 (V_FRONTPORCH) *           vsync_len    = 3 *           flyback      = 550 * *                          flyback * hfreq *           left_margin  = --------------- - vsync_len *                           1000000 */static u32 fb_get_vblank(u32 hfreq){	u32 vblank;	vblank = (hfreq * FLYBACK)/1000;	vblank = (vblank + 500)/1000;	return (vblank + V_FRONTPORCH);}/** * fb_get_hblank_by_freq - get horizontal blank time given hfreq * @hfreq: horizontal freq * @xres: horizontal resolution in pixels * * DESCRIPTION: * *           xres * duty_cycle * hblank = ------------------ *           100 - duty_cycle * * duty cycle = percent of htotal assigned to inactive display * duty cycle = C - (M/Hfreq) * * where: C = ((offset - scale factor) * blank_scale) *            -------------------------------------- + scale factor *                        256 *        M = blank_scale * gradient * */static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres){	u32 c_val, m_val, duty_cycle, hblank;	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +		 H_SCALEFACTOR) * 1000;	m_val = (H_BLANKSCALE * H_GRADIENT)/256;	m_val = (m_val * 1000000)/hfreq;	duty_cycle = c_val - m_val;	hblank = (xres * duty_cycle)/(100000 - duty_cycle);	return (hblank);}/** * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock * @dclk: pixelclock in Hz * @xres: horizontal resolution in pixels * * DESCRIPTION: * *           xres * duty_cycle * hblank = ------------------ *           100 - duty_cycle * * duty cycle = percent of htotal assigned to inactive display * duty cycle = C - (M * h_period) * * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 *                   ----------------------------------------------- *                                    2 * M *        M = 300; *        C = 30; */static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres){	u32 duty_cycle, h_period, hblank;	dclk /= 1000;	h_period = 100 - C_VAL;	h_period *= h_period;	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);	h_period *= 10000;	h_period = int_sqrt(h_period);	h_period -= (100 - C_VAL) * 100;	h_period *= 1000;	h_period /= 2 * M_VAL;	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;	hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;	hblank &= ~15;	return (hblank);}/** * fb_get_hfreq - estimate hsync * @vfreq: vertical refresh rate * @yres: vertical resolution * * DESCRIPTION: * *          (yres + front_port) * vfreq * 1000000 * hfreq = ------------------------------------- *          (1000000 - (vfreq * FLYBACK) * */static u32 fb_get_hfreq(u32 vfreq, u32 yres){	u32 divisor, hfreq;	divisor = (1000000 - (vfreq * FLYBACK))/1000;	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;	return (hfreq/divisor);}static void fb_timings_vfreq(struct __fb_timings *timings){	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);	timings->vblank = fb_get_vblank(timings->hfreq);	timings->vtotal = timings->vactive + timings->vblank;	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,						 timings->hactive);	timings->htotal = timings->hactive + timings->hblank;	timings->dclk = timings->htotal * timings->hfreq;}static void fb_timings_hfreq(struct __fb_timings *timings){	timings->vblank = fb_get_vblank(timings->hfreq);	timings->vtotal = timings->vactive + timings->vblank;	timings->vfreq = timings->hfreq/timings->vtotal;	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,						 timings->hactive);	timings->htotal = timings->hactive + timings->hblank;	timings->dclk = timings->htotal * timings->hfreq;}static void fb_timings_dclk(struct __fb_timings *timings){	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,						timings->hactive);	timings->htotal = timings->hactive + timings->hblank;	timings->hfreq = timings->dclk/timings->htotal;	timings->vblank = fb_get_vblank(timings->hfreq);	timings->vtotal = timings->vactive + timings->vblank;	timings->vfreq = timings->hfreq/timings->vtotal;}/* * fb_get_mode - calculates video mode using VESA GTF * @flags: if: 0 - maximize vertical refresh rate *             1 - vrefresh-driven calculation; *             2 - hscan-driven calculation; *             3 - pixelclock-driven calculation; * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock * @var: pointer to fb_var_screeninfo * @info: pointer to fb_info * * DESCRIPTION: * Calculates video mode based on monitor specs using VESA GTF. * The GTF is best for VESA GTF compliant monitors but is * specifically formulated to work for older monitors as well. * * If @flag==0, the function will attempt to maximize the * refresh rate.  Otherwise, it will calculate timings based on * the flag and accompanying value. * * If FB_IGNOREMON bit is set in @flags, monitor specs will be * ignored and @var will be filled with the calculated timings. * * All calculations are based on the VESA GTF Spreadsheet * available at VESA's public ftp (http://www.vesa.org). * * NOTES: * The timings generated by the GTF will be different from VESA * DMT.  It might be a good idea to keep a table of standard * VESA modes as well.  The GTF may also not work for some displays, * such as, and especially, analog TV. * * REQUIRES: * A valid info->monspecs, otherwise 'safe numbers' will be used. */int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info){	struct __fb_timings *timings;	u32 interlace = 1, dscan = 1;	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;	timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);	if (!timings)		return -ENOMEM;	/*	 * If monspecs are invalid, use values that are enough	 * for 640x480@60	 */	if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||	    !info->monspecs.dclkmax ||	    info->monspecs.hfmax < info->monspecs.hfmin ||	    info->monspecs.vfmax < info->monspecs.vfmin ||	    info->monspecs.dclkmax < info->monspecs.dclkmin) {		hfmin = 29000; hfmax = 30000;		vfmin = 60; vfmax = 60;		dclkmin = 0; dclkmax = 25000000;	} else {		hfmin = info->monspecs.hfmin;		hfmax = info->monspecs.hfmax;		vfmin = info->monspecs.vfmin;		vfmax = info->monspecs.vfmax;		dclkmin = info->monspecs.dclkmin;		dclkmax = info->monspecs.dclkmax;	}	timings->hactive = var->xres;	timings->vactive = var->yres;	if (var->vmode & FB_VMODE_INTERLACED) {		timings->vactive /= 2;		interlace = 2;	}	if (var->vmode & FB_VMODE_DOUBLE) {		timings->vactive *= 2;		dscan = 2;	}	switch (flags & ~FB_IGNOREMON) {	case FB_MAXTIMINGS: /* maximize refresh rate */		timings->hfreq = hfmax;		fb_timings_hfreq(timings);		if (timings->vfreq > vfmax) {			timings->vfreq = vfmax;			fb_timings_vfreq(timings);		}		if (timings->dclk > dclkmax) {			timings->dclk = dclkmax;			fb_timings_dclk(timings);		}		break;	case FB_VSYNCTIMINGS: /* vrefresh driven */		timings->vfreq = val;		fb_timings_vfreq(timings);		break;	case FB_HSYNCTIMINGS: /* hsync driven */		timings->hfreq = val;		fb_timings_hfreq(timings);		break;	case FB_DCLKTIMINGS: /* pixelclock driven */		timings->dclk = PICOS2KHZ(val) * 1000;		fb_timings_dclk(timings);		break;	default:		err = -EINVAL;	}	if (err || (!(flags & FB_IGNOREMON) &&	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||	     timings->hfreq < hfmin || timings->hfreq > hfmax ||	     timings->dclk < dclkmin || timings->dclk > dclkmax))) {		err = -EINVAL;	} else {		var->pixclock = KHZ2PICOS(timings->dclk/1000);		var->hsync_len = (timings->htotal * 8)/100;		var->right_margin = (timings->hblank/2) - var->hsync_len;		var->left_margin = timings->hblank - var->right_margin -			var->hsync_len;		var->vsync_len = (3 * interlace)/dscan;		var->lower_margin = (1 * interlace)/dscan;		var->upper_margin = (timings->vblank * interlace)/dscan -			(var->vsync_len + var->lower_margin);	}	kfree(timings);	return err;}#elseint fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var){	return 1;}void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs){	specs = NULL;}void fb_destroy_modedb(struct fb_videomode *modedb){}int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,		struct fb_info *info){	return -EINVAL;}#endif /* CONFIG_FB_MODE_HELPERS *//* * fb_validate_mode - validates var against monitor capabilities * @var: pointer to fb_var_screeninfo * @info: pointer to fb_info * * DESCRIPTION: * Validates video mode against monitor capabilities specified in * info->monspecs. * * REQUIRES: * A valid info->monspecs. */int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info){	u32 hfreq, vfreq, htotal, vtotal, pixclock;	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;	/*	 * If monspecs are invalid, use values that are enough	 * for 640x480@60	 */	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||	    !info->monspecs.dclkmax ||	    info->monspecs.hfmax < info->monspecs.hfmin ||	    info->monspecs.vfmax < info->monspecs.vfmin ||	    info->monspecs.dclkmax < info->monspecs.dclkmin) {		hfmin = 29000; hfmax = 30000;		vfmin = 60; vfmax = 60;		dclkmin = 0; dclkmax = 25000000;	} else {		hfmin = info->monspecs.hfmin;		hfmax = info->monspecs.hfmax;		vfmin = info->monspecs.vfmin;		vfmax = info->monspecs.vfmax;		dclkmin = info->monspecs.dclkmin;		dclkmax = info->monspecs.dclkmax;	}	if (!var->pixclock)		return -EINVAL;	pixclock = PICOS2KHZ(var->pixclock) * 1000;	htotal = var->xres + var->right_margin + var->hsync_len +		var->left_margin;	vtotal = var->yres + var->lower_margin + var->vsync_len +		var->upper_margin;	if (var->vmode & FB_VMODE_INTERLACED)		vtotal /= 2;	if (var->vmode & FB_VMODE_DOUBLE)		vtotal *= 2;	hfreq = pixclock/htotal;	hfreq = (hfreq + 500) / 1000 * 1000;	vfreq = hfreq/vtotal;	return (vfreq < vfmin || vfreq > vfmax ||		hfreq < hfmin || hfreq > hfmax ||		pixclock < dclkmin || pixclock > dclkmax) ?		-EINVAL : 0;}#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)/* * We need to ensure that the EDID block is only returned for * the primary graphics adapter. */const unsigned char *fb_firmware_edid(struct device *device){	struct pci_dev *dev = NULL;	struct resource *res = NULL;	unsigned char *edid = NULL;	if (device)		dev = to_pci_dev(device);	if (dev)		res = &dev->resource[PCI_ROM_RESOURCE];	if (res && res->flags & IORESOURCE_ROM_SHADOW)		edid = edid_info.dummy;	return edid;}#elseconst unsigned char *fb_firmware_edid(struct device *device){	return NULL;}#endifEXPORT_SYMBOL(fb_firmware_edid);EXPORT_SYMBOL(fb_parse_edid);EXPORT_SYMBOL(fb_edid_to_monspecs);EXPORT_SYMBOL(fb_get_mode);EXPORT_SYMBOL(fb_validate_mode);EXPORT_SYMBOL(fb_destroy_modedb);

⌨️ 快捷键说明

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