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

📄 radeon_base.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,                           unsigned long arg, struct fb_info *info){        struct radeonfb_info *rinfo = info->par;	unsigned int tmp;	u32 value = 0;	int rc;	switch (cmd) {		/*		 * TODO:  set mirror accordingly for non-Mobility chipsets with 2 CRTC's		 *        and do something better using 2nd CRTC instead of just hackish		 *        routing to second output		 */		case FBIO_RADEON_SET_MIRROR:			if (!rinfo->is_mobility)				return -EINVAL;			rc = get_user(value, (__u32 __user *)arg);			if (rc)				return rc;			radeon_fifo_wait(2);			if (value & 0x01) {				tmp = INREG(LVDS_GEN_CNTL);				tmp |= (LVDS_ON | LVDS_BLON);			} else {				tmp = INREG(LVDS_GEN_CNTL);				tmp &= ~(LVDS_ON | LVDS_BLON);			}			OUTREG(LVDS_GEN_CNTL, tmp);			if (value & 0x02) {				tmp = INREG(CRTC_EXT_CNTL);				tmp |= CRTC_CRT_ON;				mirror = 1;			} else {				tmp = INREG(CRTC_EXT_CNTL);				tmp &= ~CRTC_CRT_ON;				mirror = 0;			}			OUTREG(CRTC_EXT_CNTL, tmp);			return 0;		case FBIO_RADEON_GET_MIRROR:			if (!rinfo->is_mobility)				return -EINVAL;			tmp = INREG(LVDS_GEN_CNTL);			if ((LVDS_ON | LVDS_BLON) & tmp)				value |= 0x01;			tmp = INREG(CRTC_EXT_CNTL);			if (CRTC_CRT_ON & tmp)				value |= 0x02;			return put_user(value, (__u32 __user *)arg);		default:			return -EINVAL;	}	return -EINVAL;}int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch){        u32 val;	u32 tmp_pix_clks;	int unblank = 0;	if (rinfo->lock_blank)		return 0;	radeon_engine_idle();	val = INREG(CRTC_EXT_CNTL);        val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |                 CRTC_VSYNC_DIS);        switch (blank) {	case FB_BLANK_VSYNC_SUSPEND:		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS);		break;	case FB_BLANK_HSYNC_SUSPEND:		val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS);		break;	case FB_BLANK_POWERDOWN:		val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |			CRTC_HSYNC_DIS);		break;	case FB_BLANK_NORMAL:		val |= CRTC_DISPLAY_DIS;		break;	case FB_BLANK_UNBLANK:	default:		unblank = 1;        }	OUTREG(CRTC_EXT_CNTL, val);	switch (rinfo->mon1_type) {	case MT_DFP:		if (unblank)			OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN),				~(FP_FPON | FP_TMDS_EN));		else {			if (mode_switch || blank == FB_BLANK_NORMAL)				break;			OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN));		}		break;	case MT_LCD:		del_timer_sync(&rinfo->lvds_timer);		val = INREG(LVDS_GEN_CNTL);		if (unblank) {			u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON				| LVDS_EN | (rinfo->init_state.lvds_gen_cntl					     & (LVDS_DIGON | LVDS_BL_MOD_EN));			if ((val ^ target_val) == LVDS_DISPLAY_DIS)				OUTREG(LVDS_GEN_CNTL, target_val);			else if ((val ^ target_val) != 0) {				OUTREG(LVDS_GEN_CNTL, target_val				       & ~(LVDS_ON | LVDS_BL_MOD_EN));				rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;				rinfo->init_state.lvds_gen_cntl |=					target_val & LVDS_STATE_MASK;				if (mode_switch) {					radeon_msleep(rinfo->panel_info.pwr_delay);					OUTREG(LVDS_GEN_CNTL, target_val);				}				else {					rinfo->pending_lvds_gen_cntl = target_val;					mod_timer(&rinfo->lvds_timer,					   jiffies +					   msecs_to_jiffies(rinfo->panel_info.pwr_delay));				}			}		} else {			val |= LVDS_DISPLAY_DIS;			OUTREG(LVDS_GEN_CNTL, val);			/* We don't do a full switch-off on a simple mode switch */			if (mode_switch || blank == FB_BLANK_NORMAL)				break;			/* Asic bug, when turning off LVDS_ON, we have to make sure			 * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off			 */			tmp_pix_clks = INPLL(PIXCLKS_CNTL);			if (rinfo->is_mobility || rinfo->is_IGP)				OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);			val &= ~(LVDS_BL_MOD_EN);			OUTREG(LVDS_GEN_CNTL, val);			udelay(100);			val &= ~(LVDS_ON | LVDS_EN);			OUTREG(LVDS_GEN_CNTL, val);			val &= ~LVDS_DIGON;			rinfo->pending_lvds_gen_cntl = val;			mod_timer(&rinfo->lvds_timer,				  jiffies +				  msecs_to_jiffies(rinfo->panel_info.pwr_delay));			rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;			rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK;			if (rinfo->is_mobility || rinfo->is_IGP)				OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);		}		break;	case MT_CRT:		// todo: powerdown DAC	default:		break;	}	/* let fbcon do a soft blank for us */	return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0;}static int radeonfb_blank (int blank, struct fb_info *info){        struct radeonfb_info *rinfo = info->par;	if (rinfo->asleep)		return 0;			return radeon_screen_blank(rinfo, blank, 0);}static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,                             unsigned blue, unsigned transp,			     struct radeonfb_info *rinfo){	u32 pindex;	unsigned int i;	if (regno > 255)		return 1;	red >>= 8;	green >>= 8;	blue >>= 8;	rinfo->palette[regno].red = red;	rinfo->palette[regno].green = green;	rinfo->palette[regno].blue = blue;        /* default */        pindex = regno;        if (!rinfo->asleep) {		radeon_fifo_wait(9);		if (rinfo->bpp == 16) {			pindex = regno * 8;			if (rinfo->depth == 16 && regno > 63)				return 1;			if (rinfo->depth == 15 && regno > 31)				return 1;			/* For 565, the green component is mixed one order			 * below			 */			if (rinfo->depth == 16) {		                OUTREG(PALETTE_INDEX, pindex>>1);	       	         	OUTREG(PALETTE_DATA,				       (rinfo->palette[regno>>1].red << 16) |	                        	(green << 8) |				       (rinfo->palette[regno>>1].blue));	                	green = rinfo->palette[regno<<1].green;	        	}		}		if (rinfo->depth != 16 || regno < 32) {			OUTREG(PALETTE_INDEX, pindex);			OUTREG(PALETTE_DATA, (red << 16) |			       (green << 8) | blue);		}	} 	if (regno < 16) {		u32 *pal = rinfo->info->pseudo_palette;        	switch (rinfo->depth) {		case 15:			pal[regno] = (regno << 10) | (regno << 5) | regno;			break;		case 16:			pal[regno] = (regno << 11) | (regno << 5) | regno;			break;		case 24:			pal[regno] = (regno << 16) | (regno << 8) | regno;			break;		case 32:			i = (regno << 8) | regno;			pal[regno] = (i << 16) | i;			break;		}        }	return 0;}static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green,			       unsigned blue, unsigned transp,			       struct fb_info *info){        struct radeonfb_info *rinfo = info->par;	u32 dac_cntl2, vclk_cntl = 0;	int rc;        if (!rinfo->asleep) {		if (rinfo->is_mobility) {			vclk_cntl = INPLL(VCLK_ECP_CNTL);			OUTPLL(VCLK_ECP_CNTL,			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);		}		/* Make sure we are on first palette */		if (rinfo->has_CRTC2) {			dac_cntl2 = INREG(DAC_CNTL2);			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;			OUTREG(DAC_CNTL2, dac_cntl2);		}	}	rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo);	if (!rinfo->asleep && rinfo->is_mobility)		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);	return rc;}static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info){        struct radeonfb_info *rinfo = info->par;	u16 *red, *green, *blue, *transp;	u32 dac_cntl2, vclk_cntl = 0;	int i, start, rc = 0;        if (!rinfo->asleep) {		if (rinfo->is_mobility) {			vclk_cntl = INPLL(VCLK_ECP_CNTL);			OUTPLL(VCLK_ECP_CNTL,			       vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);		}		/* Make sure we are on first palette */		if (rinfo->has_CRTC2) {			dac_cntl2 = INREG(DAC_CNTL2);			dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;			OUTREG(DAC_CNTL2, dac_cntl2);		}	}	red = cmap->red;	green = cmap->green;	blue = cmap->blue;	transp = cmap->transp;	start = cmap->start;	for (i = 0; i < cmap->len; i++) {		u_int hred, hgreen, hblue, htransp = 0xffff;		hred = *red++;		hgreen = *green++;		hblue = *blue++;		if (transp)			htransp = *transp++;		rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp,				       rinfo);		if (rc)			break;	}	if (!rinfo->asleep && rinfo->is_mobility)		OUTPLL(VCLK_ECP_CNTL, vclk_cntl);	return rc;}static void radeon_save_state (struct radeonfb_info *rinfo,			       struct radeon_regs *save){	/* CRTC regs */	save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);	save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL);	save->crtc_more_cntl = INREG(CRTC_MORE_CNTL);	save->dac_cntl = INREG(DAC_CNTL);        save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP);        save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID);        save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP);        save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID);	save->crtc_pitch = INREG(CRTC_PITCH);	save->surface_cntl = INREG(SURFACE_CNTL);	/* FP regs */	save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP);	save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP);	save->fp_gen_cntl = INREG(FP_GEN_CNTL);	save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID);	save->fp_horz_stretch = INREG(FP_HORZ_STRETCH);	save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID);	save->fp_vert_stretch = INREG(FP_VERT_STRETCH);	save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL);	save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL);	save->tmds_crc = INREG(TMDS_CRC);	save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL);	save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);	/* PLL regs */	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;	radeon_pll_errata_after_index(rinfo);	save->ppll_div_3 = INPLL(PPLL_DIV_3);	save->ppll_ref_div = INPLL(PPLL_REF_DIV);}static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode){	int i;	radeon_fifo_wait(20);	/* Workaround from XFree */	if (rinfo->is_mobility) {	        /* A temporal workaround for the occational blanking on certain laptop		 * panels. This appears to related to the PLL divider registers		 * (fail to lock?). It occurs even when all dividers are the same		 * with their old settings. In this case we really don't need to		 * fiddle with PLL registers. By doing this we can avoid the blanking		 * problem with some panels.	         */		if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&		    (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &					  (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {			/* We still have to force a switch to selected PPLL div thanks to			 * an XFree86 driver bug which will switch it away in some cases			 * even when using UseFDev */			OUTREGP(CLOCK_CNTL_INDEX,				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,				~PPLL_DIV_SEL_MASK);			radeon_pll_errata_after_index(rinfo);			radeon_pll_errata_after_data(rinfo);            		return;		}	}	/* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/	OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);	/* Reset PPLL & enable atomic update */	OUTPLLP(PPLL_CNTL,		PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,		~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));	/* Switch to selected PPLL divider */	OUTREGP(CLOCK_CNTL_INDEX,		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,		~PPLL_DIV_SEL_MASK);	radeon_pll_errata_after_index(rinfo);	radeon_pll_errata_after_data(rinfo);	/* Set PPLL ref. div */	if (rinfo->family == CHIP_FAMILY_R300 ||	    rinfo->family == CHIP_FAMILY_RS300 ||

⌨️ 快捷键说明

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