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

📄 corgi_lcd.c

📁 linux-2.6.15.6
💻 C
字号:
/* * linux/drivers/video/w100fb.c * * Corgi/Spitz LCD Specific Code * * Copyright (C) 2005 Richard Purdie * * Connectivity: *   Corgi - LCD to ATI Imageon w100 (Wallaby) *   Spitz - LCD to PXA Framebuffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include <linux/delay.h>#include <linux/kernel.h>#include <linux/platform_device.h>#include <linux/module.h>#include <linux/string.h>#include <asm/arch/akita.h>#include <asm/arch/corgi.h>#include <asm/hardware.h>#include <asm/arch/pxa-regs.h>#include <asm/arch/sharpsl.h>#include <asm/arch/spitz.h>#include <asm/hardware/scoop.h>#include <asm/mach/sharpsl_param.h>#include "generic.h"/* Register Addresses */#define RESCTL_ADRS     0x00#define PHACTRL_ADRS    0x01#define DUTYCTRL_ADRS   0x02#define POWERREG0_ADRS  0x03#define POWERREG1_ADRS  0x04#define GPOR3_ADRS      0x05#define PICTRL_ADRS     0x06#define POLCTRL_ADRS    0x07/* Resgister Bit Definitions */#define RESCTL_QVGA     0x01#define RESCTL_VGA      0x00#define POWER1_VW_ON    0x01  /* VW Supply FET ON */#define POWER1_GVSS_ON  0x02  /* GVSS(-8V) Power Supply ON */#define POWER1_VDD_ON   0x04  /* VDD(8V),SVSS(-4V) Power Supply ON */#define POWER1_VW_OFF   0x00  /* VW Supply FET OFF */#define POWER1_GVSS_OFF 0x00  /* GVSS(-8V) Power Supply OFF */#define POWER1_VDD_OFF  0x00  /* VDD(8V),SVSS(-4V) Power Supply OFF */#define POWER0_COM_DCLK 0x01  /* COM Voltage DC Bias DAC Serial Data Clock */#define POWER0_COM_DOUT 0x02  /* COM Voltage DC Bias DAC Serial Data Out */#define POWER0_DAC_ON   0x04  /* DAC Power Supply ON */#define POWER0_COM_ON   0x08  /* COM Powewr Supply ON */#define POWER0_VCC5_ON  0x10  /* VCC5 Power Supply ON */#define POWER0_DAC_OFF  0x00  /* DAC Power Supply OFF */#define POWER0_COM_OFF  0x00  /* COM Powewr Supply OFF */#define POWER0_VCC5_OFF 0x00  /* VCC5 Power Supply OFF */#define PICTRL_INIT_STATE      0x01#define PICTRL_INIOFF          0x02#define PICTRL_POWER_DOWN      0x04#define PICTRL_COM_SIGNAL_OFF  0x08#define PICTRL_DAC_SIGNAL_OFF  0x10#define POLCTRL_SYNC_POL_FALL  0x01#define POLCTRL_EN_POL_FALL    0x02#define POLCTRL_DATA_POL_FALL  0x04#define POLCTRL_SYNC_ACT_H     0x08#define POLCTRL_EN_ACT_L       0x10#define POLCTRL_SYNC_POL_RISE  0x00#define POLCTRL_EN_POL_RISE    0x00#define POLCTRL_DATA_POL_RISE  0x00#define POLCTRL_SYNC_ACT_L     0x00#define POLCTRL_EN_ACT_H       0x00#define PHACTRL_PHASE_MANUAL   0x01#define DEFAULT_PHAD_QVGA     (9)#define DEFAULT_COMADJ        (125)/* * This is only a psuedo I2C interface. We can't use the standard kernel * routines as the interface is write only. We just assume the data is acked... */static void lcdtg_ssp_i2c_send(u8 data){	corgi_ssp_lcdtg_send(POWERREG0_ADRS, data);	udelay(10);}static void lcdtg_i2c_send_bit(u8 data){	lcdtg_ssp_i2c_send(data);	lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK);	lcdtg_ssp_i2c_send(data);}static void lcdtg_i2c_send_start(u8 base){	lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);	lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);	lcdtg_ssp_i2c_send(base);}static void lcdtg_i2c_send_stop(u8 base){	lcdtg_ssp_i2c_send(base);	lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK);	lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT);}static void lcdtg_i2c_send_byte(u8 base, u8 data){	int i;	for (i = 0; i < 8; i++) {		if (data & 0x80)			lcdtg_i2c_send_bit(base | POWER0_COM_DOUT);		else			lcdtg_i2c_send_bit(base);		data <<= 1;	}}static void lcdtg_i2c_wait_ack(u8 base){	lcdtg_i2c_send_bit(base);}static void lcdtg_set_common_voltage(u8 base_data, u8 data){	/* Set Common Voltage to M62332FP via I2C */	lcdtg_i2c_send_start(base_data);	lcdtg_i2c_send_byte(base_data, 0x9c);	lcdtg_i2c_wait_ack(base_data);	lcdtg_i2c_send_byte(base_data, 0x00);	lcdtg_i2c_wait_ack(base_data);	lcdtg_i2c_send_byte(base_data, data);	lcdtg_i2c_wait_ack(base_data);	lcdtg_i2c_send_stop(base_data);}/* Set Phase Adjuct */static void lcdtg_set_phadadj(int mode){	int adj;	switch(mode) {		case 480:		case 640:			/* Setting for VGA */			adj = sharpsl_param.phadadj;			if (adj < 0) {				adj = PHACTRL_PHASE_MANUAL;			} else {				adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL;			}			break;		case 240:		case 320:		default:			/* Setting for QVGA */			adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL;			break;	}	corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj);}static int lcd_inited;static void lcdtg_hw_init(int mode){	if (!lcd_inited) {		int comadj;		/* Initialize Internal Logic & Port */		corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE	  			| PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF);		corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF				| POWER0_COM_OFF | POWER0_VCC5_OFF);		corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);		/* VDD(+8V), SVSS(-4V) ON */		corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);		mdelay(3);		/* DAC ON */		corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON				| POWER0_COM_OFF | POWER0_VCC5_OFF);		/* INIB = H, INI = L  */		/* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */		corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF);		/* Set Common Voltage */		comadj = sharpsl_param.comadj;		if (comadj < 0)			comadj = DEFAULT_COMADJ;		lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj);		/* VCC5 ON, DAC ON */		corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON |				POWER0_COM_OFF | POWER0_VCC5_ON);		/* GVSS(-8V) ON, VDD ON */		corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);		mdelay(2);		/* COM SIGNAL ON (PICTL[3] = L) */		corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE);		/* COM ON, DAC ON, VCC5_ON */		corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON				| POWER0_COM_ON | POWER0_VCC5_ON);		/* VW ON, GVSS ON, VDD ON */		corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON);		/* Signals output enable */		corgi_ssp_lcdtg_send(PICTRL_ADRS, 0);		/* Set Phase Adjuct */		lcdtg_set_phadadj(mode);		/* Initialize for Input Signals from ATI */		corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE				| POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H);		udelay(1000);		lcd_inited=1;	} else {		lcdtg_set_phadadj(mode);	}	switch(mode) {		case 480:		case 640:			/* Set Lcd Resolution (VGA) */			corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA);			break;		case 240:		case 320:		default:			/* Set Lcd Resolution (QVGA) */			corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA);			break;	}}static void lcdtg_suspend(void){	/* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */	mdelay(34);	/* (1)VW OFF */	corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON);	/* (2)COM OFF */	corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF);	corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON);	/* (3)Set Common Voltage Bias 0V */	lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0);	/* (4)GVSS OFF */	corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON);	/* (5)VCC5 OFF */	corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF);	/* (6)Set PDWN, INIOFF, DACOFF */	corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF |			PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF);	/* (7)DAC OFF */	corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF);	/* (8)VDD OFF */	corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF);	lcd_inited = 0;}/* * Corgi w100 Frame Buffer Device */#ifdef CONFIG_PXA_SHARP_C7xx#include <video/w100fb.h>static void w100_lcdtg_suspend(struct w100fb_par *par){	lcdtg_suspend();}static void w100_lcdtg_init(struct w100fb_par *par){	lcdtg_hw_init(par->xres);}static struct w100_tg_info corgi_lcdtg_info = {	.change  = w100_lcdtg_init,	.suspend = w100_lcdtg_suspend,	.resume  = w100_lcdtg_init,};static struct w100_mem_info corgi_fb_mem = {	.ext_cntl          = 0x00040003,	.sdram_mode_reg    = 0x00650021,	.ext_timing_cntl   = 0x10002a4a,	.io_cntl           = 0x7ff87012,	.size              = 0x1fffff,};static struct w100_gen_regs corgi_fb_regs = {	.lcd_format    = 0x00000003,	.lcdd_cntl1    = 0x01CC0000,	.lcdd_cntl2    = 0x0003FFFF,	.genlcd_cntl1  = 0x00FFFF0D,	.genlcd_cntl2  = 0x003F3003,	.genlcd_cntl3  = 0x000102aa,};static struct w100_gpio_regs corgi_fb_gpio = {	.init_data1   = 0x000000bf,	.init_data2   = 0x00000000,	.gpio_dir1    = 0x00000000,	.gpio_oe1     = 0x03c0feff,	.gpio_dir2    = 0x00000000,	.gpio_oe2     = 0x00000000,};static struct w100_mode corgi_fb_modes[] = {{	.xres            = 480,	.yres            = 640,	.left_margin     = 0x56,	.right_margin    = 0x55,	.upper_margin    = 0x03,	.lower_margin    = 0x00,	.crtc_ss         = 0x82360056,	.crtc_ls         = 0xA0280000,	.crtc_gs         = 0x80280028,	.crtc_vpos_gs    = 0x02830002,	.crtc_rev        = 0x00400008,	.crtc_dclk       = 0xA0000000,	.crtc_gclk       = 0x8015010F,	.crtc_goe        = 0x80100110,	.crtc_ps1_active = 0x41060010,	.pll_freq        = 75,	.fast_pll_freq   = 100,	.sysclk_src      = CLK_SRC_PLL,	.sysclk_divider  = 0,	.pixclk_src      = CLK_SRC_PLL,	.pixclk_divider  = 2,	.pixclk_divider_rotated = 6,},{	.xres            = 240,	.yres            = 320,	.left_margin     = 0x27,	.right_margin    = 0x2e,	.upper_margin    = 0x01,	.lower_margin    = 0x00,	.crtc_ss         = 0x81170027,	.crtc_ls         = 0xA0140000,	.crtc_gs         = 0xC0140014,	.crtc_vpos_gs    = 0x00010141,	.crtc_rev        = 0x00400008,	.crtc_dclk       = 0xA0000000,	.crtc_gclk       = 0x8015010F,	.crtc_goe        = 0x80100110,	.crtc_ps1_active = 0x41060010,	.pll_freq        = 0,	.fast_pll_freq   = 0,	.sysclk_src      = CLK_SRC_XTAL,	.sysclk_divider  = 0,	.pixclk_src      = CLK_SRC_XTAL,	.pixclk_divider  = 1,	.pixclk_divider_rotated = 1,},};static struct w100fb_mach_info corgi_fb_info = {	.tg         = &corgi_lcdtg_info,	.init_mode  = INIT_MODE_ROTATED,	.mem        = &corgi_fb_mem,	.regs       = &corgi_fb_regs,	.modelist   = &corgi_fb_modes[0],	.num_modes  = 2,	.gpio       = &corgi_fb_gpio,	.xtal_freq  = 12500000,	.xtal_dbl   = 0,};static struct resource corgi_fb_resources[] = {	[0] = {		.start   = 0x08000000,		.end     = 0x08ffffff,		.flags   = IORESOURCE_MEM,	},};struct platform_device corgifb_device = {	.name           = "w100fb",	.id             = -1,	.num_resources	= ARRAY_SIZE(corgi_fb_resources),	.resource	= corgi_fb_resources,	.dev            = { 		.platform_data = &corgi_fb_info, 		.parent = &corgissp_device.dev,	},};#endif/* * Spitz PXA Frame Buffer Device */#ifdef CONFIG_PXA_SHARP_Cxx00#include <asm/arch/pxafb.h>void spitz_lcd_power(int on){	if (on)		lcdtg_hw_init(480);	else		lcdtg_suspend();}#endif/* * Corgi/Spitz Touchscreen to LCD interface */static unsigned long (*get_hsync_time)(struct device *dev);static void inline sharpsl_wait_sync(int gpio){	while((GPLR(gpio) & GPIO_bit(gpio)) == 0);	while((GPLR(gpio) & GPIO_bit(gpio)) != 0);}#ifdef CONFIG_PXA_SHARP_C7xxunsigned long corgi_get_hsync_len(void){	if (!get_hsync_time)		get_hsync_time = symbol_get(w100fb_get_hsynclen);	if (!get_hsync_time)		return 0;	return get_hsync_time(&corgifb_device.dev);}void corgi_put_hsync(void){	if (get_hsync_time)		symbol_put(w100fb_get_hsynclen);	get_hsync_time = NULL;}void corgi_wait_hsync(void){	sharpsl_wait_sync(CORGI_GPIO_HSYNC);}#endif#ifdef CONFIG_PXA_SHARP_Cxx00static struct device *spitz_pxafb_dev;static int is_pxafb_device(struct device * dev, void * data){	struct platform_device *pdev = container_of(dev, struct platform_device, dev);	return (strncmp(pdev->name, "pxa2xx-fb", 9) == 0);}unsigned long spitz_get_hsync_len(void){#ifdef CONFIG_FB_PXA	if (!spitz_pxafb_dev) {		spitz_pxafb_dev = bus_find_device(&platform_bus_type, NULL, NULL, is_pxafb_device);		if (!spitz_pxafb_dev)			return 0;	}	if (!get_hsync_time)		get_hsync_time = symbol_get(pxafb_get_hsync_time);	if (!get_hsync_time)#endif		return 0;	return pxafb_get_hsync_time(spitz_pxafb_dev);}void spitz_put_hsync(void){	put_device(spitz_pxafb_dev);	if (get_hsync_time)		symbol_put(pxafb_get_hsync_time);	spitz_pxafb_dev = NULL;	get_hsync_time = NULL;}void spitz_wait_hsync(void){	sharpsl_wait_sync(SPITZ_GPIO_HSYNC);}#endif/* * Corgi/Spitz Backlight Power */#ifdef CONFIG_PXA_SHARP_C7xxvoid corgi_bl_set_intensity(int intensity){	if (intensity > 0x10)		intensity += 0x10;	/* Bits 0-4 are accessed via the SSP interface */	corgi_ssp_blduty_set(intensity & 0x1f);	/* Bit 5 is via SCOOP */	if (intensity & 0x0020)		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);	else		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);}#endif#if defined(CONFIG_MACH_SPITZ) || defined(CONFIG_MACH_BORZOI)void spitz_bl_set_intensity(int intensity){	if (intensity > 0x10)		intensity += 0x10;	/* Bits 0-4 are accessed via the SSP interface */	corgi_ssp_blduty_set(intensity & 0x1f);	/* Bit 5 is via SCOOP */	if (intensity & 0x0020)		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);	else		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_CONT);	if (intensity)		set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);	else		reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_BACKLIGHT_ON);}#endif#ifdef CONFIG_MACH_AKITAvoid akita_bl_set_intensity(int intensity){	if (intensity > 0x10)		intensity += 0x10;	/* Bits 0-4 are accessed via the SSP interface */	corgi_ssp_blduty_set(intensity & 0x1f);	/* Bit 5 is via IO-Expander */	if (intensity & 0x0020)		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);	else		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_CONT);	if (intensity)		akita_set_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);	else		akita_reset_ioexp(&akitaioexp_device.dev, AKITA_IOEXP_BACKLIGHT_ON);}#endif

⌨️ 快捷键说明

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