 if(vdisplay < 400) { h_sync_pol = 1; v_sync_pol = 0; } else if(vdisplay < 480) { h_sync_pol = 0; v_sync_pol = 1; } else if(vdisplay < 768) { h_sync_pol = 0; v_sync_pol = 0; } else { h_sync_pol = 1; v_sync_pol = 1; } 
static int aty_var_to_crtc(const struct fb_info *info,	const struct fb_var_screeninfo *var, struct crtc *crtc){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;	u32 sync, vmode, vdisplay;	u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;	u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;	u32 pix_width, dp_pix_width, dp_chain_mask;	/* input */	xres = var->xres;	yres = var->yres;	vxres = var->xres_virtual;	vyres = var->yres_virtual;	xoffset = var->xoffset;	yoffset = var->yoffset;	bpp = var->bits_per_pixel;	if (bpp == 16)		bpp = (var->green.length == 5) ? 15 : 16;	sync = var->sync;	vmode = var->vmode;	/* convert (and round up) and validate */	if (vxres < xres + xoffset)		vxres = xres + xoffset;	h_disp = xres;	if (vyres < yres + yoffset)		vyres = yres + yoffset;	v_disp = yres;	if (bpp <= 8) {		bpp = 8;		pix_width = CRTC_PIX_WIDTH_8BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_8BPP;	} else if (bpp <= 15) {		bpp = 16;		pix_width = CRTC_PIX_WIDTH_15BPP;		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_15BPP;	} else if (bpp <= 16) {		bpp = 16;		pix_width = CRTC_PIX_WIDTH_16BPP;		dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_16BPP;	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {		bpp = 24;		pix_width = CRTC_PIX_WIDTH_24BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_24BPP;	} else if (bpp <= 32) {		bpp = 32;		pix_width = CRTC_PIX_WIDTH_32BPP;		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_32BPP;	} else		FAIL("invalid bpp");	if (vxres * vyres * bpp / 8 > info->fix.smem_len)		FAIL("not enough video RAM");	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;	if((xres > 1600) || (yres > 1200)) {		FAIL("MACH64 chips are designed for max 1600x1200\n"		"select anoter resolution.");	}	h_sync_strt = h_disp + var->right_margin;	h_sync_end = h_sync_strt + var->hsync_len;	h_sync_dly  = var->right_margin & 7;	h_total = h_sync_end + h_sync_dly + var->left_margin;	v_sync_strt = v_disp + var->lower_margin;	v_sync_end = v_sync_strt + var->vsync_len;	v_total = v_sync_end + var->upper_margin;#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		if(!M64_HAS(LT_LCD_REGS)) {		    u32 lcd_index = aty_ld_le32(LCD_INDEX, par);		    crtc->lcd_index = lcd_index &			~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);		    aty_st_le32(LCD_INDEX, lcd_index, par);		}		if (!M64_HAS(MOBIL_BUS))			crtc->lcd_index |= CRTC2_DISPLAY_DIS;		crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000;		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;		crtc->lcd_gen_cntl &=			~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |			/*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/			USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;		if((crtc->lcd_gen_cntl & LCD_ON) &&			((xres > par->lcd_width) || (yres > par->lcd_height))) {			/* We cannot display the mode on the LCD. If the CRT is enabled			   we can turn off the LCD.			   If the CRT is off, it isn't a good idea to switch it on; we don't			   know if one is connected. So it's better to fail then.			 */			if (crtc->lcd_gen_cntl & CRT_ON) {				PRINTKI("Disable lcd panel, because video mode does not fit.\n");				crtc->lcd_gen_cntl &= ~LCD_ON;				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/			} else {				FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");			}		}	}	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {		int VScan = 1;		/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5		const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };		const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);		/* This is horror! When we simulate, say 640x480 on an 800x600		   lcd monitor, the CRTC should be programmed 800x600 values for		   the non visible part, but 640x480 for the visible part.		   This code has been tested on a laptop with it's 1400x1050 lcd		   monitor and a conventional monitor both switched on.		   Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,		    works with little glitches also with DOUBLESCAN modes		 */		if (yres < par->lcd_height) {			VScan = par->lcd_height / yres;			if(VScan > 1) {				VScan = 2;				vmode |= FB_VMODE_DOUBLE;			}		}		h_sync_strt = h_disp + par->lcd_right_margin;		h_sync_end = h_sync_strt + par->lcd_hsync_len;		h_sync_dly = /*DFP_h_sync_dly[ ( bpp + 1 ) / 3 ]; */par->lcd_hsync_dly;		h_total = h_disp + par->lcd_hblank_len;		v_sync_strt = v_disp + par->lcd_lower_margin / VScan;		v_sync_end = v_sync_strt + par->lcd_vsync_len / VScan;		v_total = v_disp + par->lcd_vblank_len / VScan;	}#endif /* CONFIG_FB_ATY_GENERIC_LCD */	h_disp = (h_disp >> 3) - 1;	h_sync_strt = (h_sync_strt >> 3) - 1;	h_sync_end = (h_sync_end >> 3) - 1;	h_total = (h_total >> 3) - 1;	h_sync_wid = h_sync_end - h_sync_strt;	FAIL_MAX("h_disp too large", h_disp, 0xff);	FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff);	/*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/	if(h_sync_wid > 0x1f)		h_sync_wid = 0x1f;	FAIL_MAX("h_total too large", h_total, 0x1ff);	if (vmode & FB_VMODE_DOUBLE) {		v_disp <<= 1;		v_sync_strt <<= 1;		v_sync_end <<= 1;		v_total <<= 1;	}	vdisplay = yres;#ifdef CONFIG_FB_ATY_GENERIC_LCD	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON))		vdisplay  = par->lcd_height;#endif	if(vdisplay < 400) {		h_sync_pol = 1;		v_sync_pol = 0;	} else if(vdisplay < 480) {		h_sync_pol = 0;		v_sync_pol = 1;	} else if(vdisplay < 768) {		h_sync_pol = 0;		v_sync_pol = 0;	} else {		h_sync_pol = 1;		v_sync_pol = 1;	}	v_disp--;	v_sync_strt--;	v_sync_end--;	v_total--;	v_sync_wid = v_sync_end - v_sync_strt;	FAIL_MAX("v_disp too large", v_disp, 0x7ff);	FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff);	/*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/	if(v_sync_wid > 0x1f)		v_sync_wid = 0x1f;	FAIL_MAX("v_total too large", v_total, 0x7ff);	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;	/* output */	crtc->vxres = vxres;	crtc->vyres = vyres;	crtc->xoffset = xoffset;	crtc->yoffset = yoffset;	crtc->bpp = bpp;	crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);	crtc->vline_crnt_vline = 0;	crtc->h_tot_disp = h_total | (h_disp<<16);	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |		((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21);	crtc->v_tot_disp = v_total | (v_disp<<16);	crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);	/* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */	crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync;	crtc->gen_cntl |= CRTC_VGA_LINEAR;	/* Enable doublescan mode if requested */	if (vmode & FB_VMODE_DOUBLE)		crtc->gen_cntl |= CRTC_DBL_SCAN_EN;	/* Enable interlaced mode if requested */	if (vmode & FB_VMODE_INTERLACED)		crtc->gen_cntl |= CRTC_INTERLACE_EN;#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		vdisplay = yres;		if(vmode & FB_VMODE_DOUBLE)			vdisplay <<= 1;		if(vmode & FB_VMODE_INTERLACED) {			vdisplay >>= 1;			/* The prefered mode for the lcd is not interlaced, so disable it if			   it was enabled. For doublescan there is no problem, because we can			   compensate for it in the hardware stretching (we stretch half as much)			 */			vmode &= ~FB_VMODE_INTERLACED;			/*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/		}		crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);		crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |			/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/			USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);		crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/);		/* MOBILITY M1 tested, FIXME: LT */		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);		if (!M64_HAS(LT_LCD_REGS))			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) &				~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3);		crtc->horz_stretching &=			~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |			HORZ_STRETCH_MODE | HORZ_STRETCH_EN);		if (xres < par->lcd_width) {			do {				/*				* The horizontal blender misbehaves when HDisplay is less than a				* a certain threshold (440 for a 1024-wide panel).  It doesn't				* stretch such modes enough.  Use pixel replication instead of				* blending to stretch modes that can be made to exactly fit the				* panel width.  The undocumented "NoLCDBlend" option allows the				* pixel-replicated mode to be slightly wider or narrower than the				* panel width.  It also causes a mode that is exactly half as wide				* as the panel to be pixel-replicated, rather than blended.				*/				int HDisplay  = xres & ~7;				int nStretch  = par->lcd_width / HDisplay;				int Remainder = par->lcd_width % HDisplay;				if ((!Remainder && ((nStretch > 2))) ||					(((HDisplay * 16) / par->lcd_width) < 7)) {					static const char StretchLoops[] = {10, 12, 13, 15, 16};					int horz_stretch_loop = -1, BestRemainder;					int Numerator = HDisplay, Denominator = par->lcd_width;					int Index = 5;					ATIReduceRatio(&Numerator, &Denominator);					BestRemainder = (Numerator * 16) / Denominator;					while (--Index >= 0) {						Remainder = ((Denominator - Numerator) * StretchLoops[Index]) %							Denominator;						if (Remainder < BestRemainder) {							horz_stretch_loop = Index;							if (!(BestRemainder = Remainder))								break;						}					}					if ((horz_stretch_loop >= 0) && !BestRemainder) {						int horz_stretch_ratio = 0, Accumulator = 0;						int reuse_previous = 1;						Index = StretchLoops[horz_stretch_loop];						while (--Index >= 0) {							if (Accumulator > 0)								horz_stretch_ratio |= reuse_previous;							else								Accumulator += Denominator;							Accumulator -= Numerator;							reuse_previous <<= 1;						}						crtc->horz_stretching |= (HORZ_STRETCH_EN |							((horz_stretch_loop & HORZ_STRETCH_LOOP) << 16) |							(horz_stretch_ratio & HORZ_STRETCH_RATIO));						break;      /* Out of the do { ... } while (0) */					}				}				crtc->horz_stretching |= (HORZ_STRETCH_MODE | HORZ_STRETCH_EN |					(((HDisplay * (HORZ_STRETCH_BLEND + 1)) / par->lcd_width) & HORZ_STRETCH_BLEND));			} while (0);		}		if (vdisplay < par->lcd_height) {			crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |				(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));			if (!M64_HAS(LT_LCD_REGS) &&			    xres <= (M64_HAS(MOBIL_BUS)?1024:800))				crtc->ext_vert_stretch |= VERT_STRETCH_MODE;		} else {			/*			 * Don't use vertical blending if the mode is too wide or not			 * vertically stretched.			 */			crtc->vert_stretching = 0;		}		/* copy to shadow crtc */		crtc->shadow_h_tot_disp = crtc->h_tot_disp;		crtc->shadow_h_sync_strt_wid = crtc->h_sync_strt_wid;		crtc->shadow_v_tot_disp = crtc->v_tot_disp;		crtc->shadow_v_sync_strt_wid = crtc->v_sync_strt_wid;	}#endif /* CONFIG_FB_ATY_GENERIC_LCD */	if (M64_HAS(MAGIC_FIFO)) {		/* Not VTB/GTB */		/* FIXME: magic FIFO values */		crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);	}	crtc->dp_pix_width = dp_pix_width;	crtc->dp_chain_mask = dp_chain_mask;	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/2a43b58589eac1fdcf62624e86c67c0f92f45bf7/atyfb_base.c/clean/drivers/video/aty/atyfb_base.c