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

📄 s3c2410_sm501.c

📁 s3c2410 sm501 在SMDK开发包的可运行源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*                  sm501_blank		* Save the old colormap and video mode.		*/		disp->var = fbi->fb.var;		if (disp->cmap.len)			fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);	}	fbi->currcon = con;	disp = fb_display + con;	/*	* Make sure that our colourmap contains 256 entries.	*/	fb_alloc_cmap(&fbi->fb.cmap, 256, 0);	if (disp->cmap.len)		cmap = &disp->cmap;	else		cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);	fb_copy_cmap(cmap, &fbi->fb.cmap, 0);	fbi->fb.var = disp->var;	fbi->fb.var.activate = FB_ACTIVATE_NOW;	sm501_set_var(&fbi->fb.var, con, info);	return 0;}static void sm501_blank(int blank, struct fb_info *info){	struct sm501_info *fbi = (struct sm501_info *)info;	DPRINTK("sm501_blank: blank=%d info->modename=%s\n", blank,		fbi->fb.modename);	switch (blank) {case VESA_POWERDOWN:case VESA_VSYNC_SUSPEND:case VESA_HSYNC_SUSPEND:	sm501_schedule_task(fbi, C_DISABLE);/*	if (sm501_blank_helper)	sm501_blank_helper(blank); */	printk("disable pw\n");    //hqj	break;case VESA_NO_BLANKING:/*	if (sm501_blank_helper)		sm501_blank_helper(blank);*/	sm501_schedule_task(fbi, C_ENABLE);	}}static int sm501_updatevar(int con, struct fb_info *info){	DPRINTK("entered\n");	return 0;}/** NOTE!  The following functions are purely helpers for set_ctrlr_state.* Do not call them directly; set_ctrlr_state does the correct serialisation* to ensure that things happen in the right way 100% of time time.*	-- rmk*//** FIXME: move LCD power stuff into sm501_power_up_lcd()* Also, I'm expecting that the backlight stuff should* be handled differently.*/static void sm501_backlight_on(struct sm501_info *fbi){	DPRINTK("backlight on\n");}static void sm501_backlight_off(struct sm501_info *fbi){	DPRINTK("backlight off\n");}static void sm501_power_up_lcd(struct sm501_info *fbi){	DPRINTK("LCD power on\n");}static void sm501_power_down_lcd(struct sm501_info *fbi){	DPRINTK("LCD power off\n");}static void sm501_power_up_chip(struct sm501_info *fbi){	u_long power_mode_ctrl = regRead32(POWER_MODE_CTRL);	u_long timeout = 100000;	if (FIELD_GET(power_mode_ctrl, POWER_MODE_CTRL, MODE) != POWER_MODE_CTRL_MODE_SLEEP) {		// already powered up - remember the current mode and return		sm501_last_power_mode = FIELD_GET(power_mode_ctrl, POWER_MODE_CTRL, MODE);		return;	}	power_mode_ctrl = FIELD_VALUE(power_mode_ctrl, POWER_MODE_CTRL, MODE, sm501_last_power_mode);	regWrite32(POWER_MODE_CTRL, power_mode_ctrl);	while (FIELD_GET(regRead32(POWER_MODE_CTRL), POWER_MODE_CTRL, SLEEP_STATUS) !=		POWER_MODE_CTRL_SLEEP_STATUS_INACTIVE) {			timeout--;			if (!timeout) {				printk(KERN_WARNING "Silicon Motion 501 wakeup timed out\n");				break;			}		}}static void sm501_power_down_chip(struct sm501_info *fbi){	u_long power_mode_ctrl = regRead32(POWER_MODE_CTRL);	DPRINTK("power off SM501 chip\n");	sm501_last_power_mode = FIELD_GET(power_mode_ctrl, POWER_MODE_CTRL, MODE);	power_mode_ctrl = FIELD_SET(power_mode_ctrl, POWER_MODE_CTRL, MODE, SLEEP);	regWrite32(POWER_MODE_CTRL, power_mode_ctrl);}static void sm501_enable_controller(struct sm501_info *fbi){	if (fbi->fb_type & SM501_PANEL) {		u_long panel_ctrl = regRead32(PANEL_DISPLAY_CTRL);		DPRINTK("Enabling LCD controller\n");		panel_ctrl = FIELD_SET(panel_ctrl, PANEL_DISPLAY_CTRL, PLANE, ENABLE);		regWrite32(PANEL_DISPLAY_CTRL, panel_ctrl);	}	if (fbi->fb_type & (SM501_CRT | SM501_DUPLICATE)) {		u_long panel_ctrl = regRead32(CRT_DISPLAY_CTRL);		DPRINTK("Enabling CRT controller\n");		panel_ctrl = FIELD_SET(panel_ctrl, CRT_DISPLAY_CTRL, PLANE, ENABLE);		panel_ctrl = FIELD_SET(panel_ctrl, CRT_DISPLAY_CTRL, BLANK, OFF);		panel_ctrl = FIELD_SET(panel_ctrl, CRT_DISPLAY_CTRL, SELECT, PANEL);    //hqj		regWrite32(CRT_DISPLAY_CTRL, panel_ctrl);	}}static void sm501_disable_controller(struct sm501_info *fbi){	u_long panel_ctrl = 0;	DECLARE_WAITQUEUE(wait, current);	add_wait_queue(&fbi->ctrlr_wait, &wait);	set_current_state(TASK_UNINTERRUPTIBLE);	if (fbi->fb_type & SM501_PANEL) {		DPRINTK("Disabling LCD controller\n");		panel_ctrl = regRead32(PANEL_DISPLAY_CTRL);		panel_ctrl = FIELD_SET(panel_ctrl, PANEL_DISPLAY_CTRL, PLANE, DISABLE);		regWrite32(PANEL_DISPLAY_CTRL, panel_ctrl);	}	if (fbi->fb_type & (SM501_CRT | SM501_DUPLICATE)) {		DPRINTK("Disabling CRT controller\n");		panel_ctrl = regRead32(CRT_DISPLAY_CTRL);		panel_ctrl = FIELD_SET(panel_ctrl, CRT_DISPLAY_CTRL, PLANE, DISABLE);		panel_ctrl = FIELD_SET(panel_ctrl, CRT_DISPLAY_CTRL, BLANK, ON);		regWrite32(CRT_DISPLAY_CTRL, panel_ctrl);	}	schedule_timeout(20 * HZ / 1000);	current->state = TASK_RUNNING;	remove_wait_queue(&fbi->ctrlr_wait, &wait);}/** This function must be called from task context only, since it will* sleep when disabling the LCD controller, or if we get two contending* processes trying to alter state.*/static void set_ctrlr_state(struct sm501_info *fbi, u_int state){	u_int old_state;	down(&fbi->ctrlr_sem);	old_state = fbi->state;	switch (state) {case C_DISABLE:	/*	* Disable controller	*/	if (old_state != C_DISABLE) {		fbi->state = state;		if (fbi->fb_type & SM501_PANEL) {			sm501_backlight_off(fbi);		}		sm501_disable_controller(fbi);		if (fbi->fb_type & SM501_PANEL) {			sm501_power_down_lcd(fbi);		}	}	break;case C_REENABLE:	/*	* Re-enable the controller only if it was already	* enabled.  This is so we reprogram the control	* registers.	*/	if (old_state == C_ENABLE) {		sm501_disable_controller(fbi);		sm501_enable_controller(fbi);	}	break;case C_ENABLE:	/*	* Power up the LCD screen, enable controller, and	* turn on the backlight.	*/	if (old_state != C_ENABLE) {		fbi->state = C_ENABLE;		if (fbi->fb_type & SM501_PANEL) {			sm501_power_up_lcd(fbi);		}		sm501_enable_controller(fbi);		if (fbi->fb_type & SM501_PANEL) {			sm501_backlight_on(fbi);		}	}	break;	}	up(&fbi->ctrlr_sem);}/** Our LCD controller task (which is called when we blank or unblank)* via keventd.*/static void sm501_task(void *dummy){	struct sm501_info *fbi = dummy;	u_int state = xchg(&fbi->task_state, -1);	set_ctrlr_state(fbi, state);}#ifdef CONFIG_PM/** Power management hook.  Note that we won't be called from IRQ context,* unlike the blank functions above, so we may sleep.*/static intsm501_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	struct sm501_info *fbi = pm_dev->data;	DPRINTK("pm_callback: %d\n", req);	if (req == PM_SUSPEND || req == PM_RESUME) {		int state = (int)data;		if (state == 0) {			/* Enter D0. */			set_ctrlr_state(fbi, C_ENABLE);		} else {			/* Enter D1-D3.  Disable the LCD controller.  */			set_ctrlr_state(fbi, C_DISABLE);		}	}	DPRINTK("done\n");	return 0;}#endifstatic int __init sm501_map_video_memory(struct sm501_info *fbi, int detect){	u_long fb_address;	fbi->palette_size = 256;	if (detect & SM501_PANEL) {		fb_address = FIELD_GET(regRead32(PANEL_FB_ADDRESS), PANEL_FB_ADDRESS, ADDRESS);		fbi->palette = (u32 *)(sm501Reg + PANEL_PALETTE_RAM);	}	else {		fb_address = FIELD_GET(regRead32(CRT_FB_ADDRESS), CRT_FB_ADDRESS, ADDRESS);		fbi->palette = (u32 *)(sm501Reg + CRT_PALETTE_RAM);	}	/* virtual address */	DPRINTK("fb address: %#lx\n", fb_address);	fbi->fb_virt = fb_address + sm501Mem;	/* physical address */	fbi->fb.fix.smem_start = fb_address + pSM501_BASE;	return 0;}/* Fake monspecs to fill in fbinfo structure */static struct fb_monspecs monspecs __initdata = {	30000, 70000, 50, 65, 0	/* Generic */};static struct sm501_mach_info * __init sm501_get_panel_info(void){	static struct sm501_mach_info info;	int bpp_bits, bpp_data, bpp_lookup[] = {8, 16, 32, -1};	int i;	int clock, clock_lookup[] = {366000000, 288000000, 240000000, 192000000};	int divider, divider_lookup[] = {1, 3, 5, -1};	int shift;	bpp_bits = FIELD_GET(regRead32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, FORMAT);	bpp_data = bpp_lookup[bpp_bits];	if (bpp_data == -1) {		printk("Invalid value for bpp.  PANEL_DISPLAY_CTRL: %#lx, BPP index: %#x\n",			regRead32(PANEL_DISPLAY_CTRL), bpp_bits);		return NULL;	}	info.bpp = bpp_data;	//printk("sm501_get_panel_info CURRENT_POWER_CLOCK=%x\n",regRead32(CURRENT_POWER_CLOCK));	// This yeilds a pixclock from the PCD value.	i = FIELD_GET(regRead32(CURRENT_POWER_CLOCK), CURRENT_POWER_CLOCK, P2XCLK_SELECT);	if (i == CURRENT_POWER_CLOCK_P2XCLK_SELECT_288) {		clock = 288000000;		//printk("sm501_get_panel_info P2XCLK_SELECT= CURRENT_POWER_CLOCK_P2XCLK_SELECT_288\n");	}	else {		i = FIELD_GET(regRead32(SYSTEM_DRAM_CTRL), SYSTEM_DRAM_CTRL, DIVIDER);		clock = clock_lookup[i];		// printk("sm501_get_panel_info P2XCLK_SELECT!= CURRENT_POWER_CLOCK_P2XCLK_SELECT_288\n");	}	i = FIELD_GET(regRead32(CURRENT_POWER_CLOCK), CURRENT_POWER_CLOCK, P2XCLK_DIVIDER);	divider = divider_lookup[i];	if (divider == -1) {		//printk("Invalid value for panel clock divider.  CURRENT_POWER_CLOCK: %#lx, divider index: %#x\n",		//regRead32(CURRENT_POWER_CLOCK), i);		return NULL;	}	shift = FIELD_GET(regRead32(CURRENT_POWER_CLOCK), CURRENT_POWER_CLOCK, P2XCLK_SHIFT);	DPRINTK("clock: %d, divider: %d, shift: %d\n", clock, divider, shift);	info.pixclock = (clock / divider) >> shift;	info.xres = FIELD_GET(regRead32(PANEL_PLANE_BR), PANEL_PLANE_BR, RIGHT)		- FIELD_GET(regRead32(PANEL_PLANE_TL), PANEL_PLANE_TL, LEFT) + 1;	info.yres = FIELD_GET(regRead32(PANEL_PLANE_BR), PANEL_PLANE_BR, BOTTOM)		- FIELD_GET(regRead32(PANEL_PLANE_TL), PANEL_PLANE_TL, TOP) + 1;	info.hsync_len = FIELD_GET(regRead32(PANEL_HORIZONTAL_SYNC), PANEL_HORIZONTAL_SYNC, WIDTH);	info.left_margin = FIELD_GET(regRead32(PANEL_PLANE_TL), PANEL_PLANE_TL, LEFT);	info.right_margin = FIELD_GET(regRead32(PANEL_PLANE_BR), PANEL_PLANE_BR, RIGHT);	info.vsync_len = FIELD_GET(regRead32(PANEL_VERTICAL_SYNC), PANEL_VERTICAL_SYNC, HEIGHT);	info.upper_margin = FIELD_GET(regRead32(PANEL_PLANE_TL), PANEL_PLANE_TL, TOP);	info.lower_margin = FIELD_GET(regRead32(PANEL_PLANE_BR), PANEL_PLANE_BR, BOTTOM);	info.sync = 0;	i = FIELD_GET(regRead32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, VSYNC_PHASE);	if (i == PANEL_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH)		info.sync |= FB_SYNC_HOR_HIGH_ACT;	i = FIELD_GET(regRead32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, HSYNC_PHASE);	if (i == PANEL_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH)		info.sync |= FB_SYNC_VERT_HIGH_ACT;	//#if DEBUG	/*	printk("PANEL:\n");	printk("pixclock: %ld\n", info.pixclock);	printk("bpp     : %d\n", info.bpp);	printk("xres    : %d\n", info.xres);	printk("yres    : %d\n", info.yres);	printk("hsync   : %d\n", info.hsync_len);	printk("vsync   : %d\n", info.vsync_len);	printk("left    : %d\n", info.left_margin);	printk("upper   : %d\n", info.upper_margin);	printk("right   : %d\n", info.right_margin);	printk("lower   : %d\n", info.lower_margin);	printk("sync    : %d\n", info.sync);	printk("\n");	printk("CRT_HORIZONTAL_TOTAL=%#lx\n",regRead32(MISC_CTRL));	printk("DRAM_CTRL=%#lx\n",regRead32(DRAM_CTRL));	printk("ARBITRATION_CTRL=%#lx\n",regRead32(ARBITRATION_CTRL));	printk("POWER_MODE1_GATE=%#lx\n",regRead32(POWER_MODE1_GATE));	printk("POWER_MODE0_CLOCK=%#lx\n",regRead32(POWER_MODE0_CLOCK));	printk("POWER_MODE1_CLOCK=%#lx\n",regRead32(POWER_MODE1_CLOCK));	printk("POWER_MODE_CTRL=%#lx\n",regRead32(POWER_MODE_CTRL));	printk("ENDIAN_CTRL=%#lx\n",regRead32(ENDIAN_CTRL));	printk("SYSTEM_DRAM_CTRL=%#lx\n",regRead32(SYSTEM_DRAM_CTRL));	printk("PANEL_DISPLAY_CTRL=%#lx\n",regRead32(PANEL_DISPLAY_CTRL));	printk("PANEL_PAN_CTRL=%#lx\n",regRead32(PANEL_PAN_CTRL));	printk("PANEL_COLOR_KEY=%#lx\n",regRead32(PANEL_COLOR_KEY));	printk("PANEL_FB_ADDRESS=%#lx\n",regRead32(PANEL_FB_ADDRESS));	printk("PANEL_FB_WIDTH=%#lx\n",regRead32(PANEL_FB_WIDTH));	printk("PANEL_WINDOW_WIDTH=%#lx\n",regRead32(PANEL_WINDOW_WIDTH));	printk("PANEL_WINDOW_HEIGHT=%#lx\n",regRead32(PANEL_WINDOW_HEIGHT));	printk("PANEL_PLANE_TL=%#lx\n",regRead32(PANEL_PLANE_TL));	printk("PANEL_PLANE_BR=%#lx\n",regRead32(PANEL_PLANE_BR));	printk("PANEL_HORIZONTAL_TOTAL=%#lx\n",regRead32(PANEL_HORIZONTAL_TOTAL));	printk("PANEL_HORIZONTAL_SYNC=%#lx\n",regRead32(PANEL_HORIZONTAL_SYNC));	printk("PANEL_VERTICAL_TOTAL=%#lx\n",regRead32(PANEL_VERTICAL_TOTAL));	printk("PANEL_VERTICAL_SYNC=%#lx\n",regRead32(PANEL_VERTICAL_SYNC));	printk("CRT_DISPLAY_CTRL=%#lx\n",regRead32(CRT_DISPLAY_CTRL));	printk("CRT_FB_ADDRESS=%#lx\n",regRead32(CRT_FB_ADDRESS));	printk("CRT_FB_WIDTH=%#lx\n",regRead32(CRT_FB_WIDTH));	printk("CRT_HORIZONTAL_TOTAL=%#lx\n",regRead32(CRT_HORIZONTAL_TOTAL));	printk("CRT_HORIZONTAL_SYNC=%#lx\n",regRead32(CRT_HORIZONTAL_SYNC));	printk("CRT_VERTICAL_TOTAL=%#lx\n",regRead32(CRT_VERTICAL_TOTAL));	printk("CRT_VERTICAL_SYNC=%#lx\n",regRead32(CRT_VERTICAL_SYNC));	printk("\n");*/	//#endif	return &info;}static struct sm501_mach_info * __init sm501_get_crt_info(void){	static struct sm501_mach_info info;	int bpp_bits, bpp_data, bpp_lookup[] = {8, 16, 32, -1};	int i;	int clock, clock_lookup[] = {366000000, 288000000, 240000000, 192000000};	int divider, divider_lookup[] = {1, 3, -1, -1};	int shift;	bpp_bits = FIELD_GET(regRead32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, FORMAT);	bpp_data = bpp_lookup[bpp_bits];	if (bpp_data == -1) {		printk("Invalid value for bpp.  CRT_DISPLAY_CTRL: %#lx, BPP index: %#x\n", regRead32(CRT_DISPLAY_CTRL), bpp_bits);		return NULL;	}	info.bpp = bpp_data;	// This yeilds a pixclock from the PCD value.	i = FIELD_GET(regRead32(CURRENT_POWER_CLOCK), CURRENT_POWER_CLOCK, P2XCLK_SELECT);	if (i == CURRENT_POWER_CLOCK_P2XCLK_SELECT_288) {		printk(" CURRENT_POWER_CLOCK_P2XCLK_SELECT_288\n");		clock = 288000000;

⌨️ 快捷键说明

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