diff -uNr a/arch/arm/config.in b/arch/arm/config.in --- a/arch/arm/config.in 2004-10-25 10:10:10.000000000 +0800 +++ b/arch/arm/config.in 2004-12-29 10:50:30.000000000 +0800 @@ -418,6 +418,16 @@ bool 'Workaround for XScale cache errata (see help)' CONFIG_XSCALE_CACHE_ERRATA fi +if [ "$CONFIG_ARCH_MAINSTONE" = "y" ]; then + mainmenu_option next_comment + comment 'Workaound for PXA27x errata' + bool 'Extra Keypad Matrix Interrupt in IMKP Mode (E11)' CONFIG_PXA27x_E11 + bool 'UART Character Timeout Interrupt Remains Set under Certain Conditions' CONFIG_PXA27x_E20 + bool 'LCD Overlay1 is Not Enabled Intermittently after Re-enabling LCD' CONFIG_PXA27x_E17 + bool 'LCD Enabling Overlay2 for YUV420 hangs LCD controller' CONFIG_PXA27x_E25 + endmenu +fi + # Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. @@ -526,6 +536,7 @@ "$CONFIG_ARCH_INTEGRATOR" = "y" ]; then dep_bool 'Support CPU clock change (EXPERIMENTAL)' CONFIG_CPU_FREQ $CONFIG_EXPERIMENTAL dep_bool 'Support DVM/DFM(EXPERIMENTAL)' CONFIG_DVFM $CONFIG_CPU_FREQ + dep_bool 'Support Fast DVM/DFM(EXPERIMENTAL)' CONFIG_FAST_DVFM $CONFIG_DVFM fi source drivers/pci/Config.in diff -uNr a/arch/arm/def-configs/mainstone b/arch/arm/def-configs/mainstone --- a/arch/arm/def-configs/mainstone 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/def-configs/mainstone 2004-12-29 11:08:49.000000000 +0800 @@ -168,6 +168,14 @@ CONFIG_CPU_32v5=y CONFIG_CPU_XSCALE=y # CONFIG_XSCALE_CACHE_ERRATA is not set + +# +# Workaound for PXA27x errata +# +# CONFIG_PXA27x_E11 is not set +CONFIG_PXA27x_E20=y +# CONFIG_PXA27x_E17 is not set +# CONFIG_PXA27x_E25 is not set # CONFIG_CPU_32v3 is not set # CONFIG_CPU_32v4 is not set @@ -187,8 +195,23 @@ CONFIG_ZBOOT_ROM_BSS=0 CONFIG_CPU_FREQ=y CONFIG_DVFM=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set +CONFIG_FAST_DVFM=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_CLPS6700 is not set +# CONFIG_PCMCIA_SA1100 is not set +CONFIG_PCMCIA_PXA=y + +# +# MMC device drivers +# # CONFIG_MMC is not set CONFIG_NET=y CONFIG_SYSVIPC=y @@ -208,8 +231,8 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PM=y # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="root=/dev/mtdblock2 ip=192.168.1.101 console=ttyS0,115200 mem=64M" -# CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.1.100:/nfs/ ip=192.168.1.101:192.168.1.100::::: console=ttyS0,115200n8" +CONFIG_CMDLINE="root=/dev/mtdblock2 ip=192.168.1.101:192.168.1.100::::: console=ttyS0,115200 mem=128M" +# CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.1.100:/nfs/ ip=192.168.1.101:192.168.1.100::::: console=ttyS0,115200n8 mem=128M" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -482,6 +505,22 @@ # CONFIG_WAN is not set # +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +CONFIG_PCMCIA_XIRC2PS=y +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set + +# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -552,7 +591,7 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set # CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECS=y # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -584,11 +623,9 @@ # CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -CONFIG_CHR_DEV_OSST=y -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set CONFIG_CHR_DEV_SG=y # @@ -642,6 +679,11 @@ # CONFIG_SCSI_DEBUG is not set # +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA is not set + +# # I2O device support # # CONFIG_I2O is not set @@ -717,8 +759,8 @@ CONFIG_I2C_PXA_ALGO=y CONFIG_I2C_PXA_ADAP=y CONFIG_I2C_ADCM2650=y -# CONFIG_I2C_CHARDEV is not set -# CONFIG_I2C_PROC is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y # CONFIG_I2C_DS1307 is not set # @@ -802,6 +844,12 @@ # CONFIG_DRM is not set # +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set + +# # Multimedia devices # CONFIG_VIDEO_DEV=y @@ -809,7 +857,7 @@ # # Video For Linux # -# CONFIG_VIDEO_PROC_FS is not set +CONFIG_VIDEO_PROC_FS=y # CONFIG_I2C_PARPORT is not set # @@ -994,8 +1042,8 @@ CONFIG_FB_PXA_16BPP=y # CONFIG_FB_PXA_18BPP is not set # CONFIG_FB_PXA_19BPP is not set -CONFIG_FB_PXA_VGA=y -# CONFIG_FB_PXA_QVGA is not set +# CONFIG_FB_PXA_VGA is not set +CONFIG_FB_PXA_QVGA=y # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -1075,20 +1123,20 @@ # # USB Device Class drivers # -CONFIG_USB_AUDIO=y +# CONFIG_USB_AUDIO is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_MIDI is not set CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_HP8200e=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set CONFIG_USB_ACM=y # CONFIG_USB_PRINTER is not set @@ -1161,10 +1209,10 @@ # # USB Device Support # -CONFIG_USBD=y +CONFIG_USBD=m CONFIG_USBD_VENDORID=dead CONFIG_USBD_PRODUCTID=beef -CONFIG_USBD_PRODUCT_NAME="Mainstone II board" +CONFIG_USBD_PRODUCT_NAME="Mainstone" CONFIG_USBD_MANUFACTURER="Intel" # CONFIG_USBD_USE_SERIAL_NUMBER is not set # CONFIG_USBD_SELFPOWERED is not set @@ -1183,7 +1231,7 @@ # # Network Function # -CONFIG_USBD_NET=y +CONFIG_USBD_NET=m CONFIG_USBD_NET_VENDORID=dead CONFIG_USBD_NET_PRODUCTID=beef CONFIG_USBD_NET_IFNAME="usbd" @@ -1204,7 +1252,17 @@ # # Serial Function # -# CONFIG_USBD_SERIAL is not set +CONFIG_USBD_SERIAL=m +CONFIG_USBD_SERIAL_VENDORID=dead +CONFIG_USBD_SERIAL_PRODUCTID=beef +# CONFIG_USBD_SERIAL_CDC is not set +CONFIG_USBD_SERIAL_OUT_ENDPOINT=1 +CONFIG_USBD_SERIAL_OUT_PKTSIZE=64 +CONFIG_USBD_SERIAL_IN_ENDPOINT=2 +CONFIG_USBD_SERIAL_IN_PKTSIZE=64 +CONFIG_USBD_SERIAL_INT_ENDPOINT=3 +CONFIG_USBD_SERIAL_INT_PKTSIZE=16 +# CONFIG_USBD_SERIAL_SAFE is not set # # USB Device bus interfaces @@ -1213,7 +1271,7 @@ # # USB Device Bus Interface Support # -CONFIG_USBD_BULVERDE_BUS=y +CONFIG_USBD_BULVERDE_BUS=m # CONFIG_USBD_GENERIC_BUS is not set # diff -uNr a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c 2004-10-22 10:53:24.000000000 +0800 +++ b/arch/arm/kernel/irq.c 2004-12-29 10:50:30.000000000 +0800 @@ -106,8 +106,8 @@ spin_lock_irqsave(&irq_controller_lock, flags); if (!desc->disable_depth) { - printk("enable_irq(%u) unbalanced from %p\n", irq, - __builtin_return_address(0)); + //printk("enable_irq(%u) unbalanced from %p\n", irq, + //__builtin_return_address(0)); } else if (!--desc->disable_depth) { desc->probing = 0; desc->unmask(irq); diff -uNr a/arch/arm/mach-pxa/cpu-freq-bvd.c b/arch/arm/mach-pxa/cpu-freq-bvd.c --- a/arch/arm/mach-pxa/cpu-freq-bvd.c 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/cpu-freq-bvd.c 2004-12-29 10:50:30.000000000 +0800 @@ -105,14 +105,24 @@ /* * Use newCLKCFGValue as it's parameters. */ + +#ifdef CONFIG_FAST_DVFM +extern void pxafb_wait_for_eof(unsigned int); +#else +extern void pxafb_wait_for_eof(void); +#endif void blvd_change_freq(unsigned int CLKCFGvalue) { +#ifdef CONFIG_FAST_DVFM + pxafb_wait_for_eof(CLKCFGvalue); +#else + pxafb_wait_for_eof(); bulverde_setspeed(CLKCFGvalue); +#endif /* * By call calibrate_delay we know the current system's MIPS, * also show success of freq change. Can be disabled. */ - calibrate_delay(); } /* @@ -120,27 +130,17 @@ */ unsigned int mdrefr=0; - static void set_core_freq(int L, int N, int turbo_mode_flag,int fast_bus_mode_flag) { - int CLKCFGValue = 0; - int turbo_mode=0; + int CLKCFGValue = 0; + int turbo_mode=0; int half = 0; mdrefr = MDREFR; /* get the value. */ /* First set CCCR */ - if( L == 1 ) { /* 13M special mode. */ - /* LCD run at 26Mhz. */ - CCCR = (2 << 7) | 1 |( 1 <<30) | (1 <<31) | (1<<27 ); -#if 0 - /* LCD run at 13Mhz. */ - CCCR = (2 << 7) | 1 |( 1<<30) | (1 <<31); -#endif - } - else - CCCR = (N << 7) | L |( PDIS <<30) | (PDIS <<31 | 1<< 25); /* A = 1 */ + CCCR = (N << 7) | L |( PDIS <<30) | (PDIS <<31 | 1<< 25); /* A = 1 */ #if 0 - CCCR = (N << 7) | L |( PDIS <<30) | (PDIS <<31); /* A = 0 */ + CCCR = (N << 7) | L |( PDIS <<30) | (PDIS <<31); /* A = 0 */ #endif /* Check TURBO mode. */ @@ -149,9 +149,9 @@ else if( N > 2) /* Need turbo mode. */ turbo_mode =1; - /* set up the new CLKCFG value, for an new frequency */ + /* set up the new CLKCFG value, for an new frequency */ /* 0x2 is used to set FC bit in CLKCFG. */ - CLKCFGValue = ( 0x2 | (fast_bus_mode_flag << 3) | turbo_mode); + CLKCFGValue = ( 0x2 | (fast_bus_mode_flag << 3) | turbo_mode); half =0; if( fast_bus_mode_flag ) { /* fast bus. */ @@ -160,32 +160,132 @@ } else { if( L >=17 ) half = 1; - } + } +#if 0 if( half ==1 ) { mdrefr|=(MDREFR_K0DB2|MDREFR_K2DB2|MDREFR_K1DB2); } else { mdrefr&=~(MDREFR_K0DB2|MDREFR_K2DB2|MDREFR_K1DB2); } - /* +#endif + /* * Program the CLKCFG (CP14, reigster 6) for frequency change */ - blvd_change_freq(CLKCFGValue); + blvd_change_freq(CLKCFGValue); +} + +#define CCCR_CPDIS_BIT_ON (1 << 31) +#define CCCR_PPDIS_BIT_ON (1 << 30) +#define CCCR_PLL_EARLY_EN_BIT_ON (1 << 26) +#define CCCR_LCD_26_BIT_ON (1 << 27) + +static void enter_13m_quickly(void) +{ + int cccr; + int clkcfg; + + if (CCCR & (1 << 31)) + return ; + clkcfg = bulverde_read_clkcfg(); +#ifdef CONFIG_13M_TWOSTEP + if (clkcfg & 0x5) { + bulverde_setspeed(clkcfg & 0x8); + cccr = CCCR; + while (bulverde_read_clkcfg() != (clkcfg & 0x8)) + ; + + } +#endif + cccr = CCCR; + cccr |= CCCR_CPDIS_BIT_ON; + cccr &= ~CCCR_PPDIS_BIT_ON; + cccr |= CCCR_LCD_26_BIT_ON; + CCCR = cccr; + + LCCR4 |= (1 << 25); + bulverde_setspeed(0x2); + return 0; +} + +static void exit_13m_quickly(int L, int N, int turbo_mode_flag,int fast_bus_mode_flag) +{ + int cccr, ccsr, clkcfg; + unsigned int time_delay; + + if (!(CCCR & (1 << 31))) + return; + + clkcfg = 0x2; + if (N > 2 || turbo_mode_flag) + clkcfg |= 0x1; + if (fast_bus_mode_flag) + clkcfg |= (0x1 << 3); + + cccr = CCCR; + cccr |= (CCCR_CPDIS_BIT_ON | CCCR_PLL_EARLY_EN_BIT_ON); + /* clear L and 2N */ + cccr &= ~(0x7ff); + cccr |= L | N << 7; + CCCR = cccr; + + /* Step 2 */ + cccr = CCCR; + if ((cccr & 0x84000000) != 0x84000000) { /* CPDIS, pll_early_en */ + printk("DPM: Warning: CPDIS or PLL_EARLY_EN not on\n"); + } + time_delay = OSCR; + while ((OSCR - time_delay) < 390) + ; + /* Step 3 */ + while ((CCSR & 0x30000000) == 0x30000000) + break; + /* Step 4: NOP */ + + /* Step 5 */ + /* Now clear the PLL disable bits */ + /* But leave EARLY_EN on; it will be cleared by the frequency change */ + cccr &= ~(CCCR_CPDIS_BIT_ON | CCCR_PPDIS_BIT_ON); /* Not ON */ + cccr |= CCCR_PLL_EARLY_EN_BIT_ON; + CCCR = cccr; +#ifdef CONFIG_13M_TWOSTEP + bulverde_setspeed(0x2); +#endif + LCCR4 &= ~((1 << 25)); +#ifdef CONFIG_13M_TWOSTEP + cccr = CCCR; + while(bulverde_read_clkcfg() != 0x2) + ; + if (N > 2 || turbo_mode_flag || fast_bus_mode_flag) { + CKEN &= ~CKEN16_LCD; + bulverde_setspeed(clkcfg); + CKEN |= CKEN16_LCD; + } +#else + bulverde_setspeed(clkcfg); +#endif + } static void bulverde_setspeed_oldstyle(unsigned int khz) { - unsigned int l= 0; + unsigned int l= 0; struct ipm_config conf; down(&ipm_conf_sem); memcpy(&conf, &global_conf, sizeof(struct ipm_config)); up(&ipm_conf_sem); - if( khz == 13000 ) { /* 13Mhz mode, special case.*/ - set_core_freq(1, 2, 0, 0); + if (khz == 13000) { + if (!(CCCR & (1 << 31))) + enter_13m_quickly(); return; - } + } l = bulverde_freq_getL(khz, conf); + if (CCCR & (1 << 31)) { + if (khz !=13000) + exit_13m_quickly(l, conf.turbo_mode, 0, conf.fast_bus_mode); + return; + } set_core_freq(l, conf.turbo_mode, 0, conf.fast_bus_mode); } @@ -193,89 +293,46 @@ * This should be called with a valid freq point that was * obtained via bulverde_validate_speed */ + +#ifndef CONFIG_FAST_DVFM static void bulverde_setspeed(unsigned int CLKCFGValue) +#else +void bulverde_setspeed(unsigned int CLKCFGValue) +#endif { - unsigned long flags; - unsigned int unused; - volatile int *ramstart, v; - - /* NOTE: IRQs are already turned off in ipm idle, so it is not - necessary to do it here. */ - local_irq_save(flags); - - /* - * In order to turn the sdram back on (see below) we need to - * r/w the sdram. We need to do this without the cache and - * write buffer in the way. So, we temporarily ioremap the - * first page of sdram as uncached i/o memory and use the - * aliased address - */ - - /* map the first page of sdram to an uncached virtual page */ - ramstart = (int *)ioremap(PHYS_OFFSET, 4096); - - /* - * force a tlb fault to get the mapping into the tlb - * (otherwise this will occur below when the sdram is turned off and - * something-bad(tm) will happen) - */ - v = *(volatile unsigned long *)ramstart; - *(volatile unsigned long *)ramstart = v; - - /* - * The following code works hard to get all of itself into the i-cache. - * It does this because a side affect of the frequency change is that - * the sdram clocks get shut off. If the code is not in the i-cache the - * cpu will try and burst from sdram and a bad-thing will happen. - */ - /* - * Update MDREFR[KxDB2] bit. - */ - __asm__ __volatile__(" \n\ - ldr r4, [%4] @load MDREFR \n\ - b 2f \n\ - .align 5 \n\ -1: \n\ - mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\ - \n\ - @ restart sdcke 0 / 1 \n\ - bic r5, r4, #(0x00001000 | 0x00008000) @ MDREFR_E0PIN | MDREFR_E1PIN \n\ - str r5, [%1] @clear \n\ - str r4, [%1] @restore \n\ - \n\ - @ Generate refresh cycles for all banks \n\ - ldr r4, [%3] \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - str r4, [%3] \n\ - nop \n\ - b 3f \n\ -2: nop \n\ - \n\ - b 1b \n\ -3: nop \n\ - nop \n\ - nop \n\ - nop \n\ - nop \n\ - nop \n\ - nop \n\ - nop" - : "=&r" (unused) - : "r" (&MDREFR), "r" (CLKCFGValue), "r" (ramstart), "r"(&mdrefr) - : "r4", "r5"); - - /* unmap the page we used */ - iounmap(ramstart); - /* NOTE: if we don't turn off IRQs up top, there is no point - to restoring them here. */ - local_irq_restore(flags); + unsigned long flags; + unsigned int unused; + static int count = 0; + + /* NOTE: IRQs are already turned off in ipm idle, so it is not + necessary to do it here. */ + local_irq_save(flags); + //MST_LEDDAT1 = CLKCFGValue; + __asm__ __volatile__(" \n\ + ldr r4, [%1] @load MDREFR \n\ + mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\ + ldr r5, =0xe3dfefff \n\ + and r4, r4, r5 \n\ + str r4, [%1] @restore \n\ + " + : "=&r" (unused) + : "r" (&MDREFR), "r" (CLKCFGValue) + : "r4", "r5"); + + /* NOTE: if we don't turn off IRQs up top, there is no point + to restoring them here. */ + local_irq_restore(flags); +} + +unsigned int bulverde_read_clkcfg(void) +{ + unsigned int value=0; + unsigned int un_used; + + __asm__ __volatile__("mrc p14, 0, %1, c6, c0, 0" :"=&r" (un_used) + :"r" (value)); + + return value; } static int bulverde_init_freqs( void) @@ -289,7 +346,7 @@ * A1 : 0x69054111 */ if( (cpu_ver&0x0000f000)>>12==4 && (cpu_ver & 0xffff0000)>>16==0x6905 ) - /* It is a xscale core bulverde chip. */ + /* It is a xscale core bulverde chip. */ return 1; return 0; } @@ -298,6 +355,8 @@ { unsigned int freq, n,l, ccsr; + if (CCCR & (1 << 31)) + return 13000; ccsr =CCSR; l= ccsr & 0x0000001F; /* Get L */ n= (ccsr & 0x00000780)>>7; /* Get 2N */ @@ -309,7 +368,7 @@ static int __init bulverde_clk_init(void) { unsigned int freq; - + freq = bulverde_get_freq(); /* in kHz*/ printk(KERN_INFO "Init freq:%dkHz.\n", freq); diff -uNr a/arch/arm/mach-pxa/cpu-freq-bvd.h b/arch/arm/mach-pxa/cpu-freq-bvd.h --- a/arch/arm/mach-pxa/cpu-freq-bvd.h 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/cpu-freq-bvd.h 2004-12-29 10:50:30.000000000 +0800 @@ -8,7 +8,7 @@ #define BLVD_MIN_FREQ 13000 -#define BLVD_MAX_FREQ 520000 +#define BLVD_MAX_FREQ 624000 extern struct ipm_config global_conf; extern void dump_ipm_config(char *, struct ipm_config *); diff -uNr a/arch/arm/mach-pxa/cpu-voltage-bvd.c b/arch/arm/mach-pxa/cpu-voltage-bvd.c --- a/arch/arm/mach-pxa/cpu-voltage-bvd.c 2004-10-25 10:10:10.000000000 +0800 +++ b/arch/arm/mach-pxa/cpu-voltage-bvd.c 2004-12-29 10:50:30.000000000 +0800 @@ -60,19 +60,13 @@ unsigned int mv2DAC(unsigned int mv) { - int i; - if( mvDACtable[0].mv< mv ) /* too big. */ - return mvDACtable[0].DACIn; - - if( mvDACtable[11].mv > mv ) - return mvDACtable[11].DACIn; - - for(i=0; i<=12; i++) { - if( (mvDACtable[i].mv>mv) && (mvDACtable[i+1].mv BLVD_MAX_VOL) + return MV2DAC(BLVD_MAX_VOL); + if (mv < BLVD_MIN_VOL) + return MV2DAC(BLVD_MIN_VOL); + + return MV2DAC(mv); } static int __init bulverde_voltage_init(void) diff -uNr a/arch/arm/mach-pxa/cpu-voltage-bvd.h b/arch/arm/mach-pxa/cpu-voltage-bvd.h --- a/arch/arm/mach-pxa/cpu-voltage-bvd.h 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/cpu-voltage-bvd.h 2004-12-29 10:50:30.000000000 +0800 @@ -1,35 +1,37 @@ #ifndef CPU_VOLTAGE_BLVD_H #define CPU_VOLTAGE_BLVD_H -#define BLVD_MAX_VOL 1400 /* in mV. */ -#define BLVD_MIN_VOL 650 /* in Mv. */ -#define BLVD_DEF_VOL 1400 /* the default voltage. */ +#define BLVD_MAX_VOL 1500 /* in mV. */ +#define BLVD_MIN_VOL 900 /* in Mv. */ +#define BLVD_DEF_VOL 1500 /* the default voltage. */ /* * Transfer desired mv to required DAC value. - * Vcore = 1.3v - ( 712uv * DACIn ) + * Vcore = 1.5v - ( 587uv * DACIn ) */ +#define MV2DAC(mv) ((1500-mv)*1000/587) +#if 0 struct MvDAC { unsigned int mv; unsigned int DACIn; }; - struct MvDAC mvDACtable[] = { - {1298, 0 }, - {1227, 100}, - {1156, 200}, - {1085, 300}, - {1013, 400}, - {943, 500}, - {872, 600}, - {800, 700}, - {729, 800}, - {658, 900}, - {587, 1000}, - {515, 1100}, - {0, 0} + {1500, 0}, + {1450, 85}, + {1400, 170}, + {1350, 255}, + {1300, 340}, + {1250, 425}, + {1200, 511}, + {1150, 586}, + {1100, 681}, + {1050, 767}, + {1000, 851}, + {950, 936}, + {900, 1022}, + {0, 0xffffffff} }; - +#endif unsigned int mv2DAC(unsigned int mv); void vm_setvoltage(unsigned int); extern void cpu_voltage_init(unsigned int, unsigned int, unsigned int); diff -uNr a/arch/arm/mach-pxa/ipmc.c b/arch/arm/mach-pxa/ipmc.c --- a/arch/arm/mach-pxa/ipmc.c 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/ipmc.c 2004-12-29 10:50:30.000000000 +0800 @@ -64,13 +64,14 @@ /* For put the policy maker to sleep to avoid polling event. */ struct fv_table ipm_fv_table[] = { - { 26000, 850}, - { 104000, 1000}, - { 208000, 1100}, - { 312000, 1200}, - { 416000, 1300}, - { 520000, 1400}, - { 920000, 1400}, /* This is impossible. */ + { 26000, 900}, + { 104000, 1100}, + { 208000, 1200}, + { 312000, 1300}, + { 416000, 1400}, + { 520000, 1500}, + { 624000, 1500}, + { 920000, 1500}, /* This is impossible. */ {0, 0} }; @@ -189,7 +190,7 @@ /* Get current voltage. */ while( ipm_fv_table[i].freq != 0 ) { - if( cur.core_freq < ipm_fv_table[i].freq ) { + if( cur.core_freq <= ipm_fv_table[i].freq ) { cur.core_vltg = ipm_fv_table[i].voltage; break; } @@ -198,7 +199,7 @@ i=0; /* Get target voltage. */ while( ipm_fv_table[i].freq != 0 ) { - if( target->core_freq < ipm_fv_table[i].freq ) { + if( target->core_freq <= ipm_fv_table[i].freq ) { target->core_vltg = ipm_fv_table[i].voltage; break; } diff -uNr a/arch/arm/mach-pxa/keypad.c b/arch/arm/mach-pxa/keypad.c --- a/arch/arm/mach-pxa/keypad.c 2004-10-25 10:10:10.000000000 +0800 +++ b/arch/arm/mach-pxa/keypad.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,256 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/keypad.c - * - * Low Level Routines for Bulverde Keypad controller - * - * Copyright (C) 2003, Intel Corporation (yu.tang@intel.com) - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MAX_KPES 5 - -struct kpe_queue{ - int head; - int tail; - int len; - struct kp_event kpes[MAX_KPES]; - wait_queue_head_t waitq; -}; - -static struct kpe_queue kpe_queue; - -static int kpq_init(void) -{ - unsigned int flags; - - local_irq_save(flags); - - /* init kpe queue */ - kpe_queue.head = kpe_queue.tail = 0; - kpe_queue.len = 0; - init_waitqueue_head(&kpe_queue.waitq); - - local_irq_restore(flags); - - return 0; -} - -static int kpq_empty(void) -{ - int empty; - - if (kpe_queue.len) - empty = 0; - else - empty = 1; - - return empty; -} - -static int kpq_get(struct kp_event *kpe) -{ - int flags; - - local_irq_save(flags); - - if (!kpe_queue.len) { - local_irq_restore(flags); - return -1; - } - - memcpy(kpe, kpe_queue.kpes + kpe_queue.tail, sizeof(struct kp_event)); - - kpe_queue.len--; - kpe_queue.tail = (kpe_queue.tail + 1) % MAX_KPES; - - local_irq_restore(flags); - - return 0; - -} - -static int kpq_put(struct kp_event *kpe) -{ - int flags; - - local_irq_save(flags); - - if (kpe_queue.len == MAX_KPES) { - local_irq_restore(flags); - return -1; - } - - memcpy(kpe_queue.kpes + kpe_queue.head, kpe, sizeof(struct kp_event)); - - kpe_queue.len ++; - kpe_queue.head = (kpe_queue.head + 1) % MAX_KPES; - - local_irq_restore(flags); - - /* wake up the waiting process */ - wake_up_interruptible(&kpe_queue.waitq); - - return 0; -} - -/* Interrupt Handler for KEYPAD */ -extern int pm_updatetimer(int); -static void kp_interrupt(int irq, void *ptr, struct pt_regs *regs) -{ - unsigned long kpc_val; - - /* ack interrupt */ - kpc_val = KPC; - - /* direct interrupt */ - if (kpc_val & KPC_DI) - kp_direct_scan(); - - /* matrix interrupt */ - if (kpc_val & KPC_MI) - kp_matrix_scan(); - - pm_updatetimer(0); -} - -int kp_init(void) -{ - /* flush queue */ - kpq_init(); - - return 0; -} - -int kp_direct_scan(void) -{ - struct kp_event kpe={0}; - - kpe.jiffies = jiffies; - kpe.flags = KP_DIRECT; - kpe.direct = KPDK; - kpe.rotary = KPREC; - - kpq_put(&kpe); - - return 0; -} - -int kp_matrix_scan(void) -{ - struct kp_event kpe={0}; - - KPC |= KPC_AS; - while (KPAS&KPAS_SO) ; - - kpe.jiffies = jiffies; - kpe.flags = KP_MATRIX; - kpe.matrix[0] = KPAS; - kpe.matrix[1] = KPASMKP0; - kpe.matrix[2] = KPASMKP1; - kpe.matrix[3] = KPASMKP2; - kpe.matrix[4] = KPASMKP3; - - KPC &= ~KPC_AS; - - kpq_put(&kpe); - - return 0; -} - -/* wait for keypad event, must be in task-context */ -int kp_wait(struct kp_event *kpe, signed int timeout) -{ - int err, n; - - err = 0; - - while(1) { - if (!kpq_empty()) { - n = kpq_get(kpe); - - if (n < 0) continue; - - break; - } - - /* no event available */ - if (!timeout) { - err = -EAGAIN; - break; - } - - if (timeout > 0) { - /* wait for timeout */ - timeout = interruptible_sleep_on_timeout(&kpe_queue.waitq, timeout); - - continue; - } - else{ - /* wait for kpevent/signal */ - while(1) { - interruptible_sleep_on(&kpe_queue.waitq); - if (kpq_empty() && !signal_pending(current)) - continue; - break; - } - - if (signal_pending(current)) { - err = -EINTR; - break; - } - } - } - - return err; -} - -/* poll for keypad event */ -unsigned int kp_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &kpe_queue.waitq, wait); - if (!kpq_empty()) - return POLLIN | POLLRDNORM; - - return 0; -} - -static int keyp_init(void) -{ - int err; - - kp_init(); - - /* irq */ - err = request_irq (IRQ_KEYPAD, kp_interrupt, 0, "Keypad", NULL); - - if (err) - printk (KERN_CRIT "Wow! Can't register IRQ[%d] for Keypad\n", IRQ_KEYPAD); - - return 0; -} - -__initcall(keyp_init); - -EXPORT_SYMBOL(kp_init); -EXPORT_SYMBOL(kp_poll); -EXPORT_SYMBOL(kp_wait); -EXPORT_SYMBOL(kp_direct_scan); -EXPORT_SYMBOL(kp_matrix_scan); diff -uNr a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c --- a/arch/arm/mach-pxa/mainstone.c 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/mainstone.c 2004-12-29 10:50:30.000000000 +0800 @@ -61,7 +61,7 @@ int i; while ((irq_status = MST_IRQSETCLR & mainstone_irq_en_mask)) { - for (i = 0; i < 6; i++) { + for (i = 0; i < 31; i++) { if(irq_status & (1< #include -#define BVD_MEMC_SIGHTING 1 .text /* @@ -28,41 +27,20 @@ stmfd sp!, {r1 - r9, lr} @ save registers on stack mov r1, #0x18 mov r2, #2 - ldr r3, =PSSR mov r7, #UNCACHED_PHYS_0 @ Read mem context in. ldr r8, [r7] -#ifdef BVD_MEMC_SIGHTING - @ add for sightings. - ldr r4, =MDREFR - ldr r5, [r4] - mov r6, r5 @ save old MDREFR into r6. - ldr r4, =0xE3D5AFFF - and r5, r5, r4 @ now r5 is the desired value need to set to MDREFR - ldr r4, =MDREFR @ r4 is the address of MDREFR -#endif b 1f .align 5 1: -#ifdef BVD_MEMC_SIGHTING - str r5, [r4] @ Now change MDREFR. -#endif mcr p14, 0, r2, c7, c0, 0 @ put the system into Standby @ Since after wakeup the bit will set automatically, some times @ we need to clear them. str r6, [r4] - str r1, [r3] - -#ifdef BVD_MEMC_SIGHTING -.rept 8 - str r8, [r7] -.endr -#endif - ldmfd sp!, {r1 - r9, pc} @ Restore regs and return to caller /* @@ -113,15 +91,6 @@ mov r2, #UNCACHED_PHYS_0 #endif -#ifdef BVD_MEMC_SIGHTING - @ add for sightings. - ldr r4, =MDREFR - ldr r5, [r4] - ldr r4, =0xE3D5AFFF - and r5, r5, r4 - ldr r4, =MDREFR -#endif - @ align execution to a cache line b 1f @@ -140,14 +109,6 @@ ldr r3, [r2] #endif -#ifdef BVD_MEMC_SIGHTING - @ add for sightings. - str r5, [r4] - @ force address lines low by reading at physical address 0 - mov r2, #UNCACHED_PHYS_0 - ldr r3, [r2] -#endif - @ enter sleep mode mcr p14, 0, r1, c7, c0, 0 diff -uNr a/arch/arm/mach-pxa/vcs.c b/arch/arm/mach-pxa/vcs.c --- a/arch/arm/mach-pxa/vcs.c 2004-10-22 10:53:25.000000000 +0800 +++ b/arch/arm/mach-pxa/vcs.c 2004-12-29 10:50:30.000000000 +0800 @@ -179,14 +179,14 @@ /* programming the command data bit */ set_cmd_data(dataArray, 0, 2); - /* Enable Power I2C */ - PCFR |= (0x60 | 0x1 <<10 ); } void vm_setvoltage(unsigned int DACValue) { ipm_power_change_cmd(DACValue); + /* Enable Power I2C */ + PCFR |= PCFR_PI2C_EN; /* Execute voltage change sequence */ blvd_change_voltage(); //set VC on the PWRMODE on CP14 } @@ -211,6 +211,8 @@ newCLKCFGValue = (0x2 | (fastbus_mode_flag << 3) | run_mode_flag); ipm_power_change_cmd(DACValue); + /* Enable Power I2C and FVC */ + PCFR |= PCFR_PI2C_EN | PCFR_FVC; blvd_change_freq(newCLKCFGValue); } diff -uNr a/Documentation/Configure.help b/Documentation/Configure.help --- a/Documentation/Configure.help 2004-10-22 10:53:32.000000000 +0800 +++ b/Documentation/Configure.help 2004-12-29 10:50:30.000000000 +0800 @@ -12569,6 +12569,41 @@ If you don't know what to answer, say Y. +Workaround for PXA27x keypad Errata E11 +CONFIG_PXA27x_E11 + There is an unexpected interrupt during keypad matrix manual scan in + Ingnore Multiple Keypress mode(IMKP). + + Say Y to fix this Errata. + +Workaround for PXA27x keypad Errata E19 +CONFIG_PXA27x_E19 + When the processor is in standby mode and it is programmed to wake up + by a KeyPad GPIO pulse, the PKSR(Keyboard Edge detect Status) does not + correctly report the GPIO that caused the Wakeup. + + Say Y to fix this Errata. + +Workaround for PXA27x UART Errata E20 +CONFIG_PXA27x_E20 + The issue is that randomly the character timeout interrupt does not + clear and the DR bit is not set. + + Say Y to fix this Errata. + +Workaround for PXA27x LCD Errata E17 +CONFIG_PXA27x_E17 + When enabling and disabling LCD several times,intermittently Overlay1 + output is all zeros instead of intended frame buffer overlay parren. + Overlay2 works fine. + + Say Y to fix this Errata. +Workaround for PXA27x LCD Errata E25 + Enabling OVerlay2 in YUV 420 mode causes the LCD controller to stop + operating(DMA activity stops and the screen fades away). + + Say Y to fix this Errata. + Support CD-ROM drives that are not SCSI or IDE/ATAPI CONFIG_CD_NO_IDESCSI If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y diff -uNr a/drivers/char/console.c b/drivers/char/console.c --- a/drivers/char/console.c 2004-10-22 10:52:38.000000000 +0800 +++ b/drivers/char/console.c 2004-12-29 10:50:30.000000000 +0800 @@ -3085,10 +3085,10 @@ switch (rqst) { case PM_RESUME: - unblank_screen(); + //unblank_screen(); break; case PM_SUSPEND: - do_blank_screen(0); + //do_blank_screen(0); break; } return 0; diff -uNr a/drivers/char/mainstone_keyp.c b/drivers/char/mainstone_keyp.c --- a/drivers/char/mainstone_keyp.c 1970-01-01 08:00:00.000000000 +0800 +++ b/drivers/char/mainstone_keyp.c 2004-12-29 10:50:30.000000000 +0800 @@ -0,0 +1,358 @@ +/* + * linux/drivers/char/mainstone_keyp.c + * + * Keypad driver for Mainstone Platform + * + * Copyright (C) 2004, Intel Corporation (yu.tang@intel.com) + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_PM +extern int pm_updatetimer(int); +#endif + +/* scan code */ +#define ROTARY_DEFAULT 0x7F +#define NO_KEY 0xFF +#define SCAN_CODE_SCROLL_UP 0xA +#define SCAN_CODE_SCROLL_DOWN 0xB +#define SCAN_CODE_ACTION 0xC + + +#if defined(CONFIG_MBFASTTAP) + +static u8 key_map[0x78] = { + [0] = 30, /* KEY_A */ + [1] = 34, /* KEY_G */ + [2] = 50, /* KEY_M */ + [3] = 31, /* KEY_S */ + [4] = 52, /* KEY_DOT */ + [5] = 102, /* KEY_HOME */ + [0xA] = 103, /* KEY_UP */ + [0xB] = 108, /* KEY_DOWN */ + [0xC] = 96, /* KEY_KPENTER */ + [0x10] = 48, /* KEY_B */ + [0x11] = 35, /* KEY_H */ + [0x12] = 49, /* KEY_N */ + [0x13] = 20, /* KEY_T */ + [0x14] = 215, /* KEY_EMAIL */ + [0x15] = 103, /* KEY_UP */ + [0x20] = 46, /* KEY_C */ + [0x21] = 23, /* KEY_I */ + [0x22] = 24, /* KEY_O */ + [0x23] = 22, /* KEY_U */ + [0x24] = 21, /* KEY_Y */ + [0x25] = 57, /* KEY_SPACE */ + [0x30] = 32, /* KEY_D */ + [0x31] = 36, /* KEY_J */ + [0x32] = 25, /* KEY_P */ + [0x33] = 47, /* KEY_V */ + [0x34] = 44, /* KEY_Z */ + [0x35] = 57, /* KEY_SPACE */ + [0x40] = 18, /* KEY_E */ + [0x41] = 37, /* KEY_K */ + [0x42] = 16, /* KEY_Q */ + [0x43] = 17, /* KEY_W */ + [0x44] = 53, /* KEY_SLASH */ + [0x45] = 96, /* KEY_KPENTER */ + [0x50] = 33, /* KEY_F */ + [0x51] = 38, /* KEY_L */ + [0x52] = 19, /* KEY_R */ + [0x53] = 45, /* KEY_X */ + [0x54] = 43, /* KEY_BACKSLASH */ + [0x55] = 1, /* KEY_ESC */ +}; + +static void kp_configure(void) +{ + /* setup gpio */ + set_GPIO_mode( 93 | GPIO_ALT_FN_1_IN); + set_GPIO_mode( 94 | GPIO_ALT_FN_1_IN); + set_GPIO_mode( 95 | GPIO_ALT_FN_3_IN); + set_GPIO_mode( 96 | GPIO_ALT_FN_3_OUT); + set_GPIO_mode( 97 | GPIO_ALT_FN_3_IN); + set_GPIO_mode( 98 | GPIO_ALT_FN_3_IN); + set_GPIO_mode( 99 | GPIO_ALT_FN_3_IN); + set_GPIO_mode(100 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(101 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(102 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(103 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(104 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(105 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(106 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(107 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(108 | GPIO_ALT_FN_2_OUT); + + /* set keypad control register */ + KPC = (KPC_ASACT | (7<<26) | (7<<23)| + KPC_ME | (2<<6) | KPC_REE0 | KPC_DE | + KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 |KPC_MS4 | KPC_MS5| KPC_MS6 | KPC_MS7 | + KPC_MIE | KPC_DIE | KPC_REE0 | KPC_IMKP); + + /* set debounce time to 10ms */ + KPKDI= 0x010A; + + /* set scroll wheel value to mid-point value */ + KPREC= ROTARY_DEFAULT; +} + +#elif defined(CONFIG_MBKEYPAD) + +static u8 key_map[0x34]= +{ + [0x00] = 2, /* KEY_1 */ + [0x01] = 5, /* KEY_4 */ + [0x02] = 8, /* KEY_7 */ + [0x03] = 55, /* KEY_KP* */ + [0x0A] = 103, /* KEY_UP */ + [0x0B] = 108, /* KEY_DOWN*/ + [0x0C] = 28, /* KEY_ENTER */ + [0x10] = 3, /* KEY_2 */ + [0x11] = 6, /* KEY_5 */ + [0x12] = 9, /* KEY_8 */ + [0x13] = 11, /* KEY_0 */ + [0x20] = 4, /* KEY_3 */ + [0x21] = 7, /* KEY_6 */ + [0x22] = 10, /* KEY_9 */ +}; + +static void kp_configure(void) +{ + /* setup GPIO */ + set_GPIO_mode(93 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(94 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(95 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(98 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(99 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(100 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(101 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(102 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(103 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(104 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(105 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(106 | GPIO_ALT_FN_2_OUT); + + /* set keypad control register */ + KPC = (KPC_ASACT | (3<<26) | (4<<23)| + KPC_ME | (2<<6) | KPC_REE0 | KPC_DE | + KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 | KPC_MIE | KPC_DIE | KPC_IMKP); + + /* debouce setting: matrix debouce + direct debouce */ + KPKDI= 0x010A; + + /* set scroll wheel value to mid-point value */ + KPREC= ROTARY_DEFAULT; +} + +#endif + +static int kp_direct_scan(void) +{ + static int prev; + u32 curr; + u32 direct, rotary; + u8 c = 0; + + direct = KPDK; + rotary = KPREC; + + /* Rotary */ + curr = rotary & 0xFF; + + if (rotary & KPREC_OF0) { + KPREC &= ~KPREC_OF0; + KPREC |= ROTARY_DEFAULT; + prev = ROTARY_DEFAULT; + c = SCAN_CODE_SCROLL_UP; + } + else if (rotary & KPREC_UF0) { + KPREC &= ~KPREC_UF0; + KPREC |= ROTARY_DEFAULT; + prev = ROTARY_DEFAULT; + c = SCAN_CODE_SCROLL_DOWN; + } + else if (curr > prev) { + c = SCAN_CODE_SCROLL_UP; + prev = curr; + } + else if (curr < prev) { + c = SCAN_CODE_SCROLL_DOWN; + prev = curr; + } + + if (direct & KPDK_DK2) { + c = SCAN_CODE_ACTION; + prev = curr; + } + + + if (c && key_map[c]) { + handle_scancode (key_map[c], 1); + handle_scancode (key_map[c], 0); + } + + return 0; +} + +static int kp_matrix_scan(void) +{ + static u8 last = NO_KEY; + + u32 autoscan, n; + u8 c; + + KPC |= KPC_AS; + while (KPAS&KPAS_SO) ; + + autoscan = KPAS; + + KPC &= ~KPC_AS; + + n = (autoscan >> 26) & 0x1f; + c = autoscan & 0xff; + + /* encode scan-code */ + if (!n) { + c = last; + last = NO_KEY; + } + else if ( n == 1 ) { + last = c; + } + else + c = NO_KEY; + + if ( c == NO_KEY) return 0; + + /* invalid key? */ + if ( c >= sizeof(key_map) || (key_map[c] == 0)) return 0; + + handle_scancode (key_map[c], n); + + return 0; +} + +/* Interrupt Handler for KEYPAD */ +static void kp_interrupt(int irq, void *ptr, struct pt_regs *regs) +{ + unsigned long kpc_val; + + /* ack interrupt */ + kpc_val = KPC; + + /* direct interrupt */ + if (kpc_val & KPC_DI) + kp_direct_scan(); + + /* matrix interrupt */ + if (kpc_val & KPC_MI) + kp_matrix_scan(); + +#ifdef CONFIG_PM + pm_updatetimer(0); +#endif +} + +#ifdef CONFIG_PM +static struct pm_dev *pmdev; +static unsigned long kpc,kpkdi,kprec; +static int kp_resume(void *data) +{ + kp_configure(); + + KPC = kpc; + KPKDI = kpkdi; + KPREC = kprec; + + CKEN |= CKEN19_KEYPAD; + + return 0; +} + +static int kp_suspend(void *data, int state) +{ + CKEN &= ~CKEN19_KEYPAD; + kpc = KPC; + kpkdi = KPKDI; + kprec = KPREC; + KPC &= ~(KPC_DIE | KPC_MIE); + return 0; +} + +static int kp_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + int ret; + + switch (rqst) { + case PM_SUSPEND: + ret = kp_suspend(NULL,(int)data); + break; + case PM_RESUME: + ret = kp_resume(NULL); + break; + default: + ret = -EINVAL; + break; + } + return ret; +} +#endif + +static __init int keyp_init(void) +{ + int err; + + /* irq */ + err = request_irq (IRQ_KEYPAD, kp_interrupt, 0, "Keypad", NULL); + + if (err) { + printk (KERN_CRIT "Wow! Can't register IRQ[%d] for Keypad\n", IRQ_KEYPAD); + return -1; + } + + /* enable unit clock */ + CKEN |= CKEN19_KEYPAD; + + /* setup keypad */ + kp_configure(); + +#ifdef CONFIG_PXA27x_E11 + /* FIXME : Errata E11, Matrix Key interval should be >=10ms */ + if ( (KPKDI & 0x00FF) < 0xA) { + KPKDI = (KPKDI & 0xFF00) | 0x0A; + } +#endif + +#ifdef CONFIG_PM + pmdev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, kp_pmproc); + if (pmdev) { + pmdev->data = NULL; + printk(KERN_INFO "keypad: pm register!\n"); + } else + printk(KERN_INFO "keypad: pm register failed\n"); +#endif + + return 0; +} + +__initcall(keyp_init); + diff -uNr a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/char/Makefile 2004-12-29 10:50:30.000000000 +0800 @@ -304,7 +304,7 @@ obj-$(CONFIG_NWFLASH) += nwflash.o obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o scx200.o obj-$(CONFIG_SA1100_CONSUS) += consusbutton.o -obj-$(CONFIG_ARCH_MAINSTONE) += mbkeypad.o +obj-$(CONFIG_ARCH_MAINSTONE) += mainstone_keyp.o # Only one watchdog can succeed. We probe the hardware watchdog # drivers first, then the softdog driver. This means if your hardware diff -uNr a/drivers/char/mbfasttap.c b/drivers/char/mbfasttap.c --- a/drivers/char/mbfasttap.c 2004-10-22 10:52:41.000000000 +0800 +++ b/drivers/char/mbfasttap.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,376 +0,0 @@ -/* linux/driver/char/mbfasttap.c - * - * FastTap driver for Intel Mainstone-II Development Board - * - * Copyright (c) 2003, Intel Corporation (yu.tang@intel.com) - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Direct-KEY scan-code for Mainstone-II Board */ -#define ROTARY_DEFAULT 0x7F -#define NO_KEY 0xFF -#define SCAN_CODE_SCROLL_UP 0xA -#define SCAN_CODE_SCROLL_DOWN 0xB -#define SCAN_CODE_ACTION 0xC - -static struct semaphore kpdrv_mutex; -static int kpdrv_refcount=0; - -static unsigned char get_scancode(struct kp_event *kpe) -{ - static unsigned int prev=ROTARY_DEFAULT; - unsigned int c, curr; - - c = NO_KEY; - - if (kpe->flags & KP_DIRECT) { - - curr = kpe->rotary & 0xFF; - - if (kpe->rotary & KPREC_OF0) { - KPREC &= ~KPREC_OF0; - KPREC |= ROTARY_DEFAULT; - prev = ROTARY_DEFAULT; - c = SCAN_CODE_SCROLL_UP; - } - else if (kpe->rotary & KPREC_UF0) { - KPREC &= ~KPREC_UF0; - KPREC |= ROTARY_DEFAULT; - prev = ROTARY_DEFAULT; - c = SCAN_CODE_SCROLL_DOWN; - } - else if (curr > prev) { - c = SCAN_CODE_SCROLL_UP; - prev = curr; - } - else if (curr < prev) { - c = SCAN_CODE_SCROLL_DOWN; - prev = curr; - } - else if (kpe->direct & KPDK_DK2) { - c = SCAN_CODE_ACTION; - prev = curr; - } - - } - - if (kpe->flags & KP_MATRIX) { - unsigned int num = (kpe->matrix[0] >> 26) & 0x1f; - unsigned int C, R, c0, c1, c2, c3, c4, c5, c6, c7; - - C = R = 0; - - if ( num == 1) { - c = kpe->matrix[0] & 0xff; - } - else if (num > 1) { - c0 = kpe->matrix[1] & 0xff; - c1 = (kpe->matrix[1] >> 16) & 0xff; - c2 = kpe->matrix[2] & 0xff; - c3 = (kpe->matrix[2] >> 16) & 0xff; - c4 = kpe->matrix[3] & 0xff; - c5 = (kpe->matrix[3] >> 16) & 0xff; - c6 = kpe->matrix[4] & 0xff; - c7 = (kpe->matrix[4] >> 16) & 0xff; - - if (c0) { - C = 0x7; - if (c0==0x8) - R = 0x2; - else if (c0 > 0x8) { - if (c0 <0x20) - R = 0x3; - else - R = 0x4; - } - else { - if (c0 > 0x2) - R = 0x1; - else - R = 0x0; - - } - c = (C<<4) | R; - } - else if (c1) { - C = 0x8; - - if (c1 == 0x8) - R = 0x2; - else if (c1 > 0x8) { - if (c1 < 0x20) - R = 0x3; - else - R = 0x4; - } - else { - if (c1 > 0x2) - R = 0x1; - else - R = 0x0; - } - c = (C<<4) | R; - } - else if (c2) { - C = 0x9; - - if (c2 == 0x8) - R = 0x2; - else if (c2 > 0x8) { - if (c2 < 0x20) - R = 0x3; - else - R = 0x4; - } - else { - if (c2 > 0x2) - R = 0x1; - else - R = 0x0; - } - c = (C<<4) | R; - } - else if (c3) { - C = 0xa; - - if (c3 == 0x8) - R = 0x2; - else if (c3 > 0x8) { - if (c3 < 0x20) - R = 0x3; - else - R = 0x4; - } - else { - if (c3 > 0x2) - R = 0x1; - else - R = 0x0; - } - c = (C<<4) | R; - } - else if (c4) { - C = 0xb; - - if (c4 == 0x8) - R = 0x2; - else if (c4 > 0x8) { - if (c4 < 0x20) - R = 0x3; - else - R = 0x4; - } - else { - if (c4 > 0x2) - R = 0x1; - else - R = 0x0; - } - c = (C<<4) | R; - } - } - } - - return c; -} - -static ssize_t kpdrv_read(struct file * filp, char * buf, - size_t count, loff_t *ppos) -{ - struct kp_event kpe; - int err,left,timeout; - unsigned char c; - - timeout = 0; - left = count; - do { - err = kp_wait(&kpe, timeout); - if (err) { - if ( left != count ) return (count-left); - - if (filp->f_flags & O_NONBLOCK) return err; - - if (timeout) return err; - - timeout = -1; - continue; - } - - /* parse if direct/matrix flags are set*/ - if ( (kpe.flags & KP_DIRECT) || (kpe.flags & KP_MATRIX) ) { - c = get_scancode(&kpe); - if (c != NO_KEY) { - put_user(c, buf++); - left --; - } - } - } while (left); - - return (count-left); -} - -static int kpdrv_ioctl(struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg) -{ - int interval = KPKDI & 0xffff; - int ign = (KPC & KPC_IMKP); - - switch(cmd) { - case KPIOGET_INTERVAL: - if (copy_to_user((void*)arg, &interval, sizeof(int))) - return -EFAULT; - break; - case KPIOGET_IGNMULTI: - if (copy_to_user((void*)arg, &ign, sizeof(int))) - return -EFAULT; - break; - case KPIOSET_INTERVAL: - if (copy_from_user(&interval, (void*)arg, sizeof(int))) - return -EFAULT; - - /* FIXME : sighting #34833, Matrix Key interval should be >10ms */ - if ( (interval & 0xff) < 10) return -EINVAL; - - KPKDI &= ~0xffff; - KPKDI |= (interval & 0xffff); - break; - case KPIOSET_IGNMULTI: - if (copy_from_user(&ign, (void*)arg, sizeof(int))) - return -EFAULT; - - if (ign) - KPC |= KPC_IMKP; - else - KPC &= ~KPC_IMKP; - - break; - - default: - /* unknown command */ - return -EINVAL; - } - return 0; -} - -static unsigned int kpdrv_poll(struct file *filp, poll_table * wait) { - return kp_poll(filp, wait); -} - -static int kpdrv_open(struct inode *inode, struct file *filp) -{ - down(&kpdrv_mutex); - if (!kpdrv_refcount) - kp_init(); - kpdrv_refcount++; - up(&kpdrv_mutex); - - return 0; -} - -static int kpdrv_close(struct inode *inode, struct file *filp) -{ - down(&kpdrv_mutex); - kpdrv_refcount--; - up(&kpdrv_mutex); - - return 0; -} - -static struct file_operations kpdrv_fops = { - owner: THIS_MODULE, - open: kpdrv_open, - release: kpdrv_close, - read: kpdrv_read, - ioctl: kpdrv_ioctl, - poll: kpdrv_poll, -}; - - -static struct miscdevice keypad_miscdevice = { - MISC_DYNAMIC_MINOR, "mbfasttap", &kpdrv_fops -}; - -static int __init kpdrv_init(void) -{ - int err; - - /* initial counter */ - init_MUTEX(&kpdrv_mutex); - kpdrv_refcount = 0; - - /* setup gpio */ - set_GPIO_mode( 93 | GPIO_ALT_FN_1_IN); - set_GPIO_mode( 94 | GPIO_ALT_FN_1_IN); - set_GPIO_mode( 95 | GPIO_ALT_FN_3_IN); - set_GPIO_mode( 96 | GPIO_ALT_FN_3_OUT); - set_GPIO_mode( 97 | GPIO_ALT_FN_3_IN); - set_GPIO_mode( 98 | GPIO_ALT_FN_3_IN); - set_GPIO_mode( 99 | GPIO_ALT_FN_3_IN); - set_GPIO_mode(100 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(101 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(102 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(103 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(104 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(105 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(106 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(107 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(108 | GPIO_ALT_FN_2_OUT); - - /* set keypad control register */ - KPC = (KPC_ASACT | (7<<26) | (7<<23)| - KPC_ME | (2<<6) | KPC_DEE0 | KPC_DE | - KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 |KPC_MS4 | KPC_MS5| KPC_MS6 | KPC_MS7 | - KPC_MIE | KPC_DIE | KPC_REE0); - - /* set debounce time to 10ms */ - KPKDI= 0x010A; - - /* set scroll wheel value to mid-point value */ - KPREC= 0x7F; - - /* enable unit clock */ - CKEN |= CKEN19_KEYPAD; - - /* register driver as miscdev*/ - err = misc_register(&keypad_miscdevice); - - if (err) - printk(KERN_ERR "FastTap misc_register failed\n"); - - return 0; -} - -static void __init kpdrv_cleanup(void) -{ - /* disable clock unit */ - CKEN &= ~CKEN19_KEYPAD; -} - -module_init(kpdrv_init); -module_exit(kpdrv_cleanup); - -MODULE_AUTHOR("Yu Tang "); -MODULE_DESCRIPTION("Intel Mainstone-II FastTap driver"); -MODULE_LICENSE("GPL"); diff -uNr a/drivers/char/mbkeypad.c b/drivers/char/mbkeypad.c --- a/drivers/char/mbkeypad.c 2004-10-22 10:52:41.000000000 +0800 +++ b/drivers/char/mbkeypad.c 1970-01-01 08:00:00.000000000 +0800 @@ -1,261 +0,0 @@ -/* linux/driver/char/mbkeypad.c - * - * Keypad driver for Intel Mainstone Development Board - * - * Copyright (C) 2003, Intel Corporation (yu.tang@intel.com) - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Direct-KEY scan-code for Mainstone-I Board */ -#define ROTARY_DEFAULT 0x7F -#define NO_KEY 0xFF -#define SCAN_CODE_SCROLL_UP 0xA -#define SCAN_CODE_SCROLL_DOWN 0xB -#define SCAN_CODE_ACTION 0xC - -static struct semaphore kpdrv_mutex; -static int kpdrv_refcount=0; - -static unsigned char get_scancode(struct kp_event *kpe) -{ - static unsigned int curr, prev=ROTARY_DEFAULT; - unsigned int c; - - c = NO_KEY; - - if (kpe->flags & KP_DIRECT) { - - curr = kpe->rotary & 0xFF; - - if (kpe->rotary & KPREC_OF0) { - KPREC &= ~KPREC_OF0; - KPREC |= ROTARY_DEFAULT; - prev = ROTARY_DEFAULT; - c = SCAN_CODE_SCROLL_UP; - } - else if (kpe->rotary & KPREC_UF0) { - KPREC &= ~KPREC_UF0; - KPREC |= ROTARY_DEFAULT; - prev = ROTARY_DEFAULT; - c = SCAN_CODE_SCROLL_DOWN; - } - else if (curr > prev) { - c = SCAN_CODE_SCROLL_UP; - prev = curr; - } - else if (curr < prev) { - c = SCAN_CODE_SCROLL_DOWN; - prev = curr; - } - else if (kpe->direct & KPDK_DK2) { - c = SCAN_CODE_ACTION; - prev = curr; - } - } - - if (kpe->flags & KP_MATRIX) { - unsigned int count = (kpe->matrix[0] >> 26) & 0x1f; - - c = kpe->matrix[0] & 0xff; - - /* key up */ - if (!count) c |= 0x80; - } - - return c; -} - -static ssize_t kpdrv_read(struct file * filp, char * buf, - size_t count, loff_t *ppos) -{ - struct kp_event kpe; - int err,left,timeout; - unsigned char c; - - timeout = 0; - left = count; - do { - err = kp_wait(&kpe, timeout); - if (err) { - if ( left != count ) return (count-left); - - if (filp->f_flags & O_NONBLOCK) return err; - - if (timeout) return err; - - timeout = -1; - continue; - } - - /* parse if direct/matrix flags are set*/ - if ( (kpe.flags & KP_DIRECT) || (kpe.flags & KP_MATRIX) ) { - c = get_scancode(&kpe); - if (c != NO_KEY) { - put_user(c, buf++); - left --; - } - } - } while (left); - - return (count-left); -} - -static int kpdrv_ioctl(struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg) -{ - int interval = KPKDI & 0xffff; - int ign = (KPC & KPC_IMKP); - - switch(cmd) { - case KPIOGET_INTERVAL: - if (copy_to_user((void*)arg, &interval, sizeof(int))) - return -EFAULT; - break; - case KPIOGET_IGNMULTI: - if (copy_to_user((void*)arg, &ign, sizeof(int))) - return -EFAULT; - break; - case KPIOSET_INTERVAL: - if (copy_from_user(&interval, (void*)arg, sizeof(int))) - return -EFAULT; - - /* FIXME : sighting #34833, Matrix Key interval should be >10ms */ - if ( (interval & 0xff) < 10) return -EINVAL; - - KPKDI &= ~0xffff; - KPKDI |= (interval & 0xffff); - break; - case KPIOSET_IGNMULTI: - if (copy_from_user(&ign, (void*)arg, sizeof(int))) - return -EFAULT; - - if (ign) - KPC |= KPC_IMKP; - else - KPC &= ~KPC_IMKP; - - break; - - default: - /* unknown command */ - return -EINVAL; - } - return 0; -} - -static unsigned int kpdrv_poll(struct file *filp, poll_table * wait) { - return kp_poll(filp, wait); -} - -static int kpdrv_open(struct inode *inode, struct file *filp) -{ - down(&kpdrv_mutex); - if (!kpdrv_refcount) - kp_init(); - kpdrv_refcount++; - up(&kpdrv_mutex); - - return 0; -} - -static int kpdrv_close(struct inode *inode, struct file *filp) -{ - down(&kpdrv_mutex); - kpdrv_refcount--; - up(&kpdrv_mutex); - - return 0; -} - -static struct file_operations kpdrv_fops = { - owner: THIS_MODULE, - open: kpdrv_open, - release: kpdrv_close, - read: kpdrv_read, - ioctl: kpdrv_ioctl, - poll: kpdrv_poll, -}; - - -static struct miscdevice keypad_miscdevice = { - MISC_DYNAMIC_MINOR, "mbkeypad", &kpdrv_fops -}; - -static int __init kpdrv_init(void) -{ - int err; - - /* initial counter */ - init_MUTEX(&kpdrv_mutex); - kpdrv_refcount = 0; - - /* setup gpio */ - set_GPIO_mode(93 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(94 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(95 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(98 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(99 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(100 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(101 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(102 | GPIO_ALT_FN_1_IN); - set_GPIO_mode(103 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(104 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(105 | GPIO_ALT_FN_2_OUT); - set_GPIO_mode(106 | GPIO_ALT_FN_2_OUT); - - /* set keypad control register */ - KPC = (KPC_ASACT | (3<<26) | (4<<23)| - KPC_ME | (2<<6) | KPC_DEE0 | KPC_DE | - KPC_MS0 | KPC_MS1 | KPC_MS2 | KPC_MS3 | KPC_MIE | KPC_DIE | KPC_IMKP); - - /* set debouce time low as the rotary encoder also used this value */ - KPKDI= 0x010A; - - /* set scroll wheel value to mid-point value */ - KPREC= 0x7F; - - /* enable unit clock */ - CKEN |= CKEN19_KEYPAD; - - /* register driver as miscdev*/ - err = misc_register(&keypad_miscdevice); - if (err) - printk(KERN_ERR "Keypad misc_register failed\n"); - - return 0; -} - -static void __init kpdrv_cleanup(void) -{ - /* disable clock unit */ - CKEN &= ~CKEN19_KEYPAD; -} - -module_init(kpdrv_init); -module_exit(kpdrv_cleanup); - -MODULE_AUTHOR("Yu Tang "); -MODULE_DESCRIPTION("Intel Mainstone KEYPAD driver"); -MODULE_LICENSE("GPL"); diff -uNr a/drivers/char/serial.c b/drivers/char/serial.c --- a/drivers/char/serial.c 2004-10-22 10:52:37.000000000 +0800 +++ b/drivers/char/serial.c 2004-12-29 10:50:30.000000000 +0800 @@ -232,6 +232,9 @@ #ifdef CONFIG_MAGIC_SYSRQ #include #endif +#ifdef CONFIG_PM +#include +#endif /* * All of the compatibilty code so we can compile serial.c against @@ -896,10 +899,30 @@ #endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ +#ifdef CONFIG_PXA27x_E20 +static void disable_timeout_int(struct async_struct *info) +{ + /* Disable the Receiver Time-Out interrupt via IER[RTOIE] */ + info->IER = serial_in(info, UART_IER); + info->IER &= ~UART_IER_RTOIE; + serial_outp(info, UART_IER, info->IER); +} + +static void enable_timeout_int(struct async_struct *info) +{ + /* Re-enable the Receiver Time-Out interrupt via IER[RTOIE] */ + info->IER = serial_in(info, UART_IER); + info->IER |=UART_IER_RTOIE; + serial_outp(info, UART_IER, info->IER); /* enable interrupts */ +} +#else +static void disable_timeout_int(struct async_struct *info) { } +static void enable_timeout_int(struct async_struct *info) { } +#endif + /* * This is the serial driver's interrupt routine for a single port */ -#define UART_SIGHTING_45882 1 static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) { int status, iir; @@ -930,20 +953,12 @@ #ifdef SERIAL_DEBUG_INTR printk("status = %x...", status); #endif -#ifdef UART_SIGHTING_45882 - /* Disable the Receiver Time-Out interrupt via IER[RTOIE] */ - info->IER = serial_in(info, UART_IER); - info->IER &= ~UART_IER_RTOIE; - serial_outp(info, UART_IER, info->IER); -#endif - if (status & UART_LSR_DR) + if (status & UART_LSR_DR) { + disable_timeout_int(info); receive_chars(info, &status, regs); -#ifdef UART_SIGHTING_45882 - /* Re-enable the Receiver Time-Out interrupt via IER[RTOIE] */ - info->IER = serial_in(info, UART_IER); - info->IER |=UART_IER_RTOIE; - serial_outp(info, UART_IER, info->IER); /* enable interrupts */ -#endif + enable_timeout_int(info); + } + check_modem_status(info); if ((status & UART_LSR_THRE) || /* For buggy ELAN processors */ @@ -5460,6 +5475,38 @@ #endif /* ENABLE_SERIAL_PNP */ +#ifdef CONFIG_PM +static int pm_rs_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) +{ + int i = 0; + while(i < NR_PORTS) { + struct async_struct * info = rs_table[i].info; + if (req == PM_SUSPEND && info ) { + shutdown(info); +#ifdef CONFIG_SERIAL_CONSOLE + if (info->line == sercons.index) { + acquire_console_sem(); + sercons.flags &= ~CON_ENABLED; + release_console_sem(); + } +#endif + } + else if (req == PM_RESUME && info) { +#ifdef CONFIG_SERIAL_CONSOLE + if (info->line == sercons.index) { + acquire_console_sem(); + sercons.flags |= CON_ENABLED; + release_console_sem(); + } +#endif + startup(info); + } + i++; + } + return 0; +} +#endif + /* * The serial driver boot-time initialization code! */ @@ -5623,6 +5670,9 @@ tty_register_devfs(&callout_driver, 0, callout_driver.minor_start + state->line); } +#ifdef CONFIG_PM + pm_register(PM_SYS_DEV, PM_SYS_COM, pm_rs_callback); +#endif #ifdef ENABLE_SERIAL_PCI probe_serial_pci(); #endif diff -uNr a/drivers/media/video/adcm2650.c b/drivers/media/video/adcm2650.c --- a/drivers/media/video/adcm2650.c 2004-10-22 10:53:03.000000000 +0800 +++ b/drivers/media/video/adcm2650.c 2004-12-29 10:50:30.000000000 +0800 @@ -63,7 +63,8 @@ // enable pixel clock(sensor will provide pclock) and master clock = 7MHZ //ci_set_clock(camera_context->clk_reg_base, 1, 1, MCLK_DEFT); // reset mclk to 5.6MHz to enable camera work in different frequency. - ci_set_clock(camera_context->clk_reg_base, 1, 1, 560); + //ci_set_clock(camera_context->clk_reg_base, 1, 1, 560); + ci_set_clock(camera_context->clk_reg_base, 1, 1, 650); //cs:6.5Mhz MCLK // data sample on rising and h,vsync active high ci_set_polarity(0, 0, 0); @@ -96,7 +97,8 @@ // power on the module // note: pll is NOT enabled, ADCM is using external clock - status = adcm2650_power_on(MCLK_DEFT);// external mclk = 7M HZ + //status = adcm2650_power_on(MCLK_DEFT);// external mclk = 7M HZ + status = adcm2650_power_on(0x0680);//cs: external mclk = 6.5M HZ 8.8 format // set default output format status = adcm2650_switch_to_normal(VIEWFINDER_MODE); @@ -109,6 +111,7 @@ regv &= ~VIDEO_CONFIG_SS; //regv |= VIDEO_CONFIG_V_MIRROR | VIDEO_CONFIG_H_MIRROR; regv |= VIDEO_CONFIG_V_MIRROR; + regv &= ~(0x0008); //cs: full power mode adcm2650_pipeline_write(VIDEO_CONFIG, regv); // testing only @@ -121,11 +124,14 @@ // gives 34 fps QCIF adcm2650_pipeline_read(PLL_CTRL_1, ®v); - adcm2650_pipeline_write(PLL_CTRL_1, 0x4848); +// adcm2650_pipeline_write(PLL_CTRL_1, 0x4848); + adcm2650_pipeline_write(PLL_CTRL_1, 0x4F04); //cs: VCO_DIV=79, REF_DIV=4 adcm2650_pipeline_read(PLL_CTRL_2, ®v); - adcm2650_pipeline_write(PLL_CTRL_2, 0x9010); - adcm2650_pipeline_write(CMD_2, 0x0300); +// adcm2650_pipeline_write(PLL_CTRL_2, 0x9010); + adcm2650_pipeline_write(PLL_CTRL_2, 0x4F04); //cs: VCO_DIV=79, REF_DIV=4 + adcm2650_pipeline_write(PLL_DIVBY_VID, 0x0c10); + adcm2650_pipeline_write(CMD_2, 0x0300); //start PLL and update shadow registers return 0; } diff -uNr a/drivers/media/video/adcm2650_hw.c b/drivers/media/video/adcm2650_hw.c --- a/drivers/media/video/adcm2650_hw.c 2004-10-22 10:53:03.000000000 +0800 +++ b/drivers/media/video/adcm2650_hw.c 2004-12-29 10:50:30.000000000 +0800 @@ -343,7 +343,8 @@ // /////////////////////////////////////////////////////////////// -int adcm2650_power_on( u8 clk ) +//int adcm2650_power_on( u8 clk ) +int adcm2650_power_on( u16 clk ) //cs:need more accuracy on mclk { // 1 Turn on M_VCC and wait for 20 ms. // 2 Turn on M_CLK using xx MHz and wait for 150 ms. @@ -667,9 +668,10 @@ return ADCM_ERR_NONE; } -int adcm2650_master_clock( u8 clk ) +int adcm2650_master_clock( u16 clk ) { - W( MASTER_CLK_FREQ, ((u16)clk) << 8 ); +// W( MASTER_CLK_FREQ, ((u16)clk) << 8 ); + W( MASTER_CLK_FREQ, ((u16)clk)); //cs:need more accuracy on mclk return ADCM_ERR_NONE; } diff -uNr a/drivers/media/video/adcm2650_hw.h b/drivers/media/video/adcm2650_hw.h --- a/drivers/media/video/adcm2650_hw.h 2004-10-22 10:53:03.000000000 +0800 +++ b/drivers/media/video/adcm2650_hw.h 2004-12-29 10:50:30.000000000 +0800 @@ -398,7 +398,8 @@ void adcm2650_wait( int ms ); // Configuration Procedures -int adcm2650_power_on( u8 ); +//int adcm2650_power_on( u8 ); +int adcm2650_power_on( u16 clk ); //cs: need more accuracy on mclk int adcm2650_power_off( void ); int adcm2650_change_viewfinder_mode(adcm_window_size * input_win, adcm_window_size *vf_output_win, adcm_window_size *sf_output_win ); int adcm2650_jpeg_slow_still_frame( void ); @@ -424,7 +425,8 @@ int adcm2650_pll_deactive( void ); int adcm2650_pll_configuration( void ); int adcm2650_pll_synchronized( void ); -int adcm2650_master_clock( u8 clk ); +//int adcm2650_master_clock( u8 clk ); +int adcm2650_master_clock( u16 clk ); //cs:need more accuracy on mclk int adcm2650_sensor_voltage( u8 vltg ); int adcm2650_factory_overwrite( void ); int adcm2650_viewfinder_input_size( adcm_window_size * win ); diff -uNr a/drivers/media/video/Config.in b/drivers/media/video/Config.in --- a/drivers/media/video/Config.in 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/media/video/Config.in 2004-12-29 10:50:30.000000000 +0800 @@ -50,7 +50,7 @@ dep_tristate ' Sony Vaio Picturebook Motion Eye Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_MEYE $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_SONYPI fi if [ "$CONFIG_ARCH_MAINSTONE" = "y" ]; then - dep_tristate ' Camera Interface for Bulverde(Mainstone) ' CONFIG_PXA_CAMERA_MS $CONFIG_VIDEO_DEV $CONFIG_ARCH_MAINSTONE + dep_tristate ' Camera Interface for Intel(R) PXA27x Processor Developer Kit ' CONFIG_PXA_CAMERA_MS $CONFIG_VIDEO_DEV $CONFIG_ARCH_MAINSTONE fi # unfortunately, this depends on having CONFIG_FB_CYBER2000 # set as well - we hook off of the VGA driver diff -uNr a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c --- a/drivers/media/video/pxa_camera.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/media/video/pxa_camera.c 2004-12-29 10:50:30.000000000 +0800 @@ -1079,6 +1079,19 @@ retval = -EFAULT; break; } +/* get last buffer id */ + case VIDIOBUFID: + { + int id; + id = camera_get_last_frame_buffer_id(cam_ctx); + if (id == -1) { + retval = -EFAULT; + break; + } + if (copy_to_user((void *)param, (void *)&id, sizeof(int))) + retval = -EFAULT; + break; + } /* Application extended IOCTL. */ /* Register access interface */ diff -uNr a/drivers/mtd/maps/mainstone.c b/drivers/mtd/maps/mainstone.c --- a/drivers/mtd/maps/mainstone.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/mtd/maps/mainstone.c 2004-12-29 10:50:30.000000000 +0800 @@ -21,7 +21,7 @@ #define ROM_ADDR 0x00000000 -#define WINDOW_SIZE 32*1024*1024 +#define WINDOW_SIZE 64*1024*1024 #ifdef CONFIG_PM struct pm_dev *flash_pmdev; @@ -48,7 +48,7 @@ size: 0x1000000, offset: 0x00240000 },{ - name: "Junk", + name: "unused", size: MTDPART_SIZ_FULL, offset: 0x1240000 } diff -uNr a/drivers/net/smc91x.c b/drivers/net/smc91x.c --- a/drivers/net/smc91x.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/net/smc91x.c 2004-12-29 10:50:30.000000000 +0800 @@ -1958,6 +1958,7 @@ switch (rqst) { case PM_SUSPEND: + netif_device_detach(global_dev); smc_shutdown(global_dev); break; case PM_RESUME: @@ -1967,6 +1968,7 @@ SMC_SET_MAC_ADDR(global_dev->dev_addr); if (lp->version >= 0x70) smc_phy_configure(global_dev); + netif_device_attach(global_dev); break; } return 0; diff -uNr a/drivers/pcmcia/pxa/mainstone.c b/drivers/pcmcia/pxa/mainstone.c --- a/drivers/pcmcia/pxa/mainstone.c 1970-01-01 08:00:00.000000000 +0800 +++ b/drivers/pcmcia/pxa/mainstone.c 2004-12-29 10:50:30.000000000 +0800 @@ -0,0 +1,180 @@ +/* + * linux/drivers/pcmcia/pxa/mainstone_pcmcia.c + * + * Sept. 30, 2004 Created by Alek Du(alek.du@intel.com) for mainstone PCMCIA SLOT + * + * Created: Aug 30, 2003 + * Copyright: Intel Co. Ltd. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include + +#include + +#include +#include +#include +#include + +/* define bzero here */ +#define bzero(d, n) memset((d), 0, (n)) + +static int +pccard_config_gpio(struct pcmcia_init *init) { + + /* Turn PCMCIA SLOT power off */ + MST_PCMCIA0 = 0; + MST_PCMCIA1 = 0; + + if (request_irq(MAINSTONE_S0_CD_IRQ, init->handler,SA_INTERRUPT, "Mainstone PCMCIA (0) CD",NULL) < 0 || + request_irq(MAINSTONE_S1_CD_IRQ, init->handler,SA_INTERRUPT, "Mainstone PCMCIA (1) CD", NULL) < 0 || + request_irq(MAINSTONE_S0_STSCHG_IRQ, init->handler,SA_INTERRUPT, "Mainstone PCMCIA (0) STSCHG",NULL) < 0 || + request_irq(MAINSTONE_S1_STSCHG_IRQ, init->handler,SA_INTERRUPT, "Mainstone PCMCIA (1) STSCHG", NULL) < 0) { + return -1; + } + + /* set GPIO for PCMCIA SLOT */ + + GPSR1 |= GPIO_bit(48) | GPIO_bit(49) | GPIO_bit(50) | GPIO_bit(51) | GPIO_bit(55) | GPIO_bit(56) | GPIO_bit(57); + GPSR2 |= GPIO_bit(79) | GPIO_bit(85); + + set_GPIO_mode(48 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(49 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(50 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(51 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(54 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(55 | GPIO_ALT_FN_2_OUT); + set_GPIO_mode(56 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(57 | GPIO_ALT_FN_1_IN); + set_GPIO_mode(79 | GPIO_ALT_FN_1_OUT); + set_GPIO_mode(85 | GPIO_ALT_FN_1_OUT); + + return 2; +} + +static int +pccard_power_off(void) +{ + free_irq (MAINSTONE_S0_CD_IRQ, NULL); + free_irq (MAINSTONE_S1_CD_IRQ, NULL); + free_irq (MAINSTONE_S0_STSCHG_IRQ, NULL); + free_irq (MAINSTONE_S1_STSCHG_IRQ, NULL); + /* Turn PCMCIA SLOT power off */ + MST_PCMCIA0 = 0; + MST_PCMCIA1 = 0; + return 0; +} + +static int +assign_state(struct pcmcia_state *state,unsigned long status) +{ + bzero(state,sizeof(struct pcmcia_state)); + if (!(status & MST_PCMCIA_nCD)) + state->detect=1; + if (status & MST_PCMCIA_nIRQ) + state->ready=1; + if (status & MST_PCMCIA_nSTSCHG_BVD1) + state->bvd1=1; + if (status & MST_PCMCIA_nSPKR_BVD2) + state->bvd2=1; + if (!(status & MST_PCMCIA_nVS1)) + state->vs_3v=1; + if (!(status & MST_PCMCIA_nVS2)) + state->vs_Xv=1; + return 1; +} +static int +pccard_set_slot_state(struct pcmcia_state_array *state_array) +{ + if (state_array->size < 2) + return -1; + + assign_state(&state_array->state[0],MST_PCMCIA0); + assign_state(&state_array->state[1],MST_PCMCIA1); + + return 1; +} + +static int +pccard_get_irq_info(struct pcmcia_irq_info *info) +{ + if (info->sock==0) + info->irq = MAINSTONE_S0_IRQ; + else if (info->sock==1) + info->irq = MAINSTONE_S1_IRQ; + else + return -1; + return 0; +} + +static int +pccard_configure_socket(unsigned int sock, socket_state_t *state) +{ + unsigned long flags, power; + + local_irq_save(flags); + + power = 0; + switch (state->Vcc) { + case 0: + power |= MST_PCMCIA_PWR_VCC_0; + break; + case 33: + power |= MST_PCMCIA_PWR_VCC_33; + break; + case 50: + power |= MST_PCMCIA_PWR_VCC_50; + break; + default: + printk(KERN_ERR "Can not support VCC %u\n",state->Vcc); + break; + } + + switch (state->Vpp) { + case 0: + power |= MST_PCMCIA_PWR_VPP_0; + break; + case 120: + power |= MST_PCMCIA_PWR_VPP_120; + break; + default: + if(state->Vpp == state->Vcc) + power |= MST_PCMCIA_PWR_VPP_VCC; + else { + printk(KERN_ERR "Can not support VPP %u\n",state->Vpp); + break; + } + } + + if (sock==0) + MST_PCMCIA0 = power |((state->flags & SS_RESET) ? MST_PCMCIA_RESET : 0); + else if (sock==1) + MST_PCMCIA1 = power |((state->flags & SS_RESET) ? MST_PCMCIA_RESET : 0); + + local_irq_restore(flags); + return 1; +} + +struct pcmcia_low_level mainstone_pcmcia_ops = { + pccard_config_gpio, + pccard_power_off, + pccard_set_slot_state, + pccard_get_irq_info, + pccard_configure_socket +}; diff -uNr a/drivers/pcmcia/pxa/Makefile b/drivers/pcmcia/pxa/Makefile --- a/drivers/pcmcia/pxa/Makefile 2004-10-22 10:53:01.000000000 +0800 +++ b/drivers/pcmcia/pxa/Makefile 2004-12-29 10:50:30.000000000 +0800 @@ -5,14 +5,19 @@ # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). -O_TARGET := pxa_cs.o +O_TARGET := pxa_cs.o +list-multi := pxa_cs_mod.o -obj-y := pxa.o -obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o -obj-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o -obj-$(CONFIG_ARCH_TRIZEPS2) += trizeps2.o -obj-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o +pxa_cs_mod-objs-y := pxa.o +pxa_cs_mod-objs-$(CONFIG_ARCH_LUBBOCK) += lubbock.o +pxa_cs_mod-objs-$(CONFIG_ARCH_MAINSTONE) += mainstone.o +pxa_cs_mod-objs-$(CONFIG_ARCH_PXA_IDP) += pxa_idp.o +pxa_cs_mod-objs-$(CONFIG_ARCH_PXA_CERF) += ../sa1100_cerf.o +pxa_cs_mod-objs := $(pxa_cs_mod-objs-y) -obj-m := $(O_TARGET) +obj-$(CONFIG_PCMCIA_PXA) += pxa_cs_mod.o include $(TOPDIR)/Rules.make + +pxa_cs_mod.o: $(pxa_cs_mod-objs) + $(LD) -r -o $@ $(pxa_cs_mod-objs) diff -uNr a/drivers/pcmcia/pxa/pxa.c b/drivers/pcmcia/pxa/pxa.c --- a/drivers/pcmcia/pxa/pxa.c 2004-10-22 10:53:01.000000000 +0800 +++ b/drivers/pcmcia/pxa/pxa.c 2004-12-29 10:50:30.000000000 +0800 @@ -1,6 +1,8 @@ /* * linux/drivers/pcmcia/pxa/pxa.c * + * Sept. 30, 2004 Modified by Alek Du(alek.du@intel.com) for mainstone PCMCIA SLOT + * * Author: George Davis * Created: Jan 10, 2002 * Copyright: MontaVista Software Inc. @@ -70,14 +72,10 @@ #include #include #include -#include +#include #include "pxa.h" -#ifdef PCMCIA_DEBUG -static int pc_debug; -#endif - MODULE_AUTHOR("George Davis "); MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA250/210 Socket Controller"); @@ -198,53 +196,11 @@ return -1; } - /* Setup GPIOs for PCMCIA/CF alternate function mode. - * - * It would be nice if set_GPIO_mode included support - * for driving GPIO outputs to default high/low state - * before programming GPIOs as outputs. Setting GPIO - * outputs to default high/low state via GPSR/GPCR - * before defining them as outputs should reduce - * the possibility of glitching outputs during GPIO - * setup. This of course assumes external terminators - * are present to hold GPIOs in a defined state. - * - * In the meantime, setup default state of GPIO - * outputs before we enable them as outputs. - */ - - GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | - GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | - GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - set_GPIO_mode(GPIO48_nPOE_MD); - set_GPIO_mode(GPIO49_nPWE_MD); - set_GPIO_mode(GPIO50_nPIOR_MD); - set_GPIO_mode(GPIO51_nPIOW_MD); - set_GPIO_mode(GPIO52_nPCE_1_MD); - set_GPIO_mode(GPIO53_nPCE_2_MD); - set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */ - set_GPIO_mode(GPIO55_nPREG_MD); - set_GPIO_mode(GPIO56_nPWAIT_MD); - set_GPIO_mode(GPIO57_nIOIS16_MD); - - - if(machine_is_lubbock()){ -#if defined(CONFIG_ARCH_LUBBOCK) || defined(CONFIG_ARCH_CSB226) - pcmcia_low_level=&lubbock_pcmcia_ops; -#endif - } else if (machine_is_pxa_idp()) { - pcmcia_low_level=&pxa_idp_pcmcia_ops; - } else if( machine_is_pxa_cerf()){ - pcmcia_low_level=&cerf_pcmcia_ops; - } else if (machine_is_trizeps2()){ -#ifdef CONFIG_ARCH_TRIZEPS2 - pcmcia_low_level=&trizeps2_pcmcia_ops; + if(machine_is_mainstone()){ +#ifdef CONFIG_ARCH_MAINSTONE + pcmcia_low_level=&mainstone_pcmcia_ops; #endif - } + } if (!pcmcia_low_level) { printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n"); @@ -529,7 +485,7 @@ if(pxa_pcmcia_socket[i].handler!=NULL) pxa_pcmcia_socket[i].handler(pxa_pcmcia_socket[i].handler_info, events); - } + } } while(all_events); } /* pxa_pcmcia_task_handler() */ diff -uNr a/drivers/pcmcia/pxa/pxa.h b/drivers/pcmcia/pxa/pxa.h --- a/drivers/pcmcia/pxa/pxa.h 2004-10-22 10:53:01.000000000 +0800 +++ b/drivers/pcmcia/pxa/pxa.h 2004-12-29 10:50:30.000000000 +0800 @@ -68,6 +68,17 @@ * reserved on the SA-1100.) */ +#define MECR_SOCKET_0_SHIFT (0) +#define MECR_SOCKET_1_SHIFT (16) + +#define MECR_BS_MASK (0x1f) +#define MECR_FAST_MODE_MASK (0x01) + +#define MECR_BSIO_SHIFT (0) +#define MECR_BSA_SHIFT (5) +#define MECR_BSM_SHIFT (10) +#define MECR_FAST_SHIFT (15) + #define MCXX_SETUP_MASK (0x7f) #define MCXX_ASST_MASK (0x1f) #define MCXX_HOLD_MASK (0x3f) @@ -122,19 +133,19 @@ static inline u_int pxa_mcxx_hold(u_int pcmcia_cycle_ns, u_int mem_clk_10khz){ u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 300000) + ((code % 300000) ? 1 : 0); + return (code / 300000) + ((code % 300000) ? 1 : 0) - 1; } static inline u_int pxa_mcxx_asst(u_int pcmcia_cycle_ns, u_int mem_clk_10khz){ u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 300000) + ((code % 300000) ? 1 : 0); + return (code / 300000) + ((code % 300000) ? 1 : 0) - 1; } static inline u_int pxa_mcxx_setup(u_int pcmcia_cycle_ns, u_int mem_clk_10khz){ u_int code = pcmcia_cycle_ns * mem_clk_10khz; - return (code / 100000) + ((code % 100000) ? 1 : 0) + 1; + return (code / 100000) + ((code % 100000) ? 1 : 0) - 1; } /* This function returns the (approxmiate) command assertion period, in @@ -225,9 +236,6 @@ /* * Declaration for all implementation specific low_level operations. */ -extern struct pcmcia_low_level lubbock_pcmcia_ops; -extern struct pcmcia_low_level pxa_idp_pcmcia_ops; -extern struct pcmcia_low_level cerf_pcmcia_ops; -extern struct pcmcia_low_level trizeps2_pcmcia_ops; +extern struct pcmcia_low_level mainstone_pcmcia_ops; #endif /* !defined(_PCMCIA_PXA_H) */ diff -uNr a/drivers/sound/pxa-ac97.c b/drivers/sound/pxa-ac97.c --- a/drivers/sound/pxa-ac97.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/sound/pxa-ac97.c 2004-12-29 10:50:30.000000000 +0800 @@ -52,32 +52,23 @@ #ifdef CONFIG_PM static int pxa_ac97_pm_callback(struct pm_dev *dev,pm_request_t rqst,void *data) { - struct ac97_codec *codec =( struct ac97_codec *)(dev->data); - int ret; - down(&pxa_ac97_mutex); + struct ac97_codec *codec =( struct ac97_codec *)(dev->data); + int ret; + down(&pxa_ac97_mutex); - if (rqst == PM_RESUME ) { - CKEN |= CKEN2_AC97; + if (rqst == PM_RESUME ) { + CKEN |= CKEN2_AC97; #if defined(CONFIG_ARCH_MAINSTONE) /* enable audio amplifier */ - MST_MSCWR2 &= 0xffff000b; -#endif - set_GPIO_mode(GPIO31_SYNC_AC97_MD); - set_GPIO_mode(GPIO30_SDATA_OUT_AC97_MD); - set_GPIO_mode(GPIO28_BITCLK_AC97_MD); - set_GPIO_mode(GPIO29_SDATA_IN_AC97_MD); - -#if defined(CONFIG_ARCH_MAINSTONE) - GPCR3 |= GPIO113_BIT; /* workaround to reset the codec */ - udelay(100); -#endif - GCR = 0; - udelay(120); - GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE; -#if defined(CONFIG_ARCH_MAINSTONE) - GPSR3 |= GPIO113_BIT; /* workaround to reset the code */ - udelay(30); + MST_MSCWR2 &= 0xffff000b; #endif + /* cold reset the codec */ + GCR = 0; + CKEN |= (1 << 31); + udelay(120); + CKEN &= ~(1 << 31); + GCR = GCR_COLD_RST|GCR_CDONE_IE|GCR_SDONE_IE; + udelay(30); ret = ac97_probe_codec(codec); if (ret != 1) @@ -176,7 +167,12 @@ static void pxa_ac97_irq(int irq, void *dev_id, struct pt_regs *regs) { - int gsr = GSR; + volatile int gsr = GSR; + volatile int pisr = PISR; + + if (pisr & 0x08) + PISR = 0x08; + GSR = gsr & (GSR_SDONE|GSR_CDONE); //write a 1 to clear if (gsr & waitingForMask) { diff -uNr a/drivers/usb/device/bi/bvd.c b/drivers/usb/device/bi/bvd.c --- a/drivers/usb/device/bi/bvd.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/usb/device/bi/bvd.c 2004-12-29 10:50:30.000000000 +0800 @@ -936,6 +936,8 @@ ) { u32 config_reg; + + UDCCR &= ~(UDCCR_UDE); config_reg = ((configuration&0x3)<<25) | ((interface&0x7)<<22) | ((alternate&0x7)<<19) | (eps<<15); @@ -951,7 +953,7 @@ if ( endpoint->direction == IN ) { config_reg |= 0x1000; } else { - config_reg |= 0x0000; + config_reg &= ~0x1000; } config_reg |= (endpoint->bmAttributes&0x3)<<13; @@ -967,6 +969,7 @@ ep_maps[phys_endpoints].eptype = (config_reg&0x7000)>>12; ep_maps[phys_endpoints].size = endpoint->wMaxPacketSize; + UDCCR &= UDCCR_UDE; return 0; } diff -uNr a/drivers/usb/device/serial_fd/serproto.c b/drivers/usb/device/serial_fd/serproto.c --- a/drivers/usb/device/serial_fd/serproto.c 2004-10-22 10:52:59.000000000 +0800 +++ b/drivers/usb/device/serial_fd/serproto.c 2004-12-29 10:50:30.000000000 +0800 @@ -271,7 +271,8 @@ // send at most tx_size bytes size = MIN (device->tx_size, cnt); - + if (size>device->max_queue_bytes-device->queued_bytes)// Alek (alek.du@intel.com)add this line to avoid urb fragment to speed up transfer + return count-cnt; write_lock_irqsave (&device->rwlock, flags); // Make sure we can send. if (!device->connected || diff -uNr a/drivers/video/pxafb.c b/drivers/video/pxafb.c --- a/drivers/video/pxafb.c 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/video/pxafb.c 2004-12-29 10:50:30.000000000 +0800 @@ -60,6 +60,14 @@ * debugging? */ #define DEBUG 0 +//#undef DEBUG + +#ifdef DEBUG +#define dbg(fmt,arg...) printk(KERN_ALERT "%s(): " fmt "\n", __FUNCTION__, ##arg) +#else +#define dbg(fmt,arg...) +#endif + /* * Complain if VAR is out of range. */ @@ -69,6 +77,11 @@ #include "pxafb.h" +wait_queue_head_t fcs_wait_eof; +int fcs_in_eof = 0; +#ifdef CONFIG_FAST_DVFM +unsigned int fcs_clkcfg = 0; +#endif void (*pxafb_blank_helper)(int blank); EXPORT_SYMBOL(pxafb_blank_helper); @@ -105,62 +118,117 @@ #ifdef CONFIG_CPU_BULVERDE -static int yuv420_enabled = 0; - static int overlay1fb_enable(struct fb_info *info); static int overlay2fb_enable(struct fb_info *info); static int cursorfb_enable(struct fb_info *info); -static void overlay1fb_disable(struct fb_info *info); -static void overlay2fb_disable(struct fb_info *info); -static void cursorfb_disable(struct fb_info *info); +static int overlay1fb_disable(struct fb_info *info); +static int overlay2fb_disable(struct fb_info *info); +static int cursorfb_disable(struct fb_info *info); static void overlay1fb_blank(int blank, struct fb_info *info); static void overlay2fb_blank(int blank, struct fb_info *info); static void cursorfb_blank(int blank, struct fb_info *info); static int init_pxafb_overlay(struct pxafb_info *fbi); -#define WAIT_FOR_END_OF_FRAME do { \ - int count=0; \ - LCSR0 = LCSR0_EOF0; \ - while (!(LCSR0 & LCSR0_EOF0) && (count<100) ) { \ - mdelay(10); \ - count ++; \ - } \ - } \ -while(0) - -#define DISABLE_OVERLAYS(fbi) do { \ - if (fbi->overlay1fb->enabled) { \ - fbi->overlay1fb->enabled = 0; \ - if (fbi->overlay1fb->state == C_ENABLE) { \ - overlay1fb_disable((struct fb_info*)fbi->overlay1fb); \ - fbi->overlay1fb->state = C_ENABLE; \ - } \ - } \ - if (fbi->overlay2fb->enabled) { \ - fbi->overlay2fb->enabled = 0; \ - if (fbi->overlay2fb->state == C_ENABLE) { \ - overlay2fb_disable((struct fb_info*)fbi->overlay2fb); \ - fbi->overlay2fb->state = C_ENABLE; \ - } \ - } \ - if (fbi->cursorfb->enabled) { \ - fbi->cursorfb->enabled = 0; \ - if (fbi->cursorfb->state == C_ENABLE) { \ - cursorfb_disable((struct fb_info*)fbi->cursorfb); \ - fbi->cursorfb->state = C_ENABLE; \ - } \ - } \ +#define CLEAR_LCD_INTR(reg, intr) do { \ + reg = (intr); \ +}while(0) + +#define WAIT_FOR_LCD_INTR(reg,intr,timeout) ({ \ + int __done =0; \ + int __t = timeout; \ + while (__t) { \ + __done = (reg) & (intr); \ + if (__done) break; \ + mdelay(10); \ + __t--; \ + } \ + if (!__t) dbg("wait " #intr " timeount");\ + __done; \ +}) + +#define DISABLE_OVERLAYS(fbi) do { \ + if (fbi->overlay1fb && (fbi->overlay1fb->state == C_ENABLE)) { \ + overlay1fb_disable((struct fb_info*)fbi->overlay1fb); \ + } \ + if (fbi->overlay2fb && (fbi->overlay2fb->state == C_ENABLE)) { \ + overlay2fb_disable((struct fb_info*)fbi->overlay2fb); \ + } \ + if (fbi->cursorfb && (fbi->cursorfb->state == C_ENABLE)) { \ + cursorfb_disable((struct fb_info*)fbi->cursorfb); \ + } \ +}while(0) + +#define ENABLE_OVERLAYS(fbi) do { \ + if (fbi->overlay1fb && (fbi->overlay1fb->state == C_DISABLE)){ \ + overlay1fb_enable((struct fb_info*)fbi->overlay1fb); \ + } \ + if (fbi->overlay2fb && (fbi->overlay2fb->state == C_DISABLE)){ \ + overlay2fb_unblank_workaroundYUV420((struct fb_info*)fbi->overlay2fb); \ + overlay2fb_enable((struct fb_info*)fbi->overlay2fb); \ + } \ + if (fbi->cursorfb && (fbi->cursorfb->state == C_DISABLE)){ \ + cursorfb_enable((struct fb_info*)fbi->cursorfb); \ + } \ +}while(0) + +#define BLANK_OVERLAYS(fbi) do { \ + dbg("blank lcd"); \ + if (fbi->overlay1fb && (fbi->overlay1fb->state == C_ENABLE)) { \ + overlay1fb_disable((struct fb_info*)fbi->overlay1fb); \ + fbi->overlay1fb->state = C_BLANK; \ + } \ + if (fbi->overlay2fb && (fbi->overlay2fb->state == C_ENABLE)) { \ + overlay2fb_disable((struct fb_info*)fbi->overlay2fb); \ + fbi->overlay2fb->state = C_BLANK; \ + } \ + if (fbi->cursorfb && (fbi->cursorfb->state == C_ENABLE)) { \ + cursorfb_disable((struct fb_info*)fbi->cursorfb); \ + fbi->cursorfb->state = C_BLANK; \ + } \ }while(0) -#define ENABLE_OVERLAYS(fbi) do { \ - if (fbi->overlay1fb->state == C_ENABLE) \ - overlay1fb_enable((struct fb_info*)fbi->overlay1fb); \ - if (fbi->overlay2fb->state == C_ENABLE) \ - overlay2fb_enable((struct fb_info*)fbi->overlay2fb); \ - if (fbi->cursorfb->state == C_ENABLE) \ +#define UNBLANK_OVERLAYS(fbi) do { \ + dbg("unblank lcd"); \ + if (fbi->overlay1fb && (fbi->overlay1fb->state == C_BLANK)){ \ + overlay1fb_enable((struct fb_info*)fbi->overlay1fb); \ + } \ + if (fbi->overlay2fb && (fbi->overlay2fb->state == C_BLANK)){ \ + overlay2fb_unblank_workaroundYUV420((struct fb_info*)fbi->overlay2fb); \ + overlay2fb_enable((struct fb_info*)fbi->overlay2fb); \ + } \ + if (fbi->cursorfb && (fbi->cursorfb->state == C_BLANK)){ \ cursorfb_enable((struct fb_info*)fbi->cursorfb); \ + } \ }while(0) +static struct pxafb_rgb def_rgbt_16 = { + red: { offset: 10, length: 5, }, + green: { offset: 5, length: 5, }, + blue: { offset: 0, length: 5, }, + transp: { offset: 15, length: 1, }, +}; + +static struct pxafb_rgb def_rgbt_19 = { + red: { offset: 12, length: 6, }, + green: { offset: 6, length: 6, }, + blue: { offset: 0, length: 6, }, + transp: { offset: 18, length: 1, }, +}; + +static struct pxafb_rgb def_rgbt_24 = { + red: { offset: 16, length: 7, }, + green: { offset: 8, length: 8, }, + blue: { offset: 0, length: 8, }, + transp: { offset: 0, length: 0, }, +}; + +static struct pxafb_rgb def_rgbt_25 = { + red: { offset: 16, length: 8, }, + green: { offset: 8, length: 8, }, + blue: { offset: 0, length: 8, }, + transp: { offset: 24, length: 1, }, +}; + #endif static struct pxafb_mach_info pxa_fb_info __initdata = { @@ -724,7 +792,7 @@ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) for (i = 0; i < fbi->palette_size; i++) pxafb_setpalettereg(i, 0, 0, 0, 0, info); - pxafb_schedule_task(fbi, C_DISABLE); + pxafb_schedule_task(fbi, C_BLANK); if (pxafb_blank_helper) pxafb_blank_helper(blank); break; @@ -735,7 +803,7 @@ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR || fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) fb_set_cmap(&fbi->fb.cmap, 1, pxafb_setcolreg, info); - pxafb_schedule_task(fbi, C_ENABLE); + pxafb_schedule_task(fbi, C_UNBLANK); } } @@ -770,8 +838,18 @@ if (pixclock) { #if defined(CONFIG_CPU_BULVERDE) DPRINTK("pixclock = %d\n", pixclock ); - pcd = ((get_lcd_clock_10khz() / pixclock) / 2); + /* using pixclock = lcd clock/(pcd+1) */ + pcd = (get_lcd_clock_10khz() / pixclock); if ( pcd <= 0 ) pcd = 1; + /* FIXME for lcd clock(10khz) equals 10400 or 5200, special + PCD value is used. If we use the formula to calculate the + PCD value, the LCD will flicker when DVFM. + */ + if ( get_lcd_clock_10khz() == 10400) + pcd = 16; + if ( get_lcd_clock_10khz() == 5200) + pcd = 9; + DPRINTK("lcd clock = %d\n", get_lcd_clock_10khz() ); DPRINTK("pcd = %d\n", pcd ); #else @@ -968,7 +1046,7 @@ fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma; fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + bytes_per_panel; fbi->dmadesc_fblow_cpu->fidr = 0; - fbi->dmadesc_fblow_cpu->ldcmd = bytes_per_panel; + fbi->dmadesc_fblow_cpu->ldcmd = bytes_per_panel | (1 << 21); fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */ fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma; fbi->dmadesc_fbhigh_cpu->fidr = 0; @@ -1200,12 +1278,11 @@ } } +#ifdef CONFIG_PXA27x_E17 static void pxafb_enable_controller(struct pxafb_info *fbi) { DPRINTK("Enabling LCD controller\n"); -#if CONFIG_CPU_BULVERDE - /* workaround for insight 41187 */ OVL1C2 = 0; OVL1C1 = 0; OVL2C2 = 0; @@ -1231,7 +1308,16 @@ FDADR1 = fbi->fdadr1; LCCR0 |= LCCR0_ENB; + + DPRINTK("LCCR1 = 0x%08x\n", (unsigned int)LCCR1); + DPRINTK("LCCR2 = 0x%08x\n", (unsigned int)LCCR2); + DPRINTK("LCCR3 = 0x%08x\n", (unsigned int)LCCR3); +} #else +static void pxafb_enable_controller(struct pxafb_info *fbi) +{ + DPRINTK("Enabling LCD controller\n"); + LCCR3 = fbi->reg_lccr3; LCCR2 = fbi->reg_lccr2; LCCR1 = fbi->reg_lccr1; @@ -1240,11 +1326,11 @@ FDADR0 = fbi->fdadr0; FDADR1 = fbi->fdadr1; LCCR0 |= LCCR0_ENB; -#endif DPRINTK("LCCR1 = 0x%08x\n", (unsigned int)LCCR1); DPRINTK("LCCR2 = 0x%08x\n", (unsigned int)LCCR2); DPRINTK("LCCR3 = 0x%08x\n", (unsigned int)LCCR3); } +#endif static void pxafb_disable_controller(struct pxafb_info *fbi) { @@ -1273,16 +1359,40 @@ /* * pxafb_handle_irq: Handle 'LCD DONE' interrupts. */ +#ifdef CONFIG_FAST_DVFM +extern void bulverde_setspeed(unsigned int ); +#endif + static void pxafb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) { struct pxafb_info *fbi = dev_id; unsigned int lcsr = LCSR0; + static unsigned int ou_count = 0; if (lcsr & LCSR0_LDD) { LCCR0 |= LCCR0_LDM; wake_up(&fbi->ctrlr_wait); } + if (lcsr & LCSR0_EOF0 && fcs_in_eof) { +#ifdef CONFIG_FAST_DVFM + int pcd, lccr3; + bulverde_setspeed(fcs_clkcfg); + pcd = pxafb_get_pcd(fbi->fb.var.pixclock); + + lccr3 = fbi->reg_lccr3; + fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); + if (lccr3 != fbi->reg_lccr3) + LCCR3 = fbi->reg_lccr3; +#endif + fcs_in_eof = 0; + wake_up(&fcs_wait_eof); + } + if (lcsr & LCSR0_OU) + { + ou_count++; + } + MST_LEDDAT1 = ou_count; LCSR0 = lcsr; } @@ -1307,10 +1417,10 @@ */ if (old_state != C_DISABLE) { fbi->state = state; - pxafb_disable_controller(fbi); #ifdef CONFIG_CPU_BULVERDE DISABLE_OVERLAYS(fbi); #endif + pxafb_disable_controller(fbi); } break; @@ -1321,12 +1431,12 @@ if (old_state != C_DISABLE) { fbi->state = state; pxafb_backlight_off(fbi); - if (old_state != C_DISABLE_CLKCHANGE) - pxafb_disable_controller(fbi); - pxafb_power_down_lcd(fbi); #ifdef CONFIG_CPU_BULVERDE DISABLE_OVERLAYS(fbi); #endif + if (old_state != C_DISABLE_CLKCHANGE) + pxafb_disable_controller(fbi); + pxafb_power_down_lcd(fbi); } break; @@ -1351,11 +1461,13 @@ * registers. */ if (old_state == C_ENABLE) { +#ifdef CONFIG_CPU_BULVERDE + DISABLE_OVERLAYS(fbi); +#endif pxafb_disable_controller(fbi); pxafb_setup_gpio(fbi); pxafb_enable_controller(fbi); #ifdef CONFIG_CPU_BULVERDE - DISABLE_OVERLAYS(fbi); ENABLE_OVERLAYS(fbi); #endif } @@ -1377,6 +1489,37 @@ #endif } break; + case C_UNBLANK: + /* + * Unblank the LCD screen, enable controller, and + * turn on the backlight. + */ + if (old_state != C_ENABLE) { + fbi->state = C_ENABLE; + pxafb_setup_gpio(fbi); + pxafb_power_up_lcd(fbi); + pxafb_enable_controller(fbi); + pxafb_backlight_on(fbi); +#ifdef CONFIG_CPU_BULVERDE + UNBLANK_OVERLAYS(fbi); +#endif + } + break; + case C_BLANK: + /* + * Disable controller + */ + if (old_state != C_DISABLE) { + fbi->state = state; + pxafb_backlight_off(fbi); +#ifdef CONFIG_CPU_BULVERDE + BLANK_OVERLAYS(fbi); +#endif + if (old_state != C_DISABLE_CLKCHANGE) + pxafb_disable_controller(fbi); + pxafb_power_down_lcd(fbi); + } + break; } up(&fbi->ctrlr_sem); } @@ -1399,12 +1542,31 @@ * parameters when the CPU clock is adjusted by the power management * subsystem. */ -static int -pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val, +#ifdef CONFIG_FAST_DVFM +void pxafb_wait_for_eof(unsigned int clkcfg) +#else +void pxafb_wait_for_eof() +#endif +{ + DECLARE_WAITQUEUE(wait, current); +#ifdef CONFIG_FAST_DVFM + fcs_clkcfg = clkcfg; +#endif + add_wait_queue(&fcs_wait_eof, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + fcs_in_eof = 1; + schedule_timeout(20 * HZ / 1000); + current->state = TASK_RUNNING; + remove_wait_queue(&fcs_wait_eof, &wait); +} +EXPORT_SYMBOL(pxafb_wait_for_eof); + +static int pxafb_clkchg_notifier(struct notifier_block *nb, unsigned long val, void *data) { struct pxafb_info *fbi = TO_INF(nb, clockchg); - u_int pcd; + u_int pcd, lccr3; + struct cpufreq_info *clkinfo; switch (val) { case CPUFREQ_MINMAX: @@ -1412,32 +1574,22 @@ break; case CPUFREQ_PRECHANGE: - set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); break; case CPUFREQ_POSTCHANGE: - pcd = pxafb_get_pcd(fbi->fb.var.pixclock); + clkinfo = (struct cpufreq_info *)data; + if ((clkinfo->old_freq == 13000)) + break; -#if 0 - LCSR0 |= LCSR0_EOF; - while((LCSR0 & LCSR0_EOF) == 0 ) - ; - LCSR0 |= LCSR0_EOF; -#endif +#ifndef CONFIG_FAST_DVFM + pcd = pxafb_get_pcd(fbi->fb.var.pixclock); + lccr3 = fbi->reg_lccr3; fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); - - set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); -#if 0 - pxafb_disable_controller(fbi); - pxafb_enable_controller(fbi); - pxafb_disable_controller(fbi); - pxafb_enable_controller(fbi); -#endif -#ifdef CONFIG_CPU_BULVERDE - set_ctrlr_state(fbi, C_REENABLE); -#endif + if (lccr3 != fbi->reg_lccr3) + LCCR3 = fbi->reg_lccr3; break; +#endif } return 0; } @@ -1461,6 +1613,8 @@ if (state == 0) { /* Enter D0. */ set_ctrlr_state(fbi, C_ENABLE); + LCCR4 |= (1 << 31); + LCCR4 |= (5 << 17); #ifdef CONFIG_CPU_BULVERDE set_ctrlr_state(fbi, C_REENABLE); #endif @@ -1700,7 +1854,9 @@ /* This driver cannot be unloaded at the moment */ MOD_INC_USE_COUNT; - + LCCR4 |= (1 << 31); + LCCR4 |= (5 << 17); + init_waitqueue_head(&fcs_wait_eof); return 0; failed: @@ -1729,6 +1885,10 @@ struct overlayfb_info *fbi = (struct overlayfb_info*) info; int ret = 0; +/* If basefb is disable, enable fb. */ + if (fbi->basefb && fbi->basefb->state != C_ENABLE) + pxafb_blank(VESA_NO_BLANKING, fbi->basefb); + down(&fbi->mutex); if (fbi->refcount) @@ -1748,6 +1908,7 @@ static int overlay1fb_release(struct fb_info *info, int user) { struct overlayfb_info *fbi = (struct overlayfb_info*) info; + dbg("enter,fbi->state= %d",fbi->state); down(&fbi->mutex); if (fbi->refcount) @@ -1755,8 +1916,12 @@ up(&fbi->mutex); /* disable overlay when released */ - overlay1fb_blank(1, info); + if (C_BLANK == fbi->state) + fbi->state = C_DISABLE; + else + overlay1fb_disable(info); + dbg("exit"); return 0; } @@ -1820,17 +1985,10 @@ /* disable branch/start/end of frame interrupt */ LCCR5 |= (LCCR5_IUM1 | LCCR5_BSM1 | LCCR5_EOFM1 | LCCR5_SOFM1); - /* disable overlay 1 window */ - OVL1C1 &= ~OVL1C1_O1EN; - - if (!fbi->enabled) { + if ((C_DISABLE == fbi->state) || (C_BLANK == fbi->state)) FDADR1 = (fbi->dma1->fdadr); - fbi->enabled = 1; - } - else { - + else FBR1 = fbi->dma1->fdadr | 0x1; - } /* enable overlay 1 window */ OVL1C2 = (fbi->ypos << 10) | fbi->xpos; @@ -1841,29 +1999,53 @@ return 0; } -static void overlay1fb_disable(struct fb_info *info) +static int overlay1fb_disable(struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*)info; + int done; + dbg("enter"); + + /* if overlay1 is disabled or blanked, just return 0 */ + if ((C_DISABLE == fbi->state) || (C_BLANK == fbi->state)) + return 0; fbi->state = C_DISABLE; /* clear O1EN */ OVL1C1 &= ~OVL1C1_O1EN; + + CLEAR_LCD_INTR(LCSR1, LCSR1_BS1); + FBR1 = 0x3; + done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS1, 100); + + if (!done) { + DPRINTK(KERN_INFO "%s: timeout\n", __FUNCTION__); + return -1; + } + dbg("exit"); + return 0; } static void overlay1fb_blank(int blank, struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*) info; + int err; switch(blank) { case 0: - set_ctrlr_state(fbi->basefb, C_REENABLE); - overlay1fb_enable(info); + err = overlay1fb_enable(info); + if (err) { + fbi->state = C_DISABLE; + set_ctrlr_state(fbi->basefb, C_REENABLE); + } break; case 1: - overlay1fb_disable(info); - set_ctrlr_state(fbi->basefb, C_REENABLE); + err = overlay1fb_disable(info); + if (err) { + fbi->state = C_DISABLE; + set_ctrlr_state(fbi->basefb, C_REENABLE); + } break; default: break; @@ -1911,19 +2093,15 @@ struct overlayfb_info *fbi=(struct overlayfb_info*)info; struct fb_var_screeninfo *dvar = &fbi->fb.var; int nbytes=0, err=0, pixels_per_line=0; - int xpos=0, ypos=0; + + /* if lcd is blanked, just return */ + if (C_BLANK == fbi->state) + return 0; /* validate parameters*/ err = overlay1fb_validate_var(var, fbi); if (err) return err; - xpos = var->nonstd & 0x3ff; - ypos = (var->nonstd>>10) & 0x3ff; - - if ( (fbi->xpos != xpos) || (fbi->ypos != ypos) ) { - fbi->xpos = xpos; - fbi->ypos = ypos; - } switch (var->bits_per_pixel) { case 16: @@ -1943,61 +2121,86 @@ break; } - if ( (var->xres != dvar->xres) || - (var->yres != dvar->yres) || - (var->bits_per_pixel != dvar->bits_per_pixel) ) { + if (fbi->state == C_DISABLE) + goto out1; - /* update var_screeninfo fields*/ - *dvar = *var; + if ( (var->xres == dvar->xres) && + (var->yres == dvar->yres) && + (var->bits_per_pixel == dvar->bits_per_pixel) ) + goto out2; + +out1: + /* update var_screeninfo fields*/ + *dvar = *var; - switch(var->bits_per_pixel) { - case 16: - /* 2 pixels per line */ - pixels_per_line = (fbi->fb.var.xres + 0x1) & (~0x1); - nbytes = 2; - - dvar->red = def_rgb_16.red; - dvar->green = def_rgb_16.green; - dvar->blue = def_rgb_16.blue; - dvar->transp = def_rgb_16.transp; + switch(var->bits_per_pixel) { + case 16: + /* 2 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x1) & (~0x1); + nbytes = 2; + + dvar->red = def_rgbt_16.red; + dvar->green = def_rgbt_16.green; + dvar->blue = def_rgbt_16.blue; + dvar->transp = def_rgbt_16.transp; - break; - case 18: - case 19: - /* 8 pixels per line */ - pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7); - nbytes = 3; - - dvar->red = def_rgb_18.red; - dvar->green = def_rgb_18.green; - dvar->blue = def_rgb_18.blue; - dvar->transp = def_rgb_18.transp; + break; + case 18: + /* 8 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7); + nbytes = 3; + + dvar->red = def_rgb_18.red; + dvar->green = def_rgb_18.green; + dvar->blue = def_rgb_18.blue; + dvar->transp = def_rgb_18.transp; - break; - case 24: - case 25: - pixels_per_line = fbi->fb.var.xres; - nbytes = 4; + break; + case 19: + /* 8 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7); + nbytes = 3; + + dvar->red = def_rgbt_19.red; + dvar->green = def_rgbt_19.green; + dvar->blue = def_rgbt_19.blue; + dvar->transp = def_rgbt_19.transp; - dvar->red = def_rgb_24.red; - dvar->green = def_rgb_24.green; - dvar->blue = def_rgb_24.blue; - dvar->transp = def_rgb_24.transp; + break; + case 24: + pixels_per_line = fbi->fb.var.xres; + nbytes = 4; - break; - } - - fbi->fb.fix.line_length = nbytes * pixels_per_line; - fbi->fb.fix.smem_len = fbi->fb.fix.line_length * fbi->fb.var.yres; + dvar->red = def_rgbt_24.red; + dvar->green = def_rgbt_24.green; + dvar->blue = def_rgbt_24.blue; + dvar->transp = def_rgbt_24.transp; - err= overlay1fb_map_video_memory((struct fb_info*)fbi); + break; + case 25: + pixels_per_line = fbi->fb.var.xres; + nbytes = 4; - if (err) return err; + dvar->red = def_rgbt_25.red; + dvar->green = def_rgbt_25.green; + dvar->blue = def_rgbt_25.blue; + dvar->transp = def_rgbt_25.transp; + + break; } - overlay1fb_enable((struct fb_info*)fbi); -/* set_ctrlr_state(fbi->basefb, C_REENABLE); */ + fbi->fb.fix.line_length = nbytes * pixels_per_line; + fbi->fb.fix.smem_len = fbi->fb.fix.line_length * fbi->fb.var.yres; + err= overlay1fb_map_video_memory((struct fb_info*)fbi); + + if (err) return err; + +out2: + fbi->xpos = var->nonstd & 0x3ff; + fbi->ypos = (var->nonstd>>10) & 0x3ff; + + overlay1fb_enable((struct fb_info*)fbi); return 0; } @@ -2036,6 +2239,10 @@ struct overlayfb_info *fbi = (struct overlayfb_info*) info; int ret = 0; +/* if basefb is disable, enable fb. */ + if (fbi->basefb && fbi->basefb->state != C_ENABLE) + pxafb_blank(VESA_NO_BLANKING, fbi->basefb); + down(&fbi->mutex); if (fbi->refcount) @@ -2046,7 +2253,6 @@ up(&fbi->mutex); fbi->fb.var.xres = fbi->fb.var.yres = 0; - yuv420_enabled = 0; return ret; } @@ -2062,12 +2268,15 @@ up(&fbi->mutex); /* disable overlay when released */ - overlay2fb_blank(1, info); + if (C_BLANK == fbi->state) + fbi->state = C_DISABLE; + else + overlay2fb_disable(info); return 0; } -static int overlay2fb_map_video_memory( struct fb_info *info) +static int overlay2fb_map_YUV_memory( struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*) info; unsigned int ylen, cblen, crlen, aylen, acblen, acrlen; @@ -2078,7 +2287,6 @@ ylen = cblen = crlen = aylen = acblen = acrlen = 0; yoff = cboff = croff = 0; - if (fbi->map_cpu) consistent_free((void*)fbi->map_cpu, fbi->map_size, fbi->map_dma); @@ -2168,7 +2376,6 @@ fbi->dma4->fidr = 0; fbi->dma4->ldcmd = crlen; - /* adjust for user */ fbi->fb.var.red.length = ylen; fbi->fb.var.red.offset = yoff; @@ -2180,61 +2387,165 @@ return 0; }; -/* set xpos, ypos, PPL and LP to 0 */ -static int overlay2fb_enable_RGB(struct fb_info *info) +static int overlay2fb_map_RGB_memory( struct fb_info *info) { - struct overlayfb_info *fbi = (struct overlayfb_info*)info; - struct pxafb_dma_descriptor *dma = (struct pxafb_dma_descriptor*) fbi->screen_cpu; - int timeout = 100; + struct overlayfb_info *fbi = (struct overlayfb_info*) info; + struct fb_var_screeninfo *var = &fbi->fb.var; + int pixels_per_line=0 , nbytes=0; - /* xpos,ypos = 0,0 */ - OVL2C2 = 0; - - /* 64 pixels, 16bpp */ - OVL2C1 = OVL2C1_O2EN | (63); - - dma->fdadr = fbi->screen_dma; - dma->fsadr = PHYS_OFFSET; - dma->fidr = 0; - dma->ldcmd = LDCMD_EOFINT | 128; + if (fbi->map_cpu) + consistent_free((void*)fbi->map_cpu, fbi->map_size, fbi->map_dma); + + switch(var->bits_per_pixel) { + case 16: + /* 2 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x1) & (~0x1); + nbytes = 2; + + var->red = def_rgbt_16.red; + var->green = def_rgbt_16.green; + var->blue = def_rgbt_16.blue; + var->transp = def_rgbt_16.transp; + break; - FDADR2 = fbi->screen_dma; + case 18: + /* 8 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7); + nbytes = 3; + + var->red = def_rgb_18.red; + var->green = def_rgb_18.green; + var->blue = def_rgb_18.blue; + var->transp = def_rgb_18.transp; - /* Run at least 1 frame with Overlay 2 */ - LCSR1 = LCSR1_EOF2; + break; + case 19: + /* 8 pixels per line */ + pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7); + nbytes = 3; + + var->red = def_rgbt_19.red; + var->green = def_rgbt_19.green; + var->blue = def_rgbt_19.blue; + var->transp = def_rgbt_19.transp; - while ( !(LCSR1 & LCSR1_EOF2)) { - mdelay(10); + break; + case 24: + pixels_per_line = fbi->fb.var.xres; + nbytes = 4; - if (!timeout) { - printk(KERN_INFO "%s: timeout\n", __FUNCTION__); - break; - } - timeout --; + var->red = def_rgbt_24.red; + var->green = def_rgbt_24.green; + var->blue = def_rgbt_24.blue; + var->transp = def_rgbt_24.transp; + + break; + + case 25: + pixels_per_line = fbi->fb.var.xres; + nbytes = 4; + + var->red = def_rgbt_25.red; + var->green = def_rgbt_25.green; + var->blue = def_rgbt_25.blue; + var->transp = def_rgbt_25.transp; + + break; } - return 0; + fbi->fb.fix.line_length = nbytes * pixels_per_line ; + fbi->fb.fix.smem_len = fbi->fb.fix.line_length * fbi->fb.var.yres ; + + fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE); + fbi->map_cpu = (unsigned long)consistent_alloc(GFP_KERNEL, fbi->map_size, + &fbi->map_dma, PTE_BUFFERABLE ); + + if (!fbi->map_cpu) return -ENOMEM; + + fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE; + fbi->screen_dma = fbi->map_dma + PAGE_SIZE; + + fbi->fb.fix.smem_start = fbi->screen_dma; + + /* setup dma descriptor */ + fbi->dma2 = (struct pxafb_dma_descriptor*) + (fbi->screen_cpu - sizeof(struct pxafb_dma_descriptor)); + + fbi->dma2->fdadr = (fbi->screen_dma - sizeof(struct pxafb_dma_descriptor)); + fbi->dma2->fsadr = fbi->screen_dma; + fbi->dma2->fidr = 0; + fbi->dma2->ldcmd = fbi->fb.fix.smem_len; + + return 0; } -static int overlay2fb_disable_RGB(struct fb_info *info) + +#ifdef CONFIG_PXA27x_E25 +/* set xpos, ypos, PPL and LP to 0 */ +static int overlay2fb_YUV420_workaround(struct fb_info *info) { - int count = 0; + struct overlayfb_info *fbi = (struct overlayfb_info*)info; + struct pxafb_dma_descriptor *dma; + u32 map_dma, map_cpu; + int done, ret=0; + + map_cpu = (u32)consistent_alloc(GFP_KERNEL, PAGE_SIZE, &map_dma, 0); + if (!map_cpu) return -1; + + dma = (struct pxafb_dma_descriptor*)((map_cpu + PAGE_SIZE) - sizeof(struct pxafb_dma_descriptor)); + dma->fdadr = map_dma + PAGE_SIZE - sizeof(struct pxafb_dma_descriptor); + dma->fsadr = map_dma; + dma->fidr = 0; + dma->ldcmd = LDCMD_EOFINT | 128; + + /* step 2.a - enable overlay 2 with RGB mode + * + * - (xpos,ypos) = (0,0); + * - 64 pixels, 16bpp + */ + LCCR5 |= (LCCR5_IUM4 | LCCR5_IUM3 | LCCR5_IUM2 | + LCCR5_BSM4 | LCCR5_BSM3 | LCCR5_BSM2 | + LCCR5_EOFM4 | LCCR5_EOFM3 | LCCR5_EOFM2 | + LCCR5_SOFM4 | LCCR5_SOFM3 | LCCR5_SOFM2); + OVL2C2 = 0; + OVL2C1 = OVL2C1_O2EN | 0x04 <<20 | (63); + + CLEAR_LCD_INTR(LCSR1, LCSR1_EOF2); + if ((fbi->state == C_DISABLE) || (C_BLANK == fbi->state)) + FDADR2 = dma->fdadr; + else + FBR2 = dma->fdadr | 0x1; + /* step 2.b - run at least 1 frame with overlay 2 */ + done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_EOF2, 100); + if (!done) goto err; + + /* step 2.c - disable overlay 2 */ OVL2C1 &= ~OVL2C1_O2EN; - LCSR1 = LCSR1_BS2; + CLEAR_LCD_INTR(LCSR1, LCSR1_BS2); FBR2 = 0x3; - while (!(LCSR1 & LCSR1_BS2) && (count < 100)) { - mdelay(10); - count ++; - } - if ( count == 100 ) { - printk(KERN_INFO __FUNCTION__" time out.\n"); - return -1; - } - return 0; + done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS2, 100); + if (!done) goto err; + + /* step 2.d - Wait for base EOF interrupts */ + CLEAR_LCD_INTR(LCSR0, LCSR0_EOF0); + done = WAIT_FOR_LCD_INTR(LCSR0, LCSR0_EOF0, 100); + + goto out; +err: + ret = -1; +out: + /* free buffer allocated */ + consistent_free((void*)map_cpu, PAGE_SIZE, map_dma); + + fbi->state == C_DISABLE; + return ret; } +#else +static int overlay2fb_YUV420_workaround(struct fb_info *info) {} +#endif /* workaround for overlay2 fast bus issue */ static int fastbus_set = 0; @@ -2287,80 +2598,24 @@ local_irq_restore(flags); } -static int overlay2fb_enable_YUV420(struct fb_info *info) -{ - struct overlayfb_info *fbi = (struct overlayfb_info*) info; - unsigned int xres, yres; - int count = 0; - - xres = fbi->fb.fix.line_length; - yres = fbi->fb.var.yres; - - /* disable overlay 2 window */ - OVL2C1 &= ~OVL2C1_O2EN; - - /* enable overlay 2 window */ - if ( fbi->format ) { - OVL2C2 = (fbi->format << 20) | (fbi->ypos << 10) | fbi->xpos; - OVL2C1 = ((yres-1)<<10) | (xres-1); - } else - printk(KERN_INFO __FUNCTION__": fbi->format == 0 ??\n"); - - OVL2C1 |= OVL2C1_O2EN; - - LCSR1 = LCSR1_IU2; - while (!(LCSR1 & LCSR1_IU2) && (count < 100)) { - mdelay(10); - count ++; - } - if (count == 100) { - printk(KERN_INFO __FUNCTION__" time out.\n"); - return -1; - } - - if (!fbi->enabled) { - FDADR2 = fbi->dma2->fdadr; - FDADR3 = fbi->dma3->fdadr; - FDADR4 = fbi->dma4->fdadr; - fbi->enabled = 1; - } - else { - FBR2 = fbi->dma2->fdadr | 0x1; - FBR3 = fbi->dma3->fdadr | 0x1; - FBR4 = fbi->dma4->fdadr | 0x1; - } - return 0; -} - -static int overlay2fb_disable_YUV420(struct fb_info *info) +#ifdef CONFIG_PXA27x_E25 +static void overlay2fb_unblank_workaroundYUV420(struct fb_info *info) { - int count = 0; - - /* workaround for sightings */ - // overlay2fb_set_fastbus(); - LCSR1 = LCSR1_BS2; - FBR2 = 0x3; - FBR3 = 0x3; - FBR4 = 0x3; - while (!(LCSR1 & LCSR1_BS2) && (count < 100 )) { - mdelay(10); - count++; - } - - if ( count==100 ) { - printk(KERN_INFO __FUNCTION__" time out.\n"); - return -1; - } - - return 0; + struct overlayfb_info *fbi=(struct overlayfb_info*)info; + int format = fbi->format; + + if ( (format == 0x4) && (fbi->state == C_BLANK) ) + overlay2fb_YUV420_workaround(info); } +#else +static void overlay2fb_unblank_workaroundYUV420(struct fb_info *info) {} +#endif static int overlay2fb_enable(struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*) info; unsigned long bpp2; unsigned int xres, yres; - int i; if (!fbi->map_cpu) return -EINVAL; @@ -2381,107 +2636,114 @@ bpp2 = 0xa; break; default: - break; + return -EINVAL; } - - xres = fbi->fb.fix.line_length; - yres = fbi->fb.var.yres; - + /* disable branch/start/end of frame interrupt */ LCCR5 |= (LCCR5_IUM4 | LCCR5_IUM3 | LCCR5_IUM2 | LCCR5_BSM4 | LCCR5_BSM3 | LCCR5_BSM2 | LCCR5_EOFM4 | LCCR5_EOFM3 | LCCR5_EOFM2 | LCCR5_SOFM4 | LCCR5_SOFM3 | LCCR5_SOFM2); - /* workaround for Sightings #49219, #56573 etc */ - /* overlay2fb_clear_fastbus(); */ - if ( fbi->format==0x4 ) { - overlay2fb_enable_RGB(info); - WAIT_FOR_END_OF_FRAME; - if (overlay2fb_disable_RGB(info) < 0) - return -1; - for(i = 0; i < 3; i++ ) { - WAIT_FOR_END_OF_FRAME; - } + if (fbi->format == 0) { + /* overlay2 RGB resolution, RGB and YUV have different xres value*/ + xres = fbi->fb.var.xres; + yres = fbi->fb.var.yres; - if (overlay2fb_enable_YUV420(info) < 0) { - return -1; - } - yuv420_enabled = 1; + OVL2C2 = (fbi->format << 20) | (fbi->ypos << 10) | fbi->xpos; + OVL2C1 = OVL2C1_O2EN | (bpp2 << 20) | ((yres-1)<<10) | (xres-1); + /* setup RGB DMA */ + if ((fbi->state == C_DISABLE) || (C_BLANK == fbi->state)) + FDADR2 = fbi->dma2->fdadr; + else + FBR2 = fbi->dma2->fdadr | 0x1; } else { - /* disable overlay 2 window */ - OVL2C1 &= ~OVL2C1_O2EN; + /* overlay2 YUV resolution */ + xres = fbi->fb.fix.line_length; + yres = fbi->fb.var.yres; - if (!fbi->enabled) { + OVL2C2 = (fbi->format << 20) | (fbi->ypos << 10) | fbi->xpos; + OVL2C1 = OVL2C1_O2EN | (bpp2 << 20) | ((yres-1)<<10) | (xres-1); +#ifdef CONFIG_PXA27x_E25 + /* FIXME PXA27x E25 */ + if (fbi->format == 4){ + /* FIXME */ + /* Wait util fifo emtpy */ + CLEAR_LCD_INTR(LCSR1, LCSR1_IU2); + WAIT_FOR_LCD_INTR(LCSR1, LCSR1_IU2, 100); + } +#endif + if ((fbi->state == C_DISABLE) || (C_BLANK == fbi->state)) { FDADR2 = fbi->dma2->fdadr; FDADR3 = fbi->dma3->fdadr; FDADR4 = fbi->dma4->fdadr; - fbi->enabled = 1; - } - else { - FBR2 = fbi->dma2->fdadr | 0x1; - FBR3 = fbi->dma3->fdadr | 0x1; - FBR4 = fbi->dma4->fdadr | 0x1; - } - - /* enable overlay 2 window */ - if ( fbi->format ) { - OVL2C2 = (fbi->format << 20) | - (fbi->ypos << 10) | fbi->xpos; - OVL2C1 = ((yres-1)<<10) | (xres-1); } else { - OVL2C2 = (fbi->ypos << 10) | fbi->xpos; - OVL2C1 = (bpp2 << 20) | ((yres-1)<<10) | (xres-1); + FBR2 = fbi->dma2->fdadr | 0x01; + FBR3 = fbi->dma3->fdadr | 0x01; + FBR4 = fbi->dma4->fdadr | 0x01; } - - OVL2C1 |= OVL2C1_O2EN; } + fbi->state = C_ENABLE; return 0; } -static void overlay2fb_disable(struct fb_info *info) +static int overlay2fb_disable(struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*)info; + int done; + + if ((C_DISABLE == fbi->state) || (C_BLANK == fbi->state)) + return 0; fbi->state = C_DISABLE; /* clear O2EN */ OVL2C1 &= ~OVL2C1_O2EN; - if ( yuv420_enabled && fbi->format == 0x4 ) - overlay2fb_disable_YUV420(info); +/* This sentence was lost in opt.patch. + * That make overlay2 can't disable/enable + * correctly sometimes. + */ + CLEAR_LCD_INTR(LCSR1, LCSR1_BS2); + + if (fbi->format == 0) + FBR2 = 0x3; + else { + FBR2 = 0x3; + FBR3 = 0x3; + FBR4 = 0x3; + } + + done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS2, 100); + + if (!done) { + DPRINTK(KERN_INFO "%s: timeout\n", __FUNCTION__); + return -1; + } + return 0; } static void overlay2fb_blank(int blank, struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*) info; + int err; switch(blank) { case 0: -#if 0 - if (fbi->enabled) { - overlay2fb_disable(info); + err = overlay2fb_enable(info); + if (err) { + fbi->state = C_DISABLE; set_ctrlr_state(fbi->basefb, C_REENABLE); - fbi->enabled = 0; } -#endif - set_ctrlr_state(fbi->basefb, C_REENABLE); - overlay2fb_enable(info); break; case 1: -#if 0 - if (fbi->enabled) { - overlay2fb_disable(info); - set_ctrlr_state(fbi->basefb, C_REENABLE); -#endif - fbi->enabled = 0; - overlay2fb_disable(info); + err = overlay2fb_disable(info); + if (err) { + fbi->state = C_DISABLE; set_ctrlr_state(fbi->basefb, C_REENABLE); -#if 0 } -#endif break; default: /* reserved */ @@ -2519,12 +2781,15 @@ ypos = (var->nonstd >> 10) & 0x3ff; format = (var->nonstd >>20) & 0x7; - /* Palnar YCbCr444, YCbCr422, YCbCr420 */ - if ( (format != 0x4) && (format != 0x3) && (format != 0x2) ) + /* Palnar YCbCr444, YCbCr422, YCbCr420, RGB */ + if ( (format != 0x4) && (format != 0x3) && (format != 0x2) && (format != 0x0)) return -EINVAL; /* dummy pixels */ switch(format) { + case 0x0: /* RGB */ + xres = var->xres; + break; case 0x2: /* 444 */ xres = (var->xres + 0x3) & ~(0x3); break; @@ -2559,48 +2824,53 @@ { struct overlayfb_info *fbi=(struct overlayfb_info*)info; struct fb_var_screeninfo *dvar = &fbi->fb.var; - unsigned int xpos, ypos; - int err; + int format, err; + + /* if lcd is blanked, just return */ + if (C_BLANK == fbi->state) + return 0; /* validate parameters*/ err = overlay2fb_validate_var(var, fbi); if (err) return err; - xpos = var->nonstd & 0x3ff; - ypos = (var->nonstd>>10) & 0x3ff; + format = (var->nonstd>>20) & 0x7; - /* position */ - if ( (xpos != fbi->xpos) || (ypos != fbi->ypos)){ - fbi->xpos = xpos; - fbi->ypos = ypos; - } + if (fbi->state == C_DISABLE) + goto out1; /* resolution */ - if ( (var->xres != dvar->xres) || - (var->yres != dvar->yres) || - (var->bits_per_pixel != dvar->bits_per_pixel) || - ( ((var->nonstd>>20) & 0x7) != fbi->format)) { - /* update var_screeninfo fields*/ - *dvar = *var; - - fbi->format = (var->nonstd>>20) & 0x7; + if ( (var->xres == dvar->xres) && + (var->yres == dvar->yres) && + (var->bits_per_pixel == dvar->bits_per_pixel) && + (format == fbi->format) ) + goto out2; + +out1: + /* update var_screeninfo fields*/ + *dvar = *var; + fbi->format = format; + if ( fbi->format==0 ) + err = overlay2fb_map_RGB_memory(info); + else + err = overlay2fb_map_YUV_memory(info); - err= overlay2fb_map_video_memory(info); - if (err) return err; - } + if (err) return err; -#if 0 - /* disable LCD controller for Overlay2 */ - if (fbi->enabled) { - /* set to C_DISABLE to avoid enabling */ +out2: +#ifdef CONFIG_PXA27x_E25 + if (C_ENABLE == fbi->state) overlay2fb_disable(info); - set_ctrlr_state(fbi->basefb, C_REENABLE); - } - /* enable Overlay2 */ - overlay2fb_enable(info); - set_ctrlr_state(fbi->basefb, C_REENABLE); + /* FIXME PXA27x E25 */ + if ( (format == 0x4) && + ((fbi->state == C_DISABLE) || (fbi->format != format)) ) + overlay2fb_YUV420_workaround(info); #endif + /* position */ + fbi->xpos = var->nonstd & 0x3ff; + fbi->ypos = (var->nonstd>>10) & 0x3ff; + overlay2fb_enable(info); return 0; } @@ -2666,15 +2936,12 @@ LCCR5 |= (LCCR5_IUM5 | LCCR5_BSM5 | LCCR5_EOFM5 | LCCR5_SOFM5); /* load palette and frame data */ - if(!fbi->enabled) { + if ((fbi->state == C_DISABLE) || (C_BLANK == fbi->state)) { FDADR5 = fbi->dma5_pal->fdadr; udelay(1); FDADR5 = fbi->dma5_frame->fdadr; udelay(1); - - fbi->enabled = 1; - } - else { + } else { FBR5 = fbi->dma5_pal->fdadr | 0x1; udelay(1); FBR5 = fbi->dma5_frame->fdadr | 0x1; @@ -2688,13 +2955,26 @@ return 0; } -static void cursorfb_disable(struct fb_info *info) +static int cursorfb_disable(struct fb_info *info) { struct overlayfb_info *fbi = (struct overlayfb_info*)info; + int done, ret = 0; + + if (C_DISABLE == fbi->state) + return 0; + if (C_BLANK == fbi->state) { + fbi->state = C_DISABLE; + return 0; + } fbi->state = C_DISABLE; + done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS5, 100); + if (!done) ret = -1; + CCR &= ~CCR_CEN; + + return ret; } static int cursorfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, @@ -2909,7 +3189,6 @@ fbi->xpos = 0; fbi->ypos = 0; fbi->format = -1; - fbi->enabled = 0; fbi->state = C_DISABLE; return fbi; @@ -2961,7 +3240,6 @@ fbi->xpos = 0; fbi->ypos = 0; fbi->format = -1; - fbi->enabled = 0; fbi->state = C_DISABLE; return fbi; @@ -3014,7 +3292,6 @@ fbi->xpos = 0; fbi->ypos = 0; fbi->format = -1; - fbi->enabled = 0; fbi->state = C_DISABLE; return fbi; diff -uNr a/drivers/video/pxafb.h b/drivers/video/pxafb.h --- a/drivers/video/pxafb.h 2004-10-25 10:10:10.000000000 +0800 +++ b/drivers/video/pxafb.h 2004-12-29 10:50:30.000000000 +0800 @@ -97,7 +97,6 @@ dma_addr_t map_dma; dma_addr_t palette_dma; - unsigned long enabled; volatile u_char state; /* overlay specific info */ @@ -199,11 +198,15 @@ /* * These are the actions for set_ctrlr_state */ -#define C_DISABLE (0) -#define C_ENABLE (1) -#define C_DISABLE_CLKCHANGE (2) -#define C_ENABLE_CLKCHANGE (3) -#define C_REENABLE (4) +enum { + C_DISABLE, + C_ENABLE, + C_DISABLE_CLKCHANGE, + C_ENABLE_CLKCHANGE, + C_REENABLE, + C_BLANK, + C_UNBLANK, +}; #define PXA_NAME "PXA" @@ -322,7 +325,7 @@ #define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT) #define LCD_LCCR0 (LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM | \ LCCR0_OUM | LCCR0_BM | LCCR0_QDM | LCCR0_PAS |\ - LCCR0_EFM | LCCR0_IUM | LCCR0_SFM | LCCR0_LDM ) + LCCR0_IUM | LCCR0_SFM | LCCR0_LDM ) #define LCD_LCCR3 (LCCR3_PCP | LCCR3_HSP | LCCR3_VSP) #elif defined(CONFIG_FB_PXA_QVGA) @@ -340,8 +343,8 @@ #define LCD_END_OF_FRAME_WAIT_COUNT 10 #define LCD_SYNC (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT) #define LCD_LCCR0 (LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM | \ - LCCR0_OUM | LCCR0_BM | LCCR0_QDM | LCCR0_PAS | \ - LCCR0_EFM | LCCR0_IUM | LCCR0_SFM | LCCR0_LDM) + LCCR0_BM | LCCR0_QDM | LCCR0_PAS | \ + LCCR0_IUM | LCCR0_SFM | LCCR0_LDM) #define LCD_LCCR3 (LCCR3_PCP | LCCR3_HSP | LCCR3_VSP ) #endif diff -uNr a/include/asm-arm/arch-pxa/keypad.h b/include/asm-arm/arch-pxa/keypad.h --- a/include/asm-arm/arch-pxa/keypad.h 2004-10-25 10:10:10.000000000 +0800 +++ b/include/asm-arm/arch-pxa/keypad.h 1970-01-01 08:00:00.000000000 +0800 @@ -1,32 +0,0 @@ -#ifndef _ASM_ARCH_KEYPAD_H -#define _ASM_ARCH_KEYPAD_H - -#include - -#define KPIOGET_INTERVAL _IOR('k', 0, __u16) -#define KPIOGET_IGNMULTI _IOR('k', 1, __u16) -#define KPIOSET_INTERVAL _IOW('k', 0, __u16) -#define KPIOSET_IGNMULTI _IOW('k', 1, __u16) - -#ifdef __KERNEL__ - -#define KP_DIRECT 0x1 -#define KP_MATRIX 0x2 - -struct kp_event{ - unsigned int jiffies; - unsigned int flags; - unsigned int direct; - unsigned int rotary; - unsigned int matrix[5]; -}; - -extern int kp_init(void); -extern int kp_wait(struct kp_event *kpe, int timeout); -extern unsigned int kp_poll(struct file *file, poll_table *wait); -extern int kp_direct_scan(void); -extern int kp_matrix_scan(void); - -#endif /* __KERNEL__ */ - -#endif diff -uNr a/include/asm-arm/arch-pxa/mainstone.h b/include/asm-arm/arch-pxa/mainstone.h --- a/include/asm-arm/arch-pxa/mainstone.h 2004-10-22 10:52:21.000000000 +0800 +++ b/include/asm-arm/arch-pxa/mainstone.h 2004-12-29 10:50:30.000000000 +0800 @@ -13,6 +13,24 @@ #define MST_ETH_PHYS (0x0c000000) #define MST_ETH_BASE (0xf1000000) /* phys 0x0c000000 */ +#define MST_PCMCIA0 __MST_REG(0x080000e0) +#define MST_PCMCIA1 __MST_REG(0x080000e4) +#define MST_PCMCIA_nIRQ (1 << 10) /* IRQ / ready signal */ +#define MST_PCMCIA_nSPKR_BVD2 (1 << 9) /* VDD sense / digital speaker */ +#define MST_PCMCIA_nSTSCHG_BVD1 (1 << 8) /* VDD sense / card status changed */ +#define MST_PCMCIA_nVS2 (1 << 7) /* VSS voltage sense */ +#define MST_PCMCIA_nVS1 (1 << 6) /* VSS voltage sense */ +#define MST_PCMCIA_nCD (1 << 5) /* Card detection signal */ +#define MST_PCMCIA_RESET (1 << 4) /* Card reset signal */ +#define MST_PCMCIA_PWR_MASK (0x000f) /* MAX1602 power-supply controls */ + +#define MST_PCMCIA_PWR_VPP_0 0x0 /* voltage VPP = 0V */ +#define MST_PCMCIA_PWR_VPP_120 0x2 /* voltage VPP = 12V*/ +#define MST_PCMCIA_PWR_VPP_VCC 0x1 /* voltage VPP = VCC */ +#define MST_PCMCIA_PWR_VCC_0 0x0 /* voltage VCC = 0V */ +#define MST_PCMCIA_PWR_VCC_33 0x8 /* voltage VCC = 3.3V */ +#define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */ + #define MST_P2V(x) ((x) - MST_FPGA_PHYS + MST_FPGA_VIRT) #define MST_V2P(x) ((x) - MST_FPGA_VIRT + MST_FPGA_PHYS) diff -uNr a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h --- a/include/asm-arm/arch-pxa/pxa-regs.h 2004-10-25 10:10:10.000000000 +0800 +++ b/include/asm-arm/arch-pxa/pxa-regs.h 2004-12-29 10:50:30.000000000 +0800 @@ -1655,7 +1655,7 @@ #define KPC_MIE (0x1 << 11) // Matrix Interrupt Enable #define KPC_DK_DEB_SEL (0x1 << 9) // Direct Key Debounce select #define KPC_DI (0x1 << 5) // Direct key interrupt bit -#define KPC_DEE0 (0x1 << 2) // Rotary Encoder 0 Enable +#define KPC_REE0 (0x1 << 2) // Rotary Encoder 0 Enable #define KPC_DE (0x1 << 1) // Direct Keypad Enable #define KPC_DIE (0x1 << 0) // Direct Keypad interrupt Enable diff -uNr a/include/linux/tty.h b/include/linux/tty.h --- a/include/linux/tty.h 2004-10-22 10:52:11.000000000 +0800 +++ b/include/linux/tty.h 2004-12-29 10:50:30.000000000 +0800 @@ -134,7 +134,7 @@ * located in the tty structure, and is used as a high speed interface * between the tty driver and the tty line discipline. */ -#define TTY_FLIPBUF_SIZE 512 +#define TTY_FLIPBUF_SIZE 8192 struct tty_flip_buffer { struct tq_struct tqueue; @@ -283,7 +283,7 @@ void *driver_data; struct list_head tty_files; -#define N_TTY_BUF_SIZE 4096 +#define N_TTY_BUF_SIZE 8192 /* * The following is data for the N_TTY line discipline. For diff -uNr a/include/linux/videodev.h b/include/linux/videodev.h --- a/include/linux/videodev.h 2004-10-22 10:52:11.000000000 +0800 +++ b/include/linux/videodev.h 2004-12-29 10:50:30.000000000 +0800 @@ -331,7 +331,7 @@ #define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */ #define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */ #define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */ - +#define VIDIOBUFID _IOR('v',30, int) /* Get last buffer id */ #define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */ diff -uNr a/kernel/pm.c b/kernel/pm.c --- a/kernel/pm.c 2004-10-22 10:52:10.000000000 +0800 +++ b/kernel/pm.c 2004-12-29 10:50:30.000000000 +0800 @@ -246,9 +246,9 @@ down(&pm_devs_lock); if (rqst == PM_SUSPEND) - entry = pm_devs.prev; - else entry = pm_devs.next; + else + entry = pm_devs.prev; while (entry != &pm_devs) { struct pm_dev *dev = list_entry(entry, struct pm_dev, entry); @@ -266,9 +266,9 @@ } } if (rqst == PM_SUSPEND) - entry = entry->prev; - else entry = entry->next; + else + entry = entry->prev; } up(&pm_devs_lock); return 0; diff -uNr a/Makefile b/Makefile --- a/Makefile 2004-10-25 10:10:10.000000000 +0800 +++ b/Makefile 2004-12-29 10:50:30.000000000 +0800 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION =-rmk1-pxa1-intc2 +EXTRAVERSION =-rmk1-pxa1-intc4 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -140,7 +140,6 @@ DRIVERS-y += drivers/serial/serial.o \ drivers/char/char.o \ drivers/block/block.o \ - drivers/misc/misc.o \ drivers/net/net.o DRIVERS-$(CONFIG_AGP) += drivers/char/agp/agp.o DRIVERS-$(CONFIG_DRM_NEW) += drivers/char/drm/drm.o @@ -164,6 +163,7 @@ DRIVERS-$(CONFIG_SSI) += drivers/ssi/ssi.o DRIVERS-$(CONFIG_SOUND) += drivers/sound/sounddrivers.o +DRIVERS-y += drivers/misc/misc.o DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o DRIVERS-$(CONFIG_MMC) += drivers/mmc/mmcdrivers.o