fbmon.c

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

C
1,261
字号
	specs->modedb = fb_create_modedb(edid, &specs->modedb_len);	DPRINTK("========================================\n");}char *get_EDID_from_firmware(struct device *dev){	unsigned char *pedid = NULL;#if defined(CONFIG_EDID_FIRMWARE) && defined(CONFIG_X86)	pedid = edid_info.dummy;	if (!pedid)		return NULL;#endif	return pedid;}/*  * 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;	/* 	 * 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;	}	memset(&timings, 0, sizeof(struct __fb_timings));	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:		return -EINVAL;			} 		if (!(flags & FB_IGNOREMON) && 	    (timings.vfreq < vfmin || timings.vfreq > vfmax || 	     timings.hfreq < hfmin || timings.hfreq > hfmax ||	     timings.dclk < dclkmin || timings.dclk > dclkmax))		return -EINVAL;	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);		return 0;}#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;}char *get_EDID_from_firmware(struct device *dev){	return NULL;}struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize){	return NULL;}void fb_destroy_modedb(struct fb_videomode *modedb){}int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs){	return 1;}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;	vfreq = hfreq/vtotal;	return (vfreq < vfmin || vfreq > vfmax || 		hfreq < hfmin || hfreq > hfmax ||		pixclock < dclkmin || pixclock > dclkmax) ?		-EINVAL : 0;}EXPORT_SYMBOL(fb_parse_edid);EXPORT_SYMBOL(fb_edid_to_monspecs);EXPORT_SYMBOL(get_EDID_from_firmware);EXPORT_SYMBOL(fb_get_mode);EXPORT_SYMBOL(fb_validate_mode);EXPORT_SYMBOL(fb_create_modedb);EXPORT_SYMBOL(fb_destroy_modedb);EXPORT_SYMBOL(fb_get_monitor_limits);

⌨️ 快捷键说明

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