diff options
Diffstat (limited to 'target/linux')
28 files changed, 0 insertions, 25195 deletions
diff --git a/target/linux/ep93xx/config-2.6.30 b/target/linux/ep93xx/config-2.6.30 deleted file mode 100644 index 28309626d1..0000000000 --- a/target/linux/ep93xx/config-2.6.30 +++ /dev/null @@ -1,208 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_EP93XX=y -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_THUMB=y -CONFIG_ARM_VIC=y -# CONFIG_ARPD is not set -# CONFIG_BINARY_PRINTF is not set -CONFIG_BITREVERSE=y -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CMDLINE="console=ttyAM0,57600 init=/etc/preinit" -CONFIG_COMMON_CLKDEV=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CPU_32=y -CONFIG_CPU_32v4T=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_NOIFAR=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CRC7=y -CONFIG_CRC_ITU_T=y -CONFIG_CRUNCH=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_DEBUG_USER=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_DM9000 is not set -CONFIG_DNOTIFY=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_ELF_CORE=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_EP93XX_EARLY_UART1=y -# CONFIG_EP93XX_EARLY_UART2 is not set -# CONFIG_EP93XX_EARLY_UART3 is not set -CONFIG_EP93XX_ETH=y -CONFIG_EP93XX_WATCHDOG=y -CONFIG_FB=y -# CONFIG_FB_ARMCLCD is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_EP93XX=y -# CONFIG_FB_EP93XX_MONO is not set -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FONTS=y -# CONFIG_FONT_10x18 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FPE_FASTFPE is not set -CONFIG_FPE_NWFPE=y -CONFIG_FPE_NWFPE_XP=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAME_POINTER=y -# CONFIG_FW_LOADER is not set -# CONFIG_GENERIC_CLOCKEVENTS is not set -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -# CONFIG_GENERIC_TIME is not set -CONFIG_GPIOLIB=y -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HW_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_EP93XX=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -CONFIG_INPUT=y -# CONFIG_INPUT_MISC is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_ISDN_CAPI is not set -# CONFIG_ISDN_I4L is not set -CONFIG_LCD_HD44780=m -CONFIG_LCD_LINUX=m -# CONFIG_LEDS_GPIO is not set -CONFIG_LOCK_KERNEL=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_MACH_ADSSPHERE is not set -# CONFIG_MACH_EDB9302 is not set -# CONFIG_MACH_EDB9302A is not set -# CONFIG_MACH_EDB9307 is not set -# CONFIG_MACH_EDB9307A is not set -# CONFIG_MACH_EDB9312 is not set -# CONFIG_MACH_EDB9315 is not set -# CONFIG_MACH_EDB9315A is not set -# CONFIG_MACH_GESBC9312 is not set -# CONFIG_MACH_MICRO9 is not set -# CONFIG_MACH_MICRO9H is not set -# CONFIG_MACH_MICRO9L is not set -# CONFIG_MACH_MICRO9M is not set -CONFIG_MACH_SIM_ONE=y -# CONFIG_MACH_TS72XX is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SPI=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_STAA=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAM=y -# CONFIG_NO_IOPORT is not set -# CONFIG_OUTER_CACHE is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PCI_SYSCALL is not set -CONFIG_PREEMPT=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SLOW_WORK is not set -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_EP93XX=y -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_MASTER=y -# CONFIG_SPI_SPIDEV is not set -CONFIG_SPLIT_PTLOCK_CPUS=4096 -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_TOUCHSCREEN_EP93XX=y -CONFIG_TRACING_SUPPORT=y -CONFIG_UID16=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -CONFIG_USB_SUPPORT=y -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_VGA_CONSOLE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ep93xx/config-2.6.36 b/target/linux/ep93xx/config-2.6.36 deleted file mode 100644 index 6fb21942cd..0000000000 --- a/target/linux/ep93xx/config-2.6.36 +++ /dev/null @@ -1,203 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_EP93XX=y -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_ARCH_REQUIRE_GPIOLIB=y -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USES_GETTIMEOFFSET=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_L1_CACHE_SHIFT=5 -# CONFIG_ARM_SP805_WATCHDOG is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_VIC=y -CONFIG_ARM_VIC_NR=2 -# CONFIG_ARPD is not set -# CONFIG_AUTO_ZRELADDR is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_CMDLINE="console=ttyAM0,57600 init=/etc/preinit" -CONFIG_COMMON_CLKDEV=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CPU_32v4T=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CRC7=y -CONFIG_CRC_ITU_T=y -CONFIG_CRUNCH=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_USER=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_DEPRECATED_PARAM_STRUCT is not set -CONFIG_DNOTIFY=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_ELF_CORE=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_EP93XX_EARLY_UART1=y -# CONFIG_EP93XX_EARLY_UART2 is not set -# CONFIG_EP93XX_EARLY_UART3 is not set -CONFIG_EP93XX_ETH=y -CONFIG_EP93XX_SDCE0_PHYS_OFFSET=y -# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET is not set -CONFIG_EP93XX_WATCHDOG=y -CONFIG_FB=y -# CONFIG_FB_ARMCLCD is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_EP93XX=y -# CONFIG_FB_SM7XX is not set -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FONTS=y -# CONFIG_FONT_10x18 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_SUN8x16 is not set -CONFIG_FORCE_MAX_ZONEORDER=11 -# CONFIG_FPE_FASTFPE is not set -CONFIG_FPE_NWFPE=y -CONFIG_FPE_NWFPE_XP=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAME_POINTER=y -# CONFIG_FW_LOADER is not set -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GPIOLIB=y -# CONFIG_GPIO_PL061 is not set -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HW_CONSOLE=y -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_INOTIFY_USER=y -CONFIG_INPUT=y -# CONFIG_INPUT_MISC is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_KEYBOARD_EP93XX is not set -# CONFIG_LEDS_GPIO is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_MACH_EDB9302A is not set -# CONFIG_MACH_EDB9307A is not set -# CONFIG_MACH_EDB9315A is not set -CONFIG_MACH_SIM_ONE=y -# CONFIG_MACH_SNAPPER_CL15 is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SPI=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_STAA=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAM=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PCI_SYSCALL is not set -CONFIG_PERF_USE_VMALLOC=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SND_EP93XX_SOC is not set -# CONFIG_SPARSE_IRQ is not set -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_EP93XX=y -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_MASTER=y -# CONFIG_SPI_PL022 is not set -CONFIG_SPLIT_PTLOCK_CPUS=999999 -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -# CONFIG_TOUCHSCREEN_DYNAPRO is not set -CONFIG_TOUCHSCREEN_EP93XX=y -# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -CONFIG_UID16=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -CONFIG_USB_SUPPORT=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ep93xx/config-2.6.37 b/target/linux/ep93xx/config-2.6.37 deleted file mode 100644 index 6fb21942cd..0000000000 --- a/target/linux/ep93xx/config-2.6.37 +++ /dev/null @@ -1,203 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_EP93XX=y -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_ARCH_REQUIRE_GPIOLIB=y -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USES_GETTIMEOFFSET=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_L1_CACHE_SHIFT=5 -# CONFIG_ARM_SP805_WATCHDOG is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_VIC=y -CONFIG_ARM_VIC_NR=2 -# CONFIG_ARPD is not set -# CONFIG_AUTO_ZRELADDR is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_CMDLINE="console=ttyAM0,57600 init=/etc/preinit" -CONFIG_COMMON_CLKDEV=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CPU_32v4T=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CRC7=y -CONFIG_CRC_ITU_T=y -CONFIG_CRUNCH=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_USER=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_DEPRECATED_PARAM_STRUCT is not set -CONFIG_DNOTIFY=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_ELF_CORE=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_EP93XX_EARLY_UART1=y -# CONFIG_EP93XX_EARLY_UART2 is not set -# CONFIG_EP93XX_EARLY_UART3 is not set -CONFIG_EP93XX_ETH=y -CONFIG_EP93XX_SDCE0_PHYS_OFFSET=y -# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET is not set -CONFIG_EP93XX_WATCHDOG=y -CONFIG_FB=y -# CONFIG_FB_ARMCLCD is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_EP93XX=y -# CONFIG_FB_SM7XX is not set -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FONTS=y -# CONFIG_FONT_10x18 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_SUN8x16 is not set -CONFIG_FORCE_MAX_ZONEORDER=11 -# CONFIG_FPE_FASTFPE is not set -CONFIG_FPE_NWFPE=y -CONFIG_FPE_NWFPE_XP=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAME_POINTER=y -# CONFIG_FW_LOADER is not set -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GPIOLIB=y -# CONFIG_GPIO_PL061 is not set -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HW_CONSOLE=y -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_INOTIFY_USER=y -CONFIG_INPUT=y -# CONFIG_INPUT_MISC is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_KEYBOARD_EP93XX is not set -# CONFIG_LEDS_GPIO is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_MACH_EDB9302A is not set -# CONFIG_MACH_EDB9307A is not set -# CONFIG_MACH_EDB9315A is not set -CONFIG_MACH_SIM_ONE=y -# CONFIG_MACH_SNAPPER_CL15 is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SPI=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_STAA=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAM=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PCI_SYSCALL is not set -CONFIG_PERF_USE_VMALLOC=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_SERIAL_AMBA_PL011 is not set -# CONFIG_SND_EP93XX_SOC is not set -# CONFIG_SPARSE_IRQ is not set -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_EP93XX=y -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_MASTER=y -# CONFIG_SPI_PL022 is not set -CONFIG_SPLIT_PTLOCK_CPUS=999999 -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -# CONFIG_TOUCHSCREEN_DYNAPRO is not set -CONFIG_TOUCHSCREEN_EP93XX=y -# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -CONFIG_UID16=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -CONFIG_USB_SUPPORT=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ep93xx/config-2.6.38 b/target/linux/ep93xx/config-2.6.38 deleted file mode 100644 index eef1ea6a93..0000000000 --- a/target/linux/ep93xx/config-2.6.38 +++ /dev/null @@ -1,216 +0,0 @@ -CONFIG_ALIGNMENT_TRAP=y -CONFIG_ARCH_EP93XX=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y -CONFIG_ARCH_REQUIRE_GPIOLIB=y -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USES_GETTIMEOFFSET=y -CONFIG_ARM=y -CONFIG_ARM_AMBA=y -CONFIG_ARM_L1_CACHE_SHIFT=5 -# CONFIG_ARM_SP805_WATCHDOG is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM_VIC=y -CONFIG_ARM_VIC_NR=2 -# CONFIG_ARPD is not set -# CONFIG_AUTO_IRQ_AFFINITY is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CLKDEV_LOOKUP=y -CONFIG_CMDLINE="console=ttyAM0,57600 init=/etc/preinit" -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CPU_32v4T=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_LEGACY=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_USE_DOMAINS=y -CONFIG_CRC7=y -CONFIG_CRC_ITU_T=y -CONFIG_CRUNCH=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_MICHAEL_MIC=y -CONFIG_CRYPTO_PCBC=y -CONFIG_CRYPTO_PCOMP2=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_USER=y -CONFIG_DEFAULT_TCP_CONG="cubic" -CONFIG_DNOTIFY=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_ELF_CORE=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_EP93XX_EARLY_UART1=y -# CONFIG_EP93XX_EARLY_UART2 is not set -# CONFIG_EP93XX_EARLY_UART3 is not set -CONFIG_EP93XX_ETH=y -CONFIG_EP93XX_SDCE0_PHYS_OFFSET=y -# CONFIG_EP93XX_SDCE1_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE2_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET is not set -# CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET is not set -CONFIG_EP93XX_WATCHDOG=y -CONFIG_FB=y -# CONFIG_FB_ARMCLCD is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_EP93XX=y -# CONFIG_FB_SM7XX is not set -# CONFIG_FB_WMT_GE_ROPS is not set -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FONTS=y -# CONFIG_FONT_10x18 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_SUN8x16 is not set -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAME_POINTER=y -# CONFIG_FW_LOADER is not set -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_GPIO=y -# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set -# CONFIG_GENERIC_PENDING_IRQ is not set -CONFIG_GPIOLIB=y -# CONFIG_GPIO_PL061 is not set -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_GENERIC_HARDIRQS=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_IRQ_WORK=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_SPARSE_IRQ=y -CONFIG_HW_CONSOLE=y -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_INOTIFY_USER=y -CONFIG_INPUT=y -# CONFIG_INPUT_MISC is not set -CONFIG_INPUT_TOUCHSCREEN=y -# CONFIG_IRQ_PER_CPU is not set -# CONFIG_LEDS_GPIO is not set -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_MACH_EDB9302A is not set -# CONFIG_MACH_EDB9307A is not set -# CONFIG_MACH_EDB9315A is not set -CONFIG_MACH_NO_WESTBRIDGE=y -CONFIG_MACH_SIM_ONE=y -# CONFIG_MACH_SNAPPER_CL15 is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SPI=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_STAA=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_RAM=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_PER_CPU_KM=y -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PCI_SYSCALL is not set -CONFIG_PERF_USE_VMALLOC=y -# CONFIG_PREEMPT_RCU is not set -# CONFIG_QUOTACTL is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_AMBA_PL010=y -CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -# CONFIG_SERIAL_AMBA_PL011 is not set -CONFIG_SPI=y -CONFIG_SPI_BITBANG=y -CONFIG_SPI_EP93XX=y -# CONFIG_SPI_GPIO is not set -CONFIG_SPI_MASTER=y -# CONFIG_SPI_PL022 is not set -# CONFIG_SPI_PXA2XX_PCI is not set -CONFIG_SPLIT_PTLOCK_CPUS=999999 -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -# CONFIG_TOUCHSCREEN_DYNAPRO is not set -CONFIG_TOUCHSCREEN_EP93XX=y -# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -CONFIG_UID16=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -CONFIG_USB_SUPPORT=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_XZ_DEC=y -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ep93xx/patches-2.6.30/001-ep93xx-regs.patch b/target/linux/ep93xx/patches-2.6.30/001-ep93xx-regs.patch deleted file mode 100644 index 9b3128bfcf..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/001-ep93xx-regs.patch +++ /dev/null @@ -1,479 +0,0 @@ ---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -@@ -57,6 +57,33 @@ - #define EP93XX_APB_SIZE 0x00200000 - - -+/* 8081_0000 - 8081_ffff: Timers */ -+#define TIMERS_OFFSET 0x010000 -+#define TIMERS_BASE (EP93XX_APB_VIRT_BASE|TIMERS_OFFSET) -+ -+#define TIMER1LOAD (TIMERS_BASE+0x00) -+#define TIMER1VALUE (TIMERS_BASE+0x04) -+#define TIMER1CONTROL (TIMERS_BASE+0x08) -+#define TIMER1CLEAR (TIMERS_BASE+0x0C) -+#define TIMER1TEST (TIMERS_BASE+0x10) -+ -+#define TIMER2LOAD (TIMERS_BASE+0x20) -+#define TIMER2VALUE (TIMERS_BASE+0x24) -+#define TIMER2CONTROL (TIMERS_BASE+0x28) -+#define TIMER2CLEAR (TIMERS_BASE+0x2C) -+#define TIMER2TEST (TIMERS_BASE+0x30) -+ -+#define TIMER3LOAD (TIMERS_BASE+0x80) -+#define TIMER3VALUE (TIMERS_BASE+0x84) -+#define TIMER3CONTROL (TIMERS_BASE+0x88) -+#define TIMER3CLEAR (TIMERS_BASE+0x8C) -+#define TIMER3TEST (TIMERS_BASE+0x90) -+ -+#define TTIMERBZCONT (TIMERS_BASE+0x40) -+ -+#define TIMER4VALUELOW (TIMERS_BASE+0x60) -+#define TIMER4VALUEHIGH (TIMERS_BASE+0x64) -+ - /* AHB peripherals */ - #define EP93XX_DMA_BASE ((void __iomem *) \ - (EP93XX_AHB_VIRT_BASE + 0x00000000)) -@@ -105,6 +132,8 @@ - #define EP93XX_I2S_BASE (EP93XX_APB_VIRT_BASE + 0x00020000) - - #define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000) -+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) - - #define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) - #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) -@@ -127,6 +156,7 @@ - #define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) - - #define EP93XX_SPI_BASE (EP93XX_APB_VIRT_BASE + 0x000a0000) -+#define EP93XX_SPI_BASE_PHYS (EP93XX_APB_PHYS_BASE + 0x000a0000) - - #define EP93XX_IRDA_BASE (EP93XX_APB_VIRT_BASE + 0x000b0000) - -@@ -164,8 +194,425 @@ - #define EP93XX_SYSCON_DEVICE_CONFIG_U2EN (1<<20) - #define EP93XX_SYSCON_DEVICE_CONFIG_U1EN (1<<18) - #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) -+#define EP93XX_SYSCON_CHIP_ID EP93XX_SYSCON_REG(0x94) -+#define EP93XX_SYSCON_BMAR EP93XX_SYSCON_REG(0x54) -+#define EP93XX_SYSCON_I2SDIV EP93XX_SYSCON_REG(0x8C) -+#define EP93XX_SYSCON_DEVCFG_CONFIG_Mong 0x02000000 -+#define EP93XX_SYSCON_DEVCFG_CONFIG_Tong 0x04000000 -+#define EP93XX_SYSCON_DEVCFG_CONFIG_I2SONSSP 0x00000080 -+#define EP93XX_SYSCON_DEVCFG_CONFIG_I2SONAC97 0x00000040 -+#define EP93XX_SYSCON_DEVCFG_RasOnP3 0x00000010 -+#define EP93XX_SYSCON_DEVCFG_A1onG 0x00200000 -+#define EP93XX_SYSCON_DEVCFG_A2onG 0x00400000 -+#define EP93XX_SYSCON_DEVCFG_U1EN 0x00040000 -+#define EP93XX_SYSCON_DEVCFG_TIN 0x00020000 - - #define EP93XX_WATCHDOG_BASE (EP93XX_APB_VIRT_BASE + 0x00140000) - - -+#define SYSCON_PWRCNT (EP93XX_SYSCON_BASE+0x0004) -+#define SYSCON_VIDDIV (EP93XX_SYSCON_BASE+0x0084) -+#define SYSCON_MIRDIV (EP93XX_SYSCON_BASE+0x0088) -+#define SYSCON_KTDIV (EP93XX_SYSCON_BASE+0x0090) -+#define SYSCON_KTDIV_TSEN 0x80000000 -+//----------------------------------------------------------------------------- -+// SYSCON_CLKSET1 -+//----------------------------------------------------------------------------- -+#define SYSCON_CLKSET1_PLL1_X2IPD_SHIFT 0 -+#define SYSCON_CLKSET1_PLL1_X2IPD_MASK 0x0000001f -+#define SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT 5 -+#define SYSCON_CLKSET1_PLL1_X2FBD2_MASK 0x000007e0 -+#define SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT 11 -+#define SYSCON_CLKSET1_PLL1_X1FBD1_MASK 0x0000f800 -+#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16 -+#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000 -+#define SYSCON_CLKSET1_PCLKDIV_SHIFT 18 -+#define SYSCON_CLKSET1_PCLKDIV_MASK 0x000c0000 -+#define SYSCON_CLKSET1_HCLKDIV_SHIFT 20 -+#define SYSCON_CLKSET1_HCLKDIV_MASK 0x00700000 -+#define SYSCON_CLKSET1_nBYP1 0x00800000 -+#define SYSCON_CLKSET1_SMCROM 0x01000000 -+#define SYSCON_CLKSET1_FCLKDIV_SHIFT 25 -+#define SYSCON_CLKSET1_FCLKDIV_MASK 0x0e000000 -+ -+#define SYSCON_CLKSET1_HSEL 0x00000001 -+#define SYSCON_CLKSET1_PLL1_EXCLKSEL 0x00000002 -+ -+#define SYSCON_CLKSET1_PLL1_P_MASK 0x0000007C -+#define SYSCON_CLKSET1_PLL1_P_SHIFT 2 -+ -+#define SYSCON_CLKSET1_PLL1_M1_MASK 0x00000780 -+#define SYSCON_CLKSET1_PLL1_M1_SHIFT 7 -+#define SYSCON_CLKSET1_PLL1_M2_MASK 0x0000F800 -+#define SYSCON_CLKSET1_PLL1_M2_SHIFT 11 -+#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000 -+#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16 -+#define SYSCON_CLKSET1_PCLK_DIV_MASK 0x000C0000 -+#define SYSCON_CLKSET1_PCLK_DIV_SHIFT 18 -+#define SYSCON_CLKSET1_HCLK_DIV_MASK 0x00700000 -+#define SYSCON_CLKSET1_HCLK_DIV_SHIFT 20 -+#define SYSCON_CLKSET1_SMCROM 0x01000000 -+#define SYSCON_CLKSET1_FCLK_DIV_MASK 0x0E000000 -+#define SYSCON_CLKSET1_FCLK_DIV_SHIFT 25 -+ -+#define SYSCON_CLKSET2_PLL2_EN 0x00000001 -+#define SYSCON_CLKSET2_PLL2EXCLKSEL 0x00000002 -+#define SYSCON_CLKSET2_PLL2_P_MASK 0x0000007C -+#define SYSCON_CLKSET2_PLL2_P_SHIFT 2 -+#define SYSCON_CLKSET2_PLL2_M2_MASK 0x00000F80 -+#define SYSCON_CLKSET2_PLL2_M2_SHIFT 7 -+#define SYSCON_CLKSET2_PLL2_M1_MASK 0x0001F000 -+#define SYSCON_CLKSET2_PLL2_M1 12 -+#define SYSCON_CLKSET2_PLL2_PS_MASK 0x000C0000 -+#define SYSCON_CLKSET2_PLL2_PS_SHIFT 18 -+#define SYSCON_CLKSET2_USBDIV_MASK 0xF0000000 -+#define SYSCON_CLKSET2_USBDIV_SHIFT 28 -+ -+//----------------------------------------------------------------------------- -+// I2SDIV Register Defines -+//----------------------------------------------------------------------------- -+#define SYSCON_I2SDIV_MDIV_MASK 0x0000007f -+#define SYSCON_I2SDIV_MDIV_SHIFT 0 -+#define SYSCON_I2SDIV_PDIV_MASK 0x00000300 -+#define SYSCON_I2SDIV_PDIV_SHIFT 8 -+#define SYSCON_I2SDIV_PSEL 0x00002000 -+#define SYSCON_I2SDIV_ESEL 0x00004000 -+#define SYSCON_I2SDIV_MENA 0x00008000 -+#define SYSCON_I2SDIV_SDIV 0x00010000 -+#define SYSCON_I2SDIV_LRDIV_MASK 0x00060000 -+#define SYSCON_I2SDIV_LRDIV_SHIFT 17 -+#define SYSCON_I2SDIV_SPOL 0x00080000 -+#define SYSCON_I2SDIV_DROP 0x00100000 -+#define SYSCON_I2SDIV_ORIDE 0x20000000 -+#define SYSCON_I2SDIV_SLAVE 0x40000000 -+#define SYSCON_I2SDIV_SENA 0x80000000 -+ -+#define SYSCON_I2SDIV_PDIV_OFF 0x00000000 -+#define SYSCON_I2SDIV_PDIV_2 0x00000100 -+#define SYSCON_I2SDIV_PDIV_25 0x00000200 -+#define SYSCON_I2SDIV_PDIV_3 0x00000300 -+ -+#define SYSCON_I2SDIV_LRDIV_32 0x00000000 -+#define SYSCON_I2SDIV_LRDIV_64 0x00020000 -+#define SYSCON_I2SDIV_LRDIV_128 0x00040000 -+ -+//----------------------------------------------------------------------------- -+// VIDDIV Register Defines -+//----------------------------------------------------------------------------- -+#define SYSCON_VIDDIV_VDIV_MASK 0x0000007f -+#define SYSCON_VIDDIV_VDIV_SHIFT 0 -+#define SYSCON_VIDDIV_PDIV_MASK 0x00000300 -+#define SYSCON_VIDDIV_PDIV_SHIFT 8 -+#define SYSCON_VIDDIV_PSEL 0x00002000 -+#define SYSCON_VIDDIV_ESEL 0x00004000 -+#define SYSCON_VIDDIV_VENA 0x00008000 -+ -+//----------------------------------------------------------------------------- -+// MIRDIV Register Defines -+//----------------------------------------------------------------------------- -+#define SYSCON_MIRDIV_MDIV_MASK 0x0000003f -+#define SYSCON_MIRDIV_MDIV_SHIFT 0 -+#define SYSCON_MIRDIV_PDIV_MASK 0x00000300 -+#define SYSCON_MIRDIV_PDIV_SHIFT 8 -+#define SYSCON_MIRDIV_PSEL 0x00002000 -+#define SYSCON_MIRDIV_ESEL 0x00004000 -+#define SYSCON_MIRDIV_MENA 0x00008000 -+ -+/* 8082_0000 - 8082_ffff: I2S */ -+#define I2S_OFFSET 0x020000 -+#define I2S_BASE (EP93XX_APB_VIRT_BASE|I2S_OFFSET) -+#define I2S_PHYS_BASE (EP93XX_APB_PHYS_BASE + I2S_OFFSET) -+ -+ -+ -+#define I2STxClkCfg (I2S_BASE+0x00) /* 8082.0000 R/W Transmitter clock config register */ -+#define I2SRxClkCfg (I2S_BASE+0x04) /* 8082.0004 R/W Receiver clock config register */ -+#define I2SGlSts (I2S_BASE+0x08) /* 8082.0008 R/W SAI Global Status register. */ -+#define I2SGlCtrl (I2S_BASE+0x0C) /* 8082.000C R/W SAI Global Control register */ -+ -+#define I2STX0Lft (I2S_BASE+0x10) /* 8082.0010 R/W Left TX data reg for channel 0 */ -+#define I2STX0Rt (I2S_BASE+0x14) /* 8082.0014 R/W Right TX data reg for channel 0 */ -+#define I2STX1Lft (I2S_BASE+0x18) /* 8082.0018 R/W Left TX data reg for channel 1 */ -+#define I2STX1Rt (I2S_BASE+0x1C) /* 8082.001C R/W Right TX data reg for channel 1 */ -+#define I2STX2Lft (I2S_BASE+0x20) /* 8082.0020 R/W Left TX data reg for channel 2 */ -+#define I2STX2Rt (I2S_BASE+0x24) /* 8082.0024 R/W Right TX data reg for channel 2 */ -+ -+#define I2STXLinCtrlData (I2S_BASE+0x28) /* 8082.0028 R/W TX Line Control data register */ -+#define I2STXCtrl (I2S_BASE+0x2C) /* 8082.002C R/W TX Control register */ -+#define I2STXWrdLen (I2S_BASE+0x30) /* 8082.0030 R/W TX Word Length */ -+#define I2STX0En (I2S_BASE+0x34) /* 8082.0034 R/W TX0 Channel Enable */ -+#define I2STX1En (I2S_BASE+0x38) /* 8082.0038 R/W TX1 Channel Enable */ -+#define I2STX2En (I2S_BASE+0x3C) /* 8082.003C R/W TX2 Channel Enable */ -+ -+#define I2SRX0Lft (I2S_BASE+0x40) /* 8082.0040 R Left RX data reg for channel 0 */ -+#define I2SRX0Rt (I2S_BASE+0x44) /* 8082.0044 R Right RX data reg for channel 0 */ -+#define I2SRX1Lft (I2S_BASE+0x48) /* 8082.0048 R Left RX data reg for channel 1 */ -+#define I2SRX1Rt (I2S_BASE+0x4C) /* 8082.004c R Right RX data reg for channel 1 */ -+#define I2SRX2Lft (I2S_BASE+0x50) /* 8082.0050 R Left RX data reg for channel 2 */ -+#define I2SRX2Rt (I2S_BASE+0x54) /* 8082.0054 R Right RX data reg for channel 2 */ -+ -+#define I2SRXLinCtrlData (I2S_BASE+0x58) /* 8082.0058 R/W RX Line Control data register */ -+#define I2SRXCtrl (I2S_BASE+0x5C) /* 8082.005C R/W RX Control register */ -+#define I2SRXWrdLen (I2S_BASE+0x60) /* 8082.0060 R/W RX Word Length */ -+#define I2SRX0En (I2S_BASE+0x64) /* 8082.0064 R/W RX0 Channel Enable */ -+#define I2SRX1En (I2S_BASE+0x68) /* 8082.0068 R/W RX1 Channel Enable */ -+#define I2SRX2En (I2S_BASE+0x6C) /* 8082.006C R/W RX2 Channel Enable */ -+ -+/* 8084_0000 - 8084_ffff: GPIO */ -+#define GPIO_OFFSET 0x040000 -+#define GPIO_BASE (EP93XX_APB_VIRT_BASE|GPIO_OFFSET) -+#define GPIO_PADR (GPIO_BASE+0x00) -+#define GPIO_PBDR (GPIO_BASE+0x04) -+#define GPIO_PCDR (GPIO_BASE+0x08) -+#define GPIO_PDDR (GPIO_BASE+0x0C) -+#define GPIO_PADDR (GPIO_BASE+0x10) -+#define GPIO_PBDDR (GPIO_BASE+0x14) -+#define GPIO_PCDDR (GPIO_BASE+0x18) -+#define GPIO_PDDDR (GPIO_BASE+0x1C) -+#define GPIO_PEDR (GPIO_BASE+0x20) -+#define GPIO_PEDDR (GPIO_BASE+0x24) -+// #define 0x8084.0028 Reserved -+// #define 0x8084.002C Reserved -+#define GPIO_PFDR (GPIO_BASE+0x30) -+#define GPIO_PFDDR (GPIO_BASE+0x34) -+#define GPIO_PGDR (GPIO_BASE+0x38) -+#define GPIO_PGDDR (GPIO_BASE+0x3C) -+#define GPIO_PHDR (GPIO_BASE+0x40) -+#define GPIO_PHDDR (GPIO_BASE+0x44) -+// #define 0x8084.0048 RAZ RAZ -+#define GPIO_FINTTYPE1 (GPIO_BASE+0x4C) -+#define GPIO_FINTTYPE2 (GPIO_BASE+0x50) -+#define GPIO_FEOI (GPIO_BASE+0x54) /* WRITE ONLY - READ UNDEFINED */ -+#define GPIO_FINTEN (GPIO_BASE+0x58) -+#define GPIO_INTSTATUSF (GPIO_BASE+0x5C) -+#define GPIO_RAWINTSTASUSF (GPIO_BASE+0x60) -+#define GPIO_FDB (GPIO_BASE+0x64) -+#define GPIO_PAPINDR (GPIO_BASE+0x68) -+#define GPIO_PBPINDR (GPIO_BASE+0x6C) -+#define GPIO_PCPINDR (GPIO_BASE+0x70) -+#define GPIO_PDPINDR (GPIO_BASE+0x74) -+#define GPIO_PEPINDR (GPIO_BASE+0x78) -+#define GPIO_PFPINDR (GPIO_BASE+0x7C) -+#define GPIO_PGPINDR (GPIO_BASE+0x80) -+#define GPIO_PHPINDR (GPIO_BASE+0x84) -+#define GPIO_AINTTYPE1 (GPIO_BASE+0x90) -+#define GPIO_AINTTYPE2 (GPIO_BASE+0x94) -+#define GPIO_AEOI (GPIO_BASE+0x98) /* WRITE ONLY - READ UNDEFINED */ -+#define GPIO_AINTEN (GPIO_BASE+0x9C) -+#define GPIO_INTSTATUSA (GPIO_BASE+0xA0) -+#define GPIO_RAWINTSTSTISA (GPIO_BASE+0xA4) -+#define GPIO_ADB (GPIO_BASE+0xA8) -+#define GPIO_BINTTYPE1 (GPIO_BASE+0xAC) -+#define GPIO_BINTTYPE2 (GPIO_BASE+0xB0) -+#define GPIO_BEOI (GPIO_BASE+0xB4) /* WRITE ONLY - READ UNDEFINED */ -+#define GPIO_BINTEN (GPIO_BASE+0xB8) -+#define GPIO_INTSTATUSB (GPIO_BASE+0xBC) -+#define GPIO_RAWINTSTSTISB (GPIO_BASE+0xC0) -+#define GPIO_BDB (GPIO_BASE+0xC4) -+#define GPIO_EEDRIVE (GPIO_BASE+0xC8) -+//#define Reserved (GPIO_BASE+0xCC) -+#define GPIO_TCR (GPIO_BASE+0xD0) /* Test Registers */ -+#define GPIO_TISRA (GPIO_BASE+0xD4) /* Test Registers */ -+#define GPIO_TISRB (GPIO_BASE+0xD8) /* Test Registers */ -+#define GPIO_TISRC (GPIO_BASE+0xDC) /* Test Registers */ -+#define GPIO_TISRD (GPIO_BASE+0xE0) /* Test Registers */ -+#define GPIO_TISRE (GPIO_BASE+0xE4) /* Test Registers */ -+#define GPIO_TISRF (GPIO_BASE+0xE8) /* Test Registers */ -+#define GPIO_TISRG (GPIO_BASE+0xEC) /* Test Registers */ -+#define GPIO_TISRH (GPIO_BASE+0xF0) /* Test Registers */ -+#define GPIO_TCER (GPIO_BASE+0xF4) /* Test Registers */ -+ -+ -+/* 8088_0000 - 8088_ffff: Ac97 Controller (AAC) */ -+#define AC97_OFFSET 0x080000 -+#define AC97_BASE (EP93XX_APB_VIRT_BASE|AC97_OFFSET) -+#define EP93XX_AC97_PHY_BASE (EP93XX_APB_PHYS_BASE|AC97_OFFSET) -+#define AC97DR1 (AC97_BASE+0x00) /* 8088.0000 R/W Data read or written from/to FIFO1 */ -+#define AC97RXCR1 (AC97_BASE+0x04) /* 8088.0004 R/W Control register for receive */ -+#define AC97TXCR1 (AC97_BASE+0x08) /* 8088.0008 R/W Control register for transmit */ -+#define AC97SR1 (AC97_BASE+0x0C) /* 8088.000C R Status register */ -+#define AC97RISR1 (AC97_BASE+0x10) /* 8088.0010 R Raw interrupt status register */ -+#define AC97ISR1 (AC97_BASE+0x14) /* 8088.0014 R Interrupt Status */ -+#define AC97IE1 (AC97_BASE+0x18) /* 8088.0018 R/W Interrupt Enable */ -+ /* 8088.001C Reserved - RAZ */ -+#define AC97DR2 (AC97_BASE+0x20) /* 8088.0020 R/W Data read or written from/to FIFO2 */ -+#define AC97RXCR2 (AC97_BASE+0x24) /* 8088.0024 R/W Control register for receive */ -+#define AC97TXCR2 (AC97_BASE+0x28) /* 8088.0028 R/W Control register for transmit */ -+#define AC97SR2 (AC97_BASE+0x2C) /* 8088.002C R Status register */ -+#define AC97RISR2 (AC97_BASE+0x30) /* 8088.0030 R Raw interrupt status register */ -+#define AC97ISR2 (AC97_BASE+0x34) /* 8088.0034 R Interrupt Status */ -+#define AC97IE2 (AC97_BASE+0x38) /* 8088.0038 R/W Interrupt Enable */ -+ /* 8088.003C Reserved - RAZ */ -+#define AC97DR3 (AC97_BASE+0x40) /* 8088.0040 R/W Data read or written from/to FIFO3. */ -+#define AC97RXCR3 (AC97_BASE+0x44) /* 8088.0044 R/W Control register for receive */ -+#define AC97TXCR3 (AC97_BASE+0x48) /* 8088.0048 R/W Control register for transmit */ -+#define AC97SR3 (AC97_BASE+0x4C) /* 8088.004C R Status register */ -+#define AC97RISR3 (AC97_BASE+0x50) /* 8088.0050 R Raw interrupt status register */ -+#define AC97ISR3 (AC97_BASE+0x54) /* 8088.0054 R Interrupt Status */ -+#define AC97IE3 (AC97_BASE+0x58) /* 8088.0058 R/W Interrupt Enable */ -+ /* 8088.005C Reserved - RAZ */ -+#define AC97DR2 (AC97_BASE+0x20) /* 8088.0020 R/W Data read or written from/to FIFO2 */ -+#define AC97RXCR2 (AC97_BASE+0x24) /* 8088.0024 R/W Control register for receive */ -+#define AC97TXCR2 (AC97_BASE+0x28) /* 8088.0028 R/W Control register for transmit */ -+#define AC97SR2 (AC97_BASE+0x2C) /* 8088.002C R Status register */ -+#define AC97RISR2 (AC97_BASE+0x30) /* 8088.0030 R Raw interrupt status register */ -+#define AC97ISR2 (AC97_BASE+0x34) /* 8088.0034 R Interrupt Status */ -+#define AC97IE2 (AC97_BASE+0x38) /* 8088.0038 R/W Interrupt Enable */ -+ /* 8088.003C Reserved - RAZ */ -+#define AC97DR3 (AC97_BASE+0x40) /* 8088.0040 R/W Data read or written from/to FIFO3. */ -+#define AC97RXCR3 (AC97_BASE+0x44) /* 8088.0044 R/W Control register for receive */ -+#define AC97TXCR3 (AC97_BASE+0x48) /* 8088.0048 R/W Control register for transmit */ -+#define AC97SR3 (AC97_BASE+0x4C) /* 8088.004C R Status register */ -+#define AC97RISR3 (AC97_BASE+0x50) /* 8088.0050 R Raw interrupt status register */ -+#define AC97ISR3 (AC97_BASE+0x54) /* 8088.0054 R Interrupt Status */ -+#define AC97IE3 (AC97_BASE+0x58) /* 8088.0058 R/W Interrupt Enable */ -+ /* 8088.005C Reserved - RAZ */ -+#define AC97DR4 (AC97_BASE+0x60) /* 8088.0060 R/W Data read or written from/to FIFO4. */ -+#define AC97RXCR4 (AC97_BASE+0x64) /* 8088.0064 R/W Control register for receive */ -+#define AC97TXCR4 (AC97_BASE+0x68) /* 8088.0068 R/W Control register for transmit */ -+#define AC97SR4 (AC97_BASE+0x6C) /* 8088.006C R Status register */ -+#define AC97RISR4 (AC97_BASE+0x70) /* 8088.0070 R Raw interrupt status register */ -+#define AC97ISR4 (AC97_BASE+0x74) /* 8088.0074 R Interrupt Status */ -+#define AC97IE4 (AC97_BASE+0x78) /* 8088.0078 R/W Interrupt Enable */ -+ /* 8088.007C Reserved - RAZ */ -+#define AC97S1DATA (AC97_BASE+0x80) /* 8088.0080 R/W Data received/transmitted on SLOT1 */ -+#define AC97S2DATA (AC97_BASE+0x84) /* 8088.0084 R/W Data received/transmitted on SLOT2 */ -+#define AC97S12DATA (AC97_BASE+0x88) /* 8088.0088 R/W Data received/transmitted on SLOT12 */ -+#define AC97RGIS (AC97_BASE+0x8C) /* 8088.008C R/W Raw Global interrupt status register*/ -+#define AC97GIS (AC97_BASE+0x90) /* 8088.0090 R Global interrupt status register */ -+#define AC97IM (AC97_BASE+0x94) /* 8088.0094 R/W Interrupt mask register */ -+#define AC97EOI (AC97_BASE+0x98) /* 8088.0098 W Interrupt clear register */ -+#define AC97GCR (AC97_BASE+0x9C) /* 8088.009C R/W Main Control register */ -+#define AC97RESET (AC97_BASE+0xA0) /* 8088.00A0 R/W RESET control register. */ -+#define AC97SYNC (AC97_BASE+0xA4) /* 8088.00A4 R/W SYNC control register. */ -+#define AC97GCIS (AC97_BASE+0xA8) /* 8088.00A8 R Global chan FIFO int status register */ -+ -+ -+/* 800B_0000 - 800B_FFFF: VIC 0 */ -+#define VIC0_OFFSET 0x0B0000 -+#define VIC0_BASE (EP93XX_AHB_VIRT_BASE|VIC0_OFFSET) -+#define VIC0 (VIC0_BASE+0x000) -+#define VIC0IRQSTATUS (VIC0_BASE+0x000) /* R IRQ status register */ -+#define VIC0FIQSTATUS (VIC0_BASE+0x004) /* R FIQ status register */ -+#define VIC0RAWINTR (VIC0_BASE+0x008) /* R Raw interrupt status register */ -+#define VIC0INTSELECT (VIC0_BASE+0x00C) /* R/W Interrupt select register */ -+#define VIC0INTENABLE (VIC0_BASE+0x010) /* R/W Interrupt enable register */ -+#define VIC0INTENCLEAR (VIC0_BASE+0x014) /* W Interrupt enable clear register */ -+ -+/* 8003_0000 - 8003_ffff: Raster */ -+#define RASTER_OFFSET 0x030000 -+#define RASTER_BASE (EP93XX_AHB_VIRT_BASE|RASTER_OFFSET) -+#define VLINESTOTAL (RASTER_BASE+0x00) -+#define VSYNCSTRTSTOP (RASTER_BASE+0x04) -+#define VACTIVESTRTSTOP (RASTER_BASE+0x08) -+#define VCLKSTRTSTOP (RASTER_BASE+0x0C) -+#define HCLKSTOTAL (RASTER_BASE+0x10) -+#define HSYNCSTRTSTOP (RASTER_BASE+0x14) -+#define HACTIVESTRTSTOP (RASTER_BASE+0x18) -+#define HCLKSTRTSTOP (RASTER_BASE+0x1C) -+#define BRIGHTNESS (RASTER_BASE+0x20) -+#define VIDEOATTRIBS (RASTER_BASE+0x24) -+#define VIDSCRNPAGE (RASTER_BASE+0x28) -+#define VIDSCRNHPG (RASTER_BASE+0x2C) -+#define SCRNLINES (RASTER_BASE+0x30) -+#define LINELENGTH (RASTER_BASE+0x34) -+#define VLINESTEP (RASTER_BASE+0x38) -+#define LINECARRY (RASTER_BASE+0x3C) -+#define BLINKRATE (RASTER_BASE+0x40) -+#define BLINKMASK (RASTER_BASE+0x44) -+#define BLINKPATTRN (RASTER_BASE+0x48) -+#define PATTRNMASK (RASTER_BASE+0x4C) -+#define BG_OFFSET (RASTER_BASE+0x50) -+#define PIXELMODE (RASTER_BASE+0x54) -+#define PARLLIFOUT (RASTER_BASE+0x58) -+#define PARLLIFIN (RASTER_BASE+0x5C) -+#define CURSOR_ADR_START (RASTER_BASE+0x60) -+#define CURSOR_ADR_RESET (RASTER_BASE+0x64) -+#define CURSORSIZE (RASTER_BASE+0x68) -+#define CURSORCOLOR1 (RASTER_BASE+0x6C) -+#define CURSORCOLOR2 (RASTER_BASE+0x70) -+#define CURSORXYLOC (RASTER_BASE+0x74) -+#define CURSOR_DHSCAN_LH_YLOC (RASTER_BASE+0x78) -+#define RASTER_SWLOCK (RASTER_BASE+0x7C) -+#define GS_LUT (RASTER_BASE+0x80) -+#define RASTER_TCR (RASTER_BASE+0x100) -+#define RASTER_TISRA (RASTER_BASE+0x104) -+#define RASTER_TISRB (RASTER_BASE+0x108) -+#define CURSOR_TISR (RASTER_BASE+0x10C) -+#define RASTER_TOCRA (RASTER_BASE+0x110) -+#define RASTER_TOCRB (RASTER_BASE+0x114) -+#define FIFO_TOCRA (RASTER_BASE+0x118) -+#define FIFO_TOCRB (RASTER_BASE+0x11C) -+#define BLINK_TISR (RASTER_BASE+0x120) -+#define DAC_TISRA (RASTER_BASE+0x124) -+#define DAC_TISRB (RASTER_BASE+0x128) -+#define SHIFT_TISR (RASTER_BASE+0x12C) -+#define DACMUX_TOCRA (RASTER_BASE+0x130) -+#define DACMUX_TOCRB (RASTER_BASE+0x134) -+#define PELMUX_TOCR (RASTER_BASE+0x138) -+#define VIDEO_TOCRA (RASTER_BASE+0x13C) -+#define VIDEO_TOCRB (RASTER_BASE+0x140) -+#define YCRCB_TOCR (RASTER_BASE+0x144) -+#define CURSOR_TOCR (RASTER_BASE+0x148) -+#define VIDEO_TOCRC (RASTER_BASE+0x14C) -+#define SHIFT_TOCR (RASTER_BASE+0x150) -+#define BLINK_TOCR (RASTER_BASE+0x154) -+#define RASTER_TCER (RASTER_BASE+0x180) -+#define SIGVAL (RASTER_BASE+0x200) -+#define SIGCTL (RASTER_BASE+0x204) -+#define VSIGSTRTSTOP (RASTER_BASE+0x208) -+#define HSIGSTRTSTOP (RASTER_BASE+0x20C) -+#define SIGCLR (RASTER_BASE+0x210) -+#define ACRATE (RASTER_BASE+0x214) -+#define LUTCONT (RASTER_BASE+0x218) -+#define VBLANKSTRTSTOP (RASTER_BASE+0x228) -+#define HBLANKSTRTSTOP (RASTER_BASE+0x22C) -+#define LUT (RASTER_BASE+0x400) -+#define CURSORBLINK1 (RASTER_BASE+0x21C) -+#define CURSORBLINK2 (RASTER_BASE+0x220) -+#define CURSORBLINK (RASTER_BASE+0x224) -+#define EOLOFFSET (RASTER_BASE+0x230) -+#define FIFOLEVEL (RASTER_BASE+0x234) -+#define GS_LUT2 (RASTER_BASE+0x280) -+#define GS_LUT3 (RASTER_BASE+0x300) -+#define COLOR_LUT (RASTER_BASE+0x400) -+ -+/* 8004_0000 - 8004_ffff: Graphics */ -+#define GRAPHICS_OFFSET 0x040000 -+#define GRAPHICS_BASE (EP93XX_AHB_VIRT_BASE|GRAPHICS_OFFSET) -+#define SRCPIXELSTRT (GRAPHICS_BASE+0x00) -+#define DESTPIXELSTRT (GRAPHICS_BASE+0x04) -+#define BLKSRCSTRT (GRAPHICS_BASE+0x08) -+#define BLKDSTSTRT (GRAPHICS_BASE+0x0C) -+#define BLKSRCWIDTH (GRAPHICS_BASE+0x10) -+#define SRCLINELENGTH (GRAPHICS_BASE+0x14) -+#define BLKDESTWIDTH (GRAPHICS_BASE+0x18) -+#define BLKDESTHEIGHT (GRAPHICS_BASE+0x1C) -+#define DESTLINELENGTH (GRAPHICS_BASE+0x20) -+#define BLOCKCTRL (GRAPHICS_BASE+0x24) -+#define TRANSPATTRN (GRAPHICS_BASE+0x28) -+#define BLOCKMASK (GRAPHICS_BASE+0x2C) -+#define BACKGROUND (GRAPHICS_BASE+0x30) -+#define LINEINC (GRAPHICS_BASE+0x34) -+#define LINEINIT (GRAPHICS_BASE+0x38) -+#define LINEPATTRN (GRAPHICS_BASE+0x3C) -+ -+#define EP93XX_RASTER_BASE (EP93XX_AHB_VIRT_BASE + 0x00030000) -+#define EP93XX_RASTER_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00030000) -+ -+#define EP93XX_GRAPHICS_ACCEL_BASE (EP93XX_AHB_VIRT_BASE + 0x00040000) -+#define EP93XX_GRAPHICS_ACCEL_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00040000) -+ -+#ifndef __ASSEMBLY__ -+ -+#define SysconSetLocked(registername,value) \ -+ { \ -+ local_irq_disable(); \ -+ outl( 0xAA, EP93XX_SYSCON_SWLOCK); \ -+ outl( value, registername); \ -+ local_irq_enable(); \ -+ } -+ -+#endif /* Not __ASSEMBLY__ */ -+ - #endif diff --git a/target/linux/ep93xx/patches-2.6.30/002-lcd-linux-hd44780.patch b/target/linux/ep93xx/patches-2.6.30/002-lcd-linux-hd44780.patch deleted file mode 100644 index 7480b28117..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/002-lcd-linux-hd44780.patch +++ /dev/null @@ -1,4342 +0,0 @@ -Index: linux-2.6.30.9/arch/arm/Kconfig -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/Kconfig 2009-10-05 17:38:08.000000000 +0200 -+++ linux-2.6.30.9/arch/arm/Kconfig 2009-11-24 02:01:42.000000000 +0100 -@@ -1407,6 +1407,8 @@ - - source "drivers/accessibility/Kconfig" - -+source "drivers/lcd-linux/Kconfig" -+ - source "drivers/leds/Kconfig" - - source "drivers/rtc/Kconfig" -Index: linux-2.6.30.9/drivers/Makefile -=================================================================== ---- linux-2.6.30.9.orig/drivers/Makefile 2009-10-05 17:38:08.000000000 +0200 -+++ linux-2.6.30.9/drivers/Makefile 2009-11-24 02:01:42.000000000 +0100 -@@ -106,4 +106,5 @@ - obj-$(CONFIG_SSB) += ssb/ - obj-$(CONFIG_VIRTIO) += virtio/ - obj-$(CONFIG_STAGING) += staging/ -+obj-$(CONFIG_LCD_LINUX) += lcd-linux/ - obj-y += platform/ -Index: linux-2.6.30.9/drivers/lcd-linux/Config.in -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/Config.in 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,8 @@ -+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then -+ mainmenu_option next_comment -+ comment 'LCD support' -+ -+ tristate 'LCD-Linux layer' CONFIG_LCD_LINUX -+ dep_tristate ' HD44780 controller' CONFIG_LCD_HD44780 $CONFIG_LCD_LINUX -+ endmenu -+fi -Index: linux-2.6.30.9/drivers/lcd-linux/Kconfig -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/Kconfig 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,33 @@ -+menu "LCD-Linux support" -+ depends on EXPERIMENTAL -+ -+config LCD_LINUX -+ tristate "LCD-Linux layer" -+ default m -+ help -+ LCD-Linux provides an easy way to drive LCD displays under -+ Linux by creating a character which can be read or written. -+ It features complete VT102 emulation and recognizes -+ many escape sequences. If you want to use it you must also -+ choose an appropriate driver, otherwise it will not be -+ very useful. For more information see -+ http://lcd-linux.sourceforge.net/ -+ -+ To compile LCD-Linux as a module, choose M here: -+ the module will be called lcd-linux. -+ -+config LCD_HD44780 -+ tristate "HD44780 controller" -+ depends on LCD_LINUX && MACH_SIM_ONE -+ default m -+ help -+ This is a LCD-Linux driver for LCD displays based on the -+ Hitachi HD44780 (and compatible) controllers connected -+ to the SimOne LCD port. -+ -+ To compile this driver as a module, choose M here: -+ the module will be called hd44780. -+ -+ If unsure, say N. -+ -+endmenu -Index: linux-2.6.30.9/drivers/lcd-linux/Makefile -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/Makefile 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,8 @@ -+# -+# -+# Standard Makefile to statically compile LCD-Linux into the kernel -+# Linux 2.6 -+ -+obj-$(CONFIG_LCD_LINUX) += lcd-linux.o -+obj-$(CONFIG_LCD_HD44780) += hd44780.o -+ -Index: linux-2.6.30.9/drivers/lcd-linux/cgram/default.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/cgram/default.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,37 @@ -+/* default.h -+ * -+ * -+ * -+ * Default user defined characters for lcdmod. -+ * -+ * Copyright (C) by Michael McLellan (mikey@cs.auckland.ac.nz) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * -+ */ -+ -+static void init_charmap(void) -+{ -+} -+ -+static unsigned char cg0[] = { 0x1f, 0x1f, 0x11, 0x0f, 0x11, 0x1e, 0x01, 0x1f }; -+static unsigned char cg1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f }; -+static unsigned char cg2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f }; -+static unsigned char cg3[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f }; -+static unsigned char cg4[] = { 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f }; -+static unsigned char cg5[] = { 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; -+static unsigned char cg6[] = { 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; -+static unsigned char cg7[] = { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; -Index: linux-2.6.30.9/drivers/lcd-linux/charmap.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/charmap.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,79 @@ -+/* charmap.h -+ * -+ * -+ * -+ * Character mapping for HD44780 devices by Mark Haemmerling <mail@markh.de>. -+ * -+ * Translates ISO 8859-1 to HD44780 charset. -+ * HD44780 charset reference: http://markh.de/hd44780-charset.png -+ * -+ * Initial table taken from lcd.o Linux kernel driver by -+ * Nils Faerber <nilsf@users.sourceforge.net>. Thanks! -+ * -+ * This file is released under the GNU General Public License. Refer to the -+ * COPYING file distributed with this package. -+ * -+ * Following translations are being performed: -+ * - maps umlaut accent characters to the corresponding umlaut characters -+ * - maps other accent characters to the characters without accents -+ * - maps beta (=ringel-S), micro and Yen -+ * -+ * Alternative mappings: -+ * - #112 ("p") -> #240 (large "p"), orig. mapped -> #112 -+ * - #113 ("q") -> #241 (large "q"), orig. mapped -> #113 -+ * -+ * HD44780 misses backslash -+ * -+ */ -+ -+static unsigned char charmap[] = { -+ -+/* 0 - 31 */ -+ 0, 1, 2, 3, 4, 5, 6, 7, -+ 8, 9, 10, 11, 12, 13, 14, 15, -+ 16, 17, 18, 19, 20, 21, 22, 23, -+ 24, 25, 26, 27, 28, 29, 30, 31, -+ -+/* 32 - 63 */ -+ 32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63, -+ -+/* 64 - 95 */ -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 87, -+ 88, 89, 90, 91, 47, 93, 94, 95, -+ -+/* 96 - 127 */ -+ 96, 97, 98, 99, 100, 101, 102, 103, -+104, 105, 106, 107, 108, 109, 110, 111, -+112, 113, 114, 115, 116, 117, 118, 119, -+120, 121, 122, 123, 124, 125, 126, 127, -+ -+/* 128 - 159 */ -+128, 129, 130, 131, 132, 133, 134, 135, -+136, 137, 138, 139, 140, 141, 142, 143, -+144, 145, 146, 147, 148, 149, 150, 151, -+152, 153, 154, 155, 156, 157, 158, 159, -+ -+/* 160 - 191 */ -+160, 33, 236, 237, 164, 92, 124, 167, -+ 34, 169, 170, 171, 172, 173, 174, 175, -+223, 177, 178, 179, 39, 249, 247, 165, -+ 44, 185, 186, 187, 188, 189, 190, 63, -+ -+/* 192 - 223 */ -+ 65, 65, 65, 65, 225, 65, 65, 67, -+ 69, 69, 69, 69, 73, 73, 73, 73, -+ 68, 78, 79, 79, 79, 79, 239, 120, -+ 48, 85, 85, 85, 245, 89, 240, 226, -+ -+/* 224 - 255 */ -+ 97, 97, 97, 97, 225, 97, 97, 99, -+101, 101, 101, 101, 105, 105, 105, 105, -+111, 110, 111, 111, 111, 111, 239, 253, -+ 48, 117, 117, 117, 245, 121, 240, 255 -+ -+}; -Index: linux-2.6.30.9/drivers/lcd-linux/commands.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/commands.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,77 @@ -+/* commands.h -+ * -+ * -+ * -+ * LCD-Linux: -+ * Driver for HD44780 compatible displays connected to the parallel port. -+ * -+ * HD44780 commands. -+ * -+ * Copyright (C) 2004 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifndef HD44780_COMMANDS_H -+#define HD44780_COMMANDS_H -+ -+/*** HD44780 Command Set ***/ -+ -+/* Clear Display*/ -+#define CLR_DISP 0x01 /* Clear entire display; cursor at row 0, column 0 */ -+ -+/* Return Home */ -+#define RET_HOME 0x02 /* Cursor at row 0, column 0; display content doesn't change */ -+ -+/* Entry Mode Set */ -+#define ENTRY_MODE_SET 0x04 -+#define DISP_SHIFT_ON (ENTRY_MODE_SET | 0x01) /* Shift display, not cursor after data write */ -+#define DISP_SHIFT_OFF (ENTRY_MODE_SET | 0x00) /* Shift cursor, not display after data write */ -+#define CURS_INC (ENTRY_MODE_SET | 0x02) /* Shift on the right after data read/write */ -+#define CURS_DEC (ENTRY_MODE_SET | 0x00) /* Shift on the left after data read/write */ -+ -+/* Display on/off Control */ -+#define DISP_ONOFF_CNTR 0x08 -+#define BLINK_ON (DISP_ONOFF_CNTR | 0x01) /* Cursor blinking on */ -+#define BLINK_OFF (DISP_ONOFF_CNTR | 0x00) /* Cursor blinking off */ -+#define CURS_ON (DISP_ONOFF_CNTR | 0x02) /* Display Cursor */ -+#define CURS_OFF (DISP_ONOFF_CNTR | 0x00) /* Hide Cursor */ -+#define DISP_ON (DISP_ONOFF_CNTR | 0x04) /* Turn on display updating */ -+#define DISP_OFF (DISP_ONOFF_CNTR | 0x00) /* Freeze display content */ -+ -+/* Cursor or Display Shift */ -+#define CURS_DISP_SHIFT 0x10 -+#define SHIFT_RIGHT (CURS_DISP_SHIFT | 0x04) /* Shift on the right */ -+#define SHIFT_LEFT (CURS_DISP_SHIFT | 0x00) /* Shift on the left */ -+#define SHIFT_DISP (CURS_DISP_SHIFT | 0x08) /* Shift display */ -+#define SHIFT_CURS (CURS_DISP_SHIFT | 0x00) /* Shift cursor */ -+ -+/* Function Set */ -+#define FUNC_SET 0x20 -+#define FONT_5X10 (FUNC_SET | 0x04) /* Select 5x10 dots font */ -+#define FONT_5X8 (FUNC_SET | 0x00) /* Select 5x8 dots font */ -+#define DISP_2_LINES (FUNC_SET | 0x08) /* Select 2 lines display (only 5x8 font allowed) */ -+#define DISP_1_LINE (FUNC_SET | 0x00) /* Select 1 line display */ -+#define BUS_8_BITS (FUNC_SET | 0x10) /* Set 8 data bits */ -+#define BUS_4_BITS (FUNC_SET | 0x00) /* Set 4 data bits */ -+ -+/* Set CGRAM Address */ -+#define CGRAM_IO 0x40 /* Base CGRAM address */ -+ -+/* Set DDRAM Address */ -+#define DDRAM_IO 0x80 /* Base DDRAM address */ -+ -+#endif /* commands included */ -Index: linux-2.6.30.9/drivers/lcd-linux/config.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/config.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,73 @@ -+/* config.h -+ * -+ * -+ * -+ * Configure file for LCD-Linux. Here you must specify your hardware setup and -+ * timings constants. The default values will probably be right for you. -+ * -+ * Copyright (C) 2005 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * -+ */ -+ -+/* Setup the default user defined characters in CGRAM */ -+#include "cgram/default.h" -+ -+/* Don't modify the default timing constants -+ * unless you know what you are doing. -+ */ -+ -+/* Execution times (in microseconds) */ -+#define T_READ 60 /* Read execution time (min 43 us) */ -+#define T_WRITE 60 /* Write execution time (min 43 us) */ -+#define T_BF 2 /* Busy flag polling time (min 1 us) */ -+ -+/* Timings in nanoseconds */ -+#define T_AS 200 /* Address set-up time (min 140 ns) */ -+#define T_EH 500 /* Enable high time (min 450 ns) */ -+#define T_EL 600 /* Enable low time (min 500 ns) */ -+ -+/* Various constants */ -+#define DFLT_NUM_CNTR 1 /* Default number of controllers the display has */ -+#define DFLT_CNTR_ROWS 2 /* Default number of rows per controller */ -+#define DFLT_CNTR_COLS 16 /* Default number of columns the display has */ -+#define DFLT_VS_ROWS 25 /* Default number of rows for the virtual screen */ -+#define DFLT_VS_COLS 80 /* Default number of columns for the virtual screen */ -+#define DFLT_TABSTOP 3 /* Default length of tabs */ -+#define DFLT_FLAGS (HD44780_CHECK_BF | HD44780_4BITS_BUS ) /* Default flags */ -+ -+#define MAX_CNTR_ROWS 4 /* The HD44780 supports up to 4 lines as a fake 2 lines mode */ -+#define MAX_CNTR_COLS 80 /* The HD44780 supports up to 80 characters (1*80; 2*40; etc) */ -+ -+#define SETUP 4 -+#define HIGH_NIBBLE_WRITE(x) (((x) >> (4-SETUP)) & (0x0f << SETUP)) -+#define LOW_NIBBLE_WRITE(x) (((x) << SETUP) & (0x0f << SETUP)) -+#define HIGH_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) << (4-SETUP)) -+#define LOW_NIBBLE_READ(x) (((x) & (0x0f << SETUP)) >> SETUP) -+ -+ -+#define SIMONE_LCD_RS EP93XX_GPIO_LINE_A(2) /* OUT */ -+#define SIMONE_LCD_RD EP93XX_GPIO_LINE_A(3) /* OUT */ -+#define SIMONE_LCD_EN EP93XX_GPIO_LINE_B(4) /* EGPIO12 OUT */ -+#define SIMONE_LCD_BCKLIGHT EP93XX_GPIO_LINE_B(5) /* EGPIO13 OUT */ -+ -+#define SIMONE_LCD_DATA0 EP93XX_GPIO_LINE_A(4) -+#define SIMONE_LCD_DATA1 EP93XX_GPIO_LINE_A(5) -+#define SIMONE_LCD_DATA2 EP93XX_GPIO_LINE_A(6) -+#define SIMONE_LCD_DATA3 EP93XX_GPIO_LINE_A(7) -+ -+ -Index: linux-2.6.30.9/drivers/lcd-linux/hd44780.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/hd44780.c 2009-11-24 02:05:29.000000000 +0100 -@@ -0,0 +1,860 @@ -+/* hd44780.c -+ * -+ * -+ * -+ * LCD-Linux: -+ * Driver for HD44780 compatible displays connected to the parallel port. -+ * -+ * Copyright (C) 2005 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * Adapted to Sim.One Hardware by Nuccio Raciti (raciti.nuccio@gmail.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+ -+#include <linux/autoconf.h> -+ -+ -+#ifdef CONFIG_PROC_FS -+#define USE_PROC -+#else -+#undef USE_PROC -+#endif -+ -+#include <linux/bitops.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+ -+#include <linux/delay.h> -+#include <linux/fs.h> -+ -+#include <asm/uaccess.h> -+#include <linux/init.h> -+ -+#include <asm/io.h> -+#include <linux/ioport.h> -+#include <asm/gpio.h> -+ -+#ifdef USE_PROC -+#include <linux/proc_fs.h> -+#endif -+ -+#define LCD_LINUX_MAIN -+#include <linux/hd44780.h> -+ -+#include "charmap.h" -+#include "commands.h" -+#include "config.h" -+ -+/** Function prototypes **/ -+static void read_display(unsigned char *byte, unsigned char bitmask); -+static void write_display(unsigned char byte, unsigned char bitmask); -+ -+/* Initialization */ -+static int hd44780_validate_driver(void); -+static int hd44780_init_port(void); -+static int hd44780_cleanup_port(void); -+static int hd44780_init_display(void); -+static int hd44780_cleanup_display(void); -+ -+/* Write */ -+static void hd44780_address_mode(int); -+static void hd44780_clear_display(void); -+static void hd44780_write_char(unsigned int, unsigned short); -+static void hd44780_write_cgram_char(unsigned char, unsigned char *); -+ -+/* Read */ -+static void check_bf(unsigned char); -+static void hd44780_read_char(unsigned int, unsigned short *); -+static void hd44780_read_cgram_char(unsigned char, unsigned char *); -+ -+/* Input handling */ -+static int hd44780_handle_custom_char(unsigned int); -+static int hd44780_handle_custom_ioctl(unsigned int,unsigned long , unsigned int); -+ -+/* Proc operations */ -+#ifdef USE_PROC -+static void create_proc_entries(void); -+static void remove_proc_entries(void); -+#endif -+ -+/* hd44780 access */ -+#define ACCESS_TO_READ 0 -+#define ACCESS_TO_WRITE 1 -+#define ACCESS_TO_DATA 2 -+ -+/* hd44780_flags */ -+#define _CHECK_BF 0 /* Do busy-flag checking */ -+#define _4BITS_BUS 1 /* The bus is 4 bits long */ -+#define _5X10_FONT 2 /* Use 5x10 font */ -+#define CURSOR_BLINK 3 /* Make the cursor blinking */ -+#define SHOW_CURSOR 4 /* Make the cursor visible */ -+#define DISPLAY_ON 5 /* Display status: on or off */ -+#define INC_ADDR 6 /* Increment address after data read/write */ -+#define BACKLIGHT 7 /* Display backlight: on or off */ -+#define CGRAM_STATE 9 /* Controller status bitmask (bits 9->15): DDRAM or CGRAM access */ -+#define ESC_MASK 0x00ff0000 -+#define PROC_MASK 0x0f000000 -+ -+#define SET_STATE(state, mask) (hd44780_flags = (hd44780_flags & ~(mask)) | ((state) & (mask))) -+#define SET_ESC_STATE(state) SET_STATE((state) << 16, ESC_MASK) -+#define SET_PROC_LEVEL(level) SET_STATE((level) << 24, PROC_MASK) -+#define ESC_STATE ((hd44780_flags & ESC_MASK) >> 16) -+#define PROC_LEVEL ((hd44780_flags & PROC_MASK) >> 24) -+ -+/* globals */ -+static unsigned int disp_size; /* Display size (rows*columns) */ -+static unsigned int disp_offset[1]; /* Physical cursor position on the display */ -+static unsigned long hd44780_flags; /* Driver flags for internal use only */ -+ -+static struct lcd_parameters par = { -+ .name = HD44780_STRING, -+ .minor = HD44780_MINOR, -+ .flags = DFLT_FLAGS, -+ .tabstop = DFLT_TABSTOP, -+ .num_cntr = 1, -+ .cntr_rows = DFLT_CNTR_ROWS, -+ .cntr_cols = DFLT_CNTR_COLS, -+ .vs_rows = DFLT_VS_ROWS, -+ .vs_cols = DFLT_VS_COLS, -+ .cgram_chars = 8, -+ .cgram_bytes = 8, -+ .cgram_char0 = 0, -+}; -+/* End of globals */ -+ -+#ifdef MODULE -+#include <linux/device.h> -+MODULE_ALIAS_CHARDEV(LCD_MAJOR, HD44780_MINOR); -+#include <linux/kmod.h> -+ -+static unsigned short flags = DFLT_FLAGS; -+static unsigned short tabstop = DFLT_TABSTOP; -+static unsigned short cntr_rows = DFLT_CNTR_ROWS; -+static unsigned short cntr_cols = DFLT_CNTR_COLS; -+static unsigned short vs_rows = DFLT_VS_ROWS; -+static unsigned short vs_cols = DFLT_VS_COLS; -+static unsigned short minor = HD44780_MINOR; -+ -+MODULE_DESCRIPTION("LCD SimOne driver for HD44780 compatible controllers."); -+MODULE_AUTHOR("Nuccio Raciti (raciti.nuccio@gmail.com)"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+module_param(flags, ushort, 0444); -+module_param(cntr_rows, ushort, 0444); -+module_param(cntr_cols, ushort, 0444); -+module_param(vs_rows, ushort, 0444); -+module_param(vs_cols, ushort, 0444); -+module_param(tabstop, ushort, 0444); -+module_param(minor, ushort, 0444); -+ -+MODULE_PARM_DESC(flags, "Various flags (see Documentation)"); -+MODULE_PARM_DESC(cntr_rows, "Number of rows per controller on the LCD: 1, 2, 4 (default: " string(DFLT_CNTR_ROWS) ")"); -+MODULE_PARM_DESC(cntr_cols, "Number of columns on the LCD (default: " string(DFLT_CNTR_COLS) ", max: " string(MAX_CNTR_COLS) ")"); -+MODULE_PARM_DESC(vs_rows, "Number of rows of the virtual screen (default: " string(DFLT_VS_ROWS) ")"); -+MODULE_PARM_DESC(vs_cols, "Number of columns of the virtual screen (default: " string(DFLT_VS_COLS) ")"); -+MODULE_PARM_DESC(tabstop, "Tab character length (default: " string(DFLT_TABSTOP) ")"); -+MODULE_PARM_DESC(minor, "Assigned minor number (default: " string(HD44780_MINOR) ")"); -+#else -+ -+/* -+ * Parse boot command line -+ * -+ * hd44780=cntr_rows,cntr_cols,vs_rows,vs_cols,flags,minor,tabstop -+ */ -+static int __init hd44780_boot_init(char *cmdline) -+{ -+ char *str = cmdline; -+ int idx = 0; -+ unsigned short *args[] = { -+ &par.cntr_rows, -+ &par.cntr_cols, -+ &par.vs_rows, -+ &par.vs_cols, -+ &par.flags, -+ &par.num_cntr, -+ &par.minor, -+ &par.tabstop, -+ }; -+ -+ while (*cmdline && idx < (sizeof(args)/sizeof(unsigned short *))) { -+ switch (*str) { -+ case ',': -+ *str++ = 0; -+ case 0: -+ if (strlen(cmdline)) -+ *args[idx] = simple_strtoul(cmdline, NULL, 0); -+ ++idx; -+ cmdline = str; -+ break; -+ default: -+ ++str; -+ break; -+ } -+ } -+ -+ return (1); -+} -+ -+__setup("hd44780=", hd44780_boot_init); -+#endif /* MODULE */ -+ -+/* Macros for iterator handling */ -+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module) -+{ -+ return ((++iterator)%module); -+} -+ -+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module) -+{ -+ return (iterator ? --iterator : module-1); -+} -+ -+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module)) -+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module)) -+ -+static inline void set_lines(unsigned char bitmask) -+{ -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ -+ if(bitmask & ACCESS_TO_WRITE ) { -+ gpio_direction_output (SIMONE_LCD_DATA0 , 0); -+ gpio_direction_output (SIMONE_LCD_DATA1 , 0); -+ gpio_direction_output (SIMONE_LCD_DATA2 , 0); -+ gpio_direction_output (SIMONE_LCD_DATA3 , 0); -+ gpio_set_value(SIMONE_LCD_RD, 0); /* Write */ -+ } else { -+ -+ gpio_direction_input (SIMONE_LCD_DATA0); -+ gpio_direction_input (SIMONE_LCD_DATA1); -+ gpio_direction_input (SIMONE_LCD_DATA2); -+ gpio_direction_input (SIMONE_LCD_DATA3); -+ gpio_set_value(SIMONE_LCD_RD, 1); /* Read */ -+ } -+ -+ if(bitmask & ACCESS_TO_DATA ) -+ gpio_set_value(SIMONE_LCD_RS, 1); /* Data */ -+ else -+ gpio_set_value(SIMONE_LCD_RS, 0); /* Cmds*/ -+ -+ if(test_bit(BACKLIGHT, &hd44780_flags)) -+ gpio_set_value(SIMONE_LCD_BCKLIGHT, 1); -+ else -+ gpio_set_value(SIMONE_LCD_BCKLIGHT, 0); -+} -+ -+ -+/* Low level read from the display */ -+static inline unsigned char __read_display(unsigned char bitmask) -+{ -+ unsigned char byte; -+ -+ set_lines (bitmask); -+ -+ ndelay(T_AS); /* Address set-up time */ -+ gpio_set_value(SIMONE_LCD_EN, 1); /* Enable */ -+ ndelay(T_EH);/* Enable high time */ -+ -+ byte = (gpio_get_value(SIMONE_LCD_DATA0) << 4); -+ byte |= (gpio_get_value(SIMONE_LCD_DATA1) << 5); -+ byte |= (gpio_get_value(SIMONE_LCD_DATA2) << 6); -+ byte |= (gpio_get_value(SIMONE_LCD_DATA3) << 7); -+ -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ -+ ndelay(T_EL); /* Enable low time */ -+ -+ -+ return (byte); -+ -+} -+ -+/* Low level write to the display */ -+static inline void __write_display(unsigned char data, unsigned char bitmask) -+{ -+ set_lines(bitmask); -+ -+ if(data & 0x10) -+ gpio_set_value(SIMONE_LCD_DATA0, 1); -+ else -+ gpio_set_value(SIMONE_LCD_DATA0, 0); -+ -+ if(data & 0x20) -+ gpio_set_value(SIMONE_LCD_DATA1, 1); -+ else -+ gpio_set_value(SIMONE_LCD_DATA1, 0); -+ -+ if(data & 0x40) -+ gpio_set_value(SIMONE_LCD_DATA2, 1); -+ else -+ gpio_set_value(SIMONE_LCD_DATA2, 0); -+ -+ if(data & 0x80) -+ gpio_set_value(SIMONE_LCD_DATA3, 1); -+ else -+ gpio_set_value(SIMONE_LCD_DATA3, 0); -+ -+ ndelay(T_AS); /* Address set-up time */ -+ gpio_set_value(SIMONE_LCD_EN, 1); -+ ndelay(T_EH); /* Enable high time */ -+ -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ ndelay(T_EL); /* Enable low time */ -+} -+ -+ -+/* Read data from the display (4 bit bus, check busy flag) */ -+static void read_display (unsigned char *byte,unsigned char bitmask) -+{ -+ if(bitmask) check_bf(bitmask); -+ *byte = HIGH_NIBBLE_READ(__read_display(bitmask)); -+ if(bitmask) check_bf(bitmask); -+ *byte |= LOW_NIBBLE_READ(__read_display(bitmask)); -+} -+ -+ -+/* Output commands or data to the display (4 bit bus, check busy flag) */ -+static void write_display(unsigned char byte,unsigned char bitmask) -+{ -+ check_bf(bitmask); -+ __write_display(HIGH_NIBBLE_WRITE(byte),bitmask); -+ check_bf(bitmask); -+ __write_display(LOW_NIBBLE_WRITE(byte),bitmask); -+} -+ -+ -+/* Read Address Counter AC from the display */ -+static unsigned char read_ac(unsigned char bitmask) -+{ -+ unsigned char byte; -+ -+ read_display(&byte, bitmask); -+ -+ return (byte); -+} -+ -+ -+/* Do busy-flag check */ -+static void check_bf(unsigned char bitmask) -+{ -+ unsigned int timeout = 20; -+ static unsigned char do_check_bf = 5; -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ -+ gpio_direction_input (SIMONE_LCD_DATA0); -+ gpio_direction_input (SIMONE_LCD_DATA1); -+ gpio_direction_input (SIMONE_LCD_DATA2); -+ gpio_direction_input (SIMONE_LCD_DATA3); -+ -+ gpio_set_value(SIMONE_LCD_RD, 1); /* Read */ -+ gpio_set_value(SIMONE_LCD_RS, 0); /* Instru */ -+ -+ ndelay(T_AS); /* Address set-up time */ -+ gpio_set_value(SIMONE_LCD_EN, 1); /* Enable */ -+ ndelay(T_EH);/* Enable high time */ -+ -+ do{ -+ udelay(T_BF); -+ } while (gpio_get_value(SIMONE_LCD_DATA3) && --timeout); -+ -+ if (! timeout) { -+ if (! --do_check_bf) { -+ printk(KERN_NOTICE "hd44780 error: is the LCD connected?\n"); -+ } -+ } -+ -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ -+ ndelay(T_EL); /* Enable low time */ -+} -+ -+/* Send commands to the display */ -+static void write_command(unsigned char command) -+{ -+ write_display(command, ACCESS_TO_WRITE); -+ -+ if (command <= 0x03) -+ mdelay(2); -+} -+ -+static inline void set_cursor(unsigned int offset) -+{ -+ unsigned int disp_number = offset/disp_size; -+ unsigned int local_offset = offset%disp_size; -+ -+ if (disp_offset[disp_number] != local_offset || test_bit(CGRAM_STATE+disp_number, &hd44780_flags)) { -+ unsigned int disp_row = local_offset/par.cntr_cols; -+ unsigned int disp_column = local_offset%par.cntr_cols; -+ -+ write_command(DDRAM_IO | ((disp_row%2)*0x40) | (((disp_row >= 2)*par.cntr_cols)+disp_column)); -+ clear_bit(CGRAM_STATE+disp_number, &hd44780_flags); -+ disp_offset[disp_number] = local_offset; -+ } -+} -+ -+/* HD44780 DDRAM addresses are consecutive only when -+ * the cursor moves on the same row of the display. -+ * Every time the row of the cursor changes we invalidate -+ * the cursor position to force hardware cursor repositioning. -+ */ -+static inline void mov_cursor(unsigned int disp_number) -+{ -+ if (test_bit(INC_ADDR, &hd44780_flags)) { -+ iterator_inc(disp_offset[disp_number], disp_size); -+ if (disp_offset[disp_number]%par.cntr_cols == 0) -+ disp_offset[disp_number] = disp_size; -+ } else { -+ iterator_dec(disp_offset[disp_number], disp_size); -+ if (disp_offset[disp_number]%par.cntr_cols == par.cntr_cols-1) -+ disp_offset[disp_number] = disp_size; -+ } -+} -+ -+static struct lcd_driver hd44780 = { -+ .read_char = hd44780_read_char, -+ .read_cgram_char = hd44780_read_cgram_char, -+ .write_char = hd44780_write_char, -+ .write_cgram_char = hd44780_write_cgram_char, -+ .address_mode = hd44780_address_mode, -+ .clear_display = hd44780_clear_display, -+ .validate_driver = hd44780_validate_driver, -+ .init_display = hd44780_init_display, -+ .cleanup_display = hd44780_cleanup_display, -+ .init_port = hd44780_init_port, -+ .cleanup_port = hd44780_cleanup_port, -+ .handle_custom_char = hd44780_handle_custom_char, -+ .handle_custom_ioctl = hd44780_handle_custom_ioctl, -+ -+ .charmap = charmap, -+}; -+ -+static void hd44780_read_char(unsigned int offset, unsigned short *data) -+{ -+ unsigned int disp_number = offset/disp_size; -+ unsigned char tmp; -+ -+ set_cursor(offset); -+ read_display(&tmp, ACCESS_TO_DATA); -+ *data = tmp; -+ mov_cursor(disp_number); -+} -+ -+static void hd44780_read_cgram_char(unsigned char index, unsigned char *pixels) -+{ -+ unsigned int i; -+ -+ write_command(CGRAM_IO | (index << 3)); -+ set_bit(CGRAM_STATE+0, &hd44780_flags); -+ -+ for (i = 0; i < 8; ++i) { -+ read_display(pixels+i, ACCESS_TO_DATA ); -+ pixels[i] &= 0x1f; -+ } -+} -+ -+static void hd44780_write_char(unsigned int offset, unsigned short data) -+{ -+ unsigned int disp_number = offset/disp_size; -+ -+ set_cursor(offset); -+ write_display(data & 0xff, ACCESS_TO_WRITE | ACCESS_TO_DATA ); -+ mov_cursor(disp_number); -+} -+ -+static void hd44780_write_cgram_char(unsigned char index, unsigned char *pixels) -+{ -+ unsigned int i; -+ -+ /* Move address pointer to index in CGRAM */ -+ write_command(CGRAM_IO | (index << 3)); -+ -+ set_bit(CGRAM_STATE+0, &hd44780_flags); -+ -+ for (i = 0; i < 8; ++i) { -+ pixels[i] &= 0x1f; -+ write_display(pixels[i], ACCESS_TO_WRITE | ACCESS_TO_DATA ); -+ } -+} -+ -+/* Increment/decrement address mode after a data read/write */ -+static void hd44780_address_mode(int mode) -+{ -+ if (mode > 0 && ! test_bit(INC_ADDR, &hd44780_flags)) { -+ write_command(CURS_INC | DISP_SHIFT_OFF); -+ set_bit(INC_ADDR, &hd44780_flags); -+ } else if (mode < 0 && test_bit(INC_ADDR, &hd44780_flags)) { -+ write_command(CURS_DEC | DISP_SHIFT_OFF); -+ clear_bit(INC_ADDR, &hd44780_flags); -+ } -+} -+ -+static void hd44780_clear_display(void) -+{ -+ write_command(CLR_DISP); -+ if (! test_bit(INC_ADDR, &hd44780_flags)) -+ write_command(CURS_DEC | DISP_SHIFT_OFF); -+ memset(disp_offset, 0, sizeof(disp_offset)); -+} -+ -+static int hd44780_validate_driver(void) -+{ -+ if (par.cntr_rows != 1 && par.cntr_rows != 2 && par.cntr_rows != 4) -+ par.cntr_rows = DFLT_CNTR_ROWS; -+ -+ if (par.cntr_rows != 1) -+ par.flags &= ~HD44780_5X10_FONT; -+ -+ -+ if (! par.cntr_cols || par.cntr_cols > MAX_CNTR_COLS/par.cntr_rows) -+ par.cntr_cols = MAX_CNTR_COLS/par.cntr_rows; -+ -+ disp_size = par.cntr_rows*par.cntr_cols; -+ -+ /* These parameters depend on the hardware and cannot be changed */ -+ par.cgram_chars = 8; -+ par.cgram_bytes = 8; -+ par.cgram_char0 = 0; -+ -+ return (0); -+} -+ -+/* Send init commands to the display */ -+static void write_init_command(void) -+{ -+ unsigned char command = 0x30; -+ -+ __write_display(HIGH_NIBBLE_WRITE(command), ACCESS_TO_WRITE); -+ mdelay(20); /* Wait more than 4.1 ms */ -+ __write_display(HIGH_NIBBLE_WRITE(command), ACCESS_TO_WRITE); -+ udelay(200); /* Wait more than 100 us */ -+ __write_display(HIGH_NIBBLE_WRITE(command), ACCESS_TO_WRITE); -+ udelay(200); /* Wait more than 100 us */ -+ command = BUS_4_BITS; -+ command |= ((par.cntr_rows == 1) ? DISP_1_LINE : DISP_2_LINES); -+ command |= (test_bit(_5X10_FONT, &hd44780_flags) ? FONT_5X10 : FONT_5X8); -+ write_command(command); -+ /* set_bit(BACKLIGHT, &hd44780_flags); */ -+} -+ -+static int hd44780_init_display(void) -+{ -+ if (par.flags & HD44780_CHECK_BF) -+ set_bit(_CHECK_BF, &hd44780_flags); -+ else -+ clear_bit(_CHECK_BF, &hd44780_flags); -+ -+ if (par.flags & HD44780_4BITS_BUS) -+ set_bit(_4BITS_BUS, &hd44780_flags); -+ else -+ clear_bit(_4BITS_BUS, &hd44780_flags); -+ -+ if (par.flags & HD44780_5X10_FONT) -+ set_bit(_5X10_FONT, &hd44780_flags); -+ else -+ clear_bit(_5X10_FONT, &hd44780_flags); -+ -+ write_init_command(); -+ -+ hd44780_clear_display(); -+ hd44780_address_mode(1); -+ write_command(DISP_ON | CURS_OFF | BLINK_OFF); -+ set_bit(DISPLAY_ON, &hd44780_flags); -+ clear_bit(SHOW_CURSOR, &hd44780_flags); -+ clear_bit(CURSOR_BLINK, &hd44780_flags); -+ -+ /* Set the CGRAM to default values */ -+ hd44780_write_cgram_char(0, cg0); -+ hd44780_write_cgram_char(1, cg1); -+ hd44780_write_cgram_char(2, cg2); -+ hd44780_write_cgram_char(3, cg3); -+ hd44780_write_cgram_char(4, cg4); -+ hd44780_write_cgram_char(5, cg5); -+ hd44780_write_cgram_char(6, cg6); -+ hd44780_write_cgram_char(7, cg7); -+ init_charmap(); -+ -+ return (0); -+} -+ -+static int hd44780_cleanup_display(void) -+{ -+ hd44780_clear_display(); -+ -+ return (0); -+} -+ -+static int hd44780_init_port(void) -+{ -+ gpio_direction_output (SIMONE_LCD_BCKLIGHT, 0); -+ gpio_direction_output (SIMONE_LCD_RD , 0); -+ gpio_direction_output (SIMONE_LCD_RS , 0); -+ gpio_direction_output (SIMONE_LCD_EN , 0); -+ gpio_set_value(SIMONE_LCD_EN, 0); /* Disable */ -+ -+ return (0); -+} -+ -+static int hd44780_cleanup_port(void) -+{ -+ -+ gpio_direction_input (SIMONE_LCD_BCKLIGHT); -+ gpio_direction_input (SIMONE_LCD_RD); -+ gpio_direction_input (SIMONE_LCD_RS); -+ gpio_direction_input (SIMONE_LCD_EN); -+ gpio_direction_input (SIMONE_LCD_DATA0); -+ gpio_direction_input (SIMONE_LCD_DATA1); -+ gpio_direction_input (SIMONE_LCD_DATA2); -+ gpio_direction_input (SIMONE_LCD_DATA3); -+ return (0); -+} -+ -+static void display_attr(unsigned char input) -+{ -+ unsigned char command; -+ -+ switch (ESC_STATE) { -+ case 'a': /* Turn on/off the display cursor */ -+ if (input == '1') -+ set_bit(SHOW_CURSOR, &hd44780_flags); -+ else if (input == '0') -+ clear_bit(SHOW_CURSOR, &hd44780_flags); -+ break; -+ case 'b': /* Turn on/off the display cursor blinking */ -+ if (input == '1') -+ set_bit(CURSOR_BLINK, &hd44780_flags); -+ else if (input == '0') -+ clear_bit(CURSOR_BLINK, &hd44780_flags); -+ break; -+ case 'h': /* Turn on/off the display */ -+ if (input == '1') -+ set_bit(DISPLAY_ON, &hd44780_flags); -+ else if (input == '0') -+ clear_bit(DISPLAY_ON, &hd44780_flags); -+ break; -+ } -+ -+ command = (test_bit(DISPLAY_ON, &hd44780_flags) ? DISP_ON : DISP_OFF); -+ command |= (test_bit(SHOW_CURSOR, &hd44780_flags) ? CURS_ON : CURS_OFF); -+ command |= (test_bit(CURSOR_BLINK, &hd44780_flags) ? BLINK_ON : BLINK_OFF); -+ -+ if (ESC_STATE == 'h') -+ write_command(command); -+} -+ -+static int hd44780_handle_custom_char(unsigned int _input) -+{ -+ unsigned char input = _input & 0xff; -+ -+ if (_input & (~0xff)) { -+ switch (ESC_STATE) { -+ case 'a': /* Turn on/off the display cursor */ -+ case 'b': /* Turn on/off the display cursor blinking */ -+ case 'h': /* Turn on/off the the display */ -+ display_attr(input); -+ return (0); -+ case 'l': /* Turn on/off the backlight */ -+ if (input == '1') -+ set_bit(BACKLIGHT, &hd44780_flags); -+ else if (input == '0') -+ clear_bit(BACKLIGHT, &hd44780_flags); -+ read_ac(ACCESS_TO_READ); -+ return (0); -+ } -+ } -+ -+ switch (input) { -+ case 'a': /* Turn on/off the display cursor */ -+ case 'b': /* Turn on/off the display cursor blinking */ -+ case 'h': /* Turn on/off the display */ -+ case 'l': /* Turn on/off the backlight */ -+ SET_ESC_STATE(input); -+ return (1); -+ case 'd': /* Shift display cursor Right */ -+ write_command(SHIFT_CURS | SHIFT_RIGHT); -+ return (0); -+ case 'e': /* Shift display cursor Left */ -+ write_command(SHIFT_CURS | SHIFT_LEFT); -+ return (0); -+ case 'f': /* Shift display Right */ -+ write_command(SHIFT_DISP | SHIFT_RIGHT); -+ return (0); -+ case 'g': /* Shift display Left */ -+ write_command(SHIFT_DISP | SHIFT_LEFT); -+ return (0); -+ } -+ -+ return (-1); -+} -+ -+static int hd44780_handle_custom_ioctl(unsigned int num, unsigned long arg, unsigned int user_space) -+{ -+ unsigned char *buffer = (unsigned char *)arg; -+ -+ if (num != HD44780_READ_AC) -+ return (-ENOIOCTLCMD); -+ -+ if (user_space) -+ put_user(read_ac(ACCESS_TO_READ), buffer); -+ else -+ buffer[0] = read_ac(ACCESS_TO_READ); -+ -+ return (0); -+} -+ -+#ifdef USE_PROC -+static int hd44780_proc_status(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ -+ /* Print display configuration */ -+ temp += sprintf(temp, -+ "Interface:\t%u bits\n" -+ "Display rows:\t%d\n" -+ "Display cols:\t%d\n" -+ "Screen rows:\t%d\n" -+ "Screen cols:\t%d\n" -+ "Read:\t\t%sabled\n" -+ "Busy flag chk:\t%sabled\n" -+ "Assigned minor:\t%u\n", -+ (test_bit(_4BITS_BUS, &hd44780_flags) ? 4 : 8), -+ par.cntr_rows, par.cntr_cols, -+ par.vs_rows, par.vs_cols, -+ (hd44780.read_char ? "En" : "Dis"), -+ (test_bit(_CHECK_BF, &hd44780_flags) ? "En" : "Dis"), -+ par.minor); -+ -+ return (temp-buffer); -+} -+ -+static int hd44780_proc_cgram(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ unsigned int i; -+ -+ temp += sprintf(temp, "static void init_charmap(void)\n{\n" -+ "\t/*\n" -+ "\t * charmap[char mapped to cg0] = 0;\n" -+ "\t * charmap[char mapped to cg1] = 1;\n" -+ "\t * charmap[char mapped to cg2] = 2;\n" -+ "\t * charmap[char mapped to cg3] = 3;\n" -+ "\t * charmap[char mapped to cg4] = 4;\n" -+ "\t * charmap[char mapped to cg5] = 5;\n" -+ "\t * charmap[char mapped to cg6] = 6;\n" -+ "\t * charmap[char mapped to cg7] = 7;\n" -+ "\t */\n" -+ "}\n\n"); -+ -+ for (i = 0; i < 8; ++i) { -+ unsigned char cgram_buffer[8]; -+ unsigned int j; -+ -+ temp += sprintf(temp, "static unsigned char cg%u[] = { ", i); -+ hd44780_read_cgram_char(i, cgram_buffer); -+ for (j = 0; j < 8; ++j) -+ temp += sprintf(temp, "0x%.2x%s", cgram_buffer[j], (j == 7 ? " };\n" : ", ")); -+ } -+ -+ return (temp-buffer); -+} -+ -+static void create_proc_entries(void) -+{ -+ int count = 0; -+ -+ SET_PROC_LEVEL(count); -+ if (create_proc_read_entry("status", 0, hd44780.driver_proc_root, hd44780_proc_status, NULL) == NULL) { -+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/status\n", par.name); -+ return; -+ } -+ SET_PROC_LEVEL(++count); -+ if (hd44780.read_cgram_char) { -+ if (create_proc_read_entry("cgram.h", 0, hd44780.driver_proc_root, hd44780_proc_cgram, NULL) == NULL) { -+ printk(KERN_ERR "hd44780: cannot create /proc/lcd/%s/cgram.h\n", par.name); -+ return; -+ } -+ SET_PROC_LEVEL(++count); -+ } -+} -+ -+static void remove_proc_entries(void) -+{ -+ switch (PROC_LEVEL) { -+ case 2: -+ remove_proc_entry("cgram.h", hd44780.driver_proc_root); -+ case 1: -+ remove_proc_entry("status", hd44780.driver_proc_root); -+ } -+ SET_PROC_LEVEL(0); -+} -+#endif -+ -+/* Initialization */ -+static int __init hd44780_init_module(void) -+{ -+ int ret; -+ -+#ifdef MODULE -+#ifdef NOT_DEF -+ if ((ret = request_module("lcd-linux"))) { -+ if (ret != -ENOSYS) { -+ printk(KERN_ERR "hd44780: failure while loading module lcd-linux\n"); -+ return (ret); -+ } -+ printk(KERN_ERR "hd44780: your kernel does not have kmod or kerneld support;\n"); -+ printk(KERN_ERR "hd44780: remember to load the lcd-linux module before\n"); -+ printk(KERN_ERR "hd44780: loading the hd44780 module\n"); -+ } -+#endif -+ if (flags != DFLT_FLAGS) par.flags = flags; -+ if (tabstop != DFLT_TABSTOP) par.tabstop = tabstop; -+ if (cntr_rows != DFLT_CNTR_ROWS) par.cntr_rows = cntr_rows; -+ if (cntr_cols != DFLT_CNTR_COLS) par.cntr_cols = cntr_cols; -+ if (vs_rows != DFLT_VS_ROWS) par.vs_rows = vs_rows; -+ if (vs_cols != DFLT_VS_COLS) par.vs_cols = vs_cols; -+ if (minor != HD44780_MINOR) par.minor = minor; -+#endif -+ -+ lcd_driver_setup(&hd44780); -+ if ((ret = lcd_register_driver(&hd44780, &par))) -+ return (ret); -+ -+#ifdef USE_PROC -+ if (hd44780.driver_proc_root) -+ create_proc_entries(); -+#endif -+ -+ printk(KERN_INFO "HD44780 driver (LCD-Linux" HD44780_VERSION ")\n"); -+ printk(KERN_INFO "Nuccio Raciti <raciti.nuccio@gmail.com>\n"); -+ -+ -+ return (0); -+} -+ -+/* Cleanup */ -+ -+static void __exit hd44780_cleanup_module(void) -+{ -+#ifdef USE_PROC -+ if (hd44780.driver_proc_root) -+ remove_proc_entries(); -+#endif -+ -+ lcd_unregister_driver(&hd44780, &par); -+} -+ -+module_init(hd44780_init_module) -+module_exit(hd44780_cleanup_module) -Index: linux-2.6.30.9/drivers/lcd-linux/lcd-linux.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/lcd-linux/lcd-linux.c 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,2892 @@ -+/* lcd-linux.c -+ * -+ * -+ * -+ * Software layer to drive LCD displays under Linux. -+ * -+ * Copyright (C) 2005 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#include <linux/version.h> -+ -+#ifndef KERNEL_VERSION -+#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) -+#endif -+ -+#ifndef LINUX_VERSION_CODE -+#error - LINUX_VERSION_CODE undefined in 'linux/version.h' -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+#include <linux/autoconf.h> -+#else -+#include <linux/config.h> -+#endif -+#ifdef CONFIG_PROC_FS -+#define USE_PROC -+#else -+#undef USE_PROC -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -+#include <linux/semaphore.h> -+#else -+#include <asm/semaphore.h> -+#endif -+#include <linux/bitops.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/sched.h> -+ -+#include <linux/fs.h> -+ -+#include <asm/uaccess.h> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+#include <linux/device.h> -+#endif -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/slab.h> -+#include <linux/selection.h> -+#include <linux/vmalloc.h> -+ -+#ifdef USE_PROC -+#include <linux/proc_fs.h> -+#endif -+ -+#define LCD_LINUX_MAIN -+#include <linux/lcd-linux.h> -+ -+/*** struct_flags ***/ -+#define NEED_WRAP 0 /* Next char will trigger a newline */ -+#define DECIM 1 /* Insert mode */ -+#define DECAWM 2 /* Autowrap */ -+#define DECSCNM 3 /* Inverted screen */ -+#define CRLF 4 /* Follow lf, vt, ff, with a cr */ -+#define INC_CURS_POS 5 /* Increment cursor position after data read/write */ -+#define QUES 6 /* CSI Esc sequence contains a question mark */ -+#define USER_SPACE 7 /* If set, the buffer pointed by arg in do_lcd_ioctl() is -+ * assumed to be in user space otherwise it is in kernel space */ -+#define NULL_CHARMAP 8 /* The driver doesn't provide a charmap so the -+ * lcd-linux layer provides one*/ -+#define CAN_DO_COLOR 9 /* The display is color capable */ -+#define WITH_ATTR 10 /* If set, the void * buffer in do_lcd_read/write() contains -+ * attributes and therefore is an unsigned short * otherwise it -+ * is an unsigned char * -+ */ -+ -+/*** attributes ***/ -+#define I_MASK 0x03 /* Intensity (0 = low, 1 = normal, 2 = bright) */ -+#define ULINE 0x04 /* Underlined text */ -+#define REVERSE 0x08 /* Reversed video text */ -+#define BLINK 0x80 /* Blinking text */ -+ -+/*** Color attributes ***/ -+#define FG_MASK 0x0f /* Foreground color */ -+#define BG_MASK 0xf0 /* Background color */ -+ -+/* input states */ -+#define NORMAL 0x00001000 /* Normal mode */ -+#define RAW 0x00002000 /* Raw mode (console emulation disabled) */ -+#define SYN 0x00003000 /* Synchronous Idle mode */ -+#define ESC 0x00004000 /* Escape mode */ -+#define CSI 0x00005000 /* CSI escape mode */ -+#define ESC_G0 0x00006000 /* G0 character set */ -+#define ESC_G1 0x00007000 /* G1 character set */ -+#define ESC_HASH 0x00008000 /* ESC # escape sequence */ -+#define ESC_PERCENT 0x00009000 /* ESC % escape sequence */ -+#define ARG 0x0000a000 /* Waiting for arguments for the lcd-linux layer */ -+#define ARG_DRIVER 0x0000b000 /* Waiting for arguments for the display driver */ -+#define INPUT_MASK 0x0000f000 -+#define ESC_MASK 0x00ff0000 -+#define INIT_MASK 0x0f000000 -+#define PROC_MASK 0xf0000000 -+ -+#define SET_STATE(p, state, mask) ((p)->struct_flags = ((p)->struct_flags & ~(mask)) | ((state) & (mask))) -+#define SET_INPUT_STATE(p, state) SET_STATE(p, state, INPUT_MASK) -+#define SET_ESC_STATE(p, state) SET_STATE(p, (state) << 16, ESC_MASK) -+#define SET_INIT_LEVEL(p, level) SET_STATE(p, (level) << 24, INIT_MASK) -+#define SET_PROC_LEVEL(p, level) SET_STATE(p, (level) << 28, PROC_MASK) -+#define INPUT_STATE(p) ((p)->struct_flags & INPUT_MASK) -+#define ESC_STATE(p) (((p)->struct_flags & ESC_MASK) >> 16) -+#define INIT_LEVEL(p) (((p)->struct_flags & INIT_MASK) >> 24) -+#define PROC_LEVEL(p) (((p)->struct_flags & PROC_MASK) >> 28) -+ -+#define NPAR 16 /* Max number of parameters in CSI escape sequence */ -+#define FLIP_BUF_SIZE (1 << 6) /* Flip buffer size (64 bytes) */ -+ -+struct lcd_struct { -+ struct list_head lcd_list; /* Doubly linked list */ -+ struct semaphore lcd_sem; /* Locks this structure */ -+ struct lcd_driver *driver; /* The driver associated to this struct */ -+ struct lcd_parameters *par; /* The parameters associated to this struct */ -+ unsigned long struct_flags; /* Flags for internal use only */ -+ unsigned int refcount; /* Number of references to this struct */ -+ -+ unsigned short *display; /* The display buffer */ -+ -+ unsigned short *fb; /* The virtual screen framebuffer */ -+ unsigned int fb_size; /* Size of the framebuffer */ -+ unsigned int frame_base; /* Offset of row 0, column 0 of a frame in fb */ -+ unsigned int frame_size; /* Size of the frame */ -+ -+ unsigned int row; /* Current row in virtual screen */ -+ unsigned int col; /* Current column in virtual screen */ -+ unsigned int s_offset; /* Saved cursor position in virtual screen */ -+ -+ unsigned int top; /* Top scroll row in virtual screen */ -+ unsigned int bot; /* Bottom scroll row in virtual screen */ -+ -+ int esc_args; /* Number of arguments for a normal escape sequence */ -+ unsigned int csi_args[NPAR]; /* CSI parameters */ -+ unsigned int index; /* Index in csi_args and counter for cgram characters generation */ -+ unsigned char cgram_index; /* Index of the cgram character to be created */ -+ unsigned char *cgram_buffer; /* Buffer for cgram operations in this driver */ -+ -+ unsigned short erase_char; /* Character to be used when erasing */ -+ unsigned char attr; /* Current attributes */ -+ unsigned char color; /* Color for normal intensity mode */ -+ unsigned char s_color; /* Saved color for normal intensity mode */ -+ unsigned char defcolor; /* Default color for normal intensity mode */ -+ unsigned char ulcolor; /* Color for underline mode */ -+ unsigned char halfcolor; /* Color for low intensity mode */ -+ unsigned char attributes; /* Packed attributes */ -+ unsigned char s_attributes; /* Saved packed attributes */ -+ -+ unsigned char *s_charmap; /* Saved character map for this driver */ -+ unsigned char *flip_buf; /* High speed flip buffer */ -+}; -+ -+/** Function prototypes **/ -+ -+/* Init/Cleanup the driver */ -+static int init_driver(struct lcd_struct *); -+static int cleanup_driver(struct lcd_struct *); -+ -+/* Read from/Write to the driver */ -+static void read_data(struct lcd_struct *, unsigned short *); -+static void read_cgram(struct lcd_struct *, unsigned char, unsigned char *); -+static void write_data(struct lcd_struct *, unsigned short); -+static void write_cgram(struct lcd_struct *, unsigned char, unsigned char *); -+ -+/* Input handlers */ -+static void cr(struct lcd_struct *); -+static void lf(struct lcd_struct *); -+static void control_char(struct lcd_struct *, unsigned char); -+static void handle_csi(struct lcd_struct *, unsigned char); -+static int handle_custom_esc(struct lcd_struct *, unsigned int); -+static int handle_esc(struct lcd_struct *, unsigned char); -+static void handle_input(struct lcd_struct *, unsigned short); -+ -+/* Low level file operations */ -+static ssize_t do_lcd_read(struct lcd_struct *, void *, size_t); -+static ssize_t do_lcd_write(struct lcd_struct *, const void *, size_t); -+static int do_lcd_open(struct lcd_struct *); -+static int do_lcd_release(struct lcd_struct *); -+static int do_lcd_ioctl(struct lcd_struct *, unsigned int, unsigned long); -+ -+/* Proc functions */ -+#ifdef USE_PROC -+static void create_driver_proc_entries(struct lcd_struct *); -+static void remove_driver_proc_entries(struct lcd_struct *); -+#endif -+ -+/* globals */ -+static unsigned int major = LCD_MAJOR; /* Major number for LCD-Linux device */ -+static unsigned short minors = LCD_MINORS; /* Minor numbers allocated for LCD-Linux */ -+static LIST_HEAD(lcd_drivers); /* Registered lcd drivers */ -+static struct semaphore drivers_sem; /* Locks the lcd_drivers list */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+static struct class *lcd_linux_class; -+#endif -+#ifdef USE_PROC -+static struct proc_dir_entry *lcd_proc_root; -+#endif -+/* End of globals */ -+ -+#ifdef MODULE -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+#include <linux/device.h> -+MODULE_ALIAS_CHARDEV_MAJOR(LCD_MAJOR); -+#endif -+MODULE_DESCRIPTION("Software layer to drive LCD displays under Linux."); -+MODULE_AUTHOR("Mattia Jona-Lasinio <mjona@users.sourceforge.net>"); -+#ifdef MODULE_LICENSE -+MODULE_LICENSE("GPL"); -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+module_param(minors, ushort, 0444); -+#else -+MODULE_PARM(minors, "h"); -+#endif -+MODULE_PARM_DESC(minors, "Minor numbers allocated for LCD-Linux (default: " string(LCD_MINORS) ")"); -+#else -+ -+/* -+ * Parse boot command line -+ * -+ * lcd=minors -+ */ -+static int __init lcd_linux_boot_init(char *cmdline) -+{ -+ unsigned short args; -+ -+ if ((args = simple_strtoul(cmdline, NULL, 0))) -+ minors = args; -+ -+ return (1); -+} -+ -+__setup("lcd=", lcd_linux_boot_init); -+#endif /* MODULE */ -+ -+/* Macros for iterator handling */ -+static inline unsigned int iterator_inc_(unsigned int iterator, const unsigned int module) -+{ -+ return ((++iterator)%module); -+} -+ -+static inline unsigned int iterator_dec_(unsigned int iterator, const unsigned int module) -+{ -+ return (iterator ? --iterator : module-1); -+} -+ -+#define iterator_inc(iterator, module) (iterator = iterator_inc_(iterator, module)) -+#define iterator_dec(iterator, module) (iterator = iterator_dec_(iterator, module)) -+ -+/* Uncomment the following two lines -+ * for non-atomic set_bit and clear_bit -+#define set_bit __set_bit -+#define clear_bit __clear_bit -+*/ -+ -+/************************************ -+ * Low level routines and utilities * -+ ************************************/ -+/* -+ * Set whether the address counter should be incremented -+ * or decremented after a Read/Write -+ */ -+static void address_mode(struct lcd_struct *p, int mode) -+{ -+ struct lcd_driver *driver = p->driver; -+ -+ if (mode > 0 && ! test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (driver->address_mode) -+ driver->address_mode(mode); -+ set_bit(INC_CURS_POS, &p->struct_flags); -+ } else if (mode < 0 && test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (driver->address_mode) -+ driver->address_mode(mode); -+ clear_bit(INC_CURS_POS, &p->struct_flags); -+ } -+} -+ -+/* WARNING!! This function returns an int because if iterator is not -+ * within the visible area of the frame it returns -1 -+ */ -+static inline int vs_to_frame_(struct lcd_struct *p, unsigned int iterator) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int row = iterator/vs_cols; -+ unsigned int col = iterator%vs_cols; -+ unsigned int frame_base_row = p->frame_base/vs_cols; -+ unsigned int frame_base_col = p->frame_base%vs_cols; -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr; -+ unsigned int frame_cols = p->par->cntr_cols; -+ -+ if (row < frame_base_row || row >= frame_base_row+frame_rows) -+ return (-1); -+ if (col < frame_base_col || col >= frame_base_col+frame_cols) -+ return (-1); -+ -+ return ((row-frame_base_row)*frame_cols+(col-frame_base_col)); -+} -+ -+/* Given 'iterator' in vs, returns the offset in vs corresponding to the nearest -+ * visible offset in vs, or returns 'iterator' if it is already visible. -+ */ -+static unsigned int round_vs_(struct lcd_struct *p, unsigned int iterator) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int row = iterator/vs_cols; -+ unsigned int col = iterator%vs_cols; -+ unsigned int frame_base_row = p->frame_base/vs_cols; -+ unsigned int frame_base_col = p->frame_base%vs_cols; -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr; -+ unsigned int frame_cols = p->par->cntr_cols; -+ -+ if (row < frame_base_row) -+ row = frame_base_row; -+ else if (row >= frame_base_row+frame_rows) -+ row = frame_base_row+(frame_rows-1); -+ -+ if (col < frame_base_col) -+ col = frame_base_col; -+ else if (col >= frame_base_col+frame_cols) -+ col = frame_base_col+(frame_cols-1); -+ -+ return ((row*vs_cols)+col); -+} -+ -+#define round_vs(p, iterator) (iterator = round_vs_(p, iterator)) -+ -+/* -+ * Sync the frame area starting at offset s, ending at offset e with fb content. -+ */ -+static void redraw_screen(struct lcd_struct *p, unsigned int s, unsigned int e) -+{ -+ unsigned int len; -+ unsigned int row = p->row, col = p->col; -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags); -+ unsigned int frame_cols = p->par->cntr_cols; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned long flags; -+ -+ if (s >= p->fb_size || e >= p->fb_size || e < s || e < p->frame_base) -+ return; -+ -+ round_vs(p, s); -+ round_vs(p, e); -+ -+ len = 1+e-s; -+ -+ if (! inc_set) -+ s = e; -+ -+ p->row = s/vs_cols; -+ p->col = s%vs_cols; -+ -+ flags = p->struct_flags; -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ clear_bit(DECIM, &p->struct_flags); -+ set_bit(DECAWM, &p->struct_flags); -+ SET_INPUT_STATE(p, RAW); -+ if (inc_set) -+ while (len--) -+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) { -+ s += vs_cols-frame_cols; -+ len -= vs_cols-frame_cols-1; -+ p->row = s/vs_cols; -+ p->col = s%vs_cols; -+ } else { -+ write_data(p, p->fb[s++]); -+ if (test_bit(NEED_WRAP, &p->struct_flags)) { -+ cr(p); -+ lf(p); -+ } -+ } -+ else -+ while (len--) -+ if (vs_to_frame_(p, (p->row*vs_cols)+p->col) < 0) { -+ s -= vs_cols-frame_cols; -+ len -= vs_cols-frame_cols-1; -+ p->row = s/vs_cols; -+ p->col = s%vs_cols; -+ } else { -+ write_data(p, p->fb[s--]); -+ if (test_bit(NEED_WRAP, &p->struct_flags)) { -+ cr(p); -+ lf(p); -+ } -+ } -+ p->struct_flags = flags; -+ -+ p->row = row; p->col = col; -+} -+ -+static int make_cursor_visible(struct lcd_struct *p) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int frame_base, frame_base_row, frame_base_col; -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr; -+ unsigned int frame_cols = p->par->cntr_cols; -+ unsigned int tmp = frame_cols/2; -+ -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ /* cursor always on the lowest row of the display */ -+ frame_base_row = 0; -+ frame_base_col = 0; -+ if (p->row >= frame_rows) -+ frame_base_row = p->row-(frame_rows-1); -+ if (p->col >= frame_cols) { -+ frame_base_col = p->col-(frame_cols-1); -+ if (tmp) { -+ tmp = (tmp-(frame_base_col%tmp))%tmp; -+ if (frame_base_col+tmp <= vs_cols-frame_cols) -+ frame_base_col += tmp; -+ } -+ } -+ } else { -+ /* cursor always on the uppermost row of the display */ -+ frame_base_row = vs_rows-frame_rows; -+ frame_base_col = vs_cols-frame_cols; -+ if (p->row < vs_rows-frame_rows) -+ frame_base_row = p->row; -+ if (p->col < vs_cols-frame_cols) { -+ frame_base_col = p->col; -+ if (tmp) { -+ tmp = frame_base_col%tmp; -+ if (frame_base_col >= tmp) -+ frame_base_col -= tmp; -+ } -+ } -+ } -+ -+ frame_base = p->frame_base; -+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col; -+ -+ return (frame_base != p->frame_base); -+} -+ -+/* -+ * Move the visible screen area at user's wish -+ */ -+static void browse_screen(struct lcd_struct *p, unsigned char dir) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int frame_base_row = p->frame_base/vs_cols; -+ unsigned int frame_base_col = p->frame_base%vs_cols; -+ unsigned int frame_rows = p->par->cntr_rows*p->par->num_cntr; -+ unsigned int frame_cols = p->par->cntr_cols; -+ -+ switch (dir) { -+ case '1': /* Up */ -+ if (! frame_base_row) -+ return; -+ --frame_base_row; -+ break; -+ case '2': /* Down */ -+ if (frame_base_row >= vs_rows-frame_rows) -+ return; -+ ++frame_base_row; -+ break; -+ case '3': /* Left */ -+ if (! frame_base_col) -+ return; -+ --frame_base_col; -+ break; -+ case '4': /* Right */ -+ if (frame_base_col >= vs_cols-frame_cols) -+ return; -+ ++frame_base_col; -+ break; -+ default: -+ return; -+ } -+ -+ p->frame_base = (frame_base_row*vs_cols)+frame_base_col; -+ redraw_screen(p, 0, p->fb_size-1); -+} -+ -+static inline void __memset_short(unsigned short *buf, unsigned short c, unsigned int len) -+{ -+ while (len--) -+ *buf++ = c; -+} -+ -+/* -+ * A memset implementation writing to LCD instead of memory locations. -+ */ -+static void lcd_memset(struct lcd_struct *p, unsigned int d, unsigned short c, unsigned int len) -+{ -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags); -+ -+ if (! len || d >= p->fb_size) -+ return; -+ -+ if (inc_set && d+len > p->fb_size) -+ len = p->fb_size-d; -+ else if (! inc_set && len > d+1) -+ len = d+1; -+ -+ if (! inc_set) -+ d -= len-1; -+ __memset_short(p->fb+d, c, len); -+ -+ if (make_cursor_visible(p)) -+ redraw_screen(p, 0, p->fb_size-1); -+ else -+ redraw_screen(p, d, d+(len-1)); -+} -+ -+static inline void __memcpy_short(unsigned short *d, unsigned short *s, unsigned int len, int dir) -+{ -+ if (dir > 0) -+ while (len--) -+ *d++ = *s++; -+ else -+ while (len--) -+ *d-- = *s--; -+} -+ -+/* -+ * A memmove implementation writing to LCD instead of memory locations. -+ * Copy is done in a non destructive way. Display regions may overlap. -+ */ -+static void lcd_memmove(struct lcd_struct *p, unsigned int d, unsigned int s, unsigned int len) -+{ -+ if (! len || d == s || d >= p->fb_size || s >= p->fb_size) -+ return; -+ -+ if (d < s) { -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (s+len > p->fb_size) -+ len = p->fb_size-s; -+ } else { -+ if (len > d+1) -+ len = d+1; -+ d -= len-1; -+ s -= len-1; -+ } -+ __memcpy_short(p->fb+d, p->fb+s, len, 1); -+ if (make_cursor_visible(p)) -+ redraw_screen(p, 0, p->fb_size-1); -+ else -+ redraw_screen(p, d, d+(len-1)); -+ } else { -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (d+len > p->fb_size) -+ len = p->fb_size-d; -+ d += len-1; -+ s += len-1; -+ } else { -+ if (len > s+1) -+ len = s+1; -+ } -+ __memcpy_short(p->fb+d, p->fb+s, len, -1); -+ if (make_cursor_visible(p)) -+ redraw_screen(p, 0, p->fb_size-1); -+ else -+ redraw_screen(p, d-(len-1), d); -+ } -+} -+ -+static void scrup(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int d, s; -+ -+ if (t+nr >= b) -+ nr = b-t-1; -+ if (b > vs_rows || t >= b || nr < 1) -+ return; -+ d = t*vs_cols; -+ s = (t+nr)*vs_cols; -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols); -+ lcd_memset(p, d+(b-t-nr)*vs_cols, p->erase_char, nr*vs_cols); -+ } else { -+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols); -+ lcd_memset(p, d+(b-t)*vs_cols-1, p->erase_char, nr*vs_cols); -+ } -+} -+ -+static void scrdown(struct lcd_struct *p, unsigned int t, unsigned int b, unsigned int nr) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int d, s; -+ -+ if (t+nr >= b) -+ nr = b-t-1; -+ if (b > vs_rows || t >= b || nr < 1) -+ return; -+ s = t*vs_cols; -+ d = (t+nr)*vs_cols; -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ lcd_memmove(p, d, s, (b-t-nr)*vs_cols); -+ lcd_memset(p, s, p->erase_char, nr*vs_cols); -+ } else { -+ lcd_memmove(p, d+(b-t-nr)*vs_cols-1, s+(b-t-nr)*vs_cols-1, (b-t-nr)*vs_cols); -+ lcd_memset(p, s+nr*vs_cols-1, p->erase_char, nr*vs_cols); -+ } -+} -+ -+static void lcd_insert_char(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int pos = (p->row*vs_cols)+p->col; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) -+ lcd_memmove(p, pos+nr, pos, vs_cols-p->col-nr); -+ else -+ lcd_memmove(p, pos-nr, pos, p->col-(nr-1)); -+ lcd_memset(p, pos, p->erase_char, nr); -+} -+ -+static void lcd_delete_char(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int pos = (p->row*vs_cols)+p->col; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ lcd_memmove(p, pos, pos+nr, vs_cols-(p->col+nr)); -+ lcd_memset(p, (p->row+1)*vs_cols-nr, p->erase_char, nr); -+ } else { -+ lcd_memmove(p, pos, pos-nr, p->col-(nr-1)); -+ lcd_memset(p, (p->row*vs_cols)+(nr-1), p->erase_char, nr); -+ } -+} -+ -+ -+ -+ -+ -+/****************************************************************************** -+ ************************* VT 102 Emulation ************************* -+ ******************************************************************************/ -+ -+/********************** -+ * Control characters * -+ **********************/ -+static void bs(struct lcd_struct *p) -+{ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (p->col) -+ --p->col; -+ } else { -+ if (p->col+1 < p->par->vs_cols) -+ ++p->col; -+ } -+} -+ -+static void cr(struct lcd_struct *p) -+{ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ p->col = (test_bit(INC_CURS_POS, &p->struct_flags) ? 0 : p->par->vs_cols-1); -+} -+ -+static void lf(struct lcd_struct *p) -+{ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (p->row+1 == p->bot && INPUT_STATE(p) != RAW) { -+ make_cursor_visible(p); -+ scrup(p, p->top, p->bot, 1); -+ } else if (p->row+1 < p->par->vs_rows) -+ ++p->row; -+ } else { -+ if (p->row == p->top && INPUT_STATE(p) != RAW) { -+ make_cursor_visible(p); -+ scrdown(p, p->top, p->bot, 1); -+ } else if (p->row) -+ --p->row; -+ } -+} -+ -+static void ri(struct lcd_struct *p) -+{ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (p->row == p->top) { -+ make_cursor_visible(p); -+ scrdown(p, p->top, p->bot, 1); -+ } else if (p->row) -+ --p->row; -+ } else { -+ if (p->row+1 == p->bot) { -+ make_cursor_visible(p); -+ scrup(p, p->top, p->bot, 1); -+ } else if (p->row+1 < p->par->vs_rows) -+ ++p->row; -+ } -+} -+ -+static void ff(struct lcd_struct *p) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (p->driver->clear_display) { -+ p->driver->clear_display(); -+ __memset_short(p->fb, p->erase_char, p->fb_size); -+ __memset_short(p->display, p->erase_char, p->frame_size); -+ p->frame_base = 0; -+ } else if (test_bit(INC_CURS_POS, &p->struct_flags)) -+ lcd_memset(p, 0, p->erase_char, p->fb_size); -+ else -+ lcd_memset(p, p->fb_size-1, p->erase_char, p->fb_size); -+ -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) -+ p->row = p->col = 0; -+ else { -+ p->row = vs_rows-1; -+ p->col = vs_cols-1; -+ } -+} -+ -+static void tab(struct lcd_struct *p) -+{ -+ struct lcd_parameters *par = p->par; -+ unsigned int i, vs_cols = par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ -+ if (! par->tabstop) -+ return; -+ -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ i = par->tabstop-(p->col%par->tabstop); -+ if (p->col+i < vs_cols) -+ p->col += i; -+ } else { -+ i = p->col%par->tabstop; -+ i = (i == 0 ? par->tabstop : i); -+ if (p->col >= i) -+ p->col -= i; -+ } -+} -+ -+/* -+ * Control character handler. -+ */ -+static void control_char(struct lcd_struct *p, unsigned char val) -+{ -+ switch (val) { -+ case 0x08: /* BS: Back Space (^H) */ -+ case 0x7f: /* DEL: Delete */ -+ bs(p); -+ return; -+ -+ case 0x09: /* HT: Horizontal Tab (^I) */ -+ tab(p); -+ return; -+ -+ case 0x0c: /* FF: Form Feed (^L) */ -+ ff(p); -+ return; -+ -+ case 0x0a: /* LF: Line Feed (^J) */ -+ case 0x0b: /* VT: Vertical Tab (^K) */ -+ lf(p); -+ if (! test_bit(CRLF, &p->struct_flags)) -+ return; -+ -+ case 0x0d: /* CR: Carriage Return (^M) */ -+ cr(p); -+ return; -+ -+ case 0x16: /* SYN: Synchronous Idle (^V) */ -+ SET_INPUT_STATE(p, SYN); -+ return; -+ -+ case 0x1b: /* ESC: Start of escape sequence */ -+ SET_INPUT_STATE(p, ESC); -+ return; -+ -+ case 0x9b: /* CSI: Start of CSI escape sequence */ -+ memset(p->csi_args, 0, sizeof(p->csi_args)); -+ p->index = 0; -+ SET_INPUT_STATE(p, CSI); -+ return; -+ } -+} -+ -+static void gotoxy(struct lcd_struct *p, int new_col, int new_row) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (new_row < 0) -+ p->row = 0; -+ else if (new_row >= vs_rows) -+ p->row = vs_rows-1; -+ else -+ p->row = new_row; -+ -+ if (new_col < 0) -+ p->col = 0; -+ else if (new_col >= vs_cols) -+ p->col = vs_cols-1; -+ else -+ p->col = new_col; -+ -+ if (make_cursor_visible(p)) -+ redraw_screen(p, 0, p->fb_size-1); -+} -+ -+ -+/****************************** -+ * ECMA-48 CSI ESC- sequences * -+ ******************************/ -+static void csi_at(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ if (p->col+nr > vs_cols) -+ nr = vs_cols-p->col; -+ else if (! nr) -+ ++nr; -+ lcd_insert_char(p, nr); -+} -+ -+static void csi_J(struct lcd_struct *p, unsigned int action) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int pos = (p->row*vs_cols)+p->col; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ switch (action) { -+ case 0: /* From cursor to end of display */ -+ lcd_memset(p, pos, p->erase_char, p->fb_size-pos); -+ return; -+ -+ case 1: /* From start of display to cursor */ -+ lcd_memset(p, 0, p->erase_char, pos+1); -+ return; -+ -+ case 2: /* Whole display */ -+ lcd_memset(p, 0, p->erase_char, p->fb_size); -+ return; -+ } -+} -+ -+static void csi_K(struct lcd_struct *p, unsigned int action) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int row_start = p->row*vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ switch (action) { -+ case 0: /* From cursor to end of line */ -+ lcd_memset(p, row_start+p->col, p->erase_char, vs_cols-p->col); -+ return; -+ -+ case 1: /* From start of line to cursor */ -+ lcd_memset(p, row_start, p->erase_char, p->col+1); -+ return; -+ -+ case 2: /* Whole line */ -+ lcd_memset(p, row_start, p->erase_char, vs_cols); -+ return; -+ } -+} -+ -+static void csi_L(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (p->row+nr > vs_rows) -+ nr = vs_rows-p->row; -+ else if (! nr) -+ ++nr;; -+ lcd_memmove(p, (p->row+nr)*vs_cols, p->row*vs_cols, (vs_rows-p->row-nr)*vs_cols); -+ lcd_memset(p, p->row*vs_cols, p->erase_char, nr*vs_cols); -+} -+ -+static void csi_M(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (p->row+nr > vs_rows) -+ nr = vs_rows-p->row; -+ else if (! nr) -+ ++nr;; -+ lcd_memmove(p, p->row*vs_cols, (p->row+nr)*vs_cols, (vs_rows-p->row-nr)*vs_cols); -+ lcd_memset(p, (vs_rows-nr)*vs_cols, p->erase_char, nr*vs_cols); -+} -+ -+static void csi_P(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ if (p->col+nr > vs_cols) -+ nr = vs_cols-p->col; -+ else if (! nr) -+ ++nr; -+ lcd_delete_char(p, nr); -+} -+ -+static void csi_X(struct lcd_struct *p, unsigned int nr) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (p->col+nr > vs_cols) -+ nr = vs_cols-p->col; -+ else if (! nr) -+ ++nr; -+ lcd_memset(p, (p->row*vs_cols)+p->col, p->erase_char, nr); -+} -+ -+static void csi_su(struct lcd_struct *p, unsigned char input) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ if (input == 'u') { -+ p->row = p->s_offset/vs_cols; -+ p->col = p->s_offset%vs_cols; -+ p->color = p->s_color; -+ p->attributes = p->s_attributes; -+ return; -+ } -+ p->s_offset = (p->row*vs_cols)+p->col; -+ p->s_color = p->color; -+ p->s_attributes = p->attributes; -+} -+ -+static unsigned char build_attr(struct lcd_struct *p, unsigned char color, unsigned char intensity, -+ unsigned char blink, unsigned char underline, unsigned char reverse) -+{ -+ unsigned char attr; -+ -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags)) { -+ attr = color; -+ if (underline) -+ attr = (attr & BG_MASK) | p->ulcolor; -+ else if (intensity == 0) -+ attr = (attr & BG_MASK) | p->halfcolor; -+ if (reverse) -+ attr = (attr & 0x88) | ((attr & 0x70) >> 4) | ((attr & 0x07) << 4); -+ if (blink) -+ attr ^= 0x80; -+ if (intensity == 2) -+ attr ^= 0x08; -+ } else { -+ attr = intensity; -+ attr |= (underline ? ULINE : 0x00); -+ attr |= (reverse ? REVERSE : 0x00); -+ attr |= (blink ? BLINK : 0x00); -+ } -+ -+ return (attr); -+} -+ -+static void update_attr(struct lcd_struct *p) -+{ -+ unsigned char intensity = p->attributes & 0x03; -+ unsigned char underline = (p->attributes >> 2) & 0x01; -+ unsigned char reverse = (p->attributes >> 3) & 0x01; -+ unsigned char blink = (p->attributes >> 7) & 0x01; -+ unsigned char decscnm = (p->struct_flags >> DECSCNM) & 0x01; -+ -+ p->attr = build_attr(p, p->color, intensity, blink, underline, reverse^decscnm); -+ p->erase_char = (build_attr(p, p->color, 1, blink, 0, decscnm) << 8) | ' '; -+} -+ -+static void default_attr(struct lcd_struct *p) -+{ -+ p->attributes = 0x01; -+ p->color = p->defcolor; -+} -+ -+static void lcd_invert_screen(struct lcd_struct *p, unsigned int offset, unsigned int len) -+{ -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags)) -+ while (len--) { -+ p->fb[offset] = (p->fb[offset] & 0x88ff) | ((p->fb[offset] & 0x7000) >> 4) | ((p->fb[offset] & 0x0700) << 4); -+ ++offset; -+ } -+ else -+ while (len--) { -+ p->fb[offset] ^= 0x0800; -+ ++offset; -+ } -+} -+ -+static void csi_m(struct lcd_struct *p, unsigned int n) -+{ -+ int i, arg; -+ -+ for (i = 0; i <= n; ++i) -+ switch ((arg = p->csi_args[i])) -+ { -+ case 0: -+ default_attr(p); -+ break; -+ -+ case 1: -+ p->attributes = (p->attributes & ~I_MASK) | 2; -+ break; -+ -+ case 2: -+ p->attributes = (p->attributes & ~I_MASK) | 0; -+ break; -+ -+ case 4: -+ p->attributes |= ULINE; -+ break; -+ -+ case 5: -+ p->attributes |= BLINK; -+ break; -+ -+ case 7: -+ p->attributes |= REVERSE; -+ break; -+ -+ case 21: case 22: -+ p->attributes = (p->attributes & ~I_MASK) | 1; -+ break; -+ -+ case 24: -+ p->attributes &= ~ULINE; -+ break; -+ -+ case 25: -+ p->attributes &= ~BLINK; -+ break; -+ -+ case 27: -+ p->attributes &= ~REVERSE; -+ break; -+ -+ case 38: -+ p->attributes |= ULINE; -+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK); -+ break; -+ -+ case 39: -+ p->attributes &= ~ULINE; -+ p->color = (p->color & BG_MASK) | (p->defcolor & FG_MASK); -+ break; -+ -+ case 49: -+ p->color = (p->defcolor & BG_MASK) | (p->color & FG_MASK); -+ break; -+ -+ default: -+ if (arg >= 30 && arg <= 37) -+ p->color = (p->color & BG_MASK) | color_table[arg-30]; -+ else if (arg >= 40 && arg <= 47) -+ p->color = (p->color & FG_MASK) | (color_table[arg-40] << 4); -+ break; -+ } -+ -+ update_attr(p); -+} -+ -+static void csi_h(struct lcd_struct *p, unsigned char n) -+{ -+ switch (n) { -+ case 4: /* Set insert mode */ -+ set_bit(DECIM, &p->struct_flags); -+ return; -+ -+ case 5: /* Inverted screen mode */ -+ if (test_bit(QUES, &p->struct_flags) && ! test_bit(DECSCNM, &p->struct_flags)) { -+ set_bit(DECSCNM, &p->struct_flags); -+ lcd_invert_screen(p, 0, p->fb_size); -+ update_attr(p); -+ redraw_screen(p, 0, p->fb_size-1); -+ } -+ return; -+ -+ case 7: /* Set autowrap */ -+ if (test_bit(QUES, &p->struct_flags)) -+ set_bit(DECAWM, &p->struct_flags); -+ return; -+ -+ case 20: /* Set cr lf */ -+ set_bit(CRLF, &p->struct_flags); -+ return; -+ } -+} -+ -+static void csi_l(struct lcd_struct *p, unsigned char n) -+{ -+ switch (n) { -+ case 4: /* Reset insert mode */ -+ clear_bit(DECIM, &p->struct_flags); -+ return; -+ -+ case 5: /* Normal screen mode */ -+ if (test_bit(QUES, &p->struct_flags) && test_bit(DECSCNM, &p->struct_flags)) { -+ clear_bit(DECSCNM, &p->struct_flags); -+ lcd_invert_screen(p, 0, p->fb_size); -+ update_attr(p); -+ redraw_screen(p, 0, p->fb_size-1); -+ } -+ return; -+ -+ case 7: /* Reset autowrap */ -+ if (test_bit(QUES, &p->struct_flags)) -+ clear_bit(DECAWM, &p->struct_flags); -+ return; -+ -+ case 20: /* Reset cr lf */ -+ clear_bit(CRLF, &p->struct_flags); -+ return; -+ } -+} -+ -+static void csi_linux(struct lcd_struct *p) -+{ -+ switch (p->csi_args[0]) { -+ case 1: -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) { -+ p->ulcolor = color_table[p->csi_args[1]]; -+ if (p->attributes & ULINE) -+ update_attr(p); -+ } -+ return; -+ -+ case 2: -+ if (test_bit(CAN_DO_COLOR, &p->struct_flags) && p->csi_args[1] < 16) { -+ p->halfcolor = color_table[p->csi_args[1]]; -+ if ((p->attributes & I_MASK) == 0) -+ update_attr(p); -+ } -+ return; -+ -+ case 8: -+ p->defcolor = p->color; -+ default_attr(p); -+ update_attr(p); -+ return; -+ } -+} -+ -+static void csi_r(struct lcd_struct *p, unsigned int top, unsigned int bot) -+{ -+ /* Minimum allowed region is 2 lines */ -+ if (top < bot) { -+ p->top = top-1; -+ p->bot = bot; -+ gotoxy(p, 0, 0); -+ } -+} -+ -+/* -+ * ECMA-48 CSI ESC- sequence handler. -+ */ -+static void handle_csi(struct lcd_struct *p, unsigned char input) -+{ -+ if (p->index >= NPAR) { -+ SET_INPUT_STATE(p, NORMAL); -+ printk(KERN_NOTICE "LCD: too many parameters in CSI escape sequence\n"); -+ } else if (input == '?') { -+ set_bit(QUES, &p->struct_flags); -+ } else if (input == ';') { -+ ++p->index; -+ } else if (input >= '0' && input <= '9') { -+ p->csi_args[p->index] = (p->csi_args[p->index]*10)+(input-'0'); -+ } else { -+ SET_INPUT_STATE(p, NORMAL); -+ if (! test_bit(INC_CURS_POS, &p->struct_flags)) -+ return; -+ switch (input) { -+ case 'h': /* DECSET sequences and mode switches */ -+ csi_h(p, p->csi_args[0]); -+ clear_bit(QUES, &p->struct_flags); -+ return; -+ -+ case 'l': /* DECRST sequences and mode switches */ -+ csi_l(p, p->csi_args[0]); -+ clear_bit(QUES, &p->struct_flags); -+ return; -+ } -+ clear_bit(QUES, &p->struct_flags); -+ switch (input) { -+ case '@': /* Insert # Blank character */ -+ csi_at(p, p->csi_args[0]); -+ return; -+ -+ case 'G': case '`': /* Cursor to indicated column in current row */ -+ if (p->csi_args[0]) -+ --p->csi_args[0]; -+ gotoxy(p, p->csi_args[0], p->row); -+ return; -+ -+ case 'A': /* Cursor # rows Up */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, p->col, p->row-p->csi_args[0]); -+ return; -+ -+ case 'B': case 'e': /* Cursor # rows Down */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, p->col, p->row+p->csi_args[0]); -+ return; -+ -+ case 'C': case 'a': /* Cursor # columns Right */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, p->col+p->csi_args[0], p->row); -+ return; -+ -+ case 'D': /* Cursor # columns Left */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, p->col-p->csi_args[0], p->row); -+ return; -+ -+ case 'E': /* Cursor # rows Down, column 1 */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, 0, p->row+p->csi_args[0]); -+ return; -+ -+ case 'F': /* Cursor # rows Up, column 1 */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ gotoxy(p, 0, p->row-p->csi_args[0]); -+ return; -+ -+ case 'd': /* Cursor to indicated row in current column */ -+ if (p->csi_args[0]) -+ --p->csi_args[0]; -+ gotoxy(p, p->col, p->csi_args[0]); -+ return; -+ -+ case 'H': case 'f': /* Cursor to indicated row, column (origin 1, 1) */ -+ if (p->csi_args[0]) -+ --p->csi_args[0]; -+ if (p->csi_args[1]) -+ --p->csi_args[1]; -+ gotoxy(p, p->csi_args[1], p->csi_args[0]); -+ return; -+ -+ case 'J': /* Erase display */ -+ csi_J(p, p->csi_args[0]); -+ return; -+ -+ case 'K': /* Erase line */ -+ csi_K(p, p->csi_args[0]); -+ return; -+ -+ case 'L': /* Insert # blank lines */ -+ csi_L(p, p->csi_args[0]); -+ return; -+ -+ case 'M': /* Delete # blank lines */ -+ csi_M(p, p->csi_args[0]); -+ return; -+ -+ case 'P': /* Delete # characters on the current line */ -+ csi_P(p, p->csi_args[0]); -+ return; -+ -+ case 'X': /* Erase # characters on the current line */ -+ csi_X(p, p->csi_args[0]); -+ return; -+ -+ case 'm': /* Set video attributes */ -+ csi_m(p, p->index); -+ return; -+ -+ case 's': /* Save cursor position */ -+ case 'u': /* Restore cursor position */ -+ csi_su(p, input); -+ return; -+ -+ case ']': /* Linux private ESC [ ] sequence */ -+ csi_linux(p); -+ return; -+ -+ case 'r': /* Set the scrolling region */ -+ if (! p->csi_args[0]) -+ ++p->csi_args[0]; -+ if (! p->csi_args[1] || p->csi_args[1] > p->par->vs_rows) -+ p->csi_args[1] = p->par->vs_rows; -+ csi_r(p, p->csi_args[0], p->csi_args[1]); -+ return; -+ -+ /* Ignored escape sequences */ -+ case 'c': -+ case 'g': -+ case 'n': -+ case 'q': -+ return; -+ -+ default: -+ printk(KERN_NOTICE "LCD: unrecognized CSI escape sequence: ESC [ %u\n", input); -+ return; -+ } -+ } -+} -+ -+/* -+ * Custom ESC- sequence handler. -+ */ -+static int handle_custom_esc(struct lcd_struct *p, unsigned int _input) -+{ -+ unsigned char input = _input & 0xff; -+ struct lcd_parameters *par = p->par; -+ -+ if (_input & (~0xff)) { -+ switch (ESC_STATE(p)) { -+ case 's': -+ if (p->index++) { -+ unsigned char *buf = p->cgram_buffer+(p->cgram_index-par->cgram_char0)*par->cgram_bytes; -+ -+ buf[p->index-2] = input; -+ if (p->index == par->cgram_bytes+1) -+ write_cgram(p, p->cgram_index, buf); -+ } else { -+ if (! p->driver->write_cgram_char) { -+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name); -+ return (-1); -+ } -+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars) -+ p->cgram_index = input; -+ else { -+ printk(KERN_NOTICE "LCD: bad CGRAM index\n"); -+ return (-1); -+ } -+ } -+ return (0); -+ -+ case 'G': -+ if (input >= par->cgram_char0 && input < par->cgram_char0+par->cgram_chars) -+ write_data(p, (p->attr << 8) | p->driver->charmap[input]); -+ else { -+ SET_INPUT_STATE(p, NORMAL); -+ handle_input(p, (p->attr << 8) | input); -+ } -+ return (0); -+ -+ case 'r': -+ if (input == '1') -+ address_mode(p, -1); -+ else if (input == '0') -+ address_mode(p, 1); -+ return (0); -+ -+ case 'A': -+ scrup(p, p->top, p->bot, input); -+ return (0); -+ -+ case 'B': -+ scrdown(p, p->top, p->bot, input); -+ return (0); -+ -+ case 'C': -+ browse_screen(p, input); -+ return (0); -+ } -+ } -+ -+ /* These are the custom ESC- sequences */ -+ switch (input) { -+ case 's': /* CGRAM select */ -+ if (p->cgram_buffer) { -+ SET_ESC_STATE(p, input); -+ p->index = 0; -+ return (par->cgram_bytes+1); -+ } else { -+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name); -+ return (0); -+ } -+ -+ case 'A': /* Scroll up */ -+ case 'B': /* Scroll down */ -+ case 'C': /* Browse screen */ -+ case 'G': /* Enter cgram mode */ -+ case 'r': /* Decrement counter after data read/write */ -+ SET_ESC_STATE(p, input); -+ return (1); -+ } -+ -+ return (-1); -+} -+ -+/* -+ * ESC- but not CSI sequence handler. -+ */ -+static int handle_esc(struct lcd_struct *p, unsigned char input) -+{ -+ int ret; -+ -+ SET_INPUT_STATE(p, NORMAL); -+ switch (input) { -+ case 'c': /* Reset */ -+ set_bit(DECAWM, &p->struct_flags); -+ set_bit(INC_CURS_POS, &p->struct_flags); -+ ff(p); -+ return (0); -+ -+ case 'D': /* Line Feed */ -+ lf(p); -+ return (0); -+ -+ case 'E': /* New Line */ -+ cr(p); -+ lf(p); -+ return (0); -+ -+ case 'M': /* Reverse Line Feed */ -+ ri(p); -+ return (0); -+ -+ case '7': -+ case '8': -+ csi_su(p, (input == '7' ? 's' : 'u')); -+ return (0); -+ -+ /* CSI: Start of CSI escape sequence */ -+ case '[': -+ memset(p->csi_args, 0, sizeof(p->csi_args)); -+ p->index = 0; -+ SET_INPUT_STATE(p, CSI); -+ return (0); -+ -+ /* Ignored escape sequences */ -+ case '(': -+ SET_INPUT_STATE(p, ESC_G0); -+ return (1); -+ -+ case ')': -+ SET_INPUT_STATE(p, ESC_G1); -+ return (1); -+ -+ case '#': -+ SET_INPUT_STATE(p, ESC_HASH); -+ return (1); -+ -+ case '%': -+ SET_INPUT_STATE(p, ESC_PERCENT); -+ return (1); -+ -+ case 'H': -+ case 'Z': -+ case '>': -+ case '=': -+ case ']': -+ return (0); -+ } -+ -+ /* These are the custom ESC- sequences */ -+ if ((ret = handle_custom_esc(p, input)) > 0) { -+ SET_INPUT_STATE(p, ARG); -+ return (ret); -+ } -+ -+ if (ret < 0 && p->driver->handle_custom_char) -+ if ((ret = p->driver->handle_custom_char(input)) > 0) { -+ SET_INPUT_STATE(p, ARG_DRIVER); -+ return (ret); -+ } -+ -+ if (ret < 0) -+ printk(KERN_NOTICE "LCD: unrecognized escape sequence: ESC %u\n", input); -+ -+ return (0); -+} -+ -+/* -+ * Main input handler. -+ */ -+static void handle_input(struct lcd_struct *p, unsigned short _input) -+{ -+ unsigned char input = _input & 0xff; -+ struct lcd_driver *driver = p->driver; -+ -+ switch (INPUT_STATE(p)) { -+ case NORMAL: -+ if (input < 0x20 || input == 0x9b) -+ control_char(p, input); -+ else -+ write_data(p, (_input & 0xff00) | driver->charmap[input]); -+ return; -+ -+ case RAW: -+ write_data(p, (_input & 0xff00) | driver->charmap[input]); -+ return; -+ -+ case SYN: -+ write_data(p, _input); -+ SET_INPUT_STATE(p, NORMAL); -+ return; -+ -+ case ESC: -+ p->esc_args = handle_esc(p, input); -+ return; -+ -+ case ESC_G0: -+ case ESC_G1: -+ case ESC_HASH: -+ case ESC_PERCENT: -+ if (! --p->esc_args) -+ SET_INPUT_STATE(p, NORMAL); -+ return; -+ -+ case CSI: -+ handle_csi(p, input); -+ return; -+ -+ case ARG: -+ if (handle_custom_esc(p, 0x100 | input) || ! --p->esc_args) -+ SET_INPUT_STATE(p, NORMAL); -+ return; -+ -+ case ARG_DRIVER: -+ if (driver->handle_custom_char(0x100 | input) || ! --p->esc_args) -+ SET_INPUT_STATE(p, NORMAL); -+ return; -+ } -+} -+ -+ -+ -+ -+ -+/*************************************** -+ * Read from/Write to display routines * -+ ***************************************/ -+ -+/* -+ * Write character data to the display. -+ */ -+static void write_data(struct lcd_struct *p, unsigned short data) -+{ -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int pos; -+ int frame_pos; -+ -+ if (test_bit(NEED_WRAP, &p->struct_flags)) { -+ cr(p); -+ lf(p); -+ } -+ -+ if (test_bit(DECIM, &p->struct_flags)) -+ lcd_insert_char(p, 1); -+ -+ pos = (p->row*vs_cols)+p->col; -+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) { -+ make_cursor_visible(p); -+ redraw_screen(p, 0, p->fb_size-1); -+ frame_pos = vs_to_frame_(p, pos); -+ } -+ -+ if (p->display[frame_pos] != data) { -+ p->driver->write_char(frame_pos, data); -+ p->display[frame_pos] = data; -+ } -+ -+ p->fb[pos] = data; -+ -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ if (p->col+1 < vs_cols) -+ iterator_inc(p->col, vs_cols); -+ else if (test_bit(DECAWM, &p->struct_flags)) -+ set_bit(NEED_WRAP, &p->struct_flags); -+ } else { -+ if (p->col) -+ iterator_dec(p->col, vs_cols); -+ else if (test_bit(DECAWM, &p->struct_flags)) -+ set_bit(NEED_WRAP, &p->struct_flags); -+ } -+} -+ -+/* -+ * Write an entire CGRAM character to the display. -+ */ -+static void write_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels) -+{ -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags); -+ -+ if (! inc_set) -+ address_mode(p, 1); -+ -+ p->driver->write_cgram_char(index, pixels); -+ -+ if (! inc_set) -+ address_mode(p, -1); -+} -+ -+/* -+ * Read character data from the display. -+ */ -+static void read_data(struct lcd_struct *p, unsigned short *data) -+{ -+ unsigned int vs_rows = p->par->vs_rows; -+ unsigned int vs_cols = p->par->vs_cols; -+ unsigned int pos = (p->row*vs_cols)+p->col; -+ int frame_pos; -+ -+ if ((frame_pos = vs_to_frame_(p, pos)) < 0) { -+ make_cursor_visible(p); -+ redraw_screen(p, 0, p->fb_size-1); -+ frame_pos = vs_to_frame_(p, pos); -+ } -+ -+ p->driver->read_char(frame_pos, data); -+ -+ if (test_bit(INC_CURS_POS, &p->struct_flags)) { -+ iterator_inc(p->col, vs_cols); -+ if (! p->col) { -+ if (p->row+1 < vs_rows) -+ ++p->row; -+ } -+ } else { -+ iterator_dec(p->col, vs_cols); -+ if (p->col+1 == vs_cols) { -+ if (p->row) -+ --p->row; -+ } -+ } -+} -+ -+/* -+ * Read an entire CGRAM character from the display. -+ */ -+static void read_cgram(struct lcd_struct *p, unsigned char index, unsigned char *pixels) -+{ -+ unsigned int inc_set = test_bit(INC_CURS_POS, &p->struct_flags); -+ -+ if (! inc_set) -+ address_mode(p, 1); -+ -+ p->driver->read_cgram_char(index, pixels); -+ -+ if (! inc_set) -+ address_mode(p, -1); -+} -+ -+ -+ -+ -+ -+/**************************** -+ * Proc filesystem routines * -+ ****************************/ -+#ifdef USE_PROC -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -+/* create_proc_read_entry is missing in 2.2.x kernels */ -+static struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, -+ struct proc_dir_entry *parent, read_proc_t *read_proc, void *data) -+{ -+ struct proc_dir_entry *res = create_proc_entry(name, mode, parent); -+ -+ if (res) { -+ res->read_proc = read_proc; -+ res->data = data; -+ } -+ -+ return (res); -+} -+#endif -+ -+static int proc_fb_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ struct lcd_struct *p = (struct lcd_struct *)data; -+ unsigned int vs_cols; -+ static unsigned int nr, need_wrap; -+ static off_t _offset; -+ -+ down(&p->lcd_sem); -+ if (! offset) -+ _offset = 0; -+ if ((*eof = (_offset >= p->fb_size))) { -+ up(&p->lcd_sem); -+ return (0); -+ } -+ vs_cols = p->par->vs_cols; -+ if (size && need_wrap) { -+ need_wrap = 0; -+ temp += sprintf(temp, "\n"); -+ --size; -+ } -+ if (! nr) -+ nr = vs_cols; -+ *start = (char *)0; -+ while (size && nr) { -+ unsigned char c = (p->fb[_offset] & 0xff); -+ -+ temp += sprintf(temp, "%c", (c < 0x20 ? '·' : c)); -+ --size; -+ --nr; -+ ++*start; -+ ++_offset; -+ } -+ if (! nr) { -+ if (size) { -+ temp += sprintf(temp, "\n"); -+ --size; -+ } else -+ need_wrap = 1; -+ } -+ up(&p->lcd_sem); -+ -+ return (temp-buffer); -+} -+ -+static int proc_display_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ struct lcd_struct *p = (struct lcd_struct *)data; -+ unsigned int i, frame_cols; -+ int frame_pos; -+ -+ down(&p->lcd_sem); -+ frame_cols = p->par->cntr_cols; -+ frame_pos = vs_to_frame_(p, (p->row*p->par->vs_cols)+p->col); -+ temp += sprintf(temp, " "); -+ for (i = 2; i <= frame_cols; i += 2) -+ temp += sprintf(temp, " %d", i%10); -+ temp += sprintf(temp, "\n"); -+ -+ temp += sprintf(temp, " +"); -+ for (i = 0; i < frame_cols; ++i) -+ temp += sprintf(temp, "-"); -+ temp += sprintf(temp, "+\n"); -+ -+ for (i = 0; i < p->frame_size; ++i) { -+ unsigned char c = (p->display[i] & 0xff); -+ -+ if (! (i%frame_cols)) -+ temp += sprintf(temp, "%2d |", 1+i/frame_cols); -+ if (frame_pos--) -+ temp += sprintf(temp, "%c", (c < 0x20 ? '·' : c)); -+ else -+ temp += sprintf(temp, "_"); -+ if (! ((i+1)%frame_cols)) -+ temp += sprintf(temp, "|\n"); -+ } -+ -+ temp += sprintf(temp, " +"); -+ for (i = 0; i < frame_cols; ++i) -+ temp += sprintf(temp, "-"); -+ temp += sprintf(temp, "+\n"); -+ up(&p->lcd_sem); -+ -+ return (temp-buffer); -+} -+ -+static int proc_charmap_read(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ struct lcd_struct *p = (struct lcd_struct *)data; -+ unsigned char *charmap; -+ unsigned int i; -+ -+ down(&p->lcd_sem); -+ charmap = p->driver->charmap; -+ temp += sprintf(temp, "static unsigned char charmap[] = {"); -+ for (i = 0; i < 255; ++i) { -+ if (! (i & 7)) { -+ temp += sprintf(temp, "\n"); -+ if (! (i & 31)) -+ temp += sprintf(temp, "\n/* %d - %d */\n", i, i+31); -+ } -+ temp += sprintf(temp, "0x%.2x, ", *charmap++); -+ } -+ temp += sprintf(temp, "0x%.2x\n\n};\n", *charmap); -+ up(&p->lcd_sem); -+ -+ return (temp-buffer); -+} -+ -+static int proc_registered_drivers(char *buffer, char **start, off_t offset, int size, int *eof, void *data) -+{ -+ char *temp = buffer; -+ struct list_head *entry; -+ -+ down(&drivers_sem); -+ temp += sprintf(temp, "Registered drivers:\n"); -+ list_for_each(entry, &lcd_drivers) { -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list); -+ -+ down(&p->lcd_sem); -+ temp += sprintf(temp, "%3d %s\n", p->par->minor, p->par->name); -+ up(&p->lcd_sem); -+ } -+ up(&drivers_sem); -+ -+ return (temp-buffer); -+} -+ -+static void create_driver_proc_entries(struct lcd_struct *p) -+{ -+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root; -+ int proc_level = 0; -+ -+ SET_PROC_LEVEL(p, proc_level); -+ if (create_proc_read_entry("framebuffer", 0, driver_proc_root, proc_fb_read, p) == NULL) { -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/framebuffer\n", p->par->name); -+ return; -+ } -+ SET_PROC_LEVEL(p, ++proc_level); -+ if (create_proc_read_entry("display", 0, driver_proc_root, proc_display_read, p) == NULL) { -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/display\n", p->par->name); -+ return; -+ } -+ SET_PROC_LEVEL(p, ++proc_level); -+ if (create_proc_read_entry("charmap.h", 0, driver_proc_root, proc_charmap_read, p) == NULL) { -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/charmap.h\n", p->par->name); -+ return; -+ } -+ SET_PROC_LEVEL(p, ++proc_level); -+} -+ -+static void remove_driver_proc_entries(struct lcd_struct *p) -+{ -+ struct proc_dir_entry *driver_proc_root = p->driver->driver_proc_root; -+ -+ switch (PROC_LEVEL(p)) { -+ case 3: -+ remove_proc_entry("charmap.h", driver_proc_root); -+ case 2: -+ remove_proc_entry("display", driver_proc_root); -+ case 1: -+ remove_proc_entry("framebuffer", driver_proc_root); -+ } -+ SET_PROC_LEVEL(p, 0); -+} -+#endif -+ -+ -+ -+ -+ -+/***************************** -+ * Low level file operations * -+ *****************************/ -+static ssize_t do_lcd_read(struct lcd_struct *p, void *buffer, size_t length) -+{ -+ unsigned int i; -+ unsigned short tmp; -+ -+ if (! p->refcount) -+ return (-ENXIO); -+ -+ if (! p->driver->read_char) { -+ printk(KERN_NOTICE "LCD: driver %s doesn't support reading\n", p->par->name); -+ return (-ENOSYS); -+ } -+ -+ if (test_bit(WITH_ATTR, &p->struct_flags)) -+ for (i = 0; i < length; ++i) { -+ read_data(p, &tmp); -+ ((unsigned short *)buffer)[i] = tmp; -+ } -+ else -+ for (i = 0; i < length; ++i) { -+ read_data(p, &tmp); -+ ((unsigned char *)buffer)[i] = tmp & 0xff; -+ } -+ -+ return (length); -+} -+ -+static ssize_t do_lcd_write(struct lcd_struct *p, const void *buffer, size_t length) -+{ -+ unsigned int i; -+ -+ if (! p->refcount) -+ return (-ENXIO); -+ -+ if (test_bit(WITH_ATTR, &p->struct_flags)) -+ for (i = 0; i < length; ++i) -+ handle_input(p, ((const unsigned short *)buffer)[i]); -+ else -+ for (i = 0; i < length; ++i) -+ handle_input(p, (p->attr << 8) | ((const unsigned char *)buffer)[i]); -+ -+ return (length); -+} -+ -+static int do_lcd_open(struct lcd_struct *p) -+{ -+ if (! p->refcount) { -+ if (p->driver->driver_module) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+ if (! try_module_get(p->driver->driver_module)) -+ return (-EBUSY); -+#else -+ if (__MOD_IN_USE(p->driver->driver_module)) -+ return (-EBUSY); -+ -+ __MOD_INC_USE_COUNT(p->driver->driver_module); -+#endif -+ } -+ } -+ -+ ++p->refcount; -+ -+ return (0); -+} -+ -+static int do_lcd_release(struct lcd_struct *p) -+{ -+ if (! p->refcount) -+ return (0); -+ -+ if (p->refcount == 1) { -+ if (p->driver->driver_module) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+ module_put(p->driver->driver_module); -+#else -+ __MOD_DEC_USE_COUNT(p->driver->driver_module); -+#endif -+ } -+ -+ --p->refcount; -+ -+ return (0); -+} -+ -+static int cgram_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned char *argp) -+{ -+ struct lcd_parameters *par = p->par; -+ unsigned int length = par->cgram_bytes; -+ unsigned char index = argp[0]; -+ unsigned char *buffer = argp+1; -+ unsigned char *cgram_buffer = p->cgram_buffer+(index-par->cgram_char0)*length; -+ -+ if (index < par->cgram_char0 || index >= par->cgram_char0+par->cgram_chars) -+ return (-EINVAL); -+ -+ if (cmd == LCDL_SET_CGRAM_CHAR) { -+ if (! p->driver->write_cgram_char) { -+ printk(KERN_ERR "LCD: %s: missing function to write to CGRAM\n", p->par->name); -+ return (-ENOSYS); -+ } -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_from_user(cgram_buffer, buffer, length)) -+ return (-EFAULT); -+ } else -+ memcpy(cgram_buffer, buffer, length); -+ write_cgram(p, index, cgram_buffer); -+ } else { -+ if (! p->driver->read_cgram_char) { -+ printk(KERN_ERR "LCD: %s: missing function to read from CGRAM or unable to read\n", p->par->name); -+ return (-ENOSYS); -+ } -+ read_cgram(p, index, cgram_buffer); -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_to_user(buffer, cgram_buffer, length)) -+ return (-EFAULT); -+ } else -+ memcpy(buffer, cgram_buffer, length); -+ } -+ -+ return (0); -+} -+ -+static int do_lcd_ioctl(struct lcd_struct *p, unsigned int cmd, unsigned long arg) -+{ -+ int i; -+ struct lcd_driver *driver = p->driver; -+ struct lcd_parameters *par = p->par; -+ unsigned char *argp = (unsigned char *)arg; -+ -+ if (! p->refcount) -+ return (-ENXIO); -+ -+ switch (cmd) { -+ case LCDL_SET_PARAM: -+ if ((i = cleanup_driver(p))) -+ return (i); -+ i = par->minor; -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_from_user(par, argp, sizeof(struct lcd_parameters))) -+ return (-EFAULT); -+ } else -+ memcpy(par, argp, sizeof(struct lcd_parameters)); -+ par->minor = i; -+ return (init_driver(p)); -+ -+ case LCDL_GET_PARAM: -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_to_user(argp, par, sizeof(struct lcd_parameters))) -+ return (-EFAULT); -+ } else -+ memcpy(argp, par, sizeof(struct lcd_parameters)); -+ return (0); -+ -+ case LCDL_RESET_CHARMAP: -+ for (i = 0; i < 256; ++i) -+ driver->charmap[i] = i; -+ return (0); -+ -+ case LCDL_CHARSUBST: -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ get_user(i, argp); -+ get_user(driver->charmap[i], argp+1); -+ } else { -+ i = argp[0]; -+ driver->charmap[i] = argp[1]; -+ } -+ return (0); -+ -+ case LCDL_SAVE_CHARMAP: -+ memcpy(p->s_charmap, driver->charmap, 256); -+ return (0); -+ -+ case LCDL_RESTORE_CHARMAP: -+ memcpy(driver->charmap, p->s_charmap, 256); -+ return (0); -+ -+ case LCDL_SWAP_CHARMAP: -+ { -+ unsigned char *tmp; -+ -+ tmp = driver->charmap; -+ driver->charmap = p->s_charmap; -+ p->s_charmap = tmp; -+ } -+ return (0); -+ -+ case LCDL_RAW_MODE: -+ if (arg) { -+ clear_bit(NEED_WRAP, &p->struct_flags); -+ clear_bit(DECIM, &p->struct_flags); -+ clear_bit(DECAWM, &p->struct_flags); -+ SET_INPUT_STATE(p, RAW); -+ } else { -+ set_bit(DECAWM, &p->struct_flags); -+ SET_INPUT_STATE(p, NORMAL); -+ } -+ return (0); -+ -+ case LCDL_CLEAR_DISP: -+ ff(p); -+ return (0); -+ -+ case LCDL_SET_CGRAM_CHAR: -+ case LCDL_GET_CGRAM_CHAR: -+ if (p->cgram_buffer) -+ return (cgram_ioctl(p, cmd, argp)); -+ else -+ printk(KERN_NOTICE "LCD: driver %s does not support CGRAM chars\n", par->name); -+ return (0); -+ -+ case LCDL_SET_CHARMAP: -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_from_user(driver->charmap, argp, 256)) -+ return (-EFAULT); -+ } else -+ memcpy(driver->charmap, argp, 256); -+ return (0); -+ -+ case LCDL_GET_CHARMAP: -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_to_user(argp, driver->charmap, 256)) -+ return (-EFAULT); -+ } else -+ memcpy(argp, driver->charmap, 256); -+ return (0); -+ -+ case LCDL_MEMSET: -+ case LCDL_MEMMOVE: -+ { -+ int buf[3]; -+ -+ if (test_bit(USER_SPACE, &p->struct_flags)) { -+ if (copy_from_user(buf, argp, sizeof(buf))) -+ return (-EFAULT); -+ } else -+ memcpy(buf, argp, sizeof(buf)); -+ -+ if (cmd == LCDL_MEMSET) -+ lcd_memset(p, buf[0], buf[1], buf[2]); -+ else -+ lcd_memmove(p, buf[0], buf[1], buf[2]); -+ -+ return (0); -+ } -+ -+ default: -+ if (driver->handle_custom_ioctl) -+ return (driver->handle_custom_ioctl(cmd, arg, test_bit(USER_SPACE, &p->struct_flags))); -+ } -+ -+ return (-ENOIOCTLCMD); -+} -+ -+ -+ -+ -+ -+/************************************************** -+ * Kernel register/unregister lcd driver routines * -+ **************************************************/ -+/* -+ * Find a driver in lcd_drivers linked list -+ */ -+static struct lcd_struct *find_lcd_struct(unsigned short minor) -+{ -+ struct list_head *entry; -+ -+ list_for_each(entry, &lcd_drivers) { -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list); -+ -+ if (p->par->minor == minor) -+ return (p); -+ } -+ -+ return (NULL); -+} -+ -+static void list_add_sorted(struct list_head *new) -+{ -+ struct list_head *entry; -+ unsigned short new_minor = (list_entry(new, struct lcd_struct, lcd_list))->par->minor; -+ -+ list_for_each(entry, &lcd_drivers) { -+ struct lcd_struct *p = list_entry(entry, struct lcd_struct, lcd_list); -+ -+ if (p->par->minor > new_minor) -+ break; -+ } -+ list_add_tail(new, entry); -+} -+ -+/* Exported function */ -+int lcd_register_driver(struct lcd_driver *driver, struct lcd_parameters *par) -+{ -+ int ret; -+ struct lcd_struct *p; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+ struct device *lcd_device; -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+ struct class_device *lcd_class_device; -+#endif -+ -+ if (! driver || ! par || par->minor >= minors) -+ return (-EINVAL); -+ if (! driver->write_char || ! driver->init_port || ! driver->cleanup_port) { -+ printk(KERN_ERR "LCD: missing functions\n"); -+ return (-EINVAL); -+ } -+ -+ down(&drivers_sem); -+ -+ if (find_lcd_struct(par->minor)) { -+ up(&drivers_sem); -+ return (-EBUSY); -+ } -+ -+ if ((p = (struct lcd_struct *)kmalloc(sizeof(struct lcd_struct), GFP_KERNEL)) == NULL) { -+ printk(KERN_ERR "LCD: memory allocation failed (kmalloc)\n"); -+ up(&drivers_sem); -+ return (-ENOMEM); -+ } -+ memset(p, 0, sizeof(struct lcd_struct)); -+ -+ p->driver = driver; -+ p->par = par; -+ p->refcount = 0; -+ SET_INIT_LEVEL(p, 0); -+ SET_INPUT_STATE(p, NORMAL); -+ set_bit(DECAWM, &p->struct_flags); -+ set_bit(INC_CURS_POS, &p->struct_flags); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+ lcd_device = device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), "%s", par->name); -+ if (IS_ERR(lcd_device)) { -+ kfree(p); -+ up(&drivers_sem); -+ return (PTR_ERR(lcd_device)); -+ } -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15) -+ lcd_class_device = class_device_create(lcd_linux_class, NULL, MKDEV(major, par->minor), NULL, "%s", par->name); -+ if (IS_ERR(lcd_class_device)) { -+ kfree(p); -+ up(&drivers_sem); -+ return (PTR_ERR(lcd_class_device)); -+ } -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+ lcd_class_device = class_device_create(lcd_linux_class, MKDEV(major, par->minor), NULL, "%s", par->name); -+ if (IS_ERR(lcd_class_device)) { -+ kfree(p); -+ up(&drivers_sem); -+ return (PTR_ERR(lcd_class_device)); -+ } -+#endif -+ -+#ifdef USE_PROC -+ if (lcd_proc_root && (driver->driver_proc_root = proc_mkdir(par->name, lcd_proc_root)) == NULL) -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/%s/\n", par->name); -+#endif -+ -+ if ((ret = init_driver(p))) { -+#ifdef USE_PROC -+ if (driver->driver_proc_root) -+ remove_proc_entry(p->par->name, lcd_proc_root); -+#endif -+ kfree(p); -+ up(&drivers_sem); -+ return (ret); -+ } -+ -+ init_MUTEX(&p->lcd_sem); -+ -+ list_add_sorted(&p->lcd_list); -+ -+ up(&drivers_sem); -+ -+#ifdef MODULE -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+ try_module_get(THIS_MODULE); -+#else -+ MOD_INC_USE_COUNT; -+#endif -+#endif -+ -+ return (0); -+} -+EXPORT_SYMBOL(lcd_register_driver); -+ -+/* Exported function */ -+int lcd_unregister_driver(struct lcd_driver *driver, struct lcd_parameters *par) -+{ -+ int ret; -+ struct lcd_struct *p; -+ -+ if (! driver || ! par || par->minor >= minors) -+ return (-EINVAL); -+ -+ down(&drivers_sem); -+ -+ if ((p = find_lcd_struct(par->minor)) == NULL || p->driver != driver) { -+ printk(KERN_ERR "LCD: driver not found; lcd_unregister_driver failed\n"); -+ up(&drivers_sem); -+ return (-ENODEV); -+ } -+ -+ down(&p->lcd_sem); -+ -+ if (p->refcount) { -+ printk(KERN_ERR "LCD: driver busy; lcd_unregister_driver failed\n"); -+ up(&p->lcd_sem); -+ up(&drivers_sem); -+ return (-EBUSY); -+ } -+ -+ if ((ret = cleanup_driver(p))) { -+ up(&p->lcd_sem); -+ up(&drivers_sem); -+ return (ret); -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -+ device_destroy(lcd_linux_class, MKDEV(major, par->minor)); -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+ class_device_destroy(lcd_linux_class, MKDEV(major, par->minor)); -+#endif -+ -+#ifdef USE_PROC -+ if (p->driver->driver_proc_root) -+ remove_proc_entry(p->par->name, lcd_proc_root); -+#endif -+ -+ list_del(&p->lcd_list); -+ kfree(p); -+ -+ up(&drivers_sem); -+ -+#ifdef MODULE -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -+ module_put(THIS_MODULE); -+#else -+ MOD_DEC_USE_COUNT; -+#endif -+#endif -+ -+ return (0); -+} -+EXPORT_SYMBOL(lcd_unregister_driver); -+ -+ -+ -+ -+ -+/************************ -+ * Kernel I/O interface * -+ ************************/ -+/* Exported function */ -+int lcd_open(unsigned short minor, struct lcd_struct **pp) -+{ -+ int ret; -+ struct lcd_struct *p; -+ -+ down(&drivers_sem); -+ -+ if (minor >= minors || (*pp = p = find_lcd_struct(minor)) == NULL) { -+ printk(KERN_ERR "LCD: lcd_open failed. Device not found.\n"); -+ up(&drivers_sem); -+ return (-ENODEV); -+ } -+ -+ down(&p->lcd_sem); -+ up(&drivers_sem); -+ -+ ret = do_lcd_open(p); -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+EXPORT_SYMBOL(lcd_open); -+ -+/* Exported function */ -+int lcd_close(struct lcd_struct **pp) -+{ -+ int ret; -+ struct lcd_struct *p; -+ -+ if (! pp || ! (p = *pp)) { -+ printk(KERN_ERR "LCD: NULL pointer in lcd_close\n"); -+ return (-ENODEV); -+ } -+ -+ down(&p->lcd_sem); -+ -+ if (! (ret = do_lcd_release(p))) -+ *pp = NULL; -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+EXPORT_SYMBOL(lcd_close); -+ -+static inline loff_t offset_to_row_col(struct lcd_struct *p, loff_t offset) -+{ -+ unsigned long _offset = offset; -+ unsigned int vs_cols = p->par->vs_cols; -+ -+ gotoxy(p, _offset%vs_cols, _offset/vs_cols); -+ -+ return ((p->row*vs_cols)+p->col); -+} -+ -+/* Exported function */ -+ssize_t lcd_read(struct lcd_struct *p, void *bufp, size_t length, loff_t offset, unsigned int with_attr) -+{ -+ ssize_t ret = 0; -+ -+ if (! p) { -+ printk(KERN_ERR "LCD: NULL pointer in lcd_read\n"); -+ return (-ENODEV); -+ } -+ if (! bufp) -+ return (-EFAULT); -+ if (offset < 0 || offset >= p->fb_size) -+ return (-EINVAL); -+ -+ if (length+offset > p->fb_size) -+ length = p->fb_size-offset; -+ -+ if (with_attr) -+ set_bit(WITH_ATTR, &p->struct_flags); -+ -+ offset_to_row_col(p, offset); -+ ret = do_lcd_read(p, bufp, length); -+ -+ if (with_attr) -+ clear_bit(WITH_ATTR, &p->struct_flags); -+ -+ return (ret); -+} -+EXPORT_SYMBOL(lcd_read); -+ -+/* Exported function */ -+ssize_t lcd_write(struct lcd_struct *p, const void *bufp, size_t length, loff_t offset, unsigned int with_attr) -+{ -+ ssize_t ret; -+ -+ if (! p) { -+ printk(KERN_ERR "LCD: NULL pointer in lcd_write\n"); -+ return (-ENODEV); -+ } -+ if (! bufp) -+ return (-EFAULT); -+ if (offset < 0 || offset >= p->fb_size) -+ return (-EINVAL); -+ -+ if (with_attr) -+ set_bit(WITH_ATTR, &p->struct_flags); -+ -+ offset_to_row_col(p, offset); -+ ret = do_lcd_write(p, bufp, length); -+ -+ if (with_attr) -+ clear_bit(WITH_ATTR, &p->struct_flags); -+ -+ return (ret); -+} -+EXPORT_SYMBOL(lcd_write); -+ -+/* Exported function */ -+int lcd_ioctl(struct lcd_struct *p, unsigned int cmd, ...) -+{ -+ int ret; -+ unsigned long arg; -+ va_list ap; -+ -+ if (! p) { -+ printk(KERN_ERR "LCD: NULL pointer in lcd_ioctl\n"); -+ return (-ENODEV); -+ } -+ -+ down(&p->lcd_sem); -+ va_start(ap, cmd); -+ arg = va_arg(ap, unsigned long); -+ ret = do_lcd_ioctl(p, cmd, arg); -+ va_end(ap); -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+EXPORT_SYMBOL(lcd_ioctl); -+ -+ -+ -+ -+ -+/******************* -+ * File operations * -+ *******************/ -+static loff_t lcd_fops_llseek(struct file *filp, loff_t offset, int orig) -+{ -+ struct lcd_struct *p; -+ -+ if (! (p = filp->private_data)) -+ return (-ENODEV); -+ -+ down(&p->lcd_sem); -+ -+ switch (orig) { -+ case 0: -+ filp->f_pos = offset; -+ break; -+ -+ case 1: -+ filp->f_pos += offset; -+ break; -+ -+ default: -+ up(&p->lcd_sem); -+ return (-EINVAL); /* SEEK_END not supported */ -+ } -+ -+ filp->f_pos = offset_to_row_col(p, filp->f_pos); -+ -+ up(&p->lcd_sem); -+ -+ return (filp->f_pos); -+} -+ -+static ssize_t lcd_fops_read(struct file *filp, char *buffer, size_t length, loff_t *offp) -+{ -+ ssize_t ret = 0; -+ char *bufp = buffer; -+ struct lcd_struct *p; -+ -+ if (! bufp) -+ return (-EFAULT); -+ if (! (p = filp->private_data)) -+ return (-ENODEV); -+ -+ down(&p->lcd_sem); -+ -+ if (*offp < 0 || *offp >= p->fb_size) { -+ up(&p->lcd_sem); -+ return (-EINVAL); -+ } -+ -+ if (length+(*offp) > p->fb_size) -+ length = p->fb_size-(*offp); -+ -+ while (length) { -+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length); -+ if ((ret = do_lcd_read(p, p->flip_buf, ret)) < 0) -+ break; -+ *offp = (p->row*p->par->vs_cols)+p->col; -+ if (copy_to_user(bufp, p->flip_buf, ret)) { -+ ret = -EFAULT; -+ break; -+ } -+ length -= ret; -+ bufp += ret; -+ ret = bufp-buffer; -+ if (length) -+ schedule(); -+ } -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+ -+static ssize_t lcd_fops_write(struct file *filp, const char *buffer, size_t length, loff_t *offp) -+{ -+ ssize_t ret = 0; -+ const char *bufp = buffer; -+ struct lcd_struct *p; -+ -+ if (! bufp) -+ return (-EFAULT); -+ if (! (p = filp->private_data)) -+ return (-ENODEV); -+ -+ down(&p->lcd_sem); -+ -+ if (*offp < 0 || *offp >= p->fb_size) { -+ up(&p->lcd_sem); -+ return (-EINVAL); -+ } -+ -+ while (length) { -+ ret = (length > FLIP_BUF_SIZE ? FLIP_BUF_SIZE : length); -+ if (copy_from_user(p->flip_buf, bufp, ret)) { -+ ret = -EFAULT; -+ break; -+ } -+ if ((ret = do_lcd_write(p, p->flip_buf, ret)) < 0) -+ break; -+ *offp = (p->row*p->par->vs_cols)+p->col; -+ length -= ret; -+ bufp += ret; -+ ret = bufp-buffer; -+ if (length) -+ schedule(); -+ } -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+ -+static int lcd_fops_open(struct inode *inop, struct file *filp) -+{ -+ unsigned short minor; -+ int ret; -+ struct lcd_struct *p; -+ -+ down(&drivers_sem); -+ -+ if ((minor = MINOR(inop->i_rdev)) >= minors || (filp->private_data = p = find_lcd_struct(minor)) == NULL) { -+ up(&drivers_sem); -+ return (-ENODEV); -+ } -+ -+ down(&p->lcd_sem); -+ up(&drivers_sem); -+ -+ ret = do_lcd_open(p); -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+ -+static int lcd_fops_release(struct inode *inop, struct file *filp) -+{ -+ struct lcd_struct *p; -+ int ret; -+ -+ if (! (p = filp->private_data)) -+ return (-ENODEV); -+ -+ down(&p->lcd_sem); -+ -+ if (! (ret = do_lcd_release(p))) -+ filp->private_data = NULL; -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+ -+static int lcd_fops_ioctl(struct inode *inop, struct file *filp, unsigned int cmd, unsigned long arg) -+{ -+ struct lcd_struct *p; -+ int ret; -+ -+ if (! (p = filp->private_data)) -+ return (-ENODEV); -+ -+ down(&p->lcd_sem); -+ -+ set_bit(USER_SPACE, &p->struct_flags); -+ ret = do_lcd_ioctl(p, cmd, arg); -+ clear_bit(USER_SPACE, &p->struct_flags); -+ -+ up(&p->lcd_sem); -+ -+ return (ret); -+} -+ -+static struct file_operations lcd_linux_fops = { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) -+ .owner = THIS_MODULE, -+#endif -+ .llseek = lcd_fops_llseek, -+ .read = lcd_fops_read, -+ .write = lcd_fops_write, -+ .open = lcd_fops_open, -+ .release = lcd_fops_release, -+ .ioctl = lcd_fops_ioctl, -+}; -+ -+ -+ -+ -+ -+/******************************** -+ * Init/Cleanup driver routines * -+ ********************************/ -+static int do_init_driver(struct lcd_struct *p) -+{ -+ int ret, init_level; -+ struct lcd_driver *driver = p->driver; -+ struct lcd_parameters *par = p->par; -+ unsigned int frame_rows = par->cntr_rows*par->num_cntr; -+ unsigned int frame_cols = par->cntr_cols; -+ -+ switch ((init_level = INIT_LEVEL(p))) { -+ case 0: -+ if (frame_rows == 0 || frame_cols == 0 || ! par->name) { -+ printk(KERN_ERR "LCD: wrong lcd parameters\n"); -+ return (-EINVAL); -+ } -+ if (driver->validate_driver) { -+ if ((ret = driver->validate_driver()) < 0) { -+ printk(KERN_ERR "LCD: validate_driver failed\n"); -+ return (-EINVAL); -+ } else if (ret > 0) { -+ set_bit(CAN_DO_COLOR, &p->struct_flags); -+ p->defcolor = 0x07; -+ p->ulcolor = 0x0f; -+ p->halfcolor = 0x08; -+ } -+ } -+ default_attr(p); -+ update_attr(p); -+ p->frame_size = frame_rows*frame_cols; -+ if (par->vs_rows < frame_rows) -+ par->vs_rows = frame_rows; -+ if (par->vs_cols < frame_cols) -+ par->vs_cols = frame_cols; -+ p->fb_size = par->vs_rows*par->vs_cols; -+ -+ ret = sizeof(short)*p->fb_size; -+ ret += sizeof(short)*p->frame_size; -+ ret += FLIP_BUF_SIZE; -+ ret += (p->driver->charmap ? 256 : 512); -+ ret += par->cgram_chars*par->cgram_bytes; -+ if ((p->fb = (unsigned short *)vmalloc(ret)) == NULL) { -+ printk(KERN_ERR "LCD: memory allocation failed (vmalloc)\n"); -+ return (-ENOMEM); -+ } -+ __memset_short(p->fb, p->erase_char, p->fb_size+p->frame_size); -+ -+ p->display = p->fb+p->fb_size; -+ p->flip_buf = (unsigned char *)(p->display+p->frame_size); -+ -+ if (! p->driver->charmap) { -+ set_bit(NULL_CHARMAP, &p->struct_flags); -+ p->driver->charmap = p->flip_buf+FLIP_BUF_SIZE; -+ for (ret = 0; ret < 256; ++ret) -+ p->driver->charmap[ret] = ret; -+ p->s_charmap = p->driver->charmap+256; -+ } else -+ p->s_charmap = p->flip_buf+FLIP_BUF_SIZE; -+ memset(p->s_charmap, 0, 256); -+ -+ if (par->cgram_chars*par->cgram_bytes) { -+ p->cgram_buffer = p->s_charmap+256; -+ memset(p->cgram_buffer, 0, par->cgram_chars*par->cgram_bytes); -+ } else -+ p->cgram_buffer = NULL; -+ -+ p->frame_base = 0; -+ p->row = p->col = 0; -+ p->top = 0; -+ p->bot = par->vs_rows; -+ SET_INIT_LEVEL(p, ++init_level); -+ -+ case 1: -+ /* Initialize the communication port */ -+ if ((ret = driver->init_port())) { -+ printk(KERN_ERR "LCD: failure while initializing the communication port\n"); -+ return (ret); -+ } -+ SET_INIT_LEVEL(p, ++init_level); -+ -+ case 2: -+ /* Initialize LCD display */ -+ if (driver->init_display && (ret = driver->init_display())) { -+ printk(KERN_ERR "LCD: failure while initializing the display\n"); -+ return (ret); -+ } -+ -+#ifdef USE_PROC -+ /* Create entries in /proc/lcd/"driver" */ -+ if (driver->driver_proc_root) -+ create_driver_proc_entries(p); -+#endif -+ SET_INIT_LEVEL(p, ++init_level); -+ } -+ -+ return (0); -+} -+ -+static int do_cleanup_driver(struct lcd_struct *p) -+{ -+ int ret, init_level; -+ struct lcd_driver *driver = p->driver; -+ -+ switch ((init_level = INIT_LEVEL(p))) { -+ case 3: -+#ifdef USE_PROC -+ if (driver->driver_proc_root) -+ remove_driver_proc_entries(p); -+#endif -+ if (driver->cleanup_display && (ret = driver->cleanup_display())) { -+ printk(KERN_ERR "LCD: failure while cleaning the display\n"); -+ return (ret); -+ } -+ SET_INIT_LEVEL(p, --init_level); -+ -+ case 2: -+ if ((ret = driver->cleanup_port())) { -+ printk(KERN_ERR "LCD: failure while cleaning the communication port\n"); -+ return (ret); -+ } -+ SET_INIT_LEVEL(p, --init_level); -+ -+ case 1: -+ if (test_bit(NULL_CHARMAP, &p->struct_flags)) { -+ p->driver->charmap = NULL; -+ clear_bit(NULL_CHARMAP, &p->struct_flags); -+ } -+ vfree(p->fb); -+ p->fb = NULL; -+ SET_INIT_LEVEL(p, --init_level); -+ } -+ -+ return (0); -+} -+ -+static int init_driver(struct lcd_struct *p) -+{ -+ int ret; -+ -+ if ((ret = do_init_driver(p))) { -+ do_cleanup_driver(p); -+ printk(KERN_ERR "LCD: init_driver failed\n"); -+ } -+ -+ return (ret); -+} -+ -+static int cleanup_driver(struct lcd_struct *p) -+{ -+ int ret; -+ -+ if ((ret = do_cleanup_driver(p))) { -+ do_init_driver(p); -+ printk(KERN_ERR "LCD: cleanup_driver failed\n"); -+ } -+ -+ return (ret); -+} -+ -+ -+ -+ -+ -+/******************************** -+ * Init/Cleanup module routines * -+ ********************************/ -+static int __init lcd_linux_init_module(void) -+{ -+ int ret; -+ -+ if (! minors || minors > 256) -+ minors = LCD_MINORS; -+ -+ init_MUTEX(&drivers_sem); -+ -+ if ((ret = register_chrdev(major, LCD_LINUX_STRING, &lcd_linux_fops)) < 0) { -+ printk(KERN_ERR "LCD: register_chrdev failed\n"); -+ return (ret); -+ } -+ if (major == 0) -+ major = ret; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+ if (IS_ERR((lcd_linux_class = class_create(THIS_MODULE, "lcd")))) { -+ ret = PTR_ERR(lcd_linux_class); -+ unregister_chrdev(major, LCD_LINUX_STRING); -+ return (ret); -+ } -+#endif -+ -+#ifdef USE_PROC -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -+ if ((lcd_proc_root = proc_mkdir("lcd", NULL)) == NULL) -+#else -+ if ((lcd_proc_root = proc_mkdir("lcd", &proc_root)) == NULL) -+#endif -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/\n"); -+ else if (create_proc_read_entry("drivers", 0, lcd_proc_root, proc_registered_drivers, NULL) == NULL) -+ printk(KERN_ERR "LCD: cannot create /proc/lcd/drivers\n"); -+#endif -+ -+ printk(KERN_INFO "LCD: --> LCD-Linux " LCD_LINUX_VERSION " <--\n"); -+ printk(KERN_INFO "LCD: --> Mattia Jona-Lasinio <mjona@users.sourceforge.net> <--\n" ); -+ -+ -+ return (0); -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) -+static void __exit lcd_linux_cleanup_module(void) -+#else -+/* __exit is not defined in 2.2.x kernels */ -+static void lcd_linux_cleanup_module(void) -+#endif -+{ -+#ifdef USE_PROC -+ if (lcd_proc_root) { -+ remove_proc_entry("drivers", lcd_proc_root); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26) -+ remove_proc_entry("lcd", NULL); -+#else -+ remove_proc_entry("lcd", &proc_root); -+#endif -+ } -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) -+ class_destroy(lcd_linux_class); -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) -+ unregister_chrdev(major, LCD_LINUX_STRING); -+#else -+ if (unregister_chrdev(major, LCD_LINUX_STRING)) -+ printk(KERN_ERR "LCD: unregister_chrdev failed\n"); -+#endif -+} -+ -+module_init(lcd_linux_init_module) -+module_exit(lcd_linux_cleanup_module) -Index: linux-2.6.30.9/include/linux/hd44780.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/include/linux/hd44780.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,46 @@ -+/* hd44780.h -+ * -+ * -+ * LCD-Linux: -+ * Driver for HD44780 compatible displays connected to the parallel port. -+ * -+ * HD44780 header file. -+ * -+ * Copyright (C) 2004 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifndef HD44780_H -+#define HD44780_H -+ -+#include <linux/lcd-linux.h> -+ -+#define HD44780_VERSION LCD_LINUX_VERSION /* Version number */ -+#define HD44780_STRING "hd44780" -+ -+#define HD44780_MINOR 0 /* Minor number for the hd44780 driver */ -+ -+ -+/* flags */ -+#define HD44780_CHECK_BF 0x00000001 /* Do busy flag checking */ -+#define HD44780_4BITS_BUS 0x00000002 /* Set the bus length to 4 bits */ -+#define HD44780_5X10_FONT 0x00000004 /* Use 5x10 dots fonts */ -+ -+/* IOCTLs */ -+#define HD44780_READ_AC _IOR(LCD_MAJOR, 0x00, unsigned char *) -+ -+#endif /* HD44780 included */ -Index: linux-2.6.30.9/include/linux/lcd-linux.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/include/linux/lcd-linux.h 2009-11-24 02:01:42.000000000 +0100 -@@ -0,0 +1,151 @@ -+/* lcd-linux.h -+ * -+ * -+ * Software layer to drive LCD displays under Linux. -+ * -+ * External interface header file. -+ * -+ * Copyright (C) 2005 - 2007 Mattia Jona-Lasinio (mjona@users.sourceforge.net) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+ -+#ifndef LCD_LINUX_H -+#define LCD_LINUX_H -+ -+#ifndef LCD_LINUX_MAIN -+#warning -+#warning LCD-Linux is still in development stage and -+#warning aims at speed and optimization. For these -+#warning reasons there is no guarantee of backward -+#warning compatibility between different LCD-Linux -+#warning versions. Be sure to use the lcd-linux.h -+#warning file of the same version as the module. -+#warning "http://lcd-linux.sourceforge.net/" -+#warning -+#endif -+ -+#define LCD_LINUX_VERSION "0.13.6" /* Version number */ -+#define LCD_LINUX_STRING "lcd" -+ -+#define LCD_MAJOR 120 /* Major number for this device -+ * Set this to 0 for dynamic allocation -+ */ -+#define LCD_MINORS 8 /* Minors allocated for LCD-Linux*/ -+ -+#include <linux/types.h> -+ -+#define str(s) #s -+#define string(s) str(s) -+ -+struct lcd_parameters { -+ const char *name; /* Driver's name */ -+ unsigned long flags; /* Flags (see documentation) */ -+ unsigned short minor; /* Minor number of the char device */ -+ unsigned short tabstop; /* Tab character length */ -+ unsigned short num_cntr; /* Controllers to drive */ -+ unsigned short cntr_rows; /* Rows per controller */ -+ unsigned short cntr_cols; /* Display columns */ -+ unsigned short vs_rows; /* Virtual screen rows */ -+ unsigned short vs_cols; /* Virtual screen columns */ -+ unsigned short cgram_chars; /* Number of user definable characters */ -+ unsigned short cgram_bytes; /* Number of bytes required to define a -+ * user definable character */ -+ unsigned char cgram_char0; /* Ascii of first user definable character */ -+}; -+ -+/* IOCTLs */ -+#include <asm/ioctl.h> -+#define LCDL_SET_PARAM _IOW(LCD_MAJOR, 0x80, struct lcd_parameters *) -+#define LCDL_GET_PARAM _IOR(LCD_MAJOR, 0x81, struct lcd_parameters *) -+#define LCDL_CHARSUBST _IOW(LCD_MAJOR, 0x82, unsigned char *) -+#define LCDL_RAW_MODE _IOW(LCD_MAJOR, 0x83, unsigned int) -+#define LCDL_RESET_CHARMAP _IO(LCD_MAJOR, 0x84) -+#define LCDL_SAVE_CHARMAP _IO(LCD_MAJOR, 0x85) -+#define LCDL_RESTORE_CHARMAP _IO(LCD_MAJOR, 0x86) -+#define LCDL_SWAP_CHARMAP _IO(LCD_MAJOR, 0x87) -+#define LCDL_CLEAR_DISP _IO(LCD_MAJOR, 0x88) -+#define LCDL_SET_CGRAM_CHAR _IOW(LCD_MAJOR, 0x89, unsigned char *) -+#define LCDL_GET_CGRAM_CHAR _IOR(LCD_MAJOR, 0x8a, unsigned char *) -+#define LCDL_SET_CHARMAP _IOW(LCD_MAJOR, 0x8b, unsigned char *) -+#define LCDL_GET_CHARMAP _IOR(LCD_MAJOR, 0x8c, unsigned char *) -+#define LCDL_MEMSET _IOW(LCD_MAJOR, 0x8d, unsigned int *) -+#define LCDL_MEMMOVE _IOW(LCD_MAJOR, 0x8e, unsigned int *) -+ -+ -+ -+#ifdef __KERNEL__ /* The rest is for kernel only */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+ -+ -+struct lcd_driver { -+ void (*read_char)(unsigned int offset, unsigned short *data); -+ void (*read_cgram_char)(unsigned char index, unsigned char *pixmap); -+ void (*write_char)(unsigned int offset, unsigned short data); -+ void (*write_cgram_char)(unsigned char index, unsigned char *pixmap); -+ void (*clear_display)(void); -+ void (*address_mode)(int mode); -+ int (*validate_driver)(void); -+ int (*init_display)(void); -+ int (*cleanup_display)(void); -+ int (*init_port)(void); -+ int (*cleanup_port)(void); -+ int (*handle_custom_char)(unsigned int data); -+ int (*handle_custom_ioctl)(unsigned int cmd, unsigned long arg, unsigned int arg_in_userspace); -+ -+ /* The character map to be used */ -+ unsigned char *charmap; -+ -+ /* The root where the driver can create its own proc files. -+ * Will be filled by the lcd-linux layer. -+ */ -+ struct proc_dir_entry *driver_proc_root; -+ -+ /* Set this field to 'driver_module_init' or call lcd_driver_setup -+ * just before registering the driver with lcd_register_driver. -+ */ -+ struct module *driver_module; -+}; -+ -+#ifdef MODULE -+#define driver_module_init THIS_MODULE -+#else -+#define driver_module_init NULL -+#endif -+ -+/* Always call lcd_driver_setup just before registering the driver -+ * with lcd_register_driver. -+ */ -+static inline void lcd_driver_setup(struct lcd_driver *p) -+{ -+ p->driver_module = driver_module_init; -+} -+ -+/* External interface */ -+struct lcd_struct; -+int lcd_register_driver(struct lcd_driver *drv, struct lcd_parameters *par); -+int lcd_unregister_driver(struct lcd_driver *drv, struct lcd_parameters *par); -+int lcd_open(unsigned short minor, struct lcd_struct **lcd); -+int lcd_close(struct lcd_struct **lcd); -+int lcd_ioctl(struct lcd_struct *lcd, unsigned int cmd, ...); -+ssize_t lcd_write(struct lcd_struct *lcd, const void *buffer, size_t length, loff_t offset, unsigned int); -+ssize_t lcd_read(struct lcd_struct *lcd, void *buffer, size_t length, loff_t offset, unsigned int); -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* External interface included */ diff --git a/target/linux/ep93xx/patches-2.6.30/003-ep93xx-i2c.patch b/target/linux/ep93xx/patches-2.6.30/003-ep93xx-i2c.patch deleted file mode 100644 index aaf4d3ca8e..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/003-ep93xx-i2c.patch +++ /dev/null @@ -1,225 +0,0 @@ -Index: linux-2.6.30.9/drivers/i2c/busses/Kconfig -=================================================================== ---- linux-2.6.30.9.orig/drivers/i2c/busses/Kconfig 2009-11-24 21:00:21.000000000 +0100 -+++ linux-2.6.30.9/drivers/i2c/busses/Kconfig 2009-11-24 21:00:23.000000000 +0100 -@@ -326,6 +326,10 @@ - devices such as DaVinci NIC. - For details please see http://www.ti.com/davinci - -+config I2C_EP93XX -+ tristate "EP93XX I2C" -+ depends on I2C && ARCH_EP93XX -+ - config I2C_GPIO - tristate "GPIO-based bitbanging I2C" - depends on GENERIC_GPIO -Index: linux-2.6.30.9/drivers/i2c/busses/Makefile -=================================================================== ---- linux-2.6.30.9.orig/drivers/i2c/busses/Makefile 2009-11-24 21:00:21.000000000 +0100 -+++ linux-2.6.30.9/drivers/i2c/busses/Makefile 2009-11-24 21:00:23.000000000 +0100 -@@ -30,6 +30,7 @@ - obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o - obj-$(CONFIG_I2C_CPM) += i2c-cpm.o - obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o -+obj-$(CONFIG_I2C_EP93XX) += i2c-ep93xx.o - obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o - obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o - obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o -Index: linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/i2c/busses/i2c-ep93xx.c 2009-11-24 21:00:38.000000000 +0100 -@@ -0,0 +1,193 @@ -+/* ------------------------------------------------------------------------ * -+ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx * -+ * ------------------------------------------------------------------------ * -+ -+ Copyright (C) 2004 Michael Burian -+ -+ Based on i2c-parport-light.c -+ Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ 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 <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/ioport.h> -+#include <linux/delay.h> -+#include <linux/i2c.h> -+#include <linux/i2c-algo-bit.h> -+#include <asm/io.h> -+#include <mach/hardware.h> -+ -+//1/(2*clockfrequency) -+#define EE_DELAY_USEC 50 -+#define GPIOG_EECLK 1 -+#define GPIOG_EEDAT 2 -+ -+/* ----- I2C algorithm call-back functions and structures ----------------- */ -+ -+// TODO: optimize -+static void ep93xx_setscl(void *data, int state) -+{ -+ unsigned int uiPGDR, uiPGDDR; -+ -+ uiPGDR = inl(GPIO_PGDR); -+ uiPGDDR = inl(GPIO_PGDDR); -+ -+ /* Configure the clock line as output. */ -+ uiPGDDR |= GPIOG_EECLK; -+ outl(uiPGDDR, GPIO_PGDDR); -+ -+ /* Set clock line to state */ -+ if(state) -+ uiPGDR |= GPIOG_EECLK; -+ else -+ uiPGDR &= ~GPIOG_EECLK; -+ -+ outl(uiPGDR, GPIO_PGDR); -+} -+ -+static void ep93xx_setsda(void *data, int state) -+{ -+ unsigned int uiPGDR, uiPGDDR; -+ -+ uiPGDR = inl(GPIO_PGDR); -+ uiPGDDR = inl(GPIO_PGDDR); -+ -+ /* Configure the data line as output. */ -+ uiPGDDR |= GPIOG_EEDAT; -+ outl(uiPGDDR, GPIO_PGDDR); -+ -+ /* Set data line to state */ -+ if(state) -+ uiPGDR |= GPIOG_EEDAT; -+ else -+ uiPGDR &= ~GPIOG_EEDAT; -+ -+ outl(uiPGDR, GPIO_PGDR); -+} -+ -+static int ep93xx_getscl(void *data) -+{ -+ unsigned int uiPGDR, uiPGDDR; -+ -+ uiPGDR = inl(GPIO_PGDR); -+ uiPGDDR = inl(GPIO_PGDDR); -+ -+ /* Configure the clock line as input */ -+ uiPGDDR &= ~GPIOG_EECLK; -+ outl(uiPGDDR, GPIO_PGDDR); -+ -+ /* Return state of the clock line */ -+ return (inl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0; -+} -+ -+static int ep93xx_getsda(void *data) -+{ -+ unsigned int uiPGDR, uiPGDDR; -+ uiPGDR = inl(GPIO_PGDR); -+ uiPGDDR = inl(GPIO_PGDDR); -+ -+ /* Configure the data line as input */ -+ uiPGDDR &= ~GPIOG_EEDAT; -+ outl(uiPGDDR, GPIO_PGDDR); -+ -+ /* Return state of the data line */ -+ return (inl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0; -+} -+ -+/* ------------------------------------------------------------------------ -+ * Encapsulate the above functions in the correct operations structure. -+ * This is only done when more than one hardware adapter is supported. -+ */ -+ -+/* last line (us, ms, timeout) -+ * us dominates the bit rate: 10us means: 100Kbit/sec(25 means 40kbps) -+ * 10ms not known -+ * 100ms timeout -+ */ -+static struct i2c_algo_bit_data ep93xx_data = { -+ .setsda = ep93xx_setsda, -+ .setscl = ep93xx_setscl, -+ .getsda = ep93xx_getsda, -+ .getscl = ep93xx_getscl, -+ .udelay = 10, -+ //.mdelay = 10, -+ .timeout = HZ, -+}; -+ -+/* ----- I2c structure ---------------------------------------------------- */ -+static struct i2c_adapter ep93xx_adapter = { -+ .owner = THIS_MODULE, -+ .class = I2C_CLASS_HWMON, -+ .algo_data = &ep93xx_data, -+ .name = "EP93XX I2C bit-bang interface", -+}; -+ -+/* ----- Module loading, unloading and information ------------------------ */ -+ -+static int __init i2c_ep93xx_init(void) -+{ -+ unsigned long uiPGDR, uiPGDDR; -+ -+ /* Read the current value of the GPIO data and data direction registers. */ -+ uiPGDR = inl(GPIO_PGDR); -+ uiPGDDR = inl(GPIO_PGDDR); -+ -+ /* If the GPIO pins have not been configured since reset, the data -+ * and clock lines will be set as inputs and with data value of 0. -+ * External pullup resisters are pulling them high. -+ * Set them both high before configuring them as outputs. */ -+ uiPGDR |= (GPIOG_EEDAT | GPIOG_EECLK); -+ outl(uiPGDR, GPIO_PGDR); -+ -+ /* Delay to meet the EE Interface timing specification. */ -+ udelay(EE_DELAY_USEC); -+ -+ -+ /* Configure the EE data and clock lines as outputs. */ -+ uiPGDDR |= (GPIOG_EEDAT | GPIOG_EECLK); -+ outl(uiPGDDR, GPIO_PGDDR); -+ -+ /* Delay to meet the EE Interface timing specification. */ -+ udelay(EE_DELAY_USEC); -+ -+ /* Reset hardware to a sane state (SCL and SDA high) */ -+ ep93xx_setsda(NULL, 1); -+ ep93xx_setscl(NULL, 1); -+ -+ if (i2c_bit_add_bus(&ep93xx_adapter) > 0) { -+ printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n"); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit i2c_ep93xx_exit(void) -+{ -+ //i2c_bit_del_bus(&ep93xx_adapter); -+ i2c_del_adapter(&ep93xx_adapter); -+} -+ -+MODULE_AUTHOR("Michael Burian"); -+MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors"); -+MODULE_LICENSE("GPL"); -+ -+module_init(i2c_ep93xx_init); -+module_exit(i2c_ep93xx_exit); diff --git a/target/linux/ep93xx/patches-2.6.30/004-simone-rtc.patch b/target/linux/ep93xx/patches-2.6.30/004-simone-rtc.patch deleted file mode 100644 index 69f2c5a9bd..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/004-simone-rtc.patch +++ /dev/null @@ -1,78 +0,0 @@ ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -661,6 +661,13 @@ static int __devinit ds1307_probe(struct - goto exit_free; - } - -+#if (defined(CONFIG_MACH_SIM_ONE)) -+ /* SIM.ONE board needs 32khz clock on SQW/INTB pin */ -+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, -+ ds1307->regs[0] & ~DS1337_BIT_INTCN); -+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, -+ ds1307->regs[0] | (DS1337_BIT_RS1 | DS1337_BIT_RS2)); -+#endif - /* oscillator off? turn it on, so clock can tick. */ - if (ds1307->regs[0] & DS1337_BIT_nEOSC) - ds1307->regs[0] &= ~DS1337_BIT_nEOSC; ---- a/drivers/rtc/Kconfig -+++ b/drivers/rtc/Kconfig -@@ -570,6 +570,14 @@ config RTC_DRV_EP93XX - This driver can also be built as a module. If so, the module - will be called rtc-ep93xx. - -+config RTC_DRV_EP93XX_DS1337 -+ bool "Cirrus Logic EP93XX using DS1337 chip" -+ depends on RTC_DRV_EP93XX && I2C && MACH_SIM_ONE -+ help -+ If you say yes here, the EP93XX driver will use the -+ battery-backed-up DS1337 RTC chip on the SIM.ONE board. -+ You almost certainly want this. -+ - config RTC_DRV_SA1100 - tristate "SA11x0/PXA2xx" - depends on ARCH_SA1100 || ARCH_PXA ---- a/drivers/rtc/rtc-ep93xx.c -+++ b/drivers/rtc/rtc-ep93xx.c -@@ -13,6 +13,13 @@ - #include <linux/rtc.h> - #include <linux/platform_device.h> - #include <mach/hardware.h> -+#include <asm/io.h> -+ -+#if defined(CONFIG_RTC_DRV_EP93XX_DS1337) -+extern int ds1337_do_command(int id, int cmd, void *arg); -+#define DS1337_GET_DATE 0 -+#define DS1337_SET_DATE 1 -+#endif - - #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) - #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) -@@ -37,16 +44,28 @@ static int ep93xx_get_swcomp(struct devi - - static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) - { -+#if defined(CONFIG_RTC_DRV_EP93XX_DS1337) -+ /* Reroute the internal device to the DS1337 */ -+ return ds1337_do_command(0, DS1337_GET_DATE, (void *)tm); -+#else - unsigned long time = __raw_readl(EP93XX_RTC_DATA); - - rtc_time_to_tm(time, tm); - return 0; -+#endif - } - - static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) - { -+#if defined(CONFIG_RTC_DRV_EP93XX_DS1337) -+ struct rtc_time tm; -+ -+ rtc_time_to_tm(secs, &tm); -+ return ds1337_do_command(0, DS1337_SET_DATE, (void *)&tm); -+#else - __raw_writel(secs + 1, EP93XX_RTC_LOAD); - return 0; -+#endif - } - - static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) diff --git a/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch b/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch deleted file mode 100644 index 3664132021..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/005-ep93xx-dma.patch +++ /dev/null @@ -1,3622 +0,0 @@ ---- /dev/null -+++ b/arch/arm/mach-ep93xx/dma_ep93xx.c -@@ -0,0 +1,2940 @@ -+/****************************************************************************** -+ * arch/arm/mach-ep9312/dma_ep93xx.c -+ * -+ * Support functions for the ep93xx internal DMA channels. -+ * (see also Documentation/arm/ep93xx/dma.txt) -+ * -+ * Copyright (C) 2003 Cirrus Logic -+ * -+ * A large portion of this file is based on the dma api implemented by -+ * Nicolas Pitre, dma-sa1100.c, copyrighted 2000. -+ * -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ ****************************************************************************/ -+#include <linux/autoconf.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/sched.h> -+#include <linux/spinlock.h> -+#include <linux/slab.h> -+#include <linux/errno.h> -+#include <linux/delay.h> -+#include <linux/interrupt.h> -+ -+#include <asm/system.h> -+#include <asm/irq.h> -+#include <asm/hardware.h> -+#include <asm/io.h> -+#include <asm/dma.h> -+#include <asm/mach/dma.h> -+#include "dma_ep93xx.h" -+ -+/***************************************************************************** -+ * -+ * Debugging macros -+ * -+ ****************************************************************************/ -+#undef DEBUG -+//#define DEBUG 1 -+#ifdef DEBUG -+#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) -+#else -+#define DPRINTK( fmt, arg... ) -+#endif -+ -+/***************************************************************************** -+ * -+ * static global variables -+ * -+ ****************************************************************************/ -+ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS]; -+ -+/* -+ * lock used to protect the list of dma channels while searching for a free -+ * channel during dma_request. -+ */ -+//static spinlock_t dma_list_lock; -+static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED; -+ -+/***************************************************************************** -+ * -+ * Internal DMA processing functions. -+ * -+ ****************************************************************************/ -+/***************************************************************************** -+ * -+ * get_dma_channel_from_handle() -+ * -+ * If Handle is valid, returns the DMA channel # (0 to 9 for channels 1-10) -+ * If Handle is not valid, returns -1. -+ * -+ ****************************************************************************/ -+static int -+dma_get_channel_from_handle(int handle) -+{ -+ int channel; -+ -+ /* -+ * Get the DMA channel # from the handle. -+ */ -+ channel = ((int)handle & DMA_HANDLE_SPECIFIER_MASK) >> 28; -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (dma_chan[channel].last_valid_handle != (int)handle) { -+ DPRINTK("DMA ERROR - invalid handle 0x%x \n", handle); -+ return(-1); -+ } -+ -+ /* -+ * See if this instance is still open -+ */ -+ if (!dma_chan[channel].ref_count ) -+ return(-1); -+ -+ return(channel); -+} -+ -+static void dma_m2m_transfer_done(ep93xx_dma_t *dma) -+{ -+ unsigned int uiCONTROL; -+ unsigned int M2M_reg_base = dma->reg_base; -+ unsigned int read_back; -+ -+ DPRINTK("1 "); -+ -+ outl( 0, M2M_reg_base+M2M_OFFSET_INTERRUPT ); -+ -+ if (dma->total_buffers) { -+ /* -+ * The current_buffer has already been tranfered, so add the -+ * byte count to the total_bytes field. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the current_buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ /* -+ * Increment the current_buffer -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ /* -+ * check if there's a new buffer to transfer. -+ */ -+ if (dma->new_buffers && dma->xfer_enable) { -+ /* -+ * We have a new buffer to transfer so program in the -+ * buffer values. Since a STALL interrupt was -+ * triggered, we program the buffer descriptor 0 -+ * -+ * Set the SAR_BASE/DAR_BASE/BCR registers with values -+ * from the next buffer in the queue. -+ */ -+ outl( dma->buffer_queue[dma->current_buffer].source, -+ M2M_reg_base + M2M_OFFSET_SAR_BASE0 ); -+ -+ outl( dma->buffer_queue[dma->current_buffer].dest, -+ M2M_reg_base + M2M_OFFSET_DAR_BASE0 ); -+ -+ outl( dma->buffer_queue[dma->current_buffer].size, -+ M2M_reg_base + M2M_OFFSET_BCR0 ); -+ -+ DPRINTK("SAR_BASE0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].source); -+ DPRINTK("DAR_BASE0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].dest); -+ DPRINTK("BCR0 - 0x%x\n", dma->buffer_queue[dma->current_buffer].size); -+ -+ /* -+ * Decrement the new buffer counter -+ */ -+ dma->new_buffers--; -+ -+ /* -+ * If there's a second new buffer, we program the -+ * second buffer descriptor. -+ */ -+ if (dma->new_buffers) { -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2M_reg_base+M2M_OFFSET_SAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].dest, -+ M2M_reg_base+M2M_OFFSET_DAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2M_reg_base+M2M_OFFSET_BCR1 ); -+ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2M_NFBINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ dma->new_buffers--; -+ } -+ } else { -+ DPRINTK("2 \n"); -+ /* -+ * There's a chance we setup both buffer descriptors, -+ * but didn't service the NFB quickly enough, causing -+ * the channel to transfer both buffers, then enter the -+ * stall state. So, we need to be able to process the -+ * second buffer. -+ */ -+ if ((dma->used_buffers + dma->new_buffers) < dma->total_buffers) -+ { -+ DPRINTK("3 "); -+ -+ /* -+ * The current_buffer has already been -+ * tranferred, so add the byte count to the -+ * total_bytes field. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the current_buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ /* -+ * Increment the current buffer pointer. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ } -+ -+ /* -+ * No new buffers to transfer, so disable the channel. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Indicate that this channel is in the pause by -+ * starvation state by setting the pause bit to true. -+ */ -+ dma->pause = TRUE; -+ } -+ } else { -+ /* -+ * No buffers to transfer, or old buffers to mark as used, -+ * so disable the channel -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Must read the control register back after a write. -+ */ -+ read_back = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ -+ /* -+ * Indicate that this channel is in the pause by -+ * starvation state by setting the pause bit to true. -+ */ -+ dma->pause = TRUE; -+ } -+} -+ -+static void dma_m2m_next_frame_buffer(ep93xx_dma_t *dma) -+{ -+ int loop; -+ unsigned int uiCONTROL; -+ unsigned int M2M_reg_base = dma->reg_base; -+ -+ DPRINTK("5 "); -+ -+ if (dma->total_buffers) { -+ DPRINTK("6 "); -+ /* -+ * The iCurrentBuffer has already been transfered. so add the -+ * byte count from the current buffer to the total byte count. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the Current Buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ if ((dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].last) || -+ (dma->new_buffers == 0) || (dma->xfer_enable == FALSE)) { -+ DPRINTK("7 "); -+ -+ /* -+ * This is the last Buffer in this transaction, so -+ * disable the NFB interrupt. We shouldn't get an NFB -+ * int when the FSM moves to the ON state where it -+ * would typically get the NFB int indicating a new -+ * buffer can be programmed. Instead, once in the ON -+ * state, the DMA will just proceed to complete the -+ * transfer of the current buffer, move the FSB -+ * directly to the STALL state where a STALL interrupt -+ * will be generated. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_NFBINTEN ; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * The current buffer has been transferred, so -+ * increment the current buffer counter to reflect -+ * this. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ DPRINTK("End of NFB handling. \n"); -+ DPRINTK("CONTROL - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_CONTROL) ); -+ DPRINTK("STATUS - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_STATUS) ); -+ DPRINTK("SAR_BASE0 - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_SAR_BASE0) ); -+ DPRINTK("SAR_CUR0 - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_SAR_CURRENT0) ); -+ DPRINTK("DAR_BASE0 - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_DAR_BASE0) ); -+ DPRINTK("DAR_CUR0 - 0x%x \n", -+ inl(M2M_reg_base+M2M_OFFSET_DAR_CURRENT0) ); -+ -+ DPRINTK("Buffer buf_id source size last used \n"); -+ for (loop = 0; loop < 32; loop ++) -+ DPRINTK("%d 0x%x 0x%x 0x%x %d %d \n", -+ loop, dma->buffer_queue[loop].buf_id, -+ dma->buffer_queue[loop].source, -+ dma->buffer_queue[loop].size, -+ dma->buffer_queue[loop].last, -+ dma->buffer_queue[loop].used); -+ DPRINTK("pause 0x%x 0x%x 0x%x %d %d \n", -+ dma->pause_buf.buf_id, dma->pause_buf.source, -+ dma->pause_buf.size, dma->pause_buf.last, -+ dma->pause_buf.used); -+ -+ DPRINTK("Pause - %d \n", dma->pause); -+ DPRINTK("xfer_enable - %d \n", dma->xfer_enable); -+ DPRINTK("total bytes - 0x%x \n", dma->total_bytes); -+ DPRINTK("total buffer - %d \n", dma->total_buffers); -+ DPRINTK("new buffers - %d \n", dma->new_buffers); -+ DPRINTK("current buffer - %d \n", dma->current_buffer); -+ DPRINTK("last buffer - %d \n", dma->last_buffer); -+ DPRINTK("used buffers - %d \n", dma->used_buffers); -+ DPRINTK("callback addr - 0x%p \n", dma->callback); -+ -+ } else if (dma->new_buffers) { -+ DPRINTK("8 "); -+ /* -+ * We have a new buffer, so increment the current -+ * buffer to point to the next buffer, which is already -+ * programmed into the DMA. Next time around, it'll be -+ * pointing to the current buffer. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ /* -+ * We know we have a new buffer to program as the next -+ * buffer, so check which set of SAR_BASE/DAR_BASE/BCR -+ * registers to program. -+ */ -+ if ( inl(M2M_reg_base+M2M_OFFSET_STATUS) & STATUS_M2M_NB ) { -+ /* -+ * Set the SAR_BASE1/DAR_BASE1/BCR1 registers -+ * with values from the next buffer in the -+ * queue. -+ */ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2M_reg_base+M2M_OFFSET_SAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].dest, -+ M2M_reg_base+M2M_OFFSET_DAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2M_reg_base+M2M_OFFSET_BCR1 ); -+ } else { -+ /* -+ * Set the SAR_BASE0/DAR_BASE0/BCR0 registers -+ * with values from the next buffer in the -+ * queue. -+ */ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2M_reg_base+M2M_OFFSET_SAR_BASE0 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].dest, -+ M2M_reg_base+M2M_OFFSET_DAR_BASE0 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2M_reg_base+M2M_OFFSET_BCR0 ); -+ } -+ -+ /* -+ * Decrement the new buffers counter -+ */ -+ dma->new_buffers--; -+ } -+ } else { -+ /* -+ * Total number of buffers is 0 - really we should never get -+ * here, but just in case. -+ */ -+ DPRINTK("9 \n"); -+ -+ /* -+ * No new buffers to transfer, so Disable the channel -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Indicate that the channel is paused by starvation. -+ */ -+ dma->pause = 1; -+ } -+} -+ -+/***************************************************************************** -+ * -+ * dma_m2m_irq_handler -+ * -+ ****************************************************************************/ -+static irqreturn_t -+dma_m2m_irq_handler(int irq, void *dev_id) -+{ -+ ep93xx_dma_t *dma = (ep93xx_dma_t *)dev_id; -+ unsigned int M2M_reg_base = dma->reg_base; -+ ep93xx_dma_dev_t dma_int = UNDEF_INT; -+ int status; -+ -+// printk("+m2m irq=%d\n", irq); -+ -+ /* -+ * Determine what kind of dma interrupt this is. -+ */ -+ status = inl(M2M_reg_base + M2M_OFFSET_INTERRUPT); -+ if ( status & INTERRUPT_M2M_DONEINT ) -+ dma_int = DONE; // we're done with a requested dma -+ else if ( status & INTERRUPT_M2M_NFBINT ) -+ dma_int = NFB; // we're done with one dma buffer -+ -+ DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer, dma_int); -+ -+ switch (dma_int) { -+ /* -+ * Next Frame Buffer Interrupt. If there's a new buffer program it -+ * Check if this is the last buffer in the transfer, -+ * and if it is, disable the NFB int to prevent being -+ * interrupted for another buffer when we know there won't be -+ * another. -+ */ -+ case NFB: -+ dma_m2m_next_frame_buffer(dma); -+ break; -+ /* -+ * Done interrupt generated, indicating that the transfer is complete. -+ */ -+ case DONE: -+ dma_m2m_transfer_done(dma); -+ break; -+ -+ default: -+ break; -+ } -+ -+ if ((dma_int != UNDEF_INT) && dma->callback) -+ dma->callback(dma_int, dma->device, dma->user_data); -+ -+ return IRQ_HANDLED; -+} -+ -+/***************************************************************************** -+ * -+ * dma_m2p_irq_handler -+ * -+ * -+ * -+ ****************************************************************************/ -+static irqreturn_t -+dma_m2p_irq_handler(int irq, void *dev_id) -+{ -+ ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id; -+ unsigned int M2P_reg_base = dma->reg_base; -+ unsigned int read_back; -+ ep93xx_dma_dev_t dma_int = UNDEF_INT; -+ unsigned int loop, uiCONTROL, uiINTERRUPT; -+ -+ /* -+ * Determine what kind of dma interrupt this is. -+ */ -+ if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_STALLINT ) -+ dma_int = STALL; -+ else if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_NFBINT ) -+ dma_int = NFB; -+ else if ( inl(M2P_reg_base+M2P_OFFSET_INTERRUPT) & INTERRUPT_M2P_CHERRORINT ) -+ dma_int = CHERROR; -+ -+ /* -+ * Stall Interrupt: The Channel is stalled, meaning nothing is -+ * programmed to transfer right now. So, we're back to the -+ * beginnning. If there's a buffer to transfer, program it into -+ * max and base 0 registers. -+ */ -+ if (dma_int == STALL) { -+ DPRINTK("1 "); -+ -+ if (dma->total_buffers) { -+ /* -+ * The current_buffer has already been tranfered, so -+ * add the byte count to the total_bytes field. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the current_buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ /* -+ * Increment the current_buffer -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ /* -+ * check if there's a new buffer to transfer. -+ */ -+ if (dma->new_buffers && dma->xfer_enable) { -+ /* -+ * We have a new buffer to transfer so program -+ * in the buffer values. Since a STALL -+ * interrupt was triggered, we program the -+ * base0 and maxcnt0 -+ * -+ * Set the MAXCNT0 register with the buffer -+ * size -+ */ -+ outl( dma->buffer_queue[dma->current_buffer].size, -+ M2P_reg_base+M2P_OFFSET_MAXCNT0 ); -+ -+ /* -+ * Set the BASE0 register with the buffer base -+ * address -+ */ -+ outl( dma->buffer_queue[dma->current_buffer].source, -+ M2P_reg_base+M2P_OFFSET_BASE0 ); -+ -+ /* -+ * Decrement the new buffer counter -+ */ -+ dma->new_buffers--; -+ -+ if (dma->new_buffers) { -+ DPRINTK("A "); -+ /* -+ * Set the MAXCNT1 register with the -+ * buffer size -+ */ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2P_reg_base+M2P_OFFSET_MAXCNT1 ); -+ -+ /* -+ * Set the BASE1 register with the -+ * buffer base address -+ */ -+ outl( dma->buffer_queue[dma->current_buffer + 1 % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2P_reg_base+M2P_OFFSET_BASE1 ); -+ -+ /* -+ * Decrement the new buffer counter -+ */ -+ dma->new_buffers--; -+ -+ /* -+ * Enable the NFB Interrupt. -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2P_NFBINTEN; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ } -+ } else { -+ /* -+ * No new buffers. -+ */ -+ DPRINTK("2 \n"); -+ -+ /* -+ * There's a chance we setup both buffer descriptors, but -+ * didn't service the NFB quickly enough, causing the channel -+ * to transfer both buffers, then enter the stall state. -+ * So, we need to be able to process the second buffer. -+ */ -+ if ((dma->used_buffers + dma->new_buffers) < dma->total_buffers) { -+ DPRINTK("3 "); -+ -+ /* -+ * The current_buffer has already been tranfered, so add the -+ * byte count to the total_bytes field. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the current_buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ /* -+ * Increment the current buffer pointer. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS; -+ -+ } -+ -+ /* -+ * No new buffers to transfer, so disable the channel. -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Indicate that this channel is in the pause by starvation -+ * state by setting the pause bit to true. -+ */ -+ dma->pause = TRUE; -+ -+ DPRINTK("STATUS - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_STATUS) ); -+ DPRINTK("CONTROL - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CONTROL) ); -+ DPRINTK("REMAIN - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_REMAIN) ); -+ DPRINTK("PPALLOC - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_PPALLOC) ); -+ DPRINTK("BASE0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE0) ); -+ DPRINTK("MAXCNT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) ); -+ DPRINTK("CURRENT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT0) ); -+ DPRINTK("BASE1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE1) ); -+ DPRINTK("MAXCNT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) ); -+ DPRINTK("CURRENT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT1) ); -+ -+ DPRINTK("Buffer buf_id source size last used \n"); -+ for (loop = 0; loop < 32; loop ++) -+ DPRINTK("%d 0x%x 0x%x 0x%x %d %d \n", -+ loop, dma->buffer_queue[loop].buf_id, dma->buffer_queue[loop].source, -+ dma->buffer_queue[loop].size, -+ dma->buffer_queue[loop].last, dma->buffer_queue[loop].used); -+ DPRINTK("pause 0x%x 0x%x 0x%x %d %d \n", -+ dma->pause_buf.buf_id, dma->pause_buf.source, dma->pause_buf.size, -+ dma->pause_buf.last, dma->pause_buf.used); -+ -+ DPRINTK("Pause - %d \n", dma->pause); -+ DPRINTK("xfer_enable - %d \n", dma->xfer_enable); -+ DPRINTK("total bytes - 0x%x \n", dma->total_bytes); -+ DPRINTK("total buffer - %d \n", dma->total_buffers); -+ DPRINTK("new buffers - %d \n", dma->new_buffers); -+ DPRINTK("current buffer - %d \n", dma->current_buffer); -+ DPRINTK("last buffer - %d \n", dma->last_buffer); -+ DPRINTK("used buffers - %d \n", dma->used_buffers); -+ DPRINTK("callback addr - 0x%p \n", dma->callback); -+ } -+ } else { -+ /* -+ * No buffers to transfer, or old buffers to mark as used, -+ * so Disable the channel -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Must read the control register back after a write. -+ */ -+ read_back = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ -+ /* -+ * Indicate that this channel is in the pause by -+ * starvation state by setting the pause bit to true. -+ */ -+ dma->pause = TRUE; -+ } -+ } -+ -+ /* -+ * Next Frame Buffer Interrupt. If there's a new buffer program it -+ * Check if this is the last buffer in the transfer, -+ * and if it is, disable the NFB int to prevent being -+ * interrupted for another buffer when we know there won't be -+ * another. -+ */ -+ if (dma_int == NFB) { -+ DPRINTK("5 "); -+ -+ if (dma->total_buffers) { -+ DPRINTK("6 "); -+ /* -+ * The iCurrentBuffer has already been transfered. so add the -+ * byte count from the current buffer to the total byte count. -+ */ -+ dma->total_bytes = dma->total_bytes + -+ dma->buffer_queue[dma->current_buffer].size; -+ -+ /* -+ * Mark the Current Buffer as used. -+ */ -+ dma->buffer_queue[dma->current_buffer].used = TRUE; -+ -+ /* -+ * Increment the used buffer counter -+ */ -+ dma->used_buffers++; -+ -+ DPRINTK("#%d", dma->current_buffer); -+ -+ if ((dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].last) || -+ (dma->new_buffers == 0) || (dma->xfer_enable == FALSE)) { -+ DPRINTK("7 "); -+ -+ /* -+ * This is the last Buffer in this transaction, so disable -+ * the NFB interrupt. We shouldn't get an NFB int when the -+ * FSM moves to the ON state where it would typically get the -+ * NFB int indicating a new buffer can be programmed. -+ * Instead, once in the ON state, the DMA will just proceed -+ * to complet the transfer of the current buffer, move the -+ * FSB directly to the STALL state where a STALL interrupt -+ * will be generated. -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_NFBINTEN; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * The current buffer has been transferred, so increment -+ * the current buffer counter to reflect this. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS; -+ -+ DPRINTK("End of NFB handling. \n"); -+ DPRINTK("STATUS - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_STATUS) ); -+ DPRINTK("CONTROL - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CONTROL) ); -+ DPRINTK("REMAIN - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_REMAIN) ); -+ DPRINTK("PPALLOC - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_PPALLOC) ); -+ DPRINTK("BASE0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE0) ); -+ DPRINTK("MAXCNT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) ); -+ DPRINTK("CURRENT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT0) ); -+ DPRINTK("BASE1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE1) ); -+ DPRINTK("MAXCNT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) ); -+ DPRINTK("CURRENT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT1) ); -+ -+ DPRINTK("Buffer buf_id source size last used \n"); -+ for (loop = 0; loop < 32; loop ++) -+ DPRINTK("%d 0x%x 0x%x 0x%x %d %d \n", -+ loop, dma->buffer_queue[loop].buf_id, dma->buffer_queue[loop].source, -+ dma->buffer_queue[loop].size, -+ dma->buffer_queue[loop].last, dma->buffer_queue[loop].used); -+ DPRINTK("pause 0x%x 0x%x 0x%x %d %d \n", -+ dma->pause_buf.buf_id, dma->pause_buf.source, dma->pause_buf.size, -+ dma->pause_buf.last, dma->pause_buf.used); -+ -+ DPRINTK("Pause - %d \n", dma->pause); -+ DPRINTK("xfer_enable - %d \n", dma->xfer_enable); -+ DPRINTK("total bytes - 0x%x \n", dma->total_bytes); -+ DPRINTK("total buffer - %d \n", dma->total_buffers); -+ DPRINTK("new buffers - %d \n", dma->new_buffers); -+ DPRINTK("current buffer - %d \n", dma->current_buffer); -+ DPRINTK("last buffer - %d \n", dma->last_buffer); -+ DPRINTK("used buffers - %d \n", dma->used_buffers); -+ DPRINTK("callback addr - 0x%p \n", dma->callback); -+ -+ } else if (dma->new_buffers) { -+ DPRINTK("8 "); -+ /* -+ * we have a new buffer, so increment the current buffer to -+ * point to the next buffer, which is already programmed into -+ * the DMA. Next time around, it'll be pointing to the -+ * current buffer. -+ */ -+ dma->current_buffer = (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS; -+ -+ /* -+ * we know we have a new buffer to program as the next -+ * buffer, so check which set of MAXCNT and BASE registers -+ * to program. -+ */ -+ if ( inl(M2P_reg_base+M2P_OFFSET_STATUS) & STATUS_M2P_NEXTBUFFER ) { -+ /* -+ * Set the MAXCNT1 register with the buffer size -+ */ -+ outl( dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].size, -+ M2P_reg_base+M2P_OFFSET_MAXCNT1 ); -+ -+ /* -+ * Set the BASE1 register with the buffer base address -+ */ -+ outl( dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].source, -+ M2P_reg_base+M2P_OFFSET_BASE1 ); -+ } else { -+ /* -+ * Set the MAXCNT0 register with the buffer size -+ */ -+ outl( dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].size, -+ M2P_reg_base+M2P_OFFSET_MAXCNT0 ); -+ -+ /* -+ * Set the BASE0 register with the buffer base address -+ */ -+ outl( dma->buffer_queue[ -+ (dma->current_buffer + 1) % MAX_EP93XX_DMA_BUFFERS].source, -+ M2P_reg_base+M2P_OFFSET_BASE0 ); -+ } -+ -+ /* -+ * Decrement the new buffers counter -+ */ -+ dma->new_buffers--; -+ } -+ } else { -+ /* -+ * Total number of buffers is 0 - really we should never get here, -+ * but just in case. -+ */ -+ DPRINTK("9 \n"); -+ -+ /* -+ * No new buffers to transfer, so Disable the channel -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ } -+ } -+ -+ /* -+ * Channel Error Interrupt, or perhipheral interrupt, specific to the -+ * memory to/from peripheral channels. -+ */ -+ if (dma_int == CHERROR) { -+ /* -+ * just clear the interrupt, it's really up to the peripheral -+ * driver to determine if any further action is necessary. -+ */ -+ uiINTERRUPT = inl(M2P_reg_base+M2P_OFFSET_INTERRUPT); -+ uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT; -+ outl( uiINTERRUPT, M2P_reg_base+M2P_OFFSET_INTERRUPT ); -+ } -+ -+ /* -+ * Make sure the interrupt was valid, and if it was, then check -+ * if a callback function was installed for this DMA channel. If a -+ * callback was installed call it. -+ */ -+ if ((dma_int != UNDEF_INT) && dma->callback) -+ dma->callback(dma_int, dma->device, dma->user_data); -+ -+ return IRQ_HANDLED; -+} -+ -+/***************************************************************************** -+ * -+ * ep9312_dma_open_m2p(int device) -+ * -+ * Description: This function will attempt to open a M2P/P2M DMA channel. -+ * If the open is successful, the channel number is returned, -+ * otherwise a negative number is returned. -+ * -+ * Parameters: -+ * device: device for which the dma channel is requested. -+ * -+ ****************************************************************************/ -+static int -+dma_open_m2p(int device) -+{ -+ int channel = -1; -+ unsigned int loop; -+ unsigned int M2P_reg_base; -+ unsigned int uiPWRCNT; -+ /*unsigned long flags;*/ -+ -+ DPRINTK("DMA Open M2P with hw dev %d\n", device); -+ -+ /* -+ * Lock the dma channel list. -+ */ -+ //spin_lock_irqsave(&dma_list_lock, flags); -+ spin_lock(&dma_list_lock); -+ -+ /* -+ * Verify that the device requesting DMA isn't already using a DMA channel -+ */ -+ if (device >= 10) -+ loop = 1; // Rx transfer requested -+ else -+ loop = 0; // Tx transfer requested -+ -+ for (; loop < 10; loop = loop + 2) -+ /* -+ * Before checking for a matching device, check that the -+ * channel is in use, otherwise the device field is -+ * invalid. -+ */ -+ if (dma_chan[loop].ref_count) -+ if (device == dma_chan[loop].device) { -+ DPRINTK("DMA Open M2P - Error\n"); -+ return(-1); -+ } -+ -+ /* -+ * Get a DMA channel instance for the given hardware device. -+ * If this is a TX look for even numbered channels, else look for -+ * odd numbered channels -+ */ -+ if (device >= 10) -+ loop = 1; /* Rx transfer requested */ -+ else -+ loop = 0; /* Tx transfer requested */ -+ -+ for (; loop < 10; loop = loop + 2) -+ if (!dma_chan[loop].ref_count) { -+ /* -+ * Capture the channel and increment the reference count. -+ */ -+ channel = loop; -+ dma_chan[channel].ref_count++; -+ break; -+ } -+ -+ /* -+ * Unlock the dma channel list. -+ */ -+ //spin_unlock_irqrestore(&dma_list_lock, flags); -+ spin_unlock(&dma_list_lock); -+ /* -+ * See if we got a valid channel. -+ */ -+ if (channel < 0) -+ return(-1); -+ -+ /* -+ * Point regs to the correct dma channel register base. -+ */ -+ M2P_reg_base = dma_chan[channel].reg_base; -+ -+ /* -+ * Turn on the clock for the specified DMA channel -+ * TODO: need to use the correct register name for the -+ * power control register. -+ */ -+ uiPWRCNT = inl(/*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL); -+ switch (channel) { -+ case 0: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH0; -+ break; -+ -+ case 1: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH1; -+ break; -+ -+ case 2: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH2; -+ break; -+ -+ case 3: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH3; -+ break; -+ -+ case 4: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH4; -+ break; -+ -+ case 5: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH5; -+ break; -+ -+ case 6: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH6; -+ break; -+ -+ case 7: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH7; -+ break; -+ -+ case 8: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH8; -+ break; -+ -+ case 9: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH9; -+ break; -+ -+ default: -+ return(-1); -+ } -+ outl( uiPWRCNT, /*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL ); -+ -+ /* -+ * Clear out the control register before any further setup. -+ */ -+ outl( 0, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Setup the peripheral port value in the DMA channel registers. -+ */ -+ if (device < 10) -+ outl( (unsigned int)device, M2P_reg_base+M2P_OFFSET_PPALLOC ); -+ else -+ outl( (unsigned int)(device - 10), M2P_reg_base+M2P_OFFSET_PPALLOC ); -+ -+ /* -+ * Let's hold on to the value of the Hw device for comparison later. -+ */ -+ dma_chan[channel].device = device; -+ -+ /* -+ * Success. -+ */ -+ return(channel); -+} -+ -+/***************************************************************************** -+ * -+ * dma_open_m2m(int device) -+ * -+ * Description: This function will attempt to open a M2M DMA channel. -+ * If the open is successful, the channel number is returned, -+ * otherwise a negative number is returned. -+ * -+ * Parameters: -+ * device: device for which the dma channel is requested. -+ * -+ ****************************************************************************/ -+static int -+dma_open_m2m(int device) -+{ -+ int channel = -1; -+ unsigned int loop; -+ unsigned int M2M_reg_base; -+ unsigned int uiPWRCNT, uiCONTROL; -+ /*unsigned long flags;*/ -+ -+ DPRINTK("DMA Open M2M with hw dev %d\n", device); -+ -+ /* -+ * Lock the dma channel list. -+ */ -+ //spin_lock_irqsave(&dma_list_lock, flags); -+ spin_lock(&dma_list_lock); -+ -+ -+ /* -+ * Check if this device is already allocated a channel. -+ * TODO: can one M2M device be allocated multiple channels? -+ */ -+ for (loop = 10; loop < 12; loop++) -+ /* -+ * Before checking for a matching device, check that the -+ * channel is in use, otherwise the device field is -+ * invalid. -+ */ -+ if (dma_chan[loop].ref_count) -+ if (device == dma_chan[loop].device) { -+ DPRINTK("Error - dma_open_m2m - already allocated channel\n"); -+ -+ /* -+ * Unlock the dma channel list. -+ */ -+ //spin_unlock_irqrestore(&dma_list_lock, flags); -+ spin_unlock(&dma_list_lock); -+ /* -+ * Fail. -+ */ -+ return(-1); -+ } -+ -+ /* -+ * Get a DMA channel instance for the given hardware device. -+ */ -+ for (loop = 10; loop < 12; loop++) -+ if (!dma_chan[loop].ref_count) { -+ /* -+ * Capture the channel and increment the reference count. -+ */ -+ channel = loop; -+ dma_chan[channel].ref_count++; -+ break; -+ } -+ -+ /* -+ * Unlock the dma channel list. -+ */ -+ //spin_unlock(dma_list_lock); -+ spin_unlock(&dma_list_lock); -+ //spin_unlock_irqrestore(&dma_list_lock, flags); -+ -+ /* -+ * See if we got a valid channel. -+ */ -+ if (channel < 0) -+ return(-1); -+ -+ /* -+ * Point regs to the correct dma channel register base. -+ */ -+ M2M_reg_base = dma_chan[channel].reg_base; -+ -+ /* -+ * Turn on the clock for the specified DMA channel -+ * TODO: need to use the correct register name for the -+ * power control register. -+ */ -+ uiPWRCNT = inl(/*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL); -+ switch (channel) { -+ case 10: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0; -+ break; -+ -+ case 11: -+ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1; -+ break; -+ -+ default: -+ return(-1); -+ } -+ outl( uiPWRCNT, /*SYSCON_PWRCNT*/EP93XX_SYSCON_CLOCK_CONTROL); -+ -+ DPRINTK("DMA Open - power control: 0x%x \n", inl(SYSCON_PWRCNT) ); -+ -+ /* -+ * Clear out the control register before any further setup. -+ */ -+ outl( 0, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Setup the transfer mode and the request source selection within -+ * the DMA M2M channel registers. -+ */ -+ switch (device) { -+ case DMA_MEMORY: -+ /* -+ * Clear TM field, set RSS field to 0 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK); -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ break; -+ -+ case DMA_IDE: -+ /* -+ * Set RSS field to 3, Set NO_HDSK, Set PW field to 1 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_PW_MASK); -+ uiCONTROL |= (3<<CONTROL_M2M_RSS_SHIFT) | -+ CONTROL_M2M_NO_HDSK | -+ (2<<CONTROL_M2M_PW_SHIFT); -+ -+ uiCONTROL &= ~(CONTROL_M2M_ETDP_MASK); -+ uiCONTROL &= ~(CONTROL_M2M_DACKP); -+ uiCONTROL &= ~(CONTROL_M2M_DREQP_MASK); -+ -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ break; -+ -+ case DMARx_SSP: -+ /* -+ * Set RSS field to 1, Set NO_HDSK, Set TM field to 2 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK); -+ uiCONTROL |= (1<<CONTROL_M2M_RSS_SHIFT) | -+ CONTROL_M2M_NO_HDSK | -+ (2<<CONTROL_M2M_TM_SHIFT); -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ break; -+ -+ case DMATx_SSP: -+ /* -+ * Set RSS field to 2, Set NO_HDSK, Set TM field to 1 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK); -+ uiCONTROL |= (2<<CONTROL_M2M_RSS_SHIFT) | -+ CONTROL_M2M_NO_HDSK | -+ (1<<CONTROL_M2M_TM_SHIFT); -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ break; -+ -+ case DMATx_EXT_DREQ: -+ /* -+ * Set TM field to 2, set RSS field to 0 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK); -+ uiCONTROL |= 1<<CONTROL_M2M_TM_SHIFT; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ break; -+ -+ case DMARx_EXT_DREQ: -+ /* -+ * Set TM field to 2, set RSS field to 0 -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~(CONTROL_M2M_RSS_MASK|CONTROL_M2M_TM_MASK); -+ uiCONTROL |= 2<<CONTROL_M2M_TM_SHIFT; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ break; -+ -+ default: -+ return -1; -+ } -+ -+ /* -+ * Let's hold on to the value of the Hw device for comparison later. -+ */ -+ dma_chan[channel].device = device; -+ -+ /* -+ * Success. -+ */ -+ return(channel); -+} -+ -+/***************************************************************************** -+ * -+ * int dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m, -+ * dma_callback callback, unsigned int user_data) -+ * -+ * Description: Configure the DMA channel and install a callback function. -+ * This function will have to be called for every transfer -+ * -+ * dma: Pointer to the dma instance data for the M2M channel to -+ * configure. -+ * flags_m2m Flags used to configure an M2M dma channel and determine -+ * if a callback function and user_data information are included -+ * in this call. -+ * callback function pointer which is called near the end of the -+ * dma channel's irq handler. -+ * user_data defined by the calling driver. -+ * -+ ****************************************************************************/ -+static int -+dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m, -+ dma_callback callback, unsigned int user_data) -+{ -+ unsigned long flags; -+ unsigned int M2M_reg_base, uiCONTROL; -+ -+ /* -+ * Make sure the channel is disabled before configuring the channel. -+ * -+ * TODO: Is this correct?? Making a big change here... -+ */ -+ /* if (!dma->pause || (!dma->pause && dma->xfer_enable)) */ -+ if (dma->xfer_enable) { -+ /* -+ * DMA channel is not paused, so we can't configure it. -+ */ -+ DPRINTK("DMA channel not paused, so can't configure! \n"); -+ return(-1); -+ } -+ -+ /* -+ * Mask interrupts. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Setup a pointer into the dma channel's register set. -+ */ -+ M2M_reg_base = dma->reg_base; -+ -+ uiCONTROL = inl(M2M_reg_base + M2M_OFFSET_CONTROL); -+ outl(0, M2M_reg_base + M2M_OFFSET_CONTROL); -+ inl(M2M_reg_base + M2M_OFFSET_CONTROL); -+ outl(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); -+ -+ /* -+ * By default we disable the stall interrupt. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_STALLINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * By default we disable the done interrupt. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_DONEINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Set up the transfer control fields based on values passed in -+ * the flags_m2m field. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ -+ if ( flags_m2m & DESTINATION_HOLD ) -+ uiCONTROL |= CONTROL_M2M_DAH; -+ else -+ uiCONTROL &= ~CONTROL_M2M_DAH; -+ -+ if ( flags_m2m & SOURCE_HOLD ) -+ uiCONTROL |= CONTROL_M2M_SAH; -+ else -+ uiCONTROL &= ~CONTROL_M2M_SAH; -+ -+ uiCONTROL &= ~CONTROL_M2M_TM_MASK; -+ uiCONTROL |= (((flags_m2m & TRANSFER_MODE_MASK) >> TRANSFER_MODE_SHIFT) << -+ CONTROL_M2M_TM_SHIFT) & CONTROL_M2M_TM_MASK; -+ -+ uiCONTROL &= ~CONTROL_M2M_PWSC_MASK; -+ uiCONTROL |= (((flags_m2m & WAIT_STATES_MASK) >> WAIT_STATES_SHIFT) << -+ CONTROL_M2M_PWSC_SHIFT) & CONTROL_M2M_PWSC_MASK; -+ -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ inl(M2M_reg_base + M2M_OFFSET_CONTROL); -+ -+ /* -+ * Save the callback function in the dma instance for this channel. -+ */ -+ dma->callback = callback; -+ -+ /* -+ * Save the user data in the the dma instance for this channel. -+ */ -+ dma->user_data = user_data; -+ -+ /* -+ * Put the dma instance into the pause state by setting the -+ * pause bit to true. -+ */ -+ dma->pause = TRUE; -+ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int dma_start(int handle, unsigned int channels, unsigned int * handles) -+ * -+ * Description: Initiate a transfer on up to 3 channels. -+ * -+ * handle: handle for the channel to initiate transfer on. -+ * channels: number of channels to initiate transfers on. -+ * handles: pointer to an array of handles, one for each channel which -+ * is to be started. -+ * -+ ****************************************************************************/ -+static int -+dma_start_m2m(int channel, ep93xx_dma_t * dma) -+{ -+ unsigned long flags; -+ unsigned int M2M_reg_base = dma->reg_base; -+ unsigned int uiCONTROL; -+ -+ /* -+ * Mask interrupts while we get this started. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Make sure the channel has at least one buffer in the queue. -+ */ -+ if (dma->new_buffers < 1) { -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ DPRINTK("DMA Start: Channel starved.\n"); -+ -+ /* -+ * This channel does not have enough buffers queued up, -+ * so enter the pause by starvation state. -+ */ -+ dma->xfer_enable = TRUE; -+ dma->pause = TRUE; -+ -+ /* -+ * Success. -+ */ -+ return(0); -+ } -+ -+ /* -+ * Clear any pending interrupts. -+ */ -+ outl(0x0, M2M_reg_base+M2M_OFFSET_INTERRUPT); -+ -+ /* -+ * Set up one or both buffer descriptors with values from the next one or -+ * two buffers in the queue. By default disable the next frame buffer -+ * interrupt on the channel. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_NFBINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * enable the done interrupt. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2M_DONEINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ /* -+ * Update the dma channel instance transfer state. -+ */ -+ dma->xfer_enable = TRUE; -+ dma->pause = FALSE; -+ -+ /* -+ * Program up the first buffer descriptor with a source and destination -+ * and a byte count. -+ */ -+ outl( dma->buffer_queue[dma->current_buffer].source, -+ M2M_reg_base+M2M_OFFSET_SAR_BASE0 ); -+ -+ outl( dma->buffer_queue[dma->current_buffer].dest, -+ M2M_reg_base+M2M_OFFSET_DAR_BASE0 ); -+ -+ outl( dma->buffer_queue[dma->current_buffer].size, -+ M2M_reg_base+M2M_OFFSET_BCR0 ); -+ -+ /* -+ * Decrement the new buffers counter. -+ */ -+ dma->new_buffers--; -+ -+ /* -+ * Set up the second buffer descriptor with a second buffer if we have -+ * a second buffer. -+ */ -+ if (dma->new_buffers) { -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2M_reg_base+M2M_OFFSET_SAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].dest, -+ M2M_reg_base+M2M_OFFSET_DAR_BASE1 ); -+ -+ outl( dma->buffer_queue[(dma->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2M_reg_base+M2M_OFFSET_BCR1 ); -+ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2M_NFBINTEN; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ -+ dma->new_buffers--; -+ } -+ -+ /* -+ * Now we enable the channel. This initiates the transfer. -+ */ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ inl(M2M_reg_base + M2M_OFFSET_CONTROL); -+ -+ /* -+ * If this is a memory to memory transfer, we need to s/w trigger the -+ * transfer by setting the start bit within the control register. -+ */ -+ if (dma->device == DMA_MEMORY) { -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2M_START; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ } -+ -+ DPRINTK("DMA - It's been started!!"); -+ DPRINTK("CONTROL - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_CONTROL) ); -+ DPRINTK("STATUS - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_STATUS) ); -+ DPRINTK("BCR0 - 0x%x \n", dma->buffer_queue[dma->current_buffer].size); -+ DPRINTK("SAR_BASE0 - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_SAR_BASE0) ); -+ DPRINTK("SAR_CUR0 - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_SAR_CURRENT0) ); -+ DPRINTK("DAR_BASE0 - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_DAR_BASE0) ); -+ DPRINTK("DAR_CUR0 - 0x%x \n", inl(M2M_reg_base+M2M_OFFSET_DAR_CURRENT0) ); -+ -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * DMA interface functions -+ * -+ ****************************************************************************/ -+ -+/***************************************************************************** -+ * -+ * int dma_init(int handle, unsigned int flags_m2p, unsigned int flags_m2m, -+ * dma_callback callback, unsigned int user_data) -+ * -+ * Description: Configure the DMA channel and install a callback function. -+ * -+ * handle: Handle unique the each instance of the dma interface, used -+ * to verify this call. -+ * flags_m2p Flags used to configure an M2P/P2M dma channel and determine -+ * if a callback function and user_data information are included -+ * in this call. This field should be NULL if handle represents -+ * an M2M channel. -+ * flags_m2m Flags used to configure an M2M dma channel and determine -+ * if a callback function and user_data information are included -+ * in this call. This field should be NULL if handle represents -+ * an M2P/P2M channel. -+ * callback function pointer which is called near the end of the -+ * dma channel's irq handler. -+ * user_data defined by the calling driver. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m, -+ dma_callback callback, unsigned int user_data) -+{ -+ int channel; -+ ep93xx_dma_t * dma; -+ unsigned long flags; -+ unsigned int M2P_reg_base, uiCONTROL; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR -+ "DMA Config: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA Config \n"); -+ -+ dma = &dma_chan[channel]; -+ -+ local_irq_save(flags); -+ -+ /* -+ * Check if the channel is currently transferring. -+ */ -+ if (dma->xfer_enable) { -+ local_irq_restore(flags); -+ return(-EINVAL); -+ } -+ -+ /* -+ * Check if this is an m2m function. -+ */ -+ if (channel >= 10) { -+ local_irq_restore(flags); -+ -+ /* -+ * Call another function to handle m2m config. -+ */ -+ return(dma_config_m2m(dma, flags_m2m, callback, user_data)); -+ } -+ -+ /* -+ * Setup a pointer into the dma channel's register set. -+ */ -+ M2P_reg_base = dma->reg_base; -+ -+ /* -+ * By default we enable the stall interrupt. -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2P_STALLINTEN; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Configure the channel for an error from the peripheral. -+ */ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ if ( flags_m2p && CHANNEL_ERROR_INT_ENABLE ) -+ uiCONTROL |= CONTROL_M2P_CHERRORINTEN; -+ else -+ uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ if ( flags_m2p && CHANNEL_ABORT ) -+ uiCONTROL |= CONTROL_M2P_ABRT; -+ else -+ uiCONTROL &= ~CONTROL_M2P_ABRT; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ if ( flags_m2p && IGNORE_CHANNEL_ERROR ) -+ uiCONTROL |= CONTROL_M2P_ICE; -+ else -+ uiCONTROL &= ~CONTROL_M2P_ICE; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Save the callback function in the dma instance for this channel. -+ */ -+ dma->callback = callback; -+ -+ /* -+ * Save the user data in the the dma instance for this channel. -+ */ -+ dma->user_data = user_data; -+ -+ /* -+ * Put the dma instance into the pause state by setting the -+ * pause bit to true. -+ */ -+ dma->pause = TRUE; -+ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int dma_start(int handle, unsigned int channels, unsigned int * handles) -+ * -+ * Description: Initiate a transfer on up to 3 channels. -+ * -+ * handle: handle for the channel to initiate transfer on. -+ * channels: number of channels to initiate transfers on. -+ * handles: pointer to an array of handles, one for each channel which -+ * is to be started. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_start(int handle, unsigned int channels, unsigned int * handles) -+{ -+ ep93xx_dma_t * dma_pointers[3]; -+ unsigned int M2P_reg_bases[3]; -+ unsigned int loop, uiCONTROL; -+ unsigned long flags; -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Start: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ if (channels < 1) { -+ printk(KERN_ERR "DMA Start: Invalid parameter.\n"); -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA Start \n"); -+ -+ /* -+ * Mask off registers. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Check if this is a start multiple. -+ */ -+ if (channels > 1) { -+ DPRINTK("DMA ERROR: Start, multiple start not supported yet \n"); -+ return(-1); -+ } else { -+ /* -+ * Check if this channel is already transferring. -+ */ -+ if (dma_chan[channel].xfer_enable && !dma_chan[channel].pause) { -+ printk(KERN_ERR -+ "DMA Start: Invalid command for channel %d.\n", channel); -+ -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * This channel is already transferring, so return an error. -+ */ -+ return(-EINVAL); -+ } -+ -+ /* -+ * If this is an M2M channel, call a different function. -+ */ -+ if (channel >= 10) { -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Call the m2m start function. Only start one channel. -+ */ -+ return(dma_start_m2m(channel, &dma_chan[channel])); -+ } -+ -+ /* -+ * Make sure the channel has at least one buffer in the queue. -+ */ -+ if (dma_chan[channel].new_buffers < 1) { -+ DPRINTK("DMA Start: Channel starved.\n"); -+ -+ /* -+ * This channel does not have enough buffers queued up, -+ * so enter the pause by starvation state. -+ */ -+ dma_chan[channel].xfer_enable = TRUE; -+ dma_chan[channel].pause = TRUE; -+ -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+ } -+ -+ /* -+ * Set up a dma instance pointer for this dma channel. -+ */ -+ dma_pointers[0] = &dma_chan[channel]; -+ -+ /* -+ * Set up a pointer to the register set for this channel. -+ */ -+ M2P_reg_bases[0] = dma_pointers[0]->reg_base; -+ } -+ -+ /* -+ * Setup both MAXCNT registers with values from the next two buffers -+ * in the queue, and enable the next frame buffer interrupt on the channel. -+ */ -+ for (loop = 0; loop < channels; loop++) { -+ /* -+ * Check if we need to restore a paused transfer. -+ */ -+ if (dma_pointers[loop]->pause_buf.buf_id != -1) -+ outl( dma_pointers[loop]->pause_buf.size, -+ M2P_reg_bases[loop]+M2P_OFFSET_MAXCNT0 ); -+ else -+ outl( dma_pointers[loop]->buffer_queue[dma_pointers[loop]->current_buffer].size, -+ M2P_reg_bases[loop]+M2P_OFFSET_MAXCNT0 ); -+ } -+ -+ for (loop = 0; loop < channels; loop++) { -+ /* -+ * Enable the specified dma channels. -+ */ -+ uiCONTROL = inl(M2P_reg_bases[loop]+M2P_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, M2P_reg_bases[loop]+M2P_OFFSET_CONTROL ); -+ -+ /* -+ * Update the dma channel instance transfer state. -+ */ -+ dma_pointers[loop]->xfer_enable = TRUE; -+ dma_pointers[loop]->pause = FALSE; -+ } -+ -+ /* -+ * Program up the BASE0 registers for all specified channels, this -+ * will initiate transfers on all specified channels. -+ */ -+ for (loop = 0; loop < channels; loop++) -+ /* -+ * Check if we need to restore a paused transfer. -+ */ -+ if (dma_pointers[loop]->pause_buf.buf_id != -1) { -+ outl( dma_pointers[loop]->pause_buf.source, -+ M2P_reg_bases[loop]+M2P_OFFSET_BASE0 ); -+ -+ /* -+ * Set the pause buffer to NULL -+ */ -+ dma_pointers[loop]->pause_buf.buf_id = -1; -+ dma_pointers[loop]->pause_buf.size = 0; -+ } else if(dma_pointers[loop]->new_buffers){ -+ outl( dma_pointers[loop]->buffer_queue[ -+ dma_pointers[loop]->current_buffer].source, -+ M2P_reg_bases[loop]+M2P_OFFSET_BASE0 ); -+ dma_pointers[loop]->new_buffers--; -+ -+ } -+ -+ /* -+ * Before restoring irqs setup the second MAXCNT/BASE -+ * register with a second buffer. -+ */ -+ for (loop = 0; loop < channels; loop++) -+ if (dma_pointers[loop]->new_buffers) { -+ /* -+ * By default we enable the next frame buffer interrupt. -+ */ -+ uiCONTROL = inl(M2P_reg_bases[loop]+M2P_OFFSET_CONTROL); -+ uiCONTROL |= CONTROL_M2P_NFBINTEN; -+ outl( uiCONTROL, M2P_reg_bases[loop]+M2P_OFFSET_CONTROL ); -+ -+ outl( dma_pointers[loop]->buffer_queue[ -+ (dma_pointers[loop]->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].size, -+ M2P_reg_bases[loop]+M2P_OFFSET_MAXCNT1 ); -+ -+ outl( dma_pointers[loop]->buffer_queue[ -+ (dma_pointers[loop]->current_buffer + 1) % -+ MAX_EP93XX_DMA_BUFFERS].source, -+ M2P_reg_bases[loop]+M2P_OFFSET_BASE1 ); -+ dma_pointers[loop]->new_buffers--; -+ } -+ -+ /* -+ DPRINTK("DMA - It's been started!!"); -+ DPRINTK("STATUS - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_STATUS) ); -+ DPRINTK("CONTROL - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CONTROL) ); -+ DPRINTK("REMAIN - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_REMAIN) ); -+ DPRINTK("PPALLOC - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_PPALLOC) ); -+ DPRINTK("BASE0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE0) ); -+ DPRINTK("MAXCNT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) ); -+ DPRINTK("CURRENT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT0) ); -+ DPRINTK("BASE1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE1) ); -+ DPRINTK("MAXCNT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) ); -+ DPRINTK("CURRENT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT1) ); -+ -+ DPRINTK("Pause - %d \n", dma_pointers[0]->pause); -+ DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable); -+ DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes); -+ DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers); -+ DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers); -+ DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer); -+ DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer); -+ DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers); -+ */ -+ /* -+ * Unmask irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_add_buffer(int handle, unsigned int * address, -+ * unsigned int size, unsigned int last) -+ * -+ * Description: Add a buffer entry to the DMA buffer queue. -+ * -+ * handle: handle for the channel to add this buffer to. -+ * address: Pointer to an integer which is the start address of the -+ * buffer which is to be added to the queue. -+ * size: size of the buffer in bytes. -+ * last: 1 if this is the last buffer in this stream, 0 otherwise. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest, -+ unsigned int size, unsigned int last, -+ unsigned int buf_id) -+{ -+ unsigned long flags; -+ ep93xx_dma_t * dma; -+ int channel; -+#if 0 -+ static int peak_total_buffers=0; -+#endif -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR -+ "DMA Add Buffer: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ /* -+ * Get a pointer to the dma instance. -+ */ -+ dma = &dma_chan[channel]; -+ -+#if 0 -+ if( dma->total_buffers > peak_total_buffers ) -+ { -+ peak_total_buffers=dma->total_buffers; -+ printk("peak_total_buffers=%d\n", peak_total_buffers ); -+ } -+#endif -+ /* -+ * Mask interrupts and hold on to the original state. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * If the buffer queue is full, last_buffer is the same as current_buffer and -+ * we're not tranfering, or last_buffer is pointing to a used buffer, then exit. -+ * TODO: do I need to do any more checks? -+ */ -+ if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) -+ { -+ DPRINTK("too many dma buffers: MAX_EP93XX_DMA_BUFFERS set to low ?\n"); -+ /* -+ * Restore the state of the irqs -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Fail. -+ */ -+ return(-1); -+ } -+ -+ /* -+ * Add this buffer to the queue -+ */ -+ dma->buffer_queue[dma->last_buffer].source = source; -+ dma->buffer_queue[dma->last_buffer].dest = dest; -+ dma->buffer_queue[dma->last_buffer].size = size; -+ dma->buffer_queue[dma->last_buffer].last = last; -+ dma->buffer_queue[dma->last_buffer].buf_id = buf_id; -+ -+ /* -+ * Reset the used field of the buffer structure. -+ */ -+ dma->buffer_queue[dma->last_buffer].used = FALSE; -+ -+ /* -+ * Increment the End Item Pointer. -+ */ -+ dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS; -+ -+ /* -+ * Increment the new buffers counter and the total buffers counter -+ */ -+ dma->new_buffers++; -+ dma->total_buffers++; -+ -+ /* -+ * restore the interrupt state. -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Check if the channel was starved into a stopped state. -+ */ -+ if (dma->pause && dma->xfer_enable) { -+ if (dma->new_buffers >= 1) { -+ DPRINTK("DMA - calling start from add after starve. \n"); -+ -+ /* -+ * The channel was starved into a stopped state, and we've got -+ * 2 new buffers, so start tranferring again. -+ */ -+ ep93xx_dma_start(handle, 1, 0); -+ } -+ } -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_remove_buffer(int handle, unsigned int * address, -+ * unsigned int * size) -+ * -+ * Description: Remove a buffer entry from the DMA buffer queue. If -+ * buffer was removed successfully, return 0, otherwise -+ * return -1. -+ * -+ * handle: handle for the channel to remove a buffer from. -+ * address: Pointer to an integer which is filled in with the start -+ * address of the removed buffer. -+ * size: Pointer to an integer which is filled in with the size in -+ * bytes of the removed buffer. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_remove_buffer(int handle, unsigned int * buf_id) -+{ -+ unsigned int test; -+ unsigned int loop; -+ int return_val = -1; -+ unsigned long flags; -+ ep93xx_dma_t *dma; -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR -+ "DMA Remove Buffer: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * Mask interrupts and hold on to the original state. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Make sure there are used buffers to be returned. -+ */ -+ if (dma->used_buffers) { -+ test = dma->last_buffer; -+ -+ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) { -+ if (dma->buffer_queue[test].used && (dma->buffer_queue[test].buf_id != -1)) { -+ /*DPRINTK("buffer %d used \n", test); */ -+ -+ /* -+ * This is a used buffer, fill in the buf_id pointer -+ * with the buf_id for this buffer. -+ */ -+ *buf_id = dma->buffer_queue[test].buf_id; -+ -+ /* -+ * Reset this buffer structure -+ */ -+ dma->buffer_queue[test].buf_id = -1; -+ -+ /* -+ * Decrement the used buffer counter, and the total buffer counter. -+ */ -+ dma->used_buffers--; -+ dma->total_buffers--; -+ -+ /* -+ * Successful removal of a buffer, so set the return -+ * value to 0, then exit this loop. -+ */ -+ return_val = 0; -+ break; -+ } -+ -+ /* -+ * This buffer isn't used, let's see if the next one is. -+ */ -+ test = (test + 1) % MAX_EP93XX_DMA_BUFFERS; -+ } -+ } -+ -+ /* -+ * Restore interrupts. -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(return_val); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_pause(int handle, unsigned int channels, -+ * unsigned int * handles) -+ * -+ * Description: Disable any ongoing transfer for the given channel, retaining -+ * the state of the current buffer transaction so that upon -+ * resume, the dma will continue where it left off. -+ * -+ * handle: Handle for the channel to be paused. If this is a pause for -+ * for multiple channels, handle is a valid handle for one of -+ * the channels to be paused. -+ * channels: number of channel to pause transfers on. -+ * handles: Pointer to an array of handles, one for each channel which -+ * to be paused. If this pause is intended only for one -+ * channel, this field should be set to NULL. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_pause(int handle, unsigned int channels, unsigned int * handles) -+{ -+ unsigned long flags; -+ ep93xx_dma_t * dma; -+ int channel; -+ -+ DPRINTK("ep93xx_dma_pause \n"); -+ -+ /* -+ * Mask interrupts and hold on to the original state. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ /* -+ * restore interrupts. -+ */ -+ local_irq_restore(flags); -+ -+ printk(KERN_ERR -+ "DMA Pause: Invalid dma handle.\n"); -+ -+ /* -+ * Fail. -+ */ -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA %d: pause \n", channel); -+ -+ /* -+ * Set up a pointer to the dma instance data. -+ */ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * Check if we're already paused. -+ */ -+ if (dma->pause) { -+ /* -+ * We're paused, but are we stopped? -+ */ -+ if (dma->xfer_enable) -+ /* -+ * Put the channel in the stopped state. -+ */ -+ dma->xfer_enable = FALSE; -+ -+ DPRINTK("DMA Pause - already paused."); -+ } else { -+ /* -+ * Put the channel into the stopped state. -+ */ -+ dma->xfer_enable = FALSE; -+ dma->pause = TRUE; -+ } -+ -+ /* -+ * restore interrupts. -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Already paused, so exit. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * void ep93xx_dma_flush(int handle) -+ * -+ * Description: Flushes all queued buffers and transfers in progress -+ * for the given channel. Return the buffer entries -+ * to the calling function. -+ * -+ * handle: handle for the channel for which the flush is intended. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_flush(int handle) -+{ -+ unsigned int loop; -+ unsigned long flags; -+ ep93xx_dma_t * dma; -+ int channel; -+ unsigned int M2P_reg_base,uiCONTROL; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Flush: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA %d: flush \n", channel); -+ -+ /* -+ * Set up a pointer to the dma instance data for this channel -+ */ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * Mask interrupts and hold on to the original state. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * Disable the dma channel -+ */ -+ if (channel < 10) { -+ /* -+ * M2P channel -+ */ -+ uiCONTROL = inl(dma->reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, dma->reg_base+M2P_OFFSET_CONTROL ); -+ } else { -+ /* -+ * M2M channel -+ */ -+ uiCONTROL = inl(dma->reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, dma->reg_base+M2M_OFFSET_CONTROL ); -+ } -+ -+ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) -+ { -+ dma->buffer_queue[loop].buf_id = -1; -+ dma->buffer_queue[loop].last = 0; -+ } -+ -+ /* -+ * Set the Current and Last item to zero. -+ */ -+ dma->current_buffer = 0; -+ dma->last_buffer = 0; -+ -+ /* -+ * Reset the Buffer counters -+ */ -+ dma->used_buffers = 0; -+ dma->new_buffers = 0; -+ dma->total_buffers = 0; -+ -+ /* -+ * reset the Total bytes counter. -+ */ -+ dma->total_bytes = 0; -+ -+ /* -+ * Reset the paused buffer. -+ */ -+ dma->pause_buf.last = 0; -+ dma->pause_buf.buf_id = -1; -+ -+ M2P_reg_base = dma_chan[channel].reg_base; -+ -+ /* -+ * restore interrupts. -+ */ -+ local_irq_restore(flags); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_queue_full(int handle) -+ * -+ * Description: Query to determine if the DMA queue of buffers for -+ * a given channel is full. -+ * 0 = queue is full -+ * 1 = queue is not full -+ * -+ * handle: handle for the channel to query. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_queue_full(int handle) -+{ -+ int list_full = 0; -+ unsigned long flags; -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA %d: queue full \n", channel); -+ -+ /* -+ * Mask interrupts and hold on to the original state. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * If the last item is equal to the used item then -+ * the queue is full. -+ */ -+ if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS) -+ list_full = FALSE; -+ else -+ list_full = TRUE; -+ -+ /* -+ * restore interrupts. -+ */ -+ local_irq_restore(flags); -+ -+ return(list_full); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_get_position() -+ * -+ * Description: Takes two integer pointers and fills them with the start -+ * and current address of the buffer currently transferring -+ * on the specified DMA channel. -+ * -+ * handle handle for the channel to query. -+ * *buf_id buffer id for the current buffer transferring on the -+ * dma channel. -+ * *total total bytes transferred on the channel. Only counts -+ * whole buffers transferred. -+ * *current_frac number of bytes transferred so far in the current buffer. -+ ****************************************************************************/ -+int -+ep93xx_dma_get_position(int handle, unsigned int * buf_id, -+ unsigned int * total, unsigned int * current_frac ) -+{ -+ int channel; -+ ep93xx_dma_t * dma; -+ unsigned int buf_id1, total1, current_frac1, buf_id2, total2; -+ unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0; -+ unsigned int pause1, pause2; -+ -+ /* -+ * Get the DMA hw channel # from the handle. See if this is a -+ * valid handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * If DMA moves to a new buffer in the middle of us grabbing the -+ * buffer info, then do it over again. -+ */ -+ do{ -+ buf_id1 = dma->buffer_queue[dma->current_buffer].buf_id; -+ total1 = dma->total_bytes; -+ pause1 = dma->pause; -+ -+ if (channel < 10) { -+ // M2P -+ M2P_reg_base = dma->reg_base; -+ -+ Status = inl(M2P_reg_base+M2P_OFFSET_STATUS); -+ -+ NextBuffer = ((Status & STATUS_M2P_NEXTBUFFER) != 0); -+ -+ StateIsBufNext = ((Status & STATUS_M2P_CURRENT_MASK) == -+ STATUS_M2P_DMA_BUF_NEXT); -+ -+ if( NextBuffer ^ StateIsBufNext ) -+ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT1) - -+ inl(M2P_reg_base+M2P_OFFSET_BASE1); -+ else -+ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT0) - -+ inl(M2P_reg_base+M2P_OFFSET_BASE0); -+ -+ } else { -+ // M2M - TODO implement this for M2M -+ current_frac1 = 0; -+ } -+ -+ buf_id2 = dma->buffer_queue[dma->current_buffer].buf_id; -+ total2 = dma->total_bytes; -+ pause2 = dma->pause; -+ -+ } while ( (buf_id1 != buf_id2) || (total1 != total2) || (pause1 != pause2) ); -+ -+ if (pause1) -+ current_frac1 = 0; -+ -+ if (buf_id) -+ *buf_id = buf_id1; -+ -+ if (total) -+ *total = total1; -+ -+ if (current_frac) -+ *current_frac = current_frac1; -+ -+// DPRINTK("DMA buf_id %d, total %d, frac %d\n", buf_id1, total1, current_frac1); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_get_total(int handle) -+ * -+ * Description: Returns the total number of bytes transferred on the -+ * specified channel since the channel was requested. -+ * -+ * handle: handle for the channel to query. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_get_total(int handle) -+{ -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Get Total: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ DPRINTK("DMA %d: total: %d \n", channel, dma_chan[channel].total_bytes); -+ -+ /* -+ * Return the total number of bytes transferred on this channel since -+ * it was requested. -+ */ -+ return(dma_chan[channel].total_bytes); -+} -+ -+/***************************************************************************** -+ * -+ * int ep93xx_dma_is_done(int handle) -+ * -+ * Description: Determines if the specified channel is done -+ * transferring the requested data. -+ * -+ * handle: handle for the channel to query. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_is_done(int handle) -+{ -+ ep93xx_dma_t *dma; -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "ep93xx_dma_is_done: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ /* -+ * Get a pointer to the DMA channel state structure. -+ */ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * See if there are any buffers remaining to be provided to the HW. -+ */ -+ if (dma->new_buffers) -+ return 0; -+ -+ /* -+ * See if this is a M2P or M2M channel. -+ */ -+ if (channel < 10) { -+ /* -+ * If the bytes remaining register of the HW is not zero, then -+ * there is more work to be done. -+ */ -+ if (inl(dma->reg_base + M2P_OFFSET_REMAIN) != 0) -+ return 0; -+ } else { -+ /* -+ * If either byte count register in the HW is not zero, then there -+ * is more work to be done. -+ */ -+ if ((inl(dma->reg_base + M2M_OFFSET_BCR0) != 0) || -+ (inl(dma->reg_base + M2M_OFFSET_BCR1) != 0)) -+ return 0; -+ } -+ -+ /* -+ * The DMA is complete. -+ */ -+ return 1; -+} -+ -+/***************************************************************************** -+ * ep93xx_dma_request -+ * -+ * Description: This function will allocate a DMA channel for a particular -+ * hardware peripheral. Before initiating a transfer on the allocated -+ * channel, the channel must be set up and buffers have to queued up. -+ * -+ * handle: pointer to an integer which is filled in with a unique -+ * handle for this instance of the dma interface. -+ * device_id string with the device name, primarily used by /proc. -+ * device hardware device ID for which the requested dma channel will -+ * transfer data. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_request(int * handle, const char *device_id, -+ ep93xx_dma_dev_t device) -+{ -+ ep93xx_dma_t *dma = NULL; -+ int channel; -+ unsigned int error = 0; -+ unsigned int loop; -+ unsigned int M2P_reg_base; -+ -+ /* -+ * Check if the device requesting a DMA channel is a valid device. -+ */ -+ if ((device >= UNDEF_DMA) || (device < 0)) -+ return(-ENODEV); -+ -+ /* -+ * We've got a valid hardware device requesting a DMA channel. -+ * Now check if the device should open an M2P or M2M channel -+ */ -+ if (device < 20) -+ channel = dma_open_m2p(device); -+ else -+ channel = dma_open_m2m(device); -+ -+ /* -+ * Check if we successfully opened a DMA channel -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "%s: Could not open dma channel for this device.\n", -+ device_id); -+ return(-EBUSY); -+ } -+ -+ dma = &dma_chan[channel]; -+ -+ if(dma->terminated==1) { -+ free_irq(dma->irq, (void *) dma); -+ dma->terminated=0; -+ } -+ -+ /* -+ * Request the appropriate IRQ for the specified channel -+ */ -+ if (channel < 10) -+ error = request_irq(dma->irq, dma_m2p_irq_handler, -+ IRQF_DISABLED, device_id, (void *) dma); -+ else -+ error = request_irq(dma->irq, &dma_m2m_irq_handler, -+ IRQF_DISABLED, device_id, (void *) dma); -+ -+ /* -+ * Check for any errors during the irq request -+ */ -+ if (error) { -+ printk(KERN_ERR "%s: unable to request IRQ %d for DMA channel\n", -+ device_id, dma->irq); -+ return(error); -+ } -+ -+ /* -+ * Generate a valid handle and exit. -+ * -+ * Increment the last valid handle. -+ * Check for wraparound (unlikely, but we like to be complete). -+ */ -+ dma->last_valid_handle++; -+ -+ if ( (dma->last_valid_handle & DMA_HANDLE_SPECIFIER_MASK) != -+ (channel << 28) ) -+ dma->last_valid_handle = (channel << 28) + 1; -+ -+ /* -+ * Fill in the handle pointer with a valid handle for -+ * this dma channel instance. -+ */ -+ *handle = dma->last_valid_handle; -+ -+ DPRINTK("Handle for channel %d: 0x%x\n", channel, *handle); -+ -+ /* -+ * Save the device ID and device name. -+ */ -+ dma->device = device; -+ dma->device_id = device_id; -+ -+ /* -+ * Init all fields within the dma instance. -+ */ -+ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) -+ dma->buffer_queue[loop].buf_id = -1; -+ -+ /* -+ * Initialize all buffer queue variables. -+ */ -+ dma->current_buffer = 0; -+ dma->last_buffer = 0; -+ -+ dma->new_buffers = 0; -+ dma->used_buffers = 0; -+ dma->total_buffers = 0; -+ -+ /* -+ * Initialize the total bytes variable -+ */ -+ dma->total_bytes = 0; -+ -+ /* -+ * Initialize the transfer and pause state variables to 0. -+ */ -+ dma->xfer_enable = 0; -+ -+ dma->pause = 0; -+ -+ /* -+ * Initialize the pause buffer structure. -+ */ -+ dma->pause_buf.buf_id = -1; -+ -+ /* -+ * Initialize the callback function and user data fields. -+ */ -+ dma->callback = NULL; -+ -+ /* -+ * User data used as a parameter for the Callback function. The user -+ * sets up the data and sends it with the callback function. -+ */ -+ dma->user_data = 0; -+ -+ M2P_reg_base = dma_chan[channel].reg_base; -+ -+ /* -+ * Debugging message. -+ */ -+ DPRINTK("Successfully requested dma channel %d\n", channel); -+ DPRINTK("STATUS - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_STATUS) ); -+ DPRINTK("CONTROL - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CONTROL) ); -+ DPRINTK("REMAIN - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_REMAIN) ); -+ DPRINTK("PPALLOC - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_PPALLOC) ); -+ DPRINTK("BASE0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE0) ); -+ DPRINTK("MAXCNT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT0) ); -+ DPRINTK("CURRENT0 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT0) ); -+ DPRINTK("BASE1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_BASE1) ); -+ DPRINTK("MAXCNT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_MAXCNT1) ); -+ DPRINTK("CURRENT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT1) ); -+ -+ DPRINTK("Buffer source size last used \n"); -+ for (loop = 0; loop < 5; loop ++) -+ DPRINTK("%d 0x%x 0x%x %d %d \n", -+ loop, dma->buffer_queue[loop].source, dma->buffer_queue[loop].size, -+ dma->buffer_queue[loop].last, dma->buffer_queue[loop].used); -+ DPRINTK("pause 0x%x 0x%x %d %d \n", -+ dma->pause_buf.source, dma->pause_buf.size, -+ dma->pause_buf.last, dma->pause_buf.used); -+ -+ DPRINTK("Pause - %d \n", dma->pause); -+ DPRINTK("xfer_enable - %d \n", dma->xfer_enable); -+ DPRINTK("total bytes - 0x%x \n", dma->total_bytes); -+ DPRINTK("total buffer - %d \n", dma->total_buffers); -+ DPRINTK("new buffers - %d \n", dma->new_buffers); -+ DPRINTK("current buffer - %d \n", dma->current_buffer); -+ DPRINTK("last buffer - %d \n", dma->last_buffer); -+ DPRINTK("used buffers - %d \n", dma->used_buffers); -+ -+ DPRINTK("CURRENT1 - 0x%x \n", inl(M2P_reg_base+M2P_OFFSET_CURRENT1) ); -+ DPRINTK("VIC0IRQSTATUS - 0x%x, VIC0INTENABLE - 0x%x \n", -+ *(unsigned int *)(VIC0IRQSTATUS), -+ *(unsigned int *)(VIC0INTENABLE)); -+ -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * ep93xx_dma_free -+ * -+ * Description: This function will free the dma channel for future requests. -+ * -+ * handle: handle for the channel to be freed. -+ * -+ ****************************************************************************/ -+int -+ep93xx_dma_free(int handle) -+{ -+ ep93xx_dma_t *dma; -+ unsigned int M2M_reg_base, M2P_reg_base, uiCONTROL; -+ int channel; -+ -+ /* -+ * Get the DMA hw channel # from the handle. -+ */ -+ channel = dma_get_channel_from_handle(handle); -+ -+ /* -+ * See if this is a valid handle. -+ */ -+ if (channel < 0) { -+ printk(KERN_ERR "DMA Free: Invalid dma handle.\n"); -+ return(-EINVAL); -+ } -+ -+ /* -+ * Get a pointer to the dma instance. -+ */ -+ dma = &dma_chan[channel]; -+ -+ /* -+ * Disable the dma channel -+ */ -+ if (channel < 10) { -+ /* -+ * M2P channel -+ */ -+ M2P_reg_base = dma->reg_base; -+ -+ uiCONTROL = inl(M2P_reg_base+M2P_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2P_ENABLE; -+ outl( uiCONTROL, M2P_reg_base+M2P_OFFSET_CONTROL ); -+ } else { -+ /* -+ * M2M channel -+ */ -+ M2M_reg_base = dma->reg_base; -+ -+ uiCONTROL = inl(M2M_reg_base+M2M_OFFSET_CONTROL); -+ uiCONTROL &= ~CONTROL_M2M_ENABLE; -+ outl( uiCONTROL, M2M_reg_base+M2M_OFFSET_CONTROL ); -+ } -+ -+ /* -+ * Free the interrupt servicing this dma channel -+ */ -+ //free_irq(dma->irq, (void *) dma); -+ dma->terminated=1; -+ -+ /* -+ * Decrement the reference count for this instance of the dma interface -+ */ -+ dma->ref_count--; -+ -+ /* -+ * Set the transfer and pause state variables to 0 -+ * (unititialized state). -+ */ -+ dma->xfer_enable = 0; -+ dma->pause = 0; -+ -+ /* -+ * Debugging message. -+ */ -+ DPRINTK("Successfully freed dma channel %d\n", channel); -+ /* -+ * Success. -+ */ -+ return(0); -+} -+ -+/***************************************************************************** -+ * -+ * ep93xx_dma_init(void) -+ * -+ * Description: This function is called during system initialization to -+ * setup the interrupt number and register set base address for each DMA -+ * channel. -+ * -+ ****************************************************************************/ -+static int __init -+ep93xx_dma_init(void) -+{ -+ int channel; -+ -+ /* -+ * Init some values in each dma instance. -+ */ -+ for (channel = 0; channel < MAX_EP93XX_DMA_CHANNELS; channel++) { -+ /* -+ * IRQ for the specified dma channel. -+ */ -+ dma_chan[channel].irq = IRQ_EP93XX_DMAM2P0 + channel; -+ -+ dma_chan[channel].terminated = 0; -+ -+ /* -+ * Initial value of the dma channel handle. -+ */ -+ dma_chan[channel].last_valid_handle = channel << 28; -+ -+ /* -+ * Give the instance a pointer to the dma channel register -+ * base. -+ */ -+ if (channel < 10) -+ dma_chan[channel].reg_base = DMAM2PChannelBase[channel]; -+ else -+ dma_chan[channel].reg_base = DMAM2MChannelBase[channel - 10]; -+ -+ /* -+ * Initialize the reference count for this channel. -+ */ -+ dma_chan[channel].ref_count = 0; -+ } -+ -+ DPRINTK("DMA Interface intitialization complete\n"); -+ -+ /* -+ * Success -+ */ -+ return 0; -+} -+ -+arch_initcall(ep93xx_dma_init); -+ -+EXPORT_SYMBOL(ep93xx_dma_free); -+EXPORT_SYMBOL(ep93xx_dma_request); -+EXPORT_SYMBOL(ep93xx_dma_flush); -+EXPORT_SYMBOL(ep93xx_dma_pause); -+EXPORT_SYMBOL(ep93xx_dma_remove_buffer); -+EXPORT_SYMBOL(ep93xx_dma_add_buffer); -+EXPORT_SYMBOL(ep93xx_dma_start); -+EXPORT_SYMBOL(ep93xx_dma_config); ---- /dev/null -+++ b/arch/arm/mach-ep93xx/dma_ep93xx.h -@@ -0,0 +1,676 @@ -+/***************************************************************************** -+ * -+ * arch/arm/mach-ep93xx/dma_ep93xx.h -+ * -+ * DESCRIPTION: 93XX DMA controller API private defintions. -+ * -+ * Copyright Cirrus Logic Corporation, 2003. All rights reserved -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ ****************************************************************************/ -+#ifndef _EP93XX_DMA_H_ -+#define _EP93XX_DMA_H_ -+ -+// as it turns out the ide dma is the biggest dma buffer hog so far -+// in case the HDD is "thinking" (seek/buffer flush) -+// the continueing r/w DMAs to the HDD will be queued up to up to PRD_ENTRIES entries... -+#include <linux/ide.h> -+#define MAX_EP93XX_DMA_BUFFERS PRD_ENTRIES -+ -+#ifndef TRUE -+#define TRUE 1 -+#endif -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+ -+#ifndef NULL -+#define NULL 0 -+#endif -+ -+#define EP93XX_DMA_BASE (EP93XX_AHB_VIRT_BASE + 0x00000000) -+ -+/***************************************************************************** -+ * 0x8000.0000 -> 0x8000.003C M2P Channel 0 Registers (Tx) -+ * 0x8000.0040 -> 0x8000.007C M2P Channel 1 Registers (Rx) -+ * 0x8000.0080 -> 0x8000.00BC M2P Channel 2 Registers (Tx) -+ * 0x8000.00C0 -> 0x8000.00FC M2P Channel 3 Registers (Rx) -+ * 0x8000.0100 -> 0x8000.013C M2M Channel 0 Registers -+ * 0x8000.0140 -> 0x8000.017C M2M Channel 1 Registers -+ * 0x8000.0180 -> 0x8000.01BC Not Used -+ * 0x8000.01C0 -> 0x8000.01FC Not Used -+ * 0x8000.0200 -> 0x8000.023C M2P Channel 5 Registers (Rx) -+ * 0x8000.0240 -> 0x8000.027C M2P Channel 4 Registers (Tx) -+ * 0x8000.0280 -> 0x8000.02BC M2P Channel 7 Registers (Rx) -+ * 0x8000.02C0 -> 0x8000.02FC M2P Channel 6 Registers (Tx) -+ * 0x8000.0300 -> 0x8000.033C M2P Channel 9 Registers (Rx) -+ * 0x8000.0340 -> 0x8000.037C M2P Channel 8 Registers (Tx) -+ * 0x8000.0380 DMA Channel Arbitration register -+ * 0x8000.03C0 DMA Global Interrupt register -+ * 0x8000.03C4 -> 0x8000.03FC Not Used -+ * -+ * -+ * Internal M2P/P2M Channel Register Map -+ * -+ * Offset Name Access Bits Reset Value -+ * 0x00 CONTROL R/W 6 0 -+ * 0x04 INTERRUPT R/W TC* 3 0 -+ * 0x08 PPALLOC R/W 4 channel dependant -+ * (see reg description) -+ * 0x0C STATUS RO 8 0 -+ * 0x10 reserved -+ * 0x14 REMAIN RO 16 0 -+ * 0X18 Reserved -+ * 0X1C Reserved -+ * 0x20 MAXCNT0 R/W 16 0 -+ * 0x24 BASE0 R/W 32 0 -+ * 0x28 CURRENT0 RO 32 0 -+ * 0x2C Reserved -+ * 0x30 MAXCNT1 R/W 16 0 -+ * 0x34 BASE1 R/W 32 0 -+ * 0X38 CURRENT1 RO 32 0 -+ * 0X3C Reserved -+ * -+ * M2M Channel Register Map -+ * Offset Name Access Bits Reset Value -+ * -+ * 0x00 CONTROL R/W 22 0 -+ * 0x04 INTERRUPT R/W TC* 3 0 -+ * 0x08 Reserved -+ * 0x0C STATUS R/W TC* 14 0 -+ * 0x10 BCR0 R/W 16 0 -+ * 0x14 BCR1 R/W 16 0 -+ * 0x18 SAR_BASE0 R/W 32 0 -+ * 0x1C SAR_BASE1 R/W 32 0 -+ * 0x20 Reserved -+ * 0x24 SAR_CURRENT0 RO 32 0 -+ * 0x28 SAR_CURRENT1 RO 32 0 -+ * 0x2C DAR_BASE0 R/W 32 0 -+ * 0x30 DAR_BASE1 R/W 32 0 -+ * 0x34 DAR_CURRENT0 RO 32 0 -+ * 0X38 Reserved -+ * 0X3C DAR_CURRENT1 RO 32 0 -+ * * Write this location once to clear the bit (see -+ * Interrupt/Status register description for which bits -+ * this rule applies to). -+ * -+ ****************************************************************************/ -+ -+ -+/*----------------------------------------------------------------------------------*/ -+/* M2P Registers */ -+/*----------------------------------------------------------------------------------*/ -+/* -+ * M2P CONTROL register bit defines -+ */ -+#define CONTROL_M2P_STALLINTEN 0x00000001 /* Enables the STALL interrupt */ -+#define CONTROL_M2P_NFBINTEN 0x00000002 /* Enables the NFB interrupt */ -+#define CONTROL_M2P_CHERRORINTEN 0x00000008 /* Enables the ChError interrupt*/ -+#define CONTROL_M2P_ENABLE 0x00000010 /* Enables the channel */ -+#define CONTROL_M2P_ABRT 0x00000020 /* Determines how DMA behaves in*/ -+ /* NEXT state with peripheral */ -+ /* error */ -+ /* 0: NEXT -> ON, ignore error */ -+ /* 1: NEXT -> STALL, disable ch.*/ -+#define CONTROL_M2P_ICE 0x00000040 /* Ignore Channel Error */ -+ -+/* -+ * M2P INTERRUPT register bit defines -+ */ -+#define INTERRUPT_M2P_STALLINT 0x00000001 /* Indicates channel stalled. */ -+#define INTERRUPT_M2P_NFBINT 0x00000002 /* Indicates channel is hungry. */ -+#define INTERRUPT_M2P_CHERRORINT 0x00000008 /* Peripheral detects error */ -+ -+ -+/* -+ * STATUS register bit defines -+ */ -+#define STATUS_M2P_STALL 0x00000001 /* A '1' indicates channel is */ -+ /* stalled */ -+#define STATUS_M2P_NFB 0x00000002 /* A '1' indicates channel has moved*/ -+ /* from NEXT state to ON state, but */ -+ /* waiting for next buffer to be */ -+ /* programmed. */ -+#define STATUS_M2P_CHERROR 0x00000008 /* Enables the ChError interrupt */ -+#define STATUS_M2P_CURRENT_MASK 0x00000030 /* Current state of the FSM */ -+#define STATUS_M2P_CURRENT_SHIFT 4 -+#define STATUS_M2P_NEXTBUFFER 0x00000040 /* Informs the int handler after an */ -+ /* NFB int which pair of maxcnt and */ -+ /* base regs to update. */ -+#define STATUS_M2P_BYTES_MASK 0x0000f800 /* number of valid DMA data */ -+#define STATUS_M2P_BYTES_SHIFT 7 /* currently in */ -+ /* packer/unpacker */ -+ -+#define STATUS_M2P_DMA_NO_BUF 0x00000000 -+#define STATUS_M2P_DMA_BUF_ON 0x00000010 -+#define STATUS_M2P_DMA_BUF_NEXT 0x00000020 -+ -+/* -+ * Register masks to mask off reserved bits after reading register. -+ */ -+#define M2P_MASK_PPALLOC 0x0000000f -+#define M2P_MASK_REMAIN 0x0000ffff -+#define M2P_MASK_MAXCNT0 0x0000ffff -+#define M2P_MASK_BASE0 0xffffffff -+#define M2P_MASK_CURRENT0 0xffffffff -+#define M2P_MASK_MAXCNT1 0x0000ffff -+#define M2P_MASK_BASE1 0xffffffff -+#define M2P_MASK_CURRENT1 0xffffffff -+ -+ -+/*----------------------------------------------------------------------------------*/ -+/* M2M Registers */ -+/*----------------------------------------------------------------------------------*/ -+ -+#define CONTROL_M2M_STALLINTEN 0x00000001 /* Enables the STALL interrupt */ -+#define CONTROL_M2M_SCT 0x00000002 /* Source Copy Transfer. Setup a */ -+ /* block transfer from 1 memory source */ -+ /* location. */ -+#define CONTROL_M2M_DONEINTEN 0x00000004 /* Enables the DONE interrupt which */ -+ /* indicates if the xfer completed */ -+ /* successfully */ -+#define CONTROL_M2M_ENABLE 0x00000008 /* Enables the channel */ -+#define CONTROL_M2M_START 0x00000010 /* Initiates the xfer. 'software trigger' */ -+#define CONTROL_M2M_BWC_MASK 0x000001e0 /* Bandwidth control. Indicate number of */ -+#define CONTROL_M2M_BWC_SHIFT 5 /* bytes in a transfer. */ -+#define CONTROL_M2M_PW_MASK 0x00000600 /* Peripheral width. Used for xfers */ -+#define CONTROL_M2M_PW_SHIFT 9 /* between memory and external peripheral. */ -+ /* 00: byte, 01: halfword, 10: word. */ -+#define CONTROL_M2M_DAH 0x00000800 /* Destination Address Hold */ -+#define CONTROL_M2M_SAH 0x00001000 /* Source Address Hold */ -+#define CONTROL_M2M_TM_MASK 0x00006000 /* Transfer Mode. 00: sw triggered, */ -+#define CONTROL_M2M_TM_SHIFT 13 /* 01: hw initiated M2P, 01: hw initiated P2M */ -+#define CONTROL_M2M_ETDP_MASK 0x00018000 /* End-of-Transfer/Terminal Count pin */ -+#define CONTROL_M2M_ETDP_SHIFT 15 /* direction and polarity. */ -+#define CONTROL_M2M_DACKP 0x00020000 /* DMA acknowledge pin polarity */ -+ -+#define CONTROL_M2M_DREQP_MASK 0x00180000 /* DMA request pin polarity. must be set */ -+#define CONTROL_M2M_DREQP_SHIFT 19 /* before enable bit. */ -+#define CONTROL_M2M_NFBINTEN 0x00200000 /* Enables generation of the NFB interrupt. */ -+#define CONTROL_M2M_RSS_MASK 0x00c00000 /* Request source selection: */ -+#define CONTROL_M2M_RSS_SHIFT 22 /* 000 - External DReq[0] */ -+ /* 001 - External DReq[1] */ -+ /* 01X - Internal SSPRx */ -+ /* 10X - Internal SSPTx */ -+ /* 11X - Internal IDE */ -+#define CONTROL_M2M_NO_HDSK 0x01000000 /* No handshake. When set the peripheral doesn't */ -+ /* require the regular handshake protocal. Must */ -+ /* be set for SSP and IDE operations, optional */ -+ /* for external peripherals. */ -+#define CONTROL_M2M_PWSC_MASK 0xfe000000 /* Peripheral wait states count. Gives the latency */ -+#define CONTROL_M2M_PWSC_SHIFT 25 /* (in PCLK cycles) needed by the peripheral to */ -+ /* deassert its' request once the M2M xfer w/ DMA */ -+ /* is complete. */ -+ -+/* -+ * M2M INTERRUPT register bit defines -+ */ -+#define INTERRUPT_M2M_STALLINT 0x00000001 /* Stall interrupt indicates channel stalled. */ -+#define INTERRUPT_M2M_DONEINT 0x00000002 /* Transaction done. */ -+#define INTERRUPT_M2M_NFBINT 0x00000004 /* Next frame buffer interrupt indicates */ -+ /* channel requires a new buffer */ -+ -+ -+ -+/* -+ * M2M STATUS register bit defines -+ */ -+#define STATUS_M2M_STALL 0x00000001 /* A '1' indicates channel is stalled */ -+#define STATUS_M2M_CURRENTSTATE_MASK 0x0000003e /* Indicates state of M2M Channel control */ -+#define STATUS_M2M_CURRENTSTATE_SHIFT 1 /* FSM (0-2): */ -+ /* 000 - IDLE, 001 - STALL, 010 - MEM_RD, */ -+ /* 011 - MEM_WR, 100 - BWC_WAIT */ -+ /* and M2M buffer FSM (3-2): */ -+ /* 00 - NO_BUF, 01 - BUF_ON, 10 - BUF_NEXT */ -+#define STATUS_M2M_DONE 0x00000040 /* Transfer completed successfully if 1. */ -+#define STATUS_M2M_TCS_MASK 0x00000180 /* Terminal Count status. Indicates whether or */ -+#define STATUS_M2M_TCS_SHIFT 7 /* or not the actual byte count reached */ -+ /* programmed limit for buffer descriptor */ -+#define STATUS_M2M_EOTS_MASK 0x00000600 /* End-of-Transfer status for buffer */ -+#define STATUS_M2M_EOTS_SHIFT 9 -+#define STATUS_M2M_NFB 0x00000800 /* A '1' indicates channel has moved */ -+ /* from NEXT state to ON state, but the next */ -+ /* byte count reg for next buffer has not been */ -+ /* programmed yet. */ -+#define STATUS_M2M_NB 0x00001000 /* NextBuffer status. Informs NFB service */ -+ /* routine, after NFB int, which pair of buffer */ -+ /* descriptor registers is free to update. */ -+#define STATUS_M2M_DREQS 0x00002000 /* DREQ status. Reflects the status of the */ -+ /* synchronized external peripherals DMA */ -+ /* request signal. */ -+ -+/* -+ * Register masks to mask off reserved bits after reading register. -+ */ -+#define M2M_MASK_BCR0 0x0000ffff -+#define M2M_MASK_BCR1 0x0000ffff -+#define M2M_MASK_SAR_BASE0 0xffffffff -+#define M2M_MASK_SAR_BASE1 0xffffffff -+#define M2M_MASK_SAR_CURRENT0 0xffffffff -+#define M2M_MASK_SAR_CURRENT1 0xffffffff -+#define M2M_MASK_DAR_BASE0 0xffffffff -+#define M2M_MASK_DAR_BASE1 0xffffffff -+#define M2M_MASK_DAR_CURRENT0 0xffffffff -+#define M2M_MASK_DAR_CURRENT1 0xffffffff -+ -+ -+// -+/* 8000_0000 - 8000_ffff: DMA */ -+#define DMA_OFFSET 0x000000 -+#define DMA_BASE (EP93XX_DMA_BASE) -+#define DMAMP_TX_0_CONTROL (DMA_BASE+0x0000) -+#define DMAMP_TX_0_INTERRUPT (DMA_BASE+0x0004) -+#define DMAMP_TX_0_PPALLOC (DMA_BASE+0x0008) -+#define DMAMP_TX_0_STATUS (DMA_BASE+0x000C) -+#define DMAMP_TX_0_REMAIN (DMA_BASE+0x0014) -+#define DMAMP_TX_0_MAXCNT0 (DMA_BASE+0x0020) -+#define DMAMP_TX_0_BASE0 (DMA_BASE+0x0024) -+#define DMAMP_TX_0_CURRENT0 (DMA_BASE+0x0028) -+#define DMAMP_TX_0_MAXCNT1 (DMA_BASE+0x0030) -+#define DMAMP_TX_0_BASE1 (DMA_BASE+0x0034) -+#define DMAMP_TX_0_CURRENT1 (DMA_BASE+0x0038) -+ -+#define DMAMP_RX_1_CONTROL (DMA_BASE+0x0040) -+#define DMAMP_RX_1_INTERRUPT (DMA_BASE+0x0044) -+#define DMAMP_RX_1_PPALLOC (DMA_BASE+0x0048) -+#define DMAMP_RX_1_STATUS (DMA_BASE+0x004C) -+#define DMAMP_RX_1_REMAIN (DMA_BASE+0x0054) -+#define DMAMP_RX_1_MAXCNT0 (DMA_BASE+0x0060) -+#define DMAMP_RX_1_BASE0 (DMA_BASE+0x0064) -+#define DMAMP_RX_1_CURRENT0 (DMA_BASE+0x0068) -+#define DMAMP_RX_1_MAXCNT1 (DMA_BASE+0x0070) -+#define DMAMP_RX_1_BASE1 (DMA_BASE+0x0074) -+#define DMAMP_RX_1_CURRENT1 (DMA_BASE+0x0078) -+ -+#define DMAMP_TX_2_CONTROL (DMA_BASE+0x0080) -+#define DMAMP_TX_2_INTERRUPT (DMA_BASE+0x0084) -+#define DMAMP_TX_2_PPALLOC (DMA_BASE+0x0088) -+#define DMAMP_TX_2_STATUS (DMA_BASE+0x008C) -+#define DMAMP_TX_2_REMAIN (DMA_BASE+0x0094) -+#define DMAMP_TX_2_MAXCNT0 (DMA_BASE+0x00A0) -+#define DMAMP_TX_2_BASE0 (DMA_BASE+0x00A4) -+#define DMAMP_TX_2_CURRENT0 (DMA_BASE+0x00A8) -+#define DMAMP_TX_2_MAXCNT1 (DMA_BASE+0x00B0) -+#define DMAMP_TX_2_BASE1 (DMA_BASE+0x00B4) -+#define DMAMP_TX_2_CURRENT1 (DMA_BASE+0x00B8) -+ -+#define DMAMP_RX_3_CONTROL (DMA_BASE+0x00C0) -+#define DMAMP_RX_3_INTERRUPT (DMA_BASE+0x00C4) -+#define DMAMP_RX_3_PPALLOC (DMA_BASE+0x00C8) -+#define DMAMP_RX_3_STATUS (DMA_BASE+0x00CC) -+#define DMAMP_RX_3_REMAIN (DMA_BASE+0x00D4) -+#define DMAMP_RX_3_MAXCNT0 (DMA_BASE+0x00E0) -+#define DMAMP_RX_3_BASE0 (DMA_BASE+0x00E4) -+#define DMAMP_RX_3_CURRENT0 (DMA_BASE+0x00E8) -+#define DMAMP_RX_3_MAXCNT1 (DMA_BASE+0x00F0) -+#define DMAMP_RX_3_BASE1 (DMA_BASE+0x00F4) -+#define DMAMP_RX_3_CURRENT1 (DMA_BASE+0x00F8) -+ -+#define DMAMM_0_CONTROL (DMA_BASE+0x0100) -+#define DMAMM_0_INTERRUPT (DMA_BASE+0x0104) -+#define DMAMM_0_STATUS (DMA_BASE+0x010C) -+#define DMAMM_0_BCR0 (DMA_BASE+0x0110) -+#define DMAMM_0_BCR1 (DMA_BASE+0x0114) -+#define DMAMM_0_SAR_BASE0 (DMA_BASE+0x0118) -+#define DMAMM_0_SAR_BASE1 (DMA_BASE+0x011C) -+#define DMAMM_0_SAR_CURRENT0 (DMA_BASE+0x0124) -+#define DMAMM_0_SAR_CURRENT1 (DMA_BASE+0x0128) -+#define DMAMM_0_DAR_BASE0 (DMA_BASE+0x012C) -+#define DMAMM_0_DAR_BASE1 (DMA_BASE+0x0130) -+#define DMAMM_0_DAR_CURRENT0 (DMA_BASE+0x0134) -+#define DMAMM_0_DAR_CURRENT1 (DMA_BASE+0x013C) -+ -+#define DMAMM_1_CONTROL (DMA_BASE+0x0140) -+#define DMAMM_1_INTERRUPT (DMA_BASE+0x0144) -+#define DMAMM_1_STATUS (DMA_BASE+0x014C) -+#define DMAMM_1_BCR0 (DMA_BASE+0x0150) -+#define DMAMM_1_BCR1 (DMA_BASE+0x0154) -+#define DMAMM_1_SAR_BASE0 (DMA_BASE+0x0158) -+#define DMAMM_1_SAR_BASE1 (DMA_BASE+0x015C) -+#define DMAMM_1_SAR_CURRENT0 (DMA_BASE+0x0164) -+#define DMAMM_1_SAR_CURRENT1 (DMA_BASE+0x0168) -+#define DMAMM_1_DAR_BASE0 (DMA_BASE+0x016C) -+#define DMAMM_1_DAR_BASE1 (DMA_BASE+0x0170) -+#define DMAMM_1_DAR_CURRENT0 (DMA_BASE+0x0174) -+#define DMAMM_1_DAR_CURRENT1 (DMA_BASE+0x017C) -+ -+#define DMAMP_RX_5_CONTROL (DMA_BASE+0x0200) -+#define DMAMP_RX_5_INTERRUPT (DMA_BASE+0x0204) -+#define DMAMP_RX_5_PPALLOC (DMA_BASE+0x0208) -+#define DMAMP_RX_5_STATUS (DMA_BASE+0x020C) -+#define DMAMP_RX_5_REMAIN (DMA_BASE+0x0214) -+#define DMAMP_RX_5_MAXCNT0 (DMA_BASE+0x0220) -+#define DMAMP_RX_5_BASE0 (DMA_BASE+0x0224) -+#define DMAMP_RX_5_CURRENT0 (DMA_BASE+0x0228) -+#define DMAMP_RX_5_MAXCNT1 (DMA_BASE+0x0230) -+#define DMAMP_RX_5_BASE1 (DMA_BASE+0x0234) -+#define DMAMP_RX_5_CURRENT1 (DMA_BASE+0x0238) -+ -+#define DMAMP_TX_4_CONTROL (DMA_BASE+0x0240) -+#define DMAMP_TX_4_INTERRUPT (DMA_BASE+0x0244) -+#define DMAMP_TX_4_PPALLOC (DMA_BASE+0x0248) -+#define DMAMP_TX_4_STATUS (DMA_BASE+0x024C) -+#define DMAMP_TX_4_REMAIN (DMA_BASE+0x0254) -+#define DMAMP_TX_4_MAXCNT0 (DMA_BASE+0x0260) -+#define DMAMP_TX_4_BASE0 (DMA_BASE+0x0264) -+#define DMAMP_TX_4_CURRENT0 (DMA_BASE+0x0268) -+#define DMAMP_TX_4_MAXCNT1 (DMA_BASE+0x0270) -+#define DMAMP_TX_4_BASE1 (DMA_BASE+0x0274) -+#define DMAMP_TX_4_CURRENT1 (DMA_BASE+0x0278) -+ -+#define DMAMP_RX_7_CONTROL (DMA_BASE+0x0280) -+#define DMAMP_RX_7_INTERRUPT (DMA_BASE+0x0284) -+#define DMAMP_RX_7_PPALLOC (DMA_BASE+0x0288) -+#define DMAMP_RX_7_STATUS (DMA_BASE+0x028C) -+#define DMAMP_RX_7_REMAIN (DMA_BASE+0x0294) -+#define DMAMP_RX_7_MAXCNT0 (DMA_BASE+0x02A0) -+#define DMAMP_RX_7_BASE0 (DMA_BASE+0x02A4) -+#define DMAMP_RX_7_CURRENT0 (DMA_BASE+0x02A8) -+#define DMAMP_RX_7_MAXCNT1 (DMA_BASE+0x02B0) -+#define DMAMP_RX_7_BASE1 (DMA_BASE+0x02B4) -+#define DMAMP_RX_7_CURRENT1 (DMA_BASE+0x02B8) -+ -+#define DMAMP_TX_6_CONTROL (DMA_BASE+0x02C0) -+#define DMAMP_TX_6_INTERRUPT (DMA_BASE+0x02C4) -+#define DMAMP_TX_6_PPALLOC (DMA_BASE+0x02C8) -+#define DMAMP_TX_6_STATUS (DMA_BASE+0x02CC) -+#define DMAMP_TX_6_REMAIN (DMA_BASE+0x02D4) -+#define DMAMP_TX_6_MAXCNT0 (DMA_BASE+0x02E0) -+#define DMAMP_TX_6_BASE0 (DMA_BASE+0x02E4) -+#define DMAMP_TX_6_CURRENT0 (DMA_BASE+0x02E8) -+#define DMAMP_TX_6_MAXCNT1 (DMA_BASE+0x02F0) -+#define DMAMP_TX_6_BASE1 (DMA_BASE+0x02F4) -+#define DMAMP_TX_6_CURRENT1 (DMA_BASE+0x02F8) -+ -+#define DMAMP_RX_9_CONTROL (DMA_BASE+0x0300) -+#define DMAMP_RX_9_INTERRUPT (DMA_BASE+0x0304) -+#define DMAMP_RX_9_PPALLOC (DMA_BASE+0x0308) -+#define DMAMP_RX_9_STATUS (DMA_BASE+0x030C) -+#define DMAMP_RX_9_REMAIN (DMA_BASE+0x0314) -+#define DMAMP_RX_9_MAXCNT0 (DMA_BASE+0x0320) -+#define DMAMP_RX_9_BASE0 (DMA_BASE+0x0324) -+#define DMAMP_RX_9_CURRENT0 (DMA_BASE+0x0328) -+#define DMAMP_RX_9_MAXCNT1 (DMA_BASE+0x0330) -+#define DMAMP_RX_9_BASE1 (DMA_BASE+0x0334) -+#define DMAMP_RX_9_CURRENT1 (DMA_BASE+0x0338) -+ -+#define DMAMP_TX_8_CONTROL (DMA_BASE+0x0340) -+#define DMAMP_TX_8_INTERRUPT (DMA_BASE+0x0344) -+#define DMAMP_TX_8_PPALLOC (DMA_BASE+0x0348) -+#define DMAMP_TX_8_STATUS (DMA_BASE+0x034C) -+#define DMAMP_TX_8_REMAIN (DMA_BASE+0x0354) -+#define DMAMP_TX_8_MAXCNT0 (DMA_BASE+0x0360) -+#define DMAMP_TX_8_BASE0 (DMA_BASE+0x0364) -+#define DMAMP_TX_8_CURRENT0 (DMA_BASE+0x0368) -+#define DMAMP_TX_8_MAXCNT1 (DMA_BASE+0x0370) -+#define DMAMP_TX_8_BASE1 (DMA_BASE+0x0374) -+#define DMAMP_TX_8_CURRENT1 (DMA_BASE+0x0378) -+ -+#define DMA_ARBITRATION (DMA_BASE+0x0380) -+#define DMA_INTERRUPT (DMA_BASE+0x03C0) -+ -+ -+/* -+ * DMA Register Base addresses and Offsets -+ */ -+#define DMA_M2P_TX_0_BASE DMAMP_TX_0_CONTROL -+#define DMA_M2P_RX_1_BASE DMAMP_RX_1_CONTROL -+#define DMA_M2P_TX_2_BASE DMAMP_TX_2_CONTROL -+#define DMA_M2P_RX_3_BASE DMAMP_RX_3_CONTROL -+#define DMA_M2M_0_BASE DMAMM_0_CONTROL -+#define DMA_M2M_1_BASE DMAMM_1_CONTROL -+#define DMA_M2P_RX_5_BASE DMAMP_RX_5_CONTROL -+#define DMA_M2P_TX_4_BASE DMAMP_TX_4_CONTROL -+#define DMA_M2P_RX_7_BASE DMAMP_RX_7_CONTROL -+#define DMA_M2P_TX_6_BASE DMAMP_TX_6_CONTROL -+#define DMA_M2P_RX_9_BASE DMAMP_RX_9_CONTROL -+#define DMA_M2P_TX_8_BASE DMAMP_TX_8_CONTROL -+ -+#define M2P_OFFSET_CONTROL 0x0000 -+#define M2P_OFFSET_INTERRUPT 0x0004 -+#define M2P_OFFSET_PPALLOC 0x0008 -+#define M2P_OFFSET_STATUS 0x000C -+#define M2P_OFFSET_REMAIN 0x0014 -+#define M2P_OFFSET_MAXCNT0 0x0020 -+#define M2P_OFFSET_BASE0 0x0024 -+#define M2P_OFFSET_CURRENT0 0x0028 -+#define M2P_OFFSET_MAXCNT1 0x0030 -+#define M2P_OFFSET_BASE1 0x0034 -+#define M2P_OFFSET_CURRENT1 0x0038 -+ -+#define M2M_OFFSET_CONTROL 0x0000 -+#define M2M_OFFSET_INTERRUPT 0x0004 -+#define M2M_OFFSET_STATUS 0x000C -+#define M2M_OFFSET_BCR0 0x0010 -+#define M2M_OFFSET_BCR1 0x0014 -+#define M2M_OFFSET_SAR_BASE0 0x0018 -+#define M2M_OFFSET_SAR_BASE1 0x001C -+#define M2M_OFFSET_SAR_CURRENT0 0x0024 -+#define M2M_OFFSET_SAR_CURRENT1 0x0028 -+#define M2M_OFFSET_DAR_BASE0 0x002C -+#define M2M_OFFSET_DAR_BASE1 0x0030 -+#define M2M_OFFSET_DAR_CURRENT0 0x0034 -+#define M2M_OFFSET_DAR_CURRENT1 0x003C -+ -+ -+ -+//----------------------------------------------------------------------------- -+// PWRCNT Register Defines -+//----------------------------------------------------------------------------- -+#define SYSCON_PWRCNT_FIREN 0x80000000 -+#define SYSCON_PWRCNT_UARTBAUD 0x20000000 -+#define SYSCON_PWRCNT_USHEN 0x10000000 -+#define SYSCON_PWRCNT_DMA_M2MCH1 0x08000000 -+#define SYSCON_PWRCNT_DMA_M2MCH0 0x04000000 -+#define SYSCON_PWRCNT_DMA_M2PCH8 0x02000000 -+#define SYSCON_PWRCNT_DMA_M2PCH9 0x01000000 -+#define SYSCON_PWRCNT_DMA_M2PCH6 0x00800000 -+#define SYSCON_PWRCNT_DMA_M2PCH7 0x00400000 -+#define SYSCON_PWRCNT_DMA_M2PCH4 0x00200000 -+#define SYSCON_PWRCNT_DMA_M2PCH5 0x00100000 -+#define SYSCON_PWRCNT_DMA_M2PCH2 0x00080000 -+#define SYSCON_PWRCNT_DMA_M2PCH3 0x00040000 -+#define SYSCON_PWRCNT_DMA_M2PCH0 0x00020000 -+#define SYSCON_PWRCNT_DMA_M2PCH1 0x00010000 -+ -+#ifndef __ASSEMBLY__ -+/* -+ * DMA Register Base addresses -+ */ -+static unsigned int const DMAM2PChannelBase[10] = -+{ -+ DMA_M2P_TX_0_BASE, -+ DMA_M2P_RX_1_BASE, -+ DMA_M2P_TX_2_BASE, -+ DMA_M2P_RX_3_BASE, -+ DMA_M2P_TX_4_BASE, -+ DMA_M2P_RX_5_BASE, -+ DMA_M2P_TX_6_BASE, -+ DMA_M2P_RX_7_BASE, -+ DMA_M2P_TX_8_BASE, -+ DMA_M2P_RX_9_BASE -+}; -+ -+static unsigned int const DMAM2MChannelBase[2] = -+{ -+ DMA_M2M_0_BASE, -+ DMA_M2M_1_BASE -+}; -+ -+#endif /* __ASSEMBLY__ */ -+ -+/***************************************************************************** -+ * -+ * DMA buffer structure type. -+ * -+ ****************************************************************************/ -+typedef struct ep93xx_dma_buffer_s -+{ -+ unsigned int source; /* buffer physical source address. */ -+ unsigned int dest; /* buffer physical destination address, */ -+ /* only used with the 2 M2M channels. */ -+ unsigned int size; /* buffer size in bytes */ -+ unsigned int last; /* 1 if this is the last buffer */ -+ /* in this transaction. If 1, */ -+ /* disable the NFBint so we aren't */ -+ /* interrupted for another buffer */ -+ /* when we know there won't be another. */ -+ unsigned int used; /* This field is set to 1 by the DMA */ -+ /* interface after the buffer is transferred*/ -+ int buf_id; /* unique identifyer specified by the */ -+ /* the driver which requested the dma */ -+} ep93xx_dma_buffer_t; -+ -+typedef ep93xx_dma_buffer_t * ep93xx_dma_buffer_p; -+ -+/***************************************************************************** -+ * -+ * Instance definition for the DMA interface. -+ * -+ ****************************************************************************/ -+typedef struct ep9312_dma_s -+{ -+ /* -+ * This 1 when the instance is in use, and 0 when it's not. -+ */ -+ unsigned int ref_count; -+ -+ /* -+ * This is the last valid handle for this instance. When giving out a -+ * new handle this will be incremented and given out. -+ */ -+ int last_valid_handle; -+ -+ /* -+ * device specifies one of the 20 DMA hardware ports this -+ * DMA channel will service. -+ */ -+ ep93xx_dma_dev_t device; -+ -+ /* -+ * DMABufferQueue is the queue of buffer structure pointers which the -+ * dma channel will use to setup transfers. -+ */ -+ ep93xx_dma_buffer_t buffer_queue[MAX_EP93XX_DMA_BUFFERS]; -+ -+ /* -+ * currnt_buffer : This is the buffer currently being transfered on -+ * this channel. -+ * last_buffer : This is the last buffer for this transfer. -+ * Note: current_buffer + 1 is already programmed into the dma -+ * channel as the next buffer to transfer. Don't write -+ * over either entry. -+ */ -+ int current_buffer; -+ int last_buffer; -+ -+ /* -+ * The following 3 fields are buffer counters. -+ * -+ * iNewBuffers: Buffers in the queue which have not been transfered. -+ * iUsedBuffers: Buffers in the queue which have have been tranferred, -+ * and are waiting to be returned. -+ * iTotalBuffers: Total number of buffers in the queue. -+ */ -+ int new_buffers; -+ int used_buffers; -+ int total_buffers; -+ -+ /* -+ * uiTotalBytes has the total bytes transfered on the channel since the -+ * last flush. This value does not include the bytes tranfered in the -+ * current buffer. A byte count is only added after a complete buffer -+ * is tranfered. -+ */ -+ unsigned int total_bytes; -+ -+ /* -+ * Interrupt number for this channel -+ */ -+ unsigned int irq; -+ -+ /* -+ * Indicates whether or not the channel is currently enabled to transfer -+ * data. -+ */ -+ unsigned int xfer_enable; -+ -+ /* -+ * pause indicates if the dma channel was paused by calling the pause -+ * ioctl. -+ */ -+ unsigned int pause; -+ -+ /* -+ * buffer structure used during a pause to capture the current -+ * address and remaining bytes for the buffer actively being transferred -+ * on the channel. This buffer will be used to reprogram the dma -+ * channel upon a resume. -+ */ -+ ep93xx_dma_buffer_t pause_buf; -+ -+ /* -+ * DMACallback is a function pointer which the calling application can -+ * use install a function to. this fuction can be used to notify the -+ * calling application of an interrupt. -+ */ -+ dma_callback callback; -+ -+ /* -+ * User data used as a parameter for the Callback function. The user -+ * sets up the data and sends it with the callback function. -+ */ -+ unsigned int user_data; -+ -+ /* -+ * A string representation of the device attached to the channel. -+ */ -+ const char * device_id; -+ -+ /* -+ * The register base address for this dma channel. -+ */ -+ unsigned int reg_base; -+ -+ /* -+ * terminated indicates -+ */ -+ unsigned int terminated; -+ -+ -+} ep93xx_dma_t; -+ -+/***************************************************************************** -+ * -+ * DMA macros -+ * -+ ****************************************************************************/ -+#define DMA_HANDLE_SPECIFIER_MASK 0xF0000000 -+#define DMA_CH0_HANDLE_SPECIFIER 0x00000000 -+#define DMA_CH1_HANDLE_SPECIFIER 0x10000000 -+#define DMA_CH2_HANDLE_SPECIFIER 0x20000000 -+#define DMA_CH3_HANDLE_SPECIFIER 0x30000000 -+#define DMA_CH4_HANDLE_SPECIFIER 0x40000000 -+#define DMA_CH5_HANDLE_SPECIFIER 0x50000000 -+#define DMA_CH6_HANDLE_SPECIFIER 0x60000000 -+#define DMA_CH7_HANDLE_SPECIFIER 0x70000000 -+#define DMA_CH8_HANDLE_SPECIFIER 0x80000000 -+#define DMA_CH9_HANDLE_SPECIFIER 0x90000000 -+#define DMA_CH10_HANDLE_SPECIFIER 0xA0000000 -+#define DMA_CH11_HANDLE_SPECIFIER 0xB0000000 -+ -+#endif // _DMADRV_H_ diff --git a/target/linux/ep93xx/patches-2.6.30/006-ep93xx-touchscreen.patch b/target/linux/ep93xx/patches-2.6.30/006-ep93xx-touchscreen.patch deleted file mode 100644 index 7ea8edc13a..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/006-ep93xx-touchscreen.patch +++ /dev/null @@ -1,1319 +0,0 @@ -Index: linux-2.6.30.9/drivers/input/touchscreen/Kconfig -=================================================================== ---- linux-2.6.30.9.orig/drivers/input/touchscreen/Kconfig 2009-11-24 21:00:18.000000000 +0100 -+++ linux-2.6.30.9/drivers/input/touchscreen/Kconfig 2009-11-24 21:00:45.000000000 +0100 -@@ -161,6 +161,10 @@ - module will be called wacom_w8001. - - -+config TOUCHSCREEN_EP93XX -+ tristate "EP93xx Touchscreen" -+ depends on ARM && INPUT && ARCH_EP93XX -+ - config TOUCHSCREEN_MTOUCH - tristate "MicroTouch serial touchscreens" - select SERIO -Index: linux-2.6.30.9/drivers/input/touchscreen/Makefile -=================================================================== ---- linux-2.6.30.9.orig/drivers/input/touchscreen/Makefile 2009-11-24 21:00:18.000000000 +0100 -+++ linux-2.6.30.9/drivers/input/touchscreen/Makefile 2009-11-24 21:00:45.000000000 +0100 -@@ -14,6 +14,7 @@ - obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o - obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o - obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -+obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o - obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o - obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o - obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o -Index: linux-2.6.30.9/drivers/input/touchscreen/ep93xx_ts.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/input/touchscreen/ep93xx_ts.c 2009-11-24 21:09:48.000000000 +0100 -@@ -0,0 +1,1117 @@ -+/* -+ * linux/drivers/input/touchscreen/ep93xx_ts.c -+ * -+ * Copyright (C) 2003-2004 Cirrus Corp. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/wait.h> -+#include <linux/fs.h> -+#include <linux/sched.h> -+#include <linux/poll.h> -+#include <linux/miscdevice.h> -+#include <linux/init.h> -+#include <linux/compiler.h> -+#include <linux/timer.h> -+#include <linux/interrupt.h> -+#include <linux/syscalls.h> -+#include <linux/input.h> -+#include <asm/irq.h> -+#include <mach/hardware.h> -+#include <asm/io.h> -+ -+#define TOUCH_OFFSET 0x100000 -+#define TOUCH_BASE (EP93XX_APB_VIRT_BASE|TOUCH_OFFSET) -+#define TSSetup (TOUCH_BASE+0x00) /* R/W touchscreen controller setup control register. */ -+#define TSXYMaxMin (TOUCH_BASE+0x04) /* R/W touchscreen controller max/min register. */ -+#define TSXYResult (TOUCH_BASE+0x08) /* R touchscreen controller result register. */ -+#define TSDischarge (TOUCH_BASE+0x0C) /* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define TSXSample (TOUCH_BASE+0x10) /* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define TSYSample (TOUCH_BASE+0x14) /* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define TSDirect (TOUCH_BASE+0x18) /* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define TSDetect (TOUCH_BASE+0x1C) /* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define TSSWLock (TOUCH_BASE+0x20) /* NA R/W touchscreen software lock register. */ -+#define TSSetup2 (TOUCH_BASE+0x24) /* R/W touchscreen setup control register #2. */ -+ -+// -+// To customize for a new touchscreen, there are various macros that -+// have to be set. If you allow UART_HACK_DEBUG to be defined, you -+// will get real time ts data scrolling up your serial terminal -+// screen that will help you empirically determine good values for these. -+// -+ -+// -+// These are used as trigger levels to know when we have pen up/down -+// -+// The rules: -+// 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these -+// are Inverse pressure. -+// 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up. -+// 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down. -+// -+#define TS_HEAVY_INV_PRESSURE 0xFE0 //C00 -+#define TS_LIGHT_INV_PRESSURE 0xFFF //e00 -+ -+// -+// If the x, y, or inverse pressure changes more than these values -+// between two succeeding points, the point is not reported. -+// -+#define TS_MAX_VALID_XY_CHANGE 0x300 -+#define TS_MAX_VALID_PRESSURE_CHANGE 0x100 -+ -+// -+// This is the minimum Z1 Value that is valid. -+// -+#define MIN_Z1_VALUE 0x50 -+ -+// -+// Settling delay for taking each ADC measurement. Increase this -+// if ts is jittery. -+// -+#define EP93XX_TS_ADC_DELAY_USEC 2000 -+ -+// -+// Delay between TS points. -+// -+#define EP93XX_TS_PER_POINT_DELAY_USEC 10000 -+ -+//----------------------------------------------------------------------------- -+// Debug messaging thru the UARTs -+//----------------------------------------------------------------------------- -+/* -+ * Hello there! Are you trying to get this driver to work with a new -+ * touschscreen? Turn this on and you will get useful info coming -+ * out of your serial port. -+ */ -+/* #define PRINT_CALIBRATION_FACTORS */ -+#ifdef PRINT_CALIBRATION_FACTORS -+#define UART_HACK_DEBUG 1 -+int iMaxX=0, iMaxY=0, iMinX = 0xfff, iMinY = 0xfff; -+#endif -+ -+/* -+ * For debugging, let's spew messages out serial port 1 or 3 at 57,600 baud. -+ */ -+/* #define UART_HACK_DEBUG 1 */ -+#if 0 -+#ifdef UART_HACK_DEBUG -+static char szBuf[256]; -+void UARTWriteString(char * msg); -+#define DPRINTK( x... ) \ -+ sprintf( szBuf, ##x ); \ -+ UARTWriteString( szBuf ); -+#else -+static char szBuf[256]; -+#define DPRINTK( x... ) \ -+ sprintf( szBuf, ##x ); \ -+ printk( szBuf ); -+#endif -+#endif // 0 -+#define DPRINTK( x... ) -+ -+//----------------------------------------------------------------------------- -+// A few more macros... -+//----------------------------------------------------------------------------- -+#define TSSETUP_DEFAULT ( TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \ -+ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \ -+ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK) ) -+ -+#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND) -+ -+// -+// For now, we use one of the minor numbers from the local/experimental -+// range. -+// -+#define EP93XX_TS_MINOR 240 -+ -+//----------------------------------------------------------------------------- -+// Static Declarations -+//----------------------------------------------------------------------------- -+static unsigned int guiLastX, guiLastY; -+static unsigned int guiLastInvPressure; -+ -+struct TouchScreenSample -+{ -+ int currentX; -+ int currentY; -+ int currentButton; -+ int currentPressure; -+ struct timeval currentTime; -+}; -+ -+// -+// This must match the structure in tslib. -+// -+struct ts_sample { -+ int x; -+ int y; -+ unsigned int pressure; -+ struct timeval tv; -+}; -+ -+ -+static struct TouchScreenSample gSample; -+ -+// static int currentX, currentY, currentButton; -+// static int gPressure; -+// static struct timeval gtime; -+ -+static int bFreshTouchData; -+static int bCurrentPenDown; -+ -+ -+ -+static DECLARE_WAIT_QUEUE_HEAD(queue); -+static DECLARE_MUTEX(open_sem); -+static spinlock_t event_buffer_lock = SPIN_LOCK_UNLOCKED; -+static struct fasync_struct *ep93xx_fasync; -+ -+//----------------------------------------------------------------------------- -+// Typedef Declarations -+//----------------------------------------------------------------------------- -+typedef enum { -+ TS_MODE_UN_INITIALIZED, -+ TS_MODE_HARDWARE_SCAN, -+ TS_MODE_SOFT_SCAN -+} ts_mode_t; -+ -+static ts_mode_t gScanningMode; -+ -+typedef enum{ -+ TS_STATE_STOPPED = 0, -+ TS_STATE_Z1, -+ TS_STATE_Z2, -+ TS_STATE_Y, -+ TS_STATE_X, -+ TS_STATE_DONE -+} ts_states_t; -+ -+typedef struct -+{ -+ unsigned int uiX; -+ unsigned int uiY; -+ unsigned int uiZ1; -+ unsigned int uiZ2; -+ ts_states_t state; -+} ts_struct_t; -+ -+static ts_struct_t sTouch; -+ -+/* -+ * From the spec, here's how to set up the touch screen's switch registers. -+ */ -+typedef struct -+{ -+ unsigned int uiDetect; -+ unsigned int uiDischarge; -+ unsigned int uiXSample; -+ unsigned int uiYSample; -+ unsigned int uiSwitchZ1; -+ unsigned int uiSwitchZ2; -+}SwitchStructType; -+ -+// -+// Here's the switch settings for a 4-wire touchscreen. See the spec -+// for how to handle a 4, 7, or 8-wire. -+// -+const static SwitchStructType sSwitchSettings = -+/* s28en=0 -+ * TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2 -+ */ -+ {0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608}; -+ -+ -+//----------------------------------------------------------------------------- -+// Function Declarations -+//----------------------------------------------------------------------------- -+static void ep93xx_ts_set_direct( unsigned int uiADCSwitch ); -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id); -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id); -+static void ee93xx_ts_evt_add( int button, int dX, int dY, int Pressure ); -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, -+ size_t count, loff_t *l); -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait); -+static int ep93xx_ts_open(struct inode *inode, struct file *filp); -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on); -+static int ep93xx_ts_release(struct inode *inode, struct file *filp); -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos); -+static void ep93xx_ts_setup(void); -+static void ep93xx_ts_shutdown(void); -+int __init ep93xx_ts_init(void); -+void __exit ep93xx_ts_exit(void); -+static unsigned int CalculateInvPressure( void ); -+static unsigned int ADCGetData( unsigned int uiSamples, unsigned int uiMaxDiff); -+static void TS_Soft_Scan_Mode(void); -+static void TS_Hardware_Scan_Mode(void); -+static void ProcessPointData(void); -+static void Set_Timer2_uSec( unsigned int Delay_mSec ); -+static void Stop_Timer2(void); -+ -+ -+ -+//----------------------------------------------------------------------------- -+// Debug stuff... -+//----------------------------------------------------------------------------- -+ -+#ifdef UART_HACK_DEBUG -+ -+// This "array" is a cheap-n-easy way of getting access to the UART registers. -+static unsigned int * const pDebugUART=(unsigned int *)IO_ADDRESS(UART1_BASE); -+//static unsigned int * const pDebugUART=(unsigned int *)IO_ADDRESS(UART3_BASE); -+static int bUartInitialized = 0; -+ -+void SendChar(char value) -+{ -+ // wait for Tx fifo full flag to clear. -+ while (pDebugUART[0x18>>2] & 0x20); -+ -+ // send a char to the uart -+ pDebugUART[0] = value; -+} -+ -+void UARTWriteString(char * msg) -+{ -+ int index = 0; -+ unsigned int uiTemp; -+ -+ //if((pDebugUART[0x14>>2] & 0x1) == 0) -+ if( bUartInitialized == 0 ) -+ { -+ uiTemp = inl(EP93XX_SYSCON_DEVICE_CONFIG); -+ uiTemp |= EP93XX_SYSCON_DEVCFG_U1E; -+ //uiTemp |= EP93XX_SYSCON_DEVCFG_U3E; -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, uiTemp); -+ pDebugUART[0x10>>2] = 0xf; -+ pDebugUART[0xc>>2] = 0; -+ pDebugUART[0x8>>2] = 0x70; -+ pDebugUART[0x14>>2] = 0x1; -+ bUartInitialized = 1; -+ } -+ while (msg[index] != 0) -+ { -+ if (msg[index] == '\n') -+ { -+ SendChar('\r'); -+ SendChar('\n'); -+ } -+ else -+ { -+ SendChar(msg[index]); -+ } -+ index++; -+ } -+} -+#endif // UART_HACK_DEBUG -+ -+/* -+ * ep93xx_ts_isr -+ */ -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id) -+{ -+ DPRINTK("isr\n"); -+ -+ // -+ // Note that we don't clear the interrupt here. The interrupt -+ // gets cleared in TS_Soft_Scan_Mode when the TS ENABLE -+ // bit is cleared. -+ // -+ -+ // -+ // Set the ts to manual polling mode and schedule a callback. -+ // That way we can return from the isr in a reasonable amount of -+ // time and process the touch in the callback after a brief delay. -+ // -+ TS_Soft_Scan_Mode(); -+ -+ return(IRQ_HANDLED); -+} -+ -+/* -+ * Save the current ts 'event' in an atomic fashion. -+ */ -+static void ee93xx_ts_evt_add( int buttons, int iX, int iY, int iPressure ) -+{ -+#ifdef PRINT_CALIBRATION_FACTORS -+ if( iX > iMaxX ) iMaxX = iX; -+ if( iX < iMinX ) iMinX = iX; -+ if( iY > iMaxY ) iMaxY = iY; -+ if( iY < iMinY ) iMinY = iY; -+#endif -+ -+ -+ // printk("ee93xx_ts_evt_add\n"); -+ //DPRINTK("cb\n"); -+ /* -+ * Note the event, but use spinlocks to keep it from getting -+ * halfway read if we get interrupted. -+ */ -+ -+ spin_lock(&event_buffer_lock); -+ gSample.currentX = iX; -+ gSample.currentY = iY; -+ gSample.currentButton = buttons; -+ gSample.currentPressure = iPressure; -+ bFreshTouchData = 1; -+ do_gettimeofday(&gSample.currentTime); -+ -+ -+ spin_unlock(&event_buffer_lock); -+ -+ kill_fasync(&ep93xx_fasync, SIGIO, POLL_IN); -+ wake_up_interruptible(&queue); -+ -+} -+ -+ -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) -+{ -+ -+ unsigned short data[3]; -+ struct ts_sample ts_data; -+ int iReturn = -EFAULT; -+ // printk("ep93xx_ts_read\n"); -+ -+#ifdef PRINT_CALIBRATION_FACTORS -+ static int lala=0; -+ if( bFreshTouchData && (lala++ > 9) ) -+ { -+ DPRINTK("%4d, %4d - range [%4d to %4d],[%4d to %4d]\n", -+ f, currentY, iMinX, iMaxX, iMinY, iMaxY ); -+ lala = 0; -+ } -+#endif -+ if( !bFreshTouchData) -+ { -+ iReturn = 0; -+ } -+ else if( (count == sizeof(data)) ) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ data[0] = gSample.currentX; -+ data[1] = gSample.currentY; -+ data[2] = gSample.currentButton; -+ -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, data, sizeof data)) -+ return -EFAULT; -+ -+ count -= sizeof(data); -+ -+ /* return the # of bytes that got read */ -+ iReturn = sizeof(data) ; -+ } -+ else if (count == sizeof(struct ts_sample) ) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ ts_data.x = gSample.currentX; -+ ts_data.y = gSample.currentY; -+ ts_data.pressure = gSample.currentPressure; -+ ts_data.tv = gSample.currentTime; -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, &ts_data, sizeof(struct ts_sample))) -+ { -+ iReturn = -EFAULT; -+ } -+ else -+ { -+ count -= sizeof(ts_data); -+ iReturn = sizeof(ts_data); -+ } -+ -+ } -+ -+ return iReturn; -+} -+ -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait) -+{ -+ // printk("ep93xx_ts_poll\n"); -+ poll_wait(filp, &queue, wait); -+ -+ if( bFreshTouchData ) -+ { -+ return POLLIN | POLLRDNORM; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_open(struct inode *inode, struct file *filp) -+{ -+ printk("ep93xx_ts_open"); -+ -+ if( down_trylock(&open_sem) ) -+ { -+ return -EBUSY; -+ } -+ -+ ep93xx_ts_setup(); -+ -+ return 0; -+} -+ -+/* -+ * Asynchronous I/O support. -+ */ -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on) -+{ -+ int retval; -+ -+ retval = fasync_helper(fd, filp, on, &ep93xx_fasync); -+ if (retval < 0) -+ { -+ return retval; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_release(struct inode *inode, struct file *filp) -+{ -+ Stop_Timer2(); -+ -+ /* -+ * Call our async I/O support to request that this file -+ * cease to be used for async I/O. -+ */ -+ ep93xx_ts_fasync(-1, filp, 0); -+ -+ ep93xx_ts_shutdown(); -+ -+ up(&open_sem); -+ -+ return 0; -+} -+ -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ -+static int ep93xx_ts_ioctl(struct inode *inode, struct file *file, uint command, ulong u) -+{ -+ static const int version = EV_VERSION; -+ static const u_int32_t bit =(1 << EV_ABS); -+ static const u_int32_t absbit = (1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_PRESSURE); -+ int iReturn ; -+ int i = 0; -+ -+ switch(command) -+ { -+ case EVIOCGVERSION: -+ DPRINTK("ep93xx_ts_ioctl command = EVIOCGVERSION\r\n"); -+ i = copy_to_user((void __user *)u, (void *)version, sizeof(version)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(0,sizeof(u_int32_t) * 8) : -+ DPRINTK("ep93xx_ts_ioctl command = EVIOCGBIT(0,sizeof(uint32) * 8)\r\n"); -+ i = copy_to_user((void __user *)u, (void *)bit, sizeof(bit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(EV_ABS, sizeof(absbit) * 8): -+ DPRINTK("ep93xx_ts_ioctl command = EVIOCGBIT(0,sizeof(uint32) * 8)\r\n"); -+ copy_to_user((void __user *)u, (void *)absbit, sizeof(absbit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ default: -+ DPRINTK(" ep93xx_ts_ioctl unknown command = %d\n",u); -+ iReturn = -1; -+ break; -+ } -+ -+ return iReturn; -+} -+ -+static struct file_operations ep93xx_ts_fops = { -+ owner: THIS_MODULE, -+ read: ep93xx_ts_read, -+ write: ep93xx_ts_write, -+ poll: ep93xx_ts_poll, -+ open: ep93xx_ts_open, -+ ioctl: ep93xx_ts_ioctl, -+ release: ep93xx_ts_release, -+ fasync: ep93xx_ts_fasync, -+}; -+ -+static struct miscdevice ep93xx_ts_miscdev = -+{ -+ EP93XX_TS_MINOR, -+ "ep93xx_ts", -+ &ep93xx_ts_fops -+}; -+ -+void ep93xx_ts_setup(void) -+{ -+ unsigned int uiKTDIV, uiTSXYMaxMin; -+ // printk("ep93xx_hw_setup\n"); -+ -+ /* -+ * Set the TSEN bit in KTDIV so that we are enabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = inl(SYSCON_KTDIV); -+ uiKTDIV |= SYSCON_KTDIV_TSEN; -+ SysconSetLocked( SYSCON_KTDIV, uiKTDIV ); -+ -+ // -+ // Program the TSSetup and TSSetup2 registers. -+ // -+ outl( TSSETUP_DEFAULT, TSSetup ); -+ outl( TSSETUP2_DEFAULT, TSSetup2 ); -+ -+ // -+ // Set the the touch settings. -+ // -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiDischarge, TSDirect ); -+ -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiDischarge, TSDischarge ); -+ -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiSwitchZ1, TSXSample ); -+ -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiSwitchZ2, TSYSample ); -+ -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiDetect, TSDetect ); -+ -+ // -+ // X,YMin set to 0x40 = have to drag that many pixels for a new irq. -+ // X,YMax set to 0x40 = 1024 pixels is the maximum movement within the -+ // time scan limit. -+ // -+ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK; -+ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK; -+ outl( uiTSXYMaxMin, TSXYMaxMin ); -+ -+ bCurrentPenDown = 0; -+ bFreshTouchData = 0; -+ guiLastX = 0; -+ guiLastY = 0; -+ guiLastInvPressure = 0xffffff; -+ -+ // -+ // Enable the touch screen scanning engine. -+ // -+ TS_Hardware_Scan_Mode(); -+} -+ -+/* -+ * ep93xx_ts_shutdown -+ * -+ */ -+static void -+ep93xx_ts_shutdown(void) -+{ -+ unsigned int uiKTDIV; -+ -+ DPRINTK("ep93xx_ts_shutdown\n"); -+ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Disable the scanning engine. -+ */ -+ outl( 0, TSSetup ); -+ outl( 0, TSSetup2 ); -+ -+ /* -+ * Clear the TSEN bit in KTDIV so that we are disabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = inl(SYSCON_KTDIV); -+ uiKTDIV &= ~SYSCON_KTDIV_TSEN; -+ SysconSetLocked( SYSCON_KTDIV, uiKTDIV ); -+ -+} /* ep93xx_ts_shutdown */ -+ -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id) -+{ -+ DPRINTK("%d", (int)sTouch.state ); -+ -+ switch( sTouch.state ) -+ { -+ case TS_STATE_STOPPED: -+ TS_Hardware_Scan_Mode(); -+ break; -+ -+ // -+ // Get the Z1 value for pressure measurement and set up -+ // the switch register for getting the Z2 measurement. -+ // -+ case TS_STATE_Z1: -+ Set_Timer2_uSec( EP93XX_TS_ADC_DELAY_USEC ); -+ sTouch.uiZ1 = ADCGetData( 2, 200 ); -+ ep93xx_ts_set_direct( sSwitchSettings.uiSwitchZ2 ); -+ sTouch.state = TS_STATE_Z2; -+ break; -+ -+ // -+ // Get the Z2 value for pressure measurement and set up -+ // the switch register for getting the Y measurement. -+ // -+ case TS_STATE_Z2: -+ sTouch.uiZ2 = ADCGetData( 2, 200 ); -+ ep93xx_ts_set_direct( sSwitchSettings.uiYSample ); -+ sTouch.state = TS_STATE_Y; -+ break; -+ -+ // -+ // Get the Y value and set up the switch register for -+ // getting the X measurement. -+ // -+ case TS_STATE_Y: -+ sTouch.uiY = ADCGetData( 4, 20 ); -+ ep93xx_ts_set_direct( sSwitchSettings.uiXSample ); -+ sTouch.state = TS_STATE_X; -+ break; -+ -+ // -+ // Read the X value. This is the last of the 4 adc values -+ // we need so we continue on to process the data. -+ // -+ case TS_STATE_X: -+ Stop_Timer2(); -+ -+ sTouch.uiX = ADCGetData( 4, 20 ); -+ -+ outl( 0xaa, TSSWLock ); -+ outl( sSwitchSettings.uiDischarge, TSDirect ); -+ -+ sTouch.state = TS_STATE_DONE; -+ -+ /* -+ * Process this set of ADC readings. -+ */ -+ ProcessPointData(); -+ -+ break; -+ -+ -+ // -+ // Shouldn't get here. But if we do, we can recover... -+ // -+ case TS_STATE_DONE: -+ TS_Hardware_Scan_Mode(); -+ break; -+ } -+ -+ // -+ // Clear the timer2 interrupt. -+ // -+ outl( 1, TIMER2CLEAR ); -+ return(IRQ_HANDLED); -+} -+ -+/*--------------------------------------------------------------------- -+ * ProcessPointData -+ * -+ * This routine processes the ADC data into usable point data and then -+ * puts the driver into hw or sw scanning mode before returning. -+ * -+ * We calculate inverse pressure (lower number = more pressure) then -+ * do a hystheresis with the two pressure values 'light' and 'heavy'. -+ * -+ * If we are above the light, we have pen up. -+ * If we are below the heavy we have pen down. -+ * As long as the pressure stays below the light, pen stays down. -+ * When we get above the light again, pen goes back up. -+ * -+ */ -+static void ProcessPointData(void) -+{ -+ int bValidPoint = 0; -+ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff; -+ unsigned int uiInvPressure; -+ -+ // -+ // Calculate the current pressure. -+ // -+ uiInvPressure = CalculateInvPressure(); -+ -+ DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x", -+ sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2, uiInvPressure ); -+ -+ // -+ // If pen pressure is so light that it is greater than the 'max' setting -+ // then we consider this to be a pen up. -+ // -+ if( uiInvPressure >= TS_LIGHT_INV_PRESSURE ) -+ { -+ DPRINTK(" -- up \n"); -+ bCurrentPenDown = 0; -+ ee93xx_ts_evt_add( 0, guiLastX, guiLastY, 0 ); -+ TS_Hardware_Scan_Mode(); -+ return; -+ } -+ -+ // -+ // Hystheresis: -+ // If the pen pressure is hard enough to be less than the 'min' OR -+ // the pen is already down and is still less than the 'max'... -+ // -+ if( (uiInvPressure < TS_HEAVY_INV_PRESSURE) || -+ ( bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE) ) ) -+ { -+ if( bCurrentPenDown ) -+ { -+ // -+ // If pen was previously down, check the difference between -+ // the last sample and this one... if the difference between -+ // samples is too great, ignore the sample. -+ // -+ uiXDiff = abs(guiLastX - sTouch.uiX); -+ uiYDiff = abs(guiLastY - sTouch.uiY); -+ uiInvPressureDiff = abs(guiLastInvPressure - uiInvPressure); -+ -+ if( (uiXDiff < TS_MAX_VALID_XY_CHANGE) && (uiYDiff < TS_MAX_VALID_XY_CHANGE) && -+ (uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE) ) -+ { -+ DPRINTK(" -- valid(two) \n"); -+ bValidPoint = 1; -+ } -+ else -+ { -+ DPRINTK(" -- INvalid(two) \n"); -+ } -+ } -+ else -+ { -+ DPRINTK(" -- valid \n"); -+ bValidPoint = 1; -+ } -+ -+ /* -+ * If either the pen was put down or dragged make a note of it. -+ */ -+ if( bValidPoint ) -+ { -+ guiLastX = sTouch.uiX; -+ guiLastY = sTouch.uiY; -+ guiLastInvPressure = uiInvPressure; -+ bCurrentPenDown = 1; -+ ee93xx_ts_evt_add( 1, sTouch.uiX, sTouch.uiY, (0x7000000 /uiInvPressure) ); -+ } -+ -+ TS_Soft_Scan_Mode(); -+ return; -+ } -+ -+ DPRINTK(" -- fallout \n"); -+ TS_Hardware_Scan_Mode(); -+} -+ -+static void ep93xx_ts_set_direct( unsigned int uiADCSwitch ) -+{ -+ unsigned int uiResult; -+ -+ // -+ // Set the switch settings in the direct register. -+ // -+ outl( 0xaa, TSSWLock ); -+ outl( uiADCSwitch, TSDirect ); -+ -+ // -+ // Read and throw away the first sample. -+ // -+ do { -+ uiResult = inl(TSXYResult); -+ } while( !(uiResult & TSXYRESULT_SDR) ); -+ -+} -+ -+static unsigned int ADCGetData -+( -+ unsigned int uiSamples, -+ unsigned int uiMaxDiff -+) -+{ -+ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, uiAve; -+ -+ do -+ { -+ // -+ //Initialize our values. -+ // -+ uiLowest = 0xfffffff; -+ uiHighest = 0; -+ uiSum = 0; -+ -+ for( uiCount = 0 ; uiCount < uiSamples ; uiCount++ ) -+ { -+ // -+ // Read the touch screen four more times and average. -+ // -+ do { -+ uiResult = inl(TSXYResult); -+ } while( !(uiResult & TSXYRESULT_SDR) ); -+ -+ uiValue = (uiResult & TSXYRESULT_AD_MASK) >> TSXYRESULT_AD_SHIFT; -+ uiValue = ((uiValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1)) & TSXYRESULT_X_MASK; -+ -+ // -+ // Add up the values. -+ // -+ uiSum += uiValue; -+ -+ // -+ // Get the lowest and highest values. -+ // -+ if( uiValue < uiLowest ) -+ { -+ uiLowest = uiValue; -+ } -+ if( uiValue > uiHighest ) -+ { -+ uiHighest = uiValue; -+ } -+ } -+ -+ } while( (uiHighest - uiLowest) > uiMaxDiff ); -+ -+ // -+ // Calculate the Average value. -+ // -+ uiAve = uiSum / uiSamples; -+ -+ return uiAve; -+} -+ -+//**************************************************************************** -+// CalculateInvPressure -+//**************************************************************************** -+// Is the Touch Valid. Touch is not valid if the X or Y value is not -+// in range and the pressure is not enough. -+// -+// Touch resistance can be measured by the following formula: -+// -+// Rx * X * Z2 -+// Rtouch = --------- * (-- - 1) -+// 4096 Z1 -+// -+// This is simplified in the ration of Rtouch to Rx. The lower the value, the -+// higher the pressure. -+// -+// Z2 -+// InvPressure = X * (-- - 1) -+// Z1 -+// -+static unsigned int CalculateInvPressure(void) -+{ -+ unsigned int uiInvPressure; -+ -+ // -+ // Check to see if the point is valid. -+ // -+ if( sTouch.uiZ1 < MIN_Z1_VALUE ) -+ { -+ uiInvPressure = 0x10000; -+ } -+ -+ // -+ // Can omit the pressure calculation if you need to get rid of the division. -+ // -+ else -+ { -+ uiInvPressure = ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX; -+ } -+ -+ return uiInvPressure; -+} -+ -+ -+ -+//**************************************************************************** -+// TS_Hardware_Scan_Mode -+//**************************************************************************** -+// Enables the ep93xx ts scanning engine so that when the pen goes down -+// we will get an interrupt. -+// -+// -+static void TS_Hardware_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ DPRINTK("S\n"); -+ -+ // -+ // Disable the soft scanning engine. -+ // -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ // -+ // Clear the TIN (Touchscreen INactive) bit so we can go to -+ // automatic scanning mode. -+ // -+ uiDevCfg = inl( EP93XX_SYSCON_DEVICE_CONFIG ); -+ SysconSetLocked( EP93XX_SYSCON_DEVICE_CONFIG, (uiDevCfg & ~EP93XX_SYSCON_DEVCFG_TIN) ); -+ -+ // -+ // Enable the touch screen scanning state machine by setting -+ // the ENABLE bit. -+ // -+ outl( (TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup ); -+ -+ // -+ // Set the flag to show that we are in interrupt mode. -+ // -+ gScanningMode = TS_MODE_HARDWARE_SCAN; -+ -+ // -+ // Initialize TSSetup2 register. -+ // -+ outl( TSSETUP2_DEFAULT, TSSetup2 ); -+ -+} -+ -+//**************************************************************************** -+// TS_Soft_Scan_Mode -+//**************************************************************************** -+// Sets the touch screen to manual polling mode. -+// -+// -+static void TS_Soft_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ DPRINTK("M\n"); -+ -+ if( gScanningMode != TS_MODE_SOFT_SCAN ) -+ { -+ // -+ // Disable the touch screen scanning state machine by clearing -+ // the ENABLE bit. -+ // -+ outl( TSSETUP_DEFAULT, TSSetup ); -+ -+ // -+ // Set the TIN bit so we can do manual touchscreen polling. -+ // -+ uiDevCfg = inl(EP93XX_SYSCON_DEVICE_CONFIG ); -+ SysconSetLocked( EP93XX_SYSCON_DEVICE_CONFIG, (uiDevCfg | EP93XX_SYSCON_DEVCFG_TIN) ); -+ } -+ -+ // -+ // Set the switch register up for the first ADC reading -+ // -+ ep93xx_ts_set_direct( sSwitchSettings.uiSwitchZ1 ); -+ -+ // -+ // Initialize our software state machine to know which ADC -+ // reading to take -+ // -+ sTouch.state = TS_STATE_Z1; -+ -+ // -+ // Set the timer so after a mSec or two settling delay it will -+ // take the first ADC reading. -+ // -+ Set_Timer2_uSec( EP93XX_TS_PER_POINT_DELAY_USEC ); -+ -+ // -+ // Note that we are in sw scanning mode not hw scanning mode. -+ // -+ gScanningMode = TS_MODE_SOFT_SCAN; -+ -+} -+ -+static void Set_Timer2_uSec( unsigned int uiDelay_uSec ) -+{ -+ unsigned int uiClockTicks; -+ -+ /* -+ * Stop timer 2 -+ */ -+ outl( 0, TIMER2CONTROL ); -+ -+ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000; -+ outl( uiClockTicks, TIMER2LOAD ); -+ outl( uiClockTicks, TIMER2VALUE ); -+ -+ /* -+ * Set up Timer 2 for 508 kHz clock and periodic mode. -+ */ -+ outl( 0xC8, TIMER2CONTROL ); -+ -+} -+ -+static void Stop_Timer2(void) -+{ -+ outl( 0, TIMER2CONTROL ); -+} -+ -+/* -+ * Initialization and exit routines -+ */ -+int __init ep93xx_ts_init(void) -+{ -+ int retval; -+ -+ //printk("ep93xx_ts_init\n"); -+ -+ // printk("request Touchscreen interrupt.\n"); -+ retval = request_irq( IRQ_EP93XX_TOUCH, ep93xx_ts_isr, IRQF_DISABLED, "ep93xx_ts", 0); -+ if( retval ) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n"); -+ return retval; -+ } -+ -+ // printk("Request Timer interrupt.\n"); -+ retval = request_irq( IRQ_EP93XX_TIMER2, ep93xx_timer2_isr, -+ IRQF_DISABLED, "ep93xx_timer2", 0); -+ if( retval ) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n"); -+ return retval; -+ } -+ -+ // printk("Register Touchscreen Driver\n"); -+ misc_register(&ep93xx_ts_miscdev); -+ -+ sTouch.state = TS_STATE_STOPPED; -+ gScanningMode = TS_MODE_UN_INITIALIZED; -+ -+ printk(KERN_NOTICE "ep93xx touchscreen driver configured for 4-wire operation\n"); -+ -+ return 0; -+} -+void __exit -+ep93xx_ts_exit(void) -+{ -+ DPRINTK("ep93xx_ts_exit\n"); -+ -+ Stop_Timer2(); -+ -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ free_irq(IRQ_EP93XX_TIMER2, 0); -+ -+ misc_deregister(&ep93xx_ts_miscdev); -+} -+ -+module_init(ep93xx_ts_init); -+module_exit(ep93xx_ts_exit); -+ -+MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver"); -+MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx"); -Index: linux-2.6.30.9/drivers/input/touchscreen/ep93xx_ts.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/input/touchscreen/ep93xx_ts.h 2009-11-24 21:00:45.000000000 +0100 -@@ -0,0 +1,53 @@ -+/* -+ * ep93xx_ts.h -+ * -+ * The contents of this file are subject to the Mozilla Public License -+ * Version 1.1 (the "License"); you may not use this file except in -+ * compliance with the License. You may obtain a copy of the License -+ * at http://www.mozilla.org/MPL/ -+ * -+ * Software distributed under the License is distributed on an "AS IS" -+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -+ * the License for the specific language governing rights and -+ * limitations under the License. -+ * -+ * The initial developer of the original code is David A. Hinds -+ * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds -+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. -+ * -+ * Alternatively, the contents of this file may be used under the -+ * terms of the GNU General Public License version 2 (the "GPL"), in -+ * which case the provisions of the GPL are applicable instead of the -+ * above. If you wish to allow the use of your version of this file -+ * only under the terms of the GPL and not to allow others to use -+ * your version of this file under the MPL, indicate your decision by -+ * deleting the provisions above and replace them with the notice and -+ * other provisions required by the GPL. If you do not delete the -+ * provisions above, a recipient may use your version of this file -+ * under either the MPL or the GPL. -+ */ -+ -+#ifndef _LINUX_EP93XX_TS_H -+#define _LINUX_EP93XX_TS_H -+ -+/*touchscreen register defines*/ -+#define SYSCON_KTDIV EP93XX_SYSCON_KEY_TOUCH_CLOCK_DIV -+#define SYSCON_SWLOCK EP93XX_SYSCON_SWLOCK -+#define TSSetup EP93XX_TOUCHSCREEN_TSSetup -+#define TSXYMaxMin EP93XX_TOUCHSCREEN_TSXYMaxMin -+#define TSXYResult EP93XX_TOUCHSCREEN_TSDischarge -+#define TSDischarge EP93XX_TOUCHSCREEN_TSDischarge -+#define TSXSample EP93XX_TOUCHSCREEN_TSXSample -+#define TSYSample EP93XX_TOUCHSCREEN_TSYSample -+#define TSDirect EP93XX_TOUCHSCREEN_TSDirect -+#define TSDetect EP93XX_TOUCHSCREEN_TSDetect -+#define TSSWLock EP93XX_TOUCHSCREEN_TSSWLock -+#define TSSetup2 EP93XX_TOUCHSCREEN_TSSetup2 -+ -+ -+//#define SYSCON_DEVCFG EP93XX_SYSCON_DEVICE_CONFIG -+#define TIMER2CONTROL EP93XX_TIMER2_CONTROL -+#define TIMER2LOAD EP93XX_TIMER2_LOAD -+#define TIMER2VALUE EP93XX_TIMER2_VALUE -+#define TIMER2CLEAR EP93XX_TIMER2_CLEAR -+#endif -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/hardware.h -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/mach-ep93xx/include/mach/hardware.h 2009-11-24 21:00:18.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/hardware.h 2009-11-24 21:09:21.000000000 +0100 -@@ -7,6 +7,7 @@ - #include "ep93xx-regs.h" - - #define pcibios_assign_all_busses() 0 -+#include "regs_touch.h" - - #include "platform.h" - -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/regs_touch.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/regs_touch.h 2009-11-24 21:00:45.000000000 +0100 -@@ -0,0 +1,95 @@ -+/*============================================================================= -+ * -+ * FILE: regs_touch.h -+ * -+ * DESCRIPTION: Analog Touchscreen Register Definition -+ * -+ * Copyright Cirrus Logic, 2001-2003 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ *============================================================================= -+ */ -+#ifndef _REGS_TOUCH_H_ -+#define _REGS_TOUCH_H_ -+ -+/* -+ *----------------------------------------------------------------------------- -+ * Individual bit #defines -+ *----------------------------------------------------------------------------- -+ */ -+#define TSSETUP_SDLY_MASK 0x000003FF -+#define TSSETUP_SDLY_SHIFT 0 -+#define TSSETUP_NSMP_4 0x00000000 -+#define TSSETUP_NSMP_8 0x00000400 -+#define TSSETUP_NSMP_16 0x00000800 -+#define TSSETUP_NSMP_32 0x00000C00 -+#define TSSETUP_NSMP_MASK 0x00000C00 -+#define TSSETUP_DEV_4 0x00000000 -+#define TSSETUP_DEV_8 0x00001000 -+#define TSSETUP_DEV_12 0x00002000 -+#define TSSETUP_DEV_16 0x00003000 -+#define TSSETUP_DEV_24 0x00004000 -+#define TSSETUP_DEV_32 0x00005000 -+#define TSSETUP_DEV_64 0x00006000 -+#define TSSETUP_DEV_128 0x00007000 -+#define TSSETUP_ENABLE 0x00008000 -+#define TSSETUP_DLY_MASK 0x03FF0000 -+#define TSSETUP_DLY_SHIFT 16 -+#define TSSETUP_TDTCT 0x80000000 -+ -+#define TSMAXMIN_XMIN_MASK 0x000000FF -+#define TSMAXMIN_XMIN_SHIFT 0 -+#define TSMAXMIN_YMIN_MASK 0x0000FF00 -+#define TSMAXMIN_YMIN_SHIFT 8 -+#define TSMAXMIN_XMAX_MASK 0x00FF0000 -+#define TSMAXMIN_XMAX_SHIFT 16 -+#define TSMAXMIN_YMAX_MASK 0xFF000000 -+#define TSMAXMIN_YMAX_SHIFT 24 -+ -+#define TSXYRESULT_X_MASK 0x00000FFF -+#define TSXYRESULT_X_SHIFT 0 -+#define TSXYRESULT_AD_MASK 0x0000FFFF -+#define TSXYRESULT_AD_SHIFT 0 -+#define TSXYRESULT_Y_MASK 0x0FFF0000 -+#define TSXYRESULT_Y_SHIFT 16 -+#define TSXYRESULT_SDR 0x80000000 -+ -+#define TSX_SAMPLE_MASK 0x00003FFF -+#define TSX_SAMPLE_SHIFT 0x00 -+#define TSY_SAMPLE_MASK 0x3FFF0000 -+#define TSY_SAMPLE_SHIFT 0x10 -+ -+#define TSSETUP2_TINT 0x00000001 -+#define TSSETUP2_NICOR 0x00000002 -+#define TSSETUP2_PINT 0x00000004 -+#define TSSETUP2_PENSTS 0x00000008 -+#define TSSETUP2_PINTEN 0x00000010 -+#define TSSETUP2_DEVINT 0x00000020 -+#define TSSETUP2_DINTEN 0x00000040 -+#define TSSETUP2_DTMEN 0x00000080 -+#define TSSETUP2_DISDEV 0x00000100 -+#define TSSETUP2_NSIGND 0x00000200 -+#define TSSETUP2_S28EN 0x00000400 -+#define TSSETUP2_RINTEN 0x00000800 -+ -+#define TSXYRESULT_SDR 0x80000000 -+ -+/* -+ *----------------------------------------------------------------------------- -+ *----------------------------------------------------------------------------- -+ */ -+ -+ -+#endif /* _REGS_TOUCH_H_ */ diff --git a/target/linux/ep93xx/patches-2.6.30/007-ep93xx-eth.patch b/target/linux/ep93xx/patches-2.6.30/007-ep93xx-eth.patch deleted file mode 100644 index cd715bfaf1..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/007-ep93xx-eth.patch +++ /dev/null @@ -1,405 +0,0 @@ ---- /dev/null -+++ b/drivers/net/arm/ep93xx_eth.h -@@ -0,0 +1,402 @@ -+/*------------------------------------------------------------------------ -+ * ep93xx_eth.h -+ * : header file of Ethernet Device Driver for Cirrus Logic EP93xx. -+ * -+ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com -+ * This software may be used and distributed according to the terms -+ * of the GNU Public License. -+ * -+ * This file contains device related information like register info -+ * and register access method macros for the Ethernet device -+ * embedded within Cirrus Logic's EP93xx SOC chip. -+ * -+ * Information contained in this file was obtained from -+ * the EP9312 Manual Revision 0.12 and 0.14 from Cirrus Logic. -+ * -+ * History -+ * 05/18/01 Sungwook Kim Initial release -+ * 03/25/2003 Melody Modified for EP92xx -+ *--------------------------------------------------------------------------*/ -+ -+ -+#ifndef _EP9213_ETH_H_ -+#define _EP9213_ETH_H_ -+ -+ -+/*--------------------------------------------------------------- -+ * Definition of H/W Defects and Their Workarounds -+ *-------------------------------------------------------------*/ -+ -+ -+ -+/*--------------------------------------------------------------- -+ * Data types used in this driver -+ *-------------------------------------------------------------*/ -+typedef unsigned char U8; -+typedef unsigned short U16; -+typedef unsigned long U32; -+typedef unsigned int UINT; -+ -+ -+ -+/*--------------------------------------------------------------- -+ * Definition of the registers. -+ * For details, refer to the datasheet . -+ * -+ * Basically, most registers are 32 bits width register. -+ * But some are 16 bits and some are 6 or 8 bytes long. -+ *-------------------------------------------------------------*/ -+ -+#define REG_RxCTL 0x0000 /*offset to Receiver Control Reg*/ -+#define RxCTL_PauseA (1<<20) -+#define RxCTL_RxFCE1 (1<<19) -+#define RxCTL_RxFCE0 (1<<18) -+#define RxCTL_BCRC (1<<17) -+#define RxCTL_SRxON (1<<16) -+#define RxCTL_RCRCA (1<<13) -+#define RxCTL_RA (1<<12) -+#define RxCTL_PA (1<<11) -+#define RxCTL_BA (1<<10) -+#define RxCTL_MA (1<<9) -+#define RxCTL_IAHA (1<<8) -+#define RxCTL_IA3 (1<<3) -+#define RxCTL_IA2 (1<<2) -+#define RxCTL_IA1 (1<<1) -+#define RxCTL_IA0 (1<<0) -+ -+#define REG_TxCTL 0x0004 /*offset to Transmit Control Reg*/ -+#define TxCTL_DefDis (1<<7) -+#define TxCTL_MBE (1<<6) -+#define TxCTL_ICRC (1<<5) -+#define TxCTL_TxPD (1<<5) -+#define TxCTL_OColl (1<<3) -+#define TxCTL_SP (1<<2) -+#define TxCTL_PB (1<<1) -+#define TxCTL_STxON (1<<0) -+ -+#define REG_TestCTL 0x0008 /*Test Control Reg, R/W*/ -+#define TestCTL_MACF (1<<7) -+#define TestCTL_MFDX (1<<6) -+#define TestCTL_DB (1<<5) -+#define TestCTL_MIIF (1<<4) -+ -+#define REG_MIICmd 0x0010 /*offset to MII Command Reg, R/W*/ -+#define MIICmd_OP (0x03<<14) -+#define MIICmd_OP_RD (2<<14) -+#define MIICmd_OP_WR (1<<14) -+#define MIICmd_PHYAD (0x1f<<5) -+#define MIICmd_REGAD (0x1f<<0) -+ -+#define REG_MIIData 0x0014 /*offset to MII Data Reg, R/W*/ -+#define MIIData_MIIData (0xffff<<0) -+ -+#define REG_MIISts 0x0018 /*offset to MII Status Reg, R*/ -+#define MIISts_Busy (1<<0) -+ -+#define REG_SelfCTL 0x0020 /*offset to Self Control Reg*/ -+#define SelfCTL_RWP (1<<7) /*Remote Wake Pin*/ -+#define SelfCTL_GPO0 (1<<5) -+#define SelfCTL_PUWE (1<<4) -+#define SelfCTL_PDWE (1<<3) -+#define SelfCTL_MIIL (1<<2) -+#define SelfCTL_RESET (1<<0) -+ -+#define REG_IntEn 0x0024 /*Interrupt Enable Reg, R/W*/ -+#define IntEn_RWIE (1<<30) -+#define IntEn_RxMIE (1<<29) -+#define IntEn_RxBIE (1<<28) -+#define IntEn_RxSQIE (1<<27) -+#define IntEn_TxLEIE (1<<26) -+#define IntEn_ECIE (1<<25) -+#define IntEn_TxUHIE (1<<24) -+#define IntEn_MOIE (1<<18) -+#define IntEn_TxCOIE (1<<17) -+#define IntEn_RxROIE (1<<16) -+#define IntEn_MIIIE (1<<12) -+#define IntEn_PHYSIE (1<<11) -+#define IntEn_TIE (1<<10) -+#define IntEn_SWIE (1<<8) -+#define IntEn_TxSQIE (1<<3) -+#define IntEn_RxEOFIE (1<<2) -+#define IntEn_RxEOBIE (1<<1) -+#define IntEn_RxHDRIE (1<<0) -+ -+#define REG_IntStsP 0x0028 /*offset to Interrupt Status Preserve Reg, R/W*/ -+#define REG_IntStsC 0x002c /*offset to Interrupt Status Clear Reg, R*/ -+#define IntSts_RWI (1<<30) -+#define IntSts_RxMI (1<<29) -+#define IntSts_RxBI (1<<28) -+#define IntSts_RxSQI (1<<27) -+#define IntSts_TxLEI (1<<26) -+#define IntSts_ECI (1<<25) -+#define IntSts_TxUHI (1<<24) -+#define IntSts_MOI (1<<18) -+#define IntSts_TxCOI (1<<17) -+#define IntSts_RxROI (1<<16) -+#define IntSts_MIII (1<<12) -+#define IntSts_PHYSI (1<<11) -+#define IntSts_TI (1<<10) -+#define IntSts_AHBE (1<<9) -+#define IntSts_SWI (1<<8) -+#define IntSts_OTHER (1<<4) -+#define IntSts_TxSQ (1<<3) -+#define IntSts_RxSQ (1<<2) -+ -+#define REG_GT 0x0040 /*offset to General Timer Reg*/ -+#define GT_GTC (0xffff<<16) -+#define GT_GTP (0xffff<<0) -+ -+#define REG_FCT 0x0044 /*offset to Flow Control Timer Reg*/ -+#define FCT_FCT (0x00ffffff<<0) -+ -+#define REG_FCF 0x0048 /*offset to Flow Control Format Reg*/ -+#define FCF_MACCT (0xffff<<16) -+#define FCF_TPT (0xffff<<0) -+ -+#define REG_AFP 0x004c /*offset to Address Filter Pointer Reg*/ -+#define AFP_AFP (0x07<<0) /*Address Filter Pointer (bank control for REG_IndAD)*/ -+#define AFP_AFP_IA0 0 /*Primary Individual Address (MAC Addr)*/ -+#define AFP_AFP_IA1 1 /*Individual Address 1*/ -+#define AFP_AFP_IA2 2 /*Individual Address 2*/ -+#define AFP_AFP_IA3 3 /*Individual Address 3*/ -+#define AFP_AFP_DTxP 6 /*Destination Address of Tx Pause Frame*/ -+#define AFP_AFP_HASH 7 /*Hash Table*/ -+ -+#define REG_IndAD 0x0050 /*offset to Individual Address Reg, n bytes, R/W*/ -+ -+#define REG_GIntSts 0x0060 /*offset to Global Interrupt Status Reg (writing 1 will clear)*/ -+#define REG_GIntROS 0x0068 /*offset to Global Interrupt Status Read Only Reg*/ -+#define GIntSts_INT (1<<15) /*Global Interrupt Request Status*/ -+ -+#define REG_GIntMsk 0x0064 /*offset to Global Interrupt Mask Reg*/ -+#define GIntMsk_IntEn (1<<15) /*Global Interrupt Enable*/ -+ -+#define REG_GIntFrc 0x006c /*offset to Global Interrupt Force Reg*/ -+#define GIntFrc_INT (1<<15) /*Force to set GIntSts*/ -+ -+#define REG_TxCollCnt 0x0070 /*Transmit Collision Count Reg, R*/ -+#define REG_RxMissCnt 0x0074 /*Receive Miss Count Reg, R*/ -+#define REG_RxRntCnt 0x0078 /*Receive Runt Count Reg, R*/ -+ -+#define REG_BMCtl 0x0080 /*offset to Bus Master Control Reg, R/W*/ -+#define BMCtl_MT (1<<13) -+#define BMCtl_TT (1<<12) -+#define BMCtl_UnH (1<<11) -+#define BMCtl_TxChR (1<<10) -+#define BMCtl_TxDis (1<<9) -+#define BMCtl_TxEn (1<<8) -+#define BMCtl_EH2 (1<<6) -+#define BMCtl_EH1 (1<<5) -+#define BMCtl_EEOB (1<<4) -+#define BMCtl_RxChR (1<<2) -+#define BMCtl_RxDis (1<<1) -+#define BMCtl_RxEn (1<<0) -+ -+#define REG_BMSts 0x0084 /*offset to Bus Master Status Reg, R*/ -+#define BMSts_TxAct (1<<7) -+#define BMSts_TP (1<<4) -+#define BMSts_RxAct (1<<3) -+#define BMSts_QID (0x07<<0) -+#define BMSts_QID_RxDt (0<<0) -+#define BMSts_QID_TxDt (1<<0) -+#define BMSts_QID_RxSts (2<<0) -+#define BMSts_QID_TxSts (3<<0) -+#define BMSts_QID_RxDesc (4<<0) -+#define BMSts_QID_TxDesc (5<<0) -+ -+#define REG_RBCA 0x0088 /*offset to Receive Buffer Current Address Reg, R*/ -+#define REG_TBCA 0x008c /*offset to Transmit Buffer Current Address Reg, R*/ -+ -+#define REG_RxDBA 0x0090 /*offset to Receive Descriptor Queue Base Address Reg, R/W*/ -+#define REG_RxDBL 0x0094 /*offset to Receive Descriptor Queue Base Length Reg, R/W, 16bits*/ -+#define REG_RxDCL 0x0096 /*offset to Receive Descriptor Queue Current Length Reg, R/W, 16bits*/ -+#define REG_RxDCA 0x0098 /*offset to Receive Descriptor Queue Current Address Reg, R/W*/ -+ -+#define REG_RxDEQ 0x009c /*offset to Receive Descriptor Enqueue Reg, R/W*/ -+#define RxDEQ_RDV (0xffff<<16) /*R 16bit; Receive Descriptor Value*/ -+#define RxDEQ_RDI (0xff<<0) /*W 8bit; Receive Descriptor Increment*/ -+ -+#define REG_RxSBA 0x00a0 /*offset to Receive Status Queue Base Address Reg, R/W*/ -+#define REG_RxSBL 0x00a4 /*offset to Receive Status Queue Base Length Reg, R/W, 16bits*/ -+#define REG_RxSCL 0x00a6 /*offset to Receive Status Queue Current Length Reg, R/W, 16bits*/ -+#define REG_RxSCA 0x00a8 /*offset to Receive Status Queue Current Address Reg, R/W*/ -+ -+#define REG_RxSEQ 0x00ac /*offset to Receive Status Queue Current Address Reg, R/W*/ -+#define RxSEQ_RSV (0xffff<<16) -+#define RxSEQ_RSI (0xff<<0) -+ -+#define REG_TxDBA 0x00b0 /*offset to Transmit Descriptor Queue Base Address Reg, R/W*/ -+#define REG_TxDBL 0x00b4 /*offset to Transmit Descriptor Queue Base Length Reg, R/W, 16bits*/ -+#define REG_TxDCL 0x00b6 /*offset to Transmit Descriptor Queue Current Length Reg, R/W, 16bits*/ -+#define REG_TxDCA 0x00b8 /*offset to Transmit Descriptor Queue Current Address Reg, R/W*/ -+ -+#define REG_TxDEQ 0x00bc /*offset to Transmit Descriptor Queue Current Address Reg, R/W*/ -+#define TxDEQ_TDV (0xffff<<16) -+#define TxDEQ_TDI (0xff<<0) -+ -+#define REG_TxSBA 0x00c0 /*offset to Transmit Status Queue Base Address Reg, R/W*/ -+#define REG_TxSBL 0x00c4 /*offset to Transmit Status Queue Base Length Reg, R/W, 16bits*/ -+#define REG_TxSCL 0x00c6 /*offset to Transmit Status Queue Current Length Reg, R/W, 16bits*/ -+#define REG_TxSCA 0x00c8 /*offset to Transmit Status Queue Current Address Reg, R/W*/ -+ -+#define REG_RxBTH 0x00d0 /*offset to Receive Buffer Threshold Reg, R/W*/ -+#define RxBTH_RDHT (0x03ff<<16) -+#define RxBTH_RDST (0x03ff<<0) -+ -+#define REG_TxBTH 0x00d4 /*offset to Transmit Buffer Threshold Reg, R/W*/ -+#define TxBTH_TDHT (0x03ff<<16) -+#define TxBTH_TDST (0x03ff<<0) -+ -+#define REG_RxSTH 0x00d8 /*offset to Receive Status Threshold Reg, R/W*/ -+#define RxSTH_RSHT (0x003f<<16) -+#define RxSTH_RSST (0x003f<<0) -+ -+#define REG_TxSTH 0x00dc /*offset to Transmit Status Threshold Reg, R/W*/ -+#define TxSTH_TSHT (0x003f<<16) -+#define TxSTH_TSST (0x003f<<0) -+ -+#define REG_RxDTH 0x00e0 /*offset to Receive Descriptor Threshold Reg, R/W*/ -+#define RxDTH_RDHT (0x003f<<16) -+#define RxDTH_RDST (0x003f<<0) -+ -+#define REG_TxDTH 0x00e4 /*offset to Transmit Descriptor Threshold Reg, R/W*/ -+#define TxDTH_TDHT (0x003f<<16) -+#define TxDTH_TDST (0x003f<<0) -+ -+#define REG_MaxFL 0x00e8 /*offset to Max Frame Length Reg, R/W*/ -+#define MaxFL_MFL (0x07ff<<16) -+#define MaxFL_TST (0x07ff<<0) -+ -+#define REG_RxHL 0x00ec /*offset to Receive Header Length Reg, R/W*/ -+#define RxHL_RHL2 (0x07ff<<16) -+#define RxHL_RHL1 (0x03ff<<0) -+ -+#define REG_MACCFG0 0x0100 /*offset to Test Reg #0, R/W*/ -+#define MACCFG0_DbgSel (1<<7) -+#define MACCFG0_LCKEN (1<<6) -+#define MACCFG0_LRATE (1<<5) -+#define MACCFG0_RXERR (1<<4) -+#define MACCFG0_BIT33 (1<<2) -+#define MACCFG0_PMEEN (1<<1) -+#define MACCFG0_PMEST (1<<0) -+ -+#define REG_MACCFG1 0x0104 /*offset to Test Reg #1, R/W*/ -+#define REG_MACCFG2 0x0108 /*offset to Test Reg #2, R*/ -+#define REG_MACCFG3 0x010c /*offset to Test Reg #3, R*/ -+ -+ -+ -+/*--------------------------------------------------------------- -+ * Definition of Descriptor/Status Queue Entry -+ *-------------------------------------------------------------*/ -+ -+typedef union receiveDescriptor { /*data structure of Receive Descriptor Queue Entry*/ -+ struct { /*whole value*/ -+ U32 e0, /*1st dword entry*/ -+ e1; /*2nd dword entry*/ -+ } w; -+ struct { /*bit field definitions*/ -+ U32 ba:32, /*Buffer Address (keep in mind this is physical address)*/ -+ bl:16, /*b15-0; Buffer Length*/ -+ bi:15, /*b30-16; Buffer Index*/ -+ nsof:1; /*b31; Not Start Of Frame*/ -+ } f; -+} receiveDescriptor; -+ -+ -+typedef union receiveStatus { /*data structure of Receive Status Queue Entry*/ -+ struct { /*whole word*/ -+ U32 e0, /*1st dword entry*/ -+ e1; /*2nd dword entry*/ -+ } w; -+ struct { /*bit field*/ -+ U32 rsrv1:8, /*b7-0: reserved*/ -+ hti:6, /*b13-8: Hash Table Index*/ -+ rsrv2:1, /*b14: reserved*/ -+ crci:1, /*b15: CRC Included*/ -+ crce:1, /*b16: CRC Error*/ -+ edata:1, /*b17: Extra Data*/ -+ runt:1, /*b18: Runt Frame*/ -+ fe:1, /*b19: Framing Error*/ -+ oe:1, /*b20: Overrun Error*/ -+ rxerr:1, /*b21: Rx Error*/ -+ am:2, /*b23-22: Address Match*/ -+ rsrv3:4, /*b27-24: reserved*/ -+ eob:1, /*b28: End Of Buffer*/ -+ eof:1, /*b29: End Of Frame*/ -+ rwe:1, /*b30: Received Without Error*/ -+ rfp:1, /*b31: Receive Frame Processed*/ -+ fl:16, /*b15-0: frame length*/ -+ bi:15, /*b30-16: Buffer Index*/ -+ rfp2:1; /*b31: Receive Frame Processed at 2nd word*/ -+ } f; -+} receiveStatus; -+ -+ -+typedef union transmitDescriptor { /*data structure of Transmit Descriptor Queue Entry*/ -+ struct { /*whole value*/ -+ U32 e0, /*1st dword entry*/ -+ e1; /*2nd dword entry*/ -+ } w; -+ struct { /*bit field*/ -+ U32 ba:32, /*b31-0: Buffer Address (keep in mind this is physical address)*/ -+ bl:12, /*b11-0: Buffer Length*/ -+ rsrv1:3, /*b14-12: reserved*/ -+ af:1, /*b15: Abort Frame*/ -+ bi:15, /*b30-16: Buffer Index*/ -+ eof:1; /*b31: End Of Frame*/ -+ -+ } f; -+} transmitDescriptor; -+ -+ -+typedef union transmitStatus { /*data structure of Transmit Status Queue Entry*/ -+ struct { /*whole word*/ -+ U32 e0; /*1st dword entry*/ -+ } w; -+ struct { /*bit field*/ -+ U32 bi:15, /*b14-0: Buffer Index*/ -+ rsrv3:1, /*b15: reserved*/ -+ ncoll:5, /*b20-16: Number of Collisions*/ -+ rsrv2:3, /*b23-21: reserved*/ -+ ecoll:1, /*b24: Excess Collisions*/ -+ txu:1, /*b25: Tx Underrun*/ -+ ow:1, /*b26: Out of Window*/ -+ rsrv1:1, /*b27: reserved*/ -+ lcrs:1, /*b28: Loss of CRS*/ -+ fa:1, /*b29: Frame Abort*/ -+ txwe:1, /*b30: Transmitted Without Error*/ -+ txfp:1; /*b31: Transmit Frame Processed*/ -+ } f; -+} transmitStatus; -+ -+ -+ -+/*--------------------------------------------------------------- -+ * Size of device registers occupied in memory/IO address map -+ *-------------------------------------------------------------*/ -+#define DEV_REG_SPACE 0x00010000 -+ -+/* -+#define U8 unsigned char -+#define U16 unsigned short -+#define U32 unsigned long -+*/ -+ -+/*--------------------------------------------------------------- -+ * A definition of register access macros -+ *-------------------------------------------------------------*/ -+#define _RegRd(type,ofs) (*(volatile type*)(ofs)) -+#define _RegWr(type,ofs,dt) *(volatile type*)(ofs)=((type)(dt)) -+ -+#define RegRd8(ofs) _RegRd(U8,(char*)pD->base_addr+(ofs)) -+#define RegRd16(ofs) _RegRd(U16,(char*)pD->base_addr+(ofs)) -+#define RegRd32(ofs) _RegRd(U32,(char*)pD->base_addr+(ofs)) -+#define RegWr8(ofs,dt) _RegWr(U8,(char*)pD->base_addr+(ofs),(dt)) -+#define RegWr16(ofs,dt) _RegWr(U16,(char*)pD->base_addr+(ofs),(dt)) -+#define RegWr32(ofs,dt) _RegWr(U32,(char*)pD->base_addr+(ofs),(dt)) -+ -+ -+ -+#endif /* _EP9213_ETH_H_ */ -+ diff --git a/target/linux/ep93xx/patches-2.6.30/008-ep93xx-spi.patch b/target/linux/ep93xx/patches-2.6.30/008-ep93xx-spi.patch deleted file mode 100644 index 8292bbcf16..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/008-ep93xx-spi.patch +++ /dev/null @@ -1,714 +0,0 @@ -Index: linux-2.6.30.9/drivers/spi/Kconfig -=================================================================== ---- linux-2.6.30.9.orig/drivers/spi/Kconfig 2009-11-24 21:09:23.000000000 +0100 -+++ linux-2.6.30.9/drivers/spi/Kconfig 2009-11-24 21:09:53.000000000 +0100 -@@ -125,6 +125,12 @@ - - If unsure, say N. - -+config SPI_EP93XX -+ tristate "EP93xx SSP SPI master" -+ depends on SPI_MASTER && ARCH_EP93XX && EXPERIMENTAL -+ help -+ This enables the EP93xx SPI master controller. -+ - config SPI_IMX - tristate "Freescale iMX SPI controller" - depends on ARCH_IMX && EXPERIMENTAL -Index: linux-2.6.30.9/drivers/spi/Makefile -=================================================================== ---- linux-2.6.30.9.orig/drivers/spi/Makefile 2009-11-24 21:09:23.000000000 +0100 -+++ linux-2.6.30.9/drivers/spi/Makefile 2009-11-24 21:09:53.000000000 +0100 -@@ -16,6 +16,7 @@ - obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o - obj-$(CONFIG_SPI_AU1550) += au1550_spi.o - obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o -+obj-$(CONFIG_SPI_EP93XX) += spi_ep93xx.o - obj-$(CONFIG_SPI_GPIO) += spi_gpio.o - obj-$(CONFIG_SPI_GPIO_OLD) += spi_gpio_old.o - obj-$(CONFIG_SPI_IMX) += spi_imx.o -Index: linux-2.6.30.9/drivers/spi/spi_ep93xx.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/drivers/spi/spi_ep93xx.c 2009-11-24 21:21:25.000000000 +0100 -@@ -0,0 +1,680 @@ -+/* -+ * linux/drivers/spi/spi_ep93xx.c -+ * -+ * Copyright (C) 2007 Manfred Gruber <m.gruber@tirol.com> -+ * Small changes by Peter Ivanov <ivanovp@gmail.com> to support MMC over SPI, 2008 -+ * SIM.ONE changes by Nuccio Raciti Simplemachine <nuccio.raciti@gmail.com> -+ * -+ * Based on pxa2xx_spi.c/spi_imx.c and bitbang.c driver -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/blkdev.h> -+#include <linux/clk.h> -+#include <linux/delay.h> -+#include <linux/dma-mapping.h> -+#include <linux/err.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/io.h> -+#include <linux/interrupt.h> -+#include <linux/platform_device.h> -+#include <linux/spinlock.h> -+#include <linux/workqueue.h> -+ -+#include <linux/spi/spi.h> -+ -+#include <mach/hardware.h> -+#include <mach/ep93xx-regs.h> -+#include <asm/gpio.h> -+ -+/* #define SPI_EP93XX_DEBUG */ -+ -+#define DEFINE_SSP_REG(reg, off) \ -+ static inline u32 read_##reg(void *p) \ -+ { return __raw_readl(p + (off)); } \ -+ static inline void write_##reg(u32 v, void *p) \ -+ { __raw_writel(v, p + (off)); } -+ -+DEFINE_SSP_REG(SSPCR0, 0x00) -+DEFINE_SSP_REG(SSPCR1, 0x04) -+DEFINE_SSP_REG(SSPDR, 0x08) -+DEFINE_SSP_REG(SSPSR, 0x0c) -+DEFINE_SSP_REG(SSPCPSR, 0x10) -+DEFINE_SSP_REG(SSPIIR, 0x14) -+DEFINE_SSP_REG(SSPICR, 0x14) -+ -+/* Bits in SSPCR0 */ -+#define SSPCR0_DSS_MASK 0x0000000f -+#define SSPCR0_FRF_MASK 0x00000030 -+#define SSPCR0_FRF_SHIFT 4 -+#define SSPCR0_FRF_MOTOROLA (0 << SSPCR0_FRF_SHIFT) -+#define SSPCR0_FRF_TI (1 << SSPCR0_FRF_SHIFT) -+#define SSPCR0_FRF_NI (2 << SSPCR0_FRF_SHIFT) -+#define SSPCR0_SPO 0x00000040 -+#define SSPCR0_SPH 0x00000080 -+#define SSPCR0_SCR_MASK 0x0000ff00 -+#define SSPCR0_SCR_SHIFT 8 -+ -+/* Bits in SSPCR1 */ -+#define SSPC1_RIE 0x00000001 -+#define SSPC1_TIE 0x00000002 -+#define SSPC1_RORIE 0x00000004 -+#define SSPC1_LBM 0x00000008 -+#define SSPC1_SSE 0x00000010 -+#define SSPC1_MS 0x00000020 -+#define SSPC1_SOD 0x00000040 -+ -+/* Bits in SSPSR */ -+#define SSPSR_TFE 0x00000001 /* TX FIFO is empty */ -+#define SSPSR_TNF 0x00000002 /* TX FIFO is not full */ -+#define SSPSR_RNE 0x00000004 /* RX FIFO is not empty */ -+#define SSPSR_RFF 0x00000008 /* RX FIFO is full */ -+#define SSPSR_BSY 0x00000010 /* SSP is busy */ -+#define SSPSR_MASK 0x0000001F /* SSP is busy */ -+ -+/* Bits in SSPCPSR */ -+#define SSPCPSR_SCR_MASK 0x000000ff -+ -+/* Bits in SSPIIR */ -+#define SSPIIR_RIS 0x00000001 /* RX FIFO IRQ status */ -+#define SSPIIR_TIS 0x00000002 /* TX FIFO is not full */ -+#define SSPIIR_RORIS 0x00000004 /* RX FIFO is full */ -+ -+#define SPI_SSPCLK 7.4e6 -+#define SPI_SSPCLK_REV_E2 14.8e6 /* only for chip Rev E2 */ -+#define SPI_MAX_SPEED 3.7e6 -+#define SPI_MAX_SPEED_REV_E2 7.4e6 /* only for chip Rev E2 */ -+#define SPI_CPSDVR_DIV_MIN 2 -+#define SPI_CPSDVR_DIV_MAX 254 -+#define SPI_SCR_DIV_MIN 0 -+#define SPI_SCR_DIV_MAX 255 -+#define SPI_DATARATE_OK 0 -+#define SPI_DATARATE_NOK -1 -+ -+struct driver_data { -+ /* Driver model hookup */ -+ struct platform_device *pdev; -+ -+ /* SPI framework hookup */ -+ struct spi_master *master; -+ -+ /* SSP register addresses */ -+ void *ioaddr; -+ -+ /* SSP irq */ -+ int irq; -+ -+ struct list_head queue; -+ -+ /* SSP spinlock */ -+ spinlock_t lock; -+ -+ struct workqueue_struct *workqueue; -+ struct work_struct work; -+ -+ u8 busy; -+ u8 use_dma; -+}; -+ -+static unsigned ep93xx_txrx_8(struct spi_device *spi, struct spi_transfer *t) -+{ -+ struct driver_data *drv_data; -+ const u8 *tx = t->tx_buf; -+ u8 *rx = t->rx_buf; -+ unsigned count = t->len; -+ u8 byte; -+ int busy; -+ -+ drv_data = spi_master_get_devdata(spi->master); -+ -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_8: t->len %u \n", t->len); -+#endif -+ -+ while (likely(count > 0)) { -+ byte = 0; -+ if (tx) { -+ byte = *tx++; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_8: write 0x%x \n", byte); -+#endif -+ } -+ -+ write_SSPDR(byte, drv_data->ioaddr); -+ busy = read_SSPSR(drv_data->ioaddr); -+ while (busy & SSPSR_BSY) { -+ cpu_relax(); -+ busy = read_SSPSR(drv_data->ioaddr); -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_8: delay. SSPSR: 0x%X\n", busy); -+#endif -+ } -+ byte = read_SSPDR(drv_data->ioaddr); -+ -+ if (rx) { -+ *rx++ = byte; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_8: read 0x%x \n", byte); -+#endif -+ } -+ count -= 1; -+ } -+ return t->len - count; -+} -+ -+ -+static unsigned ep93xx_txrx_16(struct spi_device *spi, struct spi_transfer *t) -+{ -+ -+ struct driver_data *drv_data; -+ const u16 *tx = t->tx_buf; -+ u16 *rx = t->rx_buf; -+ unsigned count = t->len; -+ u16 word; -+ int busy; -+ -+ drv_data = spi_master_get_devdata(spi->master); -+ -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_16: t->len %u \n", t->len); -+#endif -+ while (likely(count > 0)) { -+ word = 0; -+ if (tx) { -+ word = *tx++; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_16: write 0x%x \n", word); -+#endif -+ } -+ -+ write_SSPDR(word, drv_data->ioaddr); -+ busy = read_SSPSR(drv_data->ioaddr); -+ while (busy & SSPSR_BSY) { -+ cpu_relax(); -+ busy = read_SSPSR(drv_data->ioaddr); -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_8: delay.\n"); -+#endif -+ } -+ -+ word = read_SSPDR(drv_data->ioaddr); -+ -+ if (rx) { -+ *rx++ = word; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "ep93xx_txrx_16: read 0x%x \n", word); -+#endif -+ } -+ count -= 2; -+ } -+ return t->len - count; -+} -+ -+static u32 spi_data_rate(u32 speed_hz, u32 *div_cpsdvr, u32 *div_scr, -+ struct driver_data *drv_data, struct spi_device *spi) -+{ -+ unsigned int spi_sspclk = SPI_SSPCLK; -+ unsigned int bus_speed_max = SPI_MAX_SPEED; -+ unsigned int bus_hz_tmp = 0; -+ u32 div_cpsdvr_tmp; -+ u32 div_scr_tmp; -+ u32 rv = SPI_DATARATE_NOK; -+ int chip_rev; -+ -+ /* Checking CHIP_ID */ -+ chip_rev = (__raw_readl (EP93XX_SYSCON_CHIP_ID) >> 28) & 0xF; -+ if (chip_rev == 7) -+ { -+ /* Chip version: Rev E2 */ -+ /* This device has double speed SSP clock */ -+ spi_sspclk = SPI_SSPCLK_REV_E2; -+ bus_speed_max = SPI_MAX_SPEED_REV_E2; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "Chip Rev E2 detected! This device has double speed SSP clock.\n"); -+#endif -+ } -+ -+ *div_cpsdvr = SPI_CPSDVR_DIV_MAX; -+ *div_scr = SPI_SCR_DIV_MAX; -+ -+ for (div_cpsdvr_tmp = SPI_CPSDVR_DIV_MIN; -+ div_cpsdvr_tmp <= SPI_CPSDVR_DIV_MAX && rv; div_cpsdvr_tmp++) { -+ for (div_scr_tmp = SPI_SCR_DIV_MIN; -+ div_scr_tmp <= SPI_SCR_DIV_MAX && rv; div_scr_tmp++) { -+ bus_hz_tmp = spi_sspclk / (div_cpsdvr_tmp * (1 + div_scr_tmp)); -+ if (bus_hz_tmp <= speed_hz && bus_hz_tmp <= bus_speed_max) { -+ *div_cpsdvr = div_cpsdvr_tmp; -+ *div_scr = div_scr_tmp; -+ rv = SPI_DATARATE_OK; -+ } -+ } -+ } -+#ifdef SPI_EP93XX_DEBUG -+ dev_info(&spi->dev, -+ "Needed SPI bus frequency: %i Hz\n", speed_hz); -+ dev_info(&spi->dev, -+ "Actual SPI bus frequency: %i Hz\n", bus_hz_tmp); -+#endif -+ return rv; -+} -+ -+/* Supported modes (returns -EINVAL if not supported mode requested) */ -+#define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH) -+ -+static int ep93xx_spi_setup(struct spi_device *spi) -+{ -+ struct driver_data *drv_data; -+ u16 val; -+ u32 div_scr; -+ u32 div_cpsdvr; -+ unsigned int bits = spi->bits_per_word; -+ unsigned long speed_hz = spi->max_speed_hz; -+ -+ drv_data = spi_master_get_devdata(spi->master); -+ -+ /* enable SSP */ -+ write_SSPCR1(SSPC1_SSE, drv_data->ioaddr); -+ /* Enable SSP and loopback mode (only for testing!) */ -+ /* write_SSPCR1(SSPC1_SSE | SSPC1_LBM, drv_data->ioaddr); */ -+ -+ if (bits == 0) -+ bits = 8; -+ if (bits < 4 || bits > 16) { -+ dev_err(&spi->dev, -+ "setup invalid bits_per_word %u (4 to 16)\n", bits); -+ return -EINVAL; -+ } else { -+ val = read_SSPCR0(drv_data->ioaddr); -+ val = val & ~SSPCR0_DSS_MASK ; -+ val = val | (bits-1); -+ write_SSPCR0(val, drv_data->ioaddr); -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "Bits per word: %i\n", bits); -+#endif -+ } -+ -+ if (spi->mode & ~MODEBITS) { -+ dev_err(&spi->dev, "unsupported mode bits: %x\n", -+ spi->mode & ~MODEBITS); -+ return -EINVAL; -+ } else { -+ val = read_SSPCR0(drv_data->ioaddr); -+ val = val & ~SSPCR0_SPO; -+ val = val & ~SSPCR0_SPH; -+ if (spi->mode & SPI_CPOL) -+ { -+ val = val | SSPCR0_SPO; -+ } -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "Clock polarity (CPOL): %s\n", (spi->mode & SPI_CPHA) ? "1" : "0"); -+#endif -+ if (spi->mode & SPI_CPHA) -+ { -+ val = val | SSPCR0_SPH; -+ } -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "Clock phase (CPHA): %s\n", (spi->mode & SPI_CPHA) ? "1" : "0"); -+#endif -+ write_SSPCR0(val, drv_data->ioaddr); -+ } -+ -+ if (SPI_DATARATE_OK == (spi_data_rate(speed_hz, &div_cpsdvr, -+ &div_scr, drv_data, spi))) { -+ -+ val = read_SSPCPSR(drv_data->ioaddr); -+ val = val & ~SSPCPSR_SCR_MASK; -+ val = val | div_cpsdvr; -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "SSPCPSR: 0x%X\n", val); -+#endif -+ write_SSPCPSR(val, drv_data->ioaddr); -+ -+ val = read_SSPCR0(drv_data->ioaddr); -+ val = val & ~SSPCR0_SCR_MASK; -+ val = val | (div_scr << SSPCR0_SCR_SHIFT); -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "SSPCR0: 0x%X (div_scr: 0x%X)\n", val, div_scr); -+#endif -+ write_SSPCR0(val, drv_data->ioaddr); -+ } else -+ return -EINVAL; -+ -+ /* reenable */ -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val & ~SSPC1_SSE; -+ write_SSPCR1(val, drv_data->ioaddr); -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val | SSPC1_SSE; -+ write_SSPCR1(val, drv_data->ioaddr); -+#ifdef SPI_EP93XX_DEBUG -+ dev_info (&spi->dev, "Loopback mode: %s\n", (val & SSPC1_LBM) ? "On" : "Off"); -+#endif -+ -+ return 0; -+} -+ -+static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *m) -+{ -+ struct driver_data *drv_data; -+ unsigned long flags; -+ int status = 0; -+ -+ m->actual_length = 0; -+ m->status = -EINPROGRESS; -+ -+ drv_data = spi_master_get_devdata(spi->master); -+ -+ spin_lock_irqsave(&drv_data->lock, flags); -+ if (!spi->max_speed_hz) -+ status = -ENETDOWN; -+ else { -+ list_add_tail(&m->queue, &drv_data->queue); -+ queue_work(drv_data->workqueue, &drv_data->work); -+ } -+ spin_unlock_irqrestore(&drv_data->lock, flags); -+ return status; -+} -+ -+static void ep93xx_work(struct work_struct *work) -+{ -+ struct driver_data *drv_data = -+ container_of(work, struct driver_data, work); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&drv_data->lock, flags); -+ drv_data->busy = 1; -+ -+ while (!list_empty(&drv_data->queue)) { -+ struct spi_message *m; -+ struct spi_device *spi; -+ struct spi_transfer *t = NULL; -+ int status; -+ -+ m = container_of(drv_data->queue.next, struct spi_message, -+ queue); -+ list_del_init(&m->queue); -+ spin_unlock_irqrestore(&drv_data->lock, flags); -+ -+ spi = m->spi; -+ status = 0; -+ -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ -+ if (!t->tx_buf && !t->rx_buf && t->len) { -+ status = -EINVAL; -+ break; -+ } -+ -+ if (t->len) { -+ if (!m->is_dma_mapped) { -+ t->rx_dma = 0; -+ t->tx_dma = 0; -+ } -+ if (t->bits_per_word <= 8) -+ status = ep93xx_txrx_8(spi, t); -+ else -+ status = ep93xx_txrx_16(spi, t); -+ } -+ -+ if (status != t->len) { -+ if (status > 0) -+ status = -EMSGSIZE; -+ break; -+ } -+ m->actual_length += status; -+ status = 0; -+ -+ /* protocol tweaks before next transfer */ -+ if (t->delay_usecs) -+ udelay(t->delay_usecs); -+ -+ if (t->transfer_list.next == &m->transfers) -+ break; -+ } -+ -+ m->status = status; -+ m->complete(m->context); -+ -+ spin_lock_irqsave(&drv_data->lock, flags); -+ } -+ drv_data->busy = 0; -+ spin_unlock_irqrestore(&drv_data->lock, flags); -+} -+ -+static irqreturn_t ssp_int(int irq, void *dev_id) -+{ -+ struct driver_data *drv_data = dev_id; -+ u8 status; -+ status = read_SSPIIR(drv_data->ioaddr); -+ -+ if (status & SSPIIR_RORIS) { -+ dev_err(&drv_data->pdev->dev, "SPI rx overrun.\n"); -+ -+ /* We clear the overrun here ! */ -+ write_SSPICR(0, drv_data->ioaddr); -+ } -+ -+ /* RX interrupt */ -+ if (status & SSPIIR_RIS) -+ dev_info(&drv_data->pdev->dev, "SPI RX interrupt\n"); -+ -+ /* TX interrupt */ -+ if (status & SSPIIR_TIS) -+ dev_info(&drv_data->pdev->dev, "SPI TX interrupt\n"); -+ -+ write_SSPICR(0, drv_data->ioaddr); -+ return IRQ_HANDLED; -+} -+ -+static int __init ep93xx_spi_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct spi_master *master; -+ struct driver_data *drv_data = 0; -+ struct resource *memory_resource; -+ int status = 0; -+ u16 val; -+ -+ /* Allocate master with space for drv_data and null dma buffer */ -+ master = spi_alloc_master(dev, sizeof(struct driver_data)); -+ if (!master) { -+ dev_err(&pdev->dev, "cannot alloc spi_master\n"); -+ return -ENOMEM; -+ } -+ drv_data = spi_master_get_devdata(master); -+ drv_data->master = master; -+ drv_data->pdev = pdev; -+ -+ master->num_chipselect = EP93XX_GPIO_LINE_H(7) + 1; -+ master->bus_num = pdev->id; -+ master->setup = ep93xx_spi_setup; -+ master->transfer = ep93xx_spi_transfer; -+ -+ spin_lock_init(&drv_data->lock); -+ INIT_LIST_HEAD(&drv_data->queue); -+ -+ /* Setup register addresses */ -+ memory_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!memory_resource) { -+ dev_err(&pdev->dev, "memory resources not defined\n"); -+ status = -EIO; -+ goto out_error_master_alloc; -+ } else { -+ drv_data->ioaddr = ioremap(memory_resource->start, -+ memory_resource->end - memory_resource->start); -+ if (drv_data->ioaddr == NULL) { -+ dev_err(&pdev->dev, "ioremap failed\n"); -+ status = -EIO; -+ goto out_error_master_alloc; -+ } -+ } -+ -+ /* Attach to IRQ */ -+ drv_data->irq = platform_get_irq(pdev, 0); -+ if (drv_data->irq < 0) -+ return drv_data->irq; -+ -+ if (drv_data->irq <= 0) { -+ dev_err(&pdev->dev, "IRQ resource not defined\n"); -+ status = -ENODEV; -+ goto out_error_master_alloc; -+ } -+ -+ status = request_irq(drv_data->irq, ssp_int, 0, "ep93xx-spi", drv_data); -+ if (status < 0) { -+ dev_err(&pdev->dev, "cannot get SPI IRQ 0\n"); -+ goto out_error_master_alloc; -+ } -+ -+ /* SSP default configuration, enable */ -+ write_SSPCR1(SSPC1_SSE, drv_data->ioaddr); -+ -+ /* run as master */ -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val & ~SSPC1_MS; -+ write_SSPCR1(val, drv_data->ioaddr); -+ -+ /* frame format to Motorola SPI Format */ -+ val = read_SSPCR0(drv_data->ioaddr); -+ val = val & ~SSPCR0_FRF_MASK ; -+ val = val | SSPCR0_FRF_MOTOROLA; -+ write_SSPCR0(val, drv_data->ioaddr); -+ -+ /* enable interrupts */ -+ val = read_SSPCR1(drv_data->ioaddr); -+ /* for now only overrun is handled */ -+ /* val = val | SSPC1_RIE | SSPC1_TIE | SSPC1_RORIE; */ -+ val = val | SSPC1_RORIE; -+ write_SSPCR1(val, drv_data->ioaddr); -+ -+ /* SSP default configuration, re enable */ -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val & ~SSPC1_SSE; -+ write_SSPCR1(val, drv_data->ioaddr); -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val | SSPC1_SSE; -+ write_SSPCR1(val, drv_data->ioaddr); -+ -+ /* Register with the SPI framework */ -+ platform_set_drvdata(pdev, drv_data); -+ status = spi_register_master(master); -+ if (status != 0) { -+ dev_err(&pdev->dev, "cannot register SPI master\n"); -+ goto out_error_master_alloc; -+ } else -+ dev_info(&pdev->dev, "SPI Controller initalized\n"); -+ -+ INIT_WORK(&drv_data->work, ep93xx_work); -+ spin_lock_init(&drv_data->lock); -+ INIT_LIST_HEAD(&drv_data->queue); -+ -+ /* this task is the only thing to touch the SPI bits */ -+ drv_data->busy = 0; -+ drv_data->workqueue = create_singlethread_workqueue( -+ dev_name(drv_data->master->dev.parent)); -+/* drv_data->master->cdev.dev->bus_id); */ -+ if (drv_data->workqueue == NULL) { -+ status = -EBUSY; -+ goto out_error_free_irq; -+ } -+ -+ return status; -+ -+out_error_free_irq: -+ free_irq(drv_data->irq, master); -+out_error_master_alloc: -+ if (drv_data->ioaddr != NULL) -+ iounmap(drv_data->ioaddr); -+ spi_master_put(master); -+ return status; -+} -+ -+static int __exit ep93xx_spi_remove(struct platform_device *pdev) -+{ -+ struct driver_data *drv_data = platform_get_drvdata(pdev); -+ u8 val; -+ -+ WARN_ON(!list_empty(&drv_data->queue)); -+ -+ destroy_workqueue(drv_data->workqueue); -+ -+ /* switch off SSP*/ -+ val = read_SSPCR1(drv_data->ioaddr); -+ val = val & ~SSPC1_SSE; -+ write_SSPCR1(val, drv_data->ioaddr); -+ -+ /* release irqs */ -+ if (drv_data->irq > 0) -+ free_irq(drv_data->irq, drv_data); -+ -+ /* Disconnect from the SPI framework */ -+ spi_unregister_master(drv_data->master); -+ spi_master_put(drv_data->master); -+ -+ if (drv_data->ioaddr != NULL) -+ iounmap(drv_data->ioaddr); -+ -+ /* Prevent double remove */ -+ platform_set_drvdata(pdev, NULL); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ep93xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) -+{ -+ return 0; -+} -+ -+static int ep93xx_spi_resume(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+#else -+#define ep93xx_spi_suspend NULL -+#define ep93xx_spi_resume NULL -+#endif -+ -+struct platform_driver ep93xx_spi_device = { -+ .remove = __exit_p(ep93xx_spi_remove), -+#ifdef CONFIG_PM -+ .suspend = ep93xx_spi_suspend, -+ .resume = ep93xx_spi_resume, -+#endif -+ .driver = { -+ .name = "ep93xx-spi", -+ .bus = &spi_bus_type, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+int __init ep93xx_spi_init(void) -+{ -+ return platform_driver_probe(&ep93xx_spi_device, ep93xx_spi_probe); -+} -+ -+void __exit ep93xx_spi_exit(void) -+{ -+ platform_driver_unregister(&ep93xx_spi_device); -+} -+ -+module_init(ep93xx_spi_init); -+module_exit(ep93xx_spi_exit); -+ -+MODULE_DESCRIPTION("EP93XX SPI Driver"); -+MODULE_AUTHOR("Manfred Gruber, <m.gruber@tirol.com>"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ep93xx/patches-2.6.30/009-ep93xx-fb.patch b/target/linux/ep93xx/patches-2.6.30/009-ep93xx-fb.patch deleted file mode 100644 index d7816bd722..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/009-ep93xx-fb.patch +++ /dev/null @@ -1,3565 +0,0 @@ ---- a/drivers/video/Kconfig -+++ b/drivers/video/Kconfig -@@ -255,6 +255,25 @@ config FB_CIRRUS - Say N unless you have such a graphics board or plan to get one - before you next recompile the kernel. - -+config FB_EP93XX -+ tristate "EP93xx frame buffer support" -+ depends on FB -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ help -+ This is the frame buffer device driver for the internal raster engine -+ on certain members of the EP93xx family. For VGA and LCD output. -+ -+config FB_EP93XX_MONO -+ tristate "EP93xx Mono frame buffer support" -+ depends on FB -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ help -+ This is the frame buffer device driver for the internal raster engine -+ on certain members of the EP93xx family. For LCD output. -+ - config FB_PM2 - tristate "Permedia2 support" - depends on FB && ((AMIGA && BROKEN) || PCI) ---- a/drivers/video/Makefile -+++ b/drivers/video/Makefile -@@ -95,6 +95,8 @@ obj-$(CONFIG_FB_ARMCLCD) += amba-clcd. - obj-$(CONFIG_FB_68328) += 68328fb.o - obj-$(CONFIG_FB_GBE) += gbefb.o - obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o -+obj-$(CONFIG_FB_EP93XX) += ep93xxfb.o -+obj-$(CONFIG_FB_EP93XX_MONO) += ep93xxfb_mono.o - obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o - obj-$(CONFIG_FB_PXA) += pxafb.o - obj-$(CONFIG_FB_W100) += w100fb.o ---- /dev/null -+++ b/drivers/video/ep93xxfb.c -@@ -0,0 +1,1628 @@ -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/reboot.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/mm.h> -+#include <linux/delay.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+#include <linux/dma-mapping.h> -+#include <asm/io.h> -+#include <asm/uaccess.h> -+#include "ep93xxfb.h" -+#include <mach/hardware.h> -+#include <linux/platform_device.h> -+ -+#include "console/fbcon.h" -+ -+ -+#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_EDB9307) || defined(CONFIG_MACH_EDB9301) || defined(CONFIG_MACH_EDB9302) -+#define CONFIG_EP93XX_SDCS3 -+#else -+#define CONFIG_EP93XX_SDCS0 -+#endif -+ -+//#define DEBUG 1 -+#ifdef DEBUG -+#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) -+#else -+#define DPRINTK( fmt, arg... ) -+#endif -+ -+#define FBDEV_NAME "ep93xxfb" -+ -+#define ep93xxfb_outl(value, reg) \ -+{ \ -+ outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); \ -+ outl(value, reg); \ -+} -+ -+#define DEFAULT_OUT CRT_OUT -+#define DEFAULT_MODE 7 -+#define DEFAULT_BPP 24 -+ -+static DECLARE_WAIT_QUEUE_HEAD(ep93xxfb_wait_in); -+ -+static unsigned int pseudo_palette[256]; -+static unsigned long *cursor_data = NULL; -+static struct ep93xxfb_info epinfo; -+ -+static int vout = DEFAULT_OUT; -+static int vmode = DEFAULT_MODE; -+static int depth = DEFAULT_BPP; -+ -+ -+static int ep93xxfb_setcol(struct fb_info *info, int bpp); -+ -+ -+static struct ep93xxfb_videomodes ep93xxfb_vmods[] = { -+ { -+ "Philips-LB064V02-640x480x60", -+ 640, 24, 96, 40, 480, 10, 2, 33, 60, -+ CLK_INTERNAL, EDGE_FALLING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 1 -+ "CRT-640x480-60", -+ 640, 24, 96, 40, 480, 11, 2, 32, 60, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 2 -+ "CRT-640x480-72", -+ 640, 40, 40, 144, 480, 8, 3, 30, 72, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 3 -+ "CRT-640x480-75", -+ 640, 16, 76, 120, 480, 1, 3, 16, 75, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 4 -+ "CRT-640x480-85", -+ 640, 56, 56, 80, 480, 1, 3, 25, 85, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 5 -+ "CTR-640x480-100", -+ 640, 32, 96, 96, 480, 8, 6, 36, 100, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 6 -+ "CRT-800x600-56", -+ 800, 24, 72, 128, 600, 1, 2, 22, 56, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 7 -+ "CRT-800x600-60", -+ 800, 40, 128, 88, 600, 1, 4, 23, 60, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, -+ }, -+ { // 8 -+ "CRT-800x600-72", -+ 800, 56, 120, 64, 600, 37, 6, 23, 72, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 9 -+ "CRT-800x600-85", -+ 800, 64, 64, 160, 600, 16, 5, 36, 85, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 10 -+ "CRT-800x600-100", -+ 800, 64, 64, 160, 600, 4, 6, 30, 100, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 11 -+ "CRT-1024x768-60", -+ 1024, 8, 144, 168, 768, 3, 6, 29, 60, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 12 -+ "CRT-1024x768-70", -+ 1024, 24, 136, 144, 768, 3, 6, 29, 70, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_LOW, POL_LOW, -+ }, -+ { // 13 -+ "CRT-1024x768-75", -+ 1024, 16, 96, 176, 768, 1, 3, 28, 75, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, -+ }, -+ { // 14 -+ "CRT-1024x768-85", -+ 1024, 48, 96, 208, 768, 1, 3, 36, 85, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, -+ }, -+ { // 15 -+ "CRT-1280x720-60", -+ 1280, 48, 112, 248, 720, 1, 3, 38, 60, -+ CLK_INTERNAL, EDGE_RISING, POL_LOW, POL_HIGH, POL_HIGH, -+ } -+}; -+ -+static void philips_lb064v02_on(unsigned char value) -+{ -+ DPRINTK("philips_lb064v02_on \n"); -+ outl(inl(GPIO_PADDR) | 2, GPIO_PADDR); -+ outl(inl(GPIO_PADR) | 2, GPIO_PADR); -+} -+ -+static void philips_lb064v02_off(unsigned char value) -+{ -+ DPRINTK("philips_lb064v02_off \n"); -+ outl(inl(GPIO_PADR) & ~2, GPIO_PADR); -+} -+ -+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah) -+{ -+ outl(0x00000000, BLOCKCTRL); -+ wake_up(&ep93xxfb_wait_in); -+ return IRQ_HANDLED; -+} -+ -+static void ep93xxfb_wait(void) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ add_wait_queue(&ep93xxfb_wait_in, &wait); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ -+ while (inl(BLOCKCTRL) & 0x00000001){ -+ if(/*(pls_proba==1)&&*/(!in_atomic())) -+ schedule(); -+ } -+ -+ remove_wait_queue(&ep93xxfb_wait_in, &wait); -+ set_current_state(TASK_RUNNING); -+ -+} -+ -+void ep93xxfb_fillrect(struct fb_info *p, const struct fb_fillrect *fill) -+{ -+ unsigned long blkdestwidth,tmp; -+ -+ if (!fill->width || !fill->height || -+ (fill->dx >= p->var.xres) || -+ (fill->dy >= p->var.yres) || -+ ((fill->dx + fill->width - 1) >= p->var.xres) || -+ ((fill->dy + fill->height - 1) >= p->var.yres)) -+ return; -+ -+ tmp = (( fill->dx + fill->width ) * epinfo.bpp ); -+ blkdestwidth = tmp / 32; -+ if(blkdestwidth > 0 && (tmp % 32 == 0)) -+ blkdestwidth--; -+ blkdestwidth = blkdestwidth - (fill->dx * epinfo.bpp) / 32; -+ -+ outl(fill->color, BLOCKMASK); -+ outl( ((fill->dx * epinfo.bpp) & 0x1F) | -+ ((((fill->dx + fill->width - 1) * epinfo.bpp ) & 0x1F) << 16), -+ DESTPIXELSTRT); -+ outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH); -+ outl( blkdestwidth, BLKDESTWIDTH ); -+ outl(fill->height - 1, BLKDESTHEIGHT); -+ outl((epinfo.fb_phys + (fill->dy * epinfo.xres * epinfo.bpp ) / 8 + -+ (fill->dx * epinfo.bpp ) / 8 ) -+ , BLKDSTSTRT); -+ outl( epinfo.pixformat | 0x0000000B, BLOCKCTRL); -+ ep93xxfb_wait(); -+ -+} -+ -+void ep93xxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) -+{ -+ unsigned long startsx,stopsx,startdx,stopdx,startsy,startdy; -+ unsigned long blksrcwidth,blkdestwidth,tmp; -+ unsigned long val = 0; -+ -+ if( !area->width || !area->width || -+ (area->sx >= p->var.xres) || (area->sy >= p->var.yres) || -+ (area->dx >= p->var.xres) || (area->dy >= p->var.yres) || -+ ((area->dx + area->width - 1) >= p->var.xres) || -+ ((area->dy + area->height - 1) >= p->var.yres)) -+ return; -+ -+ if(area->sx == area->dx && area->sy == area->dy) -+ return; -+ -+ if ((area->dy == area->sy) && (area->dx > area->sx) && -+ (area->dx < (area->sx + area->width - 1))) { -+ startdx = area->dx + area->width - 1; -+ stopdx = area->dx; -+ startsx = area->sx + area->width - 1; -+ stopsx = area->sx; -+ val |= 0x000000A0; -+ } -+ else { -+ startdx = area->dx; -+ stopdx = area->dx + area->width - 1; -+ startsx = area->sx; -+ stopsx = area->sx + area->width - 1; -+ } -+ -+ if (area->dy <= area->sy) { -+ startdy = area->dy; -+ startsy = area->sy; -+ } -+ else { -+ startdy = area->dy + area->height -1; -+ startsy = area->sy + area->height -1; -+ val |= 0x00000140; -+ } -+ -+ tmp = (( area->sx + area->width ) * epinfo.bpp ); -+ blksrcwidth = tmp / 32; -+ if(blksrcwidth > 0 && (tmp % 32 == 0)) -+ blksrcwidth--; -+ blksrcwidth = blksrcwidth - (area->sx * epinfo.bpp) / 32; -+ -+ tmp = (( area->dx + area->width ) * epinfo.bpp ); -+ blkdestwidth = tmp / 32; -+ if(blkdestwidth > 0 && (tmp % 32 == 0)) -+ blkdestwidth--; -+ blkdestwidth = blkdestwidth - (area->dx * epinfo.bpp) / 32; -+ -+ outl( 0x00000000 , BLOCKCTRL); -+ -+ /*** src ***/ -+ outl((((startsx * epinfo.bpp) & 0x1F) | -+ (((stopsx * epinfo.bpp ) & 0x1F) << 16)) -+ , SRCPIXELSTRT); -+ outl((epinfo.fb_phys + (startsy * epinfo.xres * epinfo.bpp ) / 8 + -+ (startsx * epinfo.bpp ) / 8 ) -+ , BLKSRCSTRT); -+ outl(((epinfo.xres * epinfo.bpp) / 32), SRCLINELENGTH); -+ outl( blksrcwidth, BLKSRCWIDTH ); -+ -+ /*** dest ***/ -+ outl((((startdx * epinfo.bpp) & 0x1F) | -+ (((stopdx * epinfo.bpp ) & 0x1F) << 16)) -+ , DESTPIXELSTRT); -+ outl((epinfo.fb_phys + (startdy * epinfo.xres * epinfo.bpp ) / 8 + -+ (startdx * epinfo.bpp ) / 8 ) -+ , BLKDSTSTRT); -+ outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH); -+ outl( blkdestwidth, BLKDESTWIDTH); -+ outl( area->height - 1 , BLKDESTHEIGHT); -+ outl( epinfo.pixformat | val | 0x00000003, BLOCKCTRL); -+ ep93xxfb_wait(); -+} -+ -+void ep93xxfb_imageblit(struct fb_info *p, const struct fb_image *image) -+{ -+// unsigned long blkdestwidth,tmp; -+// void * pucBlitBuf; -+ cfb_imageblit( p , image ); -+ return; -+/* -+ if ((image->dx >= p->var.xres) || -+ (image->dy >= p->var.yres) || -+ ((image->dx + image->width - 1) >= p->var.xres) || -+ ((image->dy + image->height - 1) >= p->var.yres)) -+ return; -+ if (epinfo.bpp != image->depth ) -+ return; -+ -+ tmp = (( image->dx + image->width ) * epinfo.bpp ); -+ blkdestwidth = tmp / 32; -+ if(blkdestwidth > 0 && (tmp % 32 == 0)) -+ blkdestwidth--; -+ blkdestwidth = blkdestwidth - (image->dx * epinfo.bpp) / 32; -+ -+ pucBlitBuf = kmalloc(1024*8,GFP_KERNEL); -+ copy_from_user(pucBlitBuf, image->data, 5000); -+ -+ outl( 0x00000000 , BLOCKCTRL); -+ -+ outl( 0x00000000, SRCPIXELSTRT); -+ outl( virt_to_phys(pucBlitBuf), BLKSRCSTRT); -+ outl( (image->width * epinfo.bpp) / 32 , SRCLINELENGTH); -+ outl(((image->width - 1) * epinfo.bpp) / 32, BLKSRCWIDTH ); -+ -+ outl(((image->dx * epinfo.bpp) & 0x1F) | -+ ((((image->dx + image->width - 1) * epinfo.bpp ) & 0x1F) << 16) -+ , DESTPIXELSTRT); -+ outl((epinfo.fb_phys + (image->dy * epinfo.xres * epinfo.bpp ) / 8 + -+ (image->dx * epinfo.bpp ) / 8 ) -+ , BLKDSTSTRT); -+ outl( ((epinfo.xres * epinfo.bpp) / 32), DESTLINELENGTH ); -+ outl( blkdestwidth, BLKDESTWIDTH ); -+ outl( image->height - 1 , BLKDESTHEIGHT); -+ outl(image->fg_color, BLOCKMASK); -+ outl(image->bg_color, BACKGROUND); -+ outl( epinfo.pixformat | 0x00000003, BLOCKCTRL ); -+ ep93xxfb_wait(); -+*/ -+} -+ -+ -+static unsigned long isqrt(unsigned long a) -+{ -+ unsigned long rem = 0; -+ unsigned long root = 0; -+ int i; -+ -+ for (i = 0; i < 16; i++) { -+ root <<= 1; -+ rem = ((rem << 2) + (a >> 30)); -+ a <<= 2; -+ root++; -+ if (root <= rem) { -+ rem -= root; -+ root++; -+ } -+ else -+ root--; -+ } -+ return root >> 1; -+} -+ -+int ep93xxfb_line(struct fb_info *info, struct ep93xx_line *line) -+{ -+ unsigned long value = 0; -+ long x, y, dx, dy, count, xinc, yinc, xval, yval, incr; -+ -+ if ((line->x1 > info->var.xres) || -+ (line->x2 > info->var.xres) || -+ (line->y1 > info->var.yres) || -+ (line->y2 > info->var.yres)) -+ return -EFAULT; -+ x = line->x1; -+ y = line->y1; -+ dx = line->x2 - line->x1; -+ dy = line->y2 - line->y1; -+ -+ if ( !dx || !dy ) -+ return -EFAULT; -+ -+ if ( dx < 0 && dy < 0 ) { -+ x = line->x2; -+ y = line->y2; -+ dx *= -1; -+ dy *= -1; -+ } -+ else if ( dx < 0 && dy > 0 ){ -+ dx *= -1; -+ value = 0x000000A0; -+ } -+ else if( dy < 0 && dx > 0 ){ -+ dy *= -1; -+ value = 0x00000140; -+ } -+ -+ if (line->flags & LINE_PRECISE) { -+ count = isqrt(((dy * dy) + (dx * dx)) * 4096); -+ xinc = (4095 * 64 * dx) / count; -+ yinc = (4095 * 64 * dy) / count; -+ xval = 2048; -+ yval = 2048; -+ count = 0; -+ while (dx || dy) { -+ incr = 0; -+ xval -= xinc; -+ if (xval <= 0) { -+ xval += 4096; -+ dx--; -+ incr = 1; -+ } -+ yval -= yinc; -+ if (yval <= 0) { -+ yval += 4096; -+ dy--; -+ incr = 1; -+ } -+ count += incr; -+ } -+ } -+ else { -+ if ( dx == dy ) { -+ xinc = 4095; -+ yinc = 4095; -+ count = dx; -+ -+ } -+ else if ( dx < dy ) { -+ xinc = ( dx * 4095 ) / dy; -+ yinc = 4095; -+ count = dy; -+ -+ } -+ else { -+ xinc = 4095; -+ yinc = ( dy * 4095 ) / dx; -+ count = dx; -+ } -+ } -+ -+ outl(0x08000800, LINEINIT); -+ if (line->flags & LINE_PATTERN) -+ outl(line->pattern, LINEPATTRN); -+ else -+ outl(0x000fffff, LINEPATTRN); -+ outl(epinfo.fb_phys + ((y * epinfo.xres * epinfo.bpp) / 8) + -+ ((x * epinfo.bpp ) / 8 ), BLKDSTSTRT); -+ -+ outl(((x * epinfo.bpp) & 0x1F) | -+ ((((x + dx - 1) * epinfo.bpp) & 0x1F ) << 16), -+ DESTPIXELSTRT); -+ outl((epinfo.xres * epinfo.bpp) / 32, DESTLINELENGTH); -+ outl(line->fgcolor, BLOCKMASK); -+ outl(line->bgcolor, BACKGROUND); -+ outl((yinc << 16) | xinc, LINEINC); -+ outl( count & 0xFFF, BLKDESTWIDTH); -+ outl( 0 , BLKDESTHEIGHT); -+ value |= (line->flags & LINE_BACKGROUND) ? 0x00004000 : 0; -+ outl(epinfo.pixformat | value | 0x00000013, BLOCKCTRL); -+ ep93xxfb_wait(); -+ return 0; -+} -+ -+int ioctl_cursor=0; -+ -+int ep93xxfb_cursor(struct fb_info *info, struct ep93xx_cursor *cursor) -+{ -+ unsigned long x,y,save; -+ -+ if((cursor->width ==0) || (cursor->height ==0) ) -+ { -+ struct fb_cursor *fbcon_cursor =(struct fb_cursor *)cursor; -+ struct fbcon_ops *ops = (struct fbcon_ops *)info->fbcon_par; -+ unsigned int scan_align = info->pixmap.scan_align - 1; -+ unsigned int buf_align = info->pixmap.buf_align - 1; -+ unsigned int i, size, dsize, s_pitch, d_pitch; -+ struct fb_image *image; -+ u8 *src, *dst; -+ -+ if(ioctl_cursor==1 ){ -+ DPRINTK("softcursor error return\n"); -+ return 0; -+ } -+ -+ -+ if (info->state != FBINFO_STATE_RUNNING) -+ return 0; -+ -+ s_pitch = (fbcon_cursor->image.width + 7) >> 3; -+ dsize = s_pitch * fbcon_cursor->image.height; -+ -+ if (dsize + sizeof(struct fb_image) != ops->cursor_size) { -+ if (ops->cursor_src != NULL) -+ kfree(ops->cursor_src); -+ ops->cursor_size = dsize + sizeof(struct fb_image); -+ -+ ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); -+ if (!ops->cursor_src) { -+ ops->cursor_size = 0; -+ return -ENOMEM; -+ } -+ } -+ src = ops->cursor_src + sizeof(struct fb_image); -+ image = (struct fb_image *)ops->cursor_src; -+ *image = fbcon_cursor->image; -+ d_pitch = (s_pitch + scan_align) & ~scan_align; -+ -+ size = d_pitch * image->height + buf_align; -+ size &= ~buf_align; -+ dst = fb_get_buffer_offset(info, &info->pixmap, size); -+ -+ if (fbcon_cursor->enable) { -+ switch (fbcon_cursor->rop) { -+ case ROP_XOR: -+ for (i = 0; i < dsize; i++) -+ src[i] = image->data[i] ^ fbcon_cursor->mask[i]; -+ break; -+ case ROP_COPY: -+ default: -+ for (i = 0; i < dsize; i++) -+ src[i] = image->data[i] & fbcon_cursor->mask[i]; -+ break; -+ } -+ } else -+ memcpy(src, image->data, dsize); -+ -+ fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); -+ image->data = dst; -+ info->fbops->fb_imageblit(info, image); -+ return 0; -+ -+ } -+ else{ -+ ioctl_cursor = 1; -+ -+ /*if (cursor->width > 16 || cursor->height > 16){ -+ DPRINTK("%s width %d or heright %d error\n",__FUNCTION__,cursor->width,cursor->height); -+ return -ENXIO; -+ }*/ -+ -+ if (cursor->flags & CURSOR_OFF) -+ outl(inl(CURSORXYLOC) & ~0x00008000, CURSORXYLOC); -+ -+ if (cursor->flags & CURSOR_SETSHAPE) { -+ copy_from_user(cursor_data, cursor->data, -+ cursor->width * cursor->height / 4); -+ save = inl(CURSORXYLOC); -+ outl(save & ~0x00008000, CURSORXYLOC); -+ -+ outl(virt_to_phys(cursor_data), CURSOR_ADR_START); -+ outl(virt_to_phys(cursor_data), CURSOR_ADR_RESET); -+ outl(((cursor->width - 1) & 0x30) << 4 | ((cursor->height - 1) << 2) | -+ ((cursor->width - 1) >> 4), CURSORSIZE); -+ outl(save, CURSORXYLOC); -+ -+ } -+ -+ if (cursor->flags & CURSOR_SETCOLOR) { -+ outl(cursor->color1, CURSORCOLOR1); -+ outl(cursor->color2, CURSORCOLOR2); -+ outl(cursor->blinkcolor1, CURSORBLINK1); -+ outl(cursor->blinkcolor2, CURSORBLINK2); -+ } -+ -+ if (cursor->flags & CURSOR_BLINK) { -+ if (cursor->blinkrate) -+ outl(0x00000100 | cursor->blinkrate, CURSORBLINK); -+ else -+ outl(0x0000000FF, CURSORBLINK); -+ } -+ -+ if (cursor->flags & CURSOR_MOVE) { -+ x = (inl(HACTIVESTRTSTOP) & 0x000007ff) - cursor->dx - 2; -+ y = (inl(VACTIVESTRTSTOP) & 0x000007ff) - cursor->dy; -+ outl((inl(CURSORXYLOC) & 0x8000) | (y << 16) | x, CURSORXYLOC); -+ } -+ -+ if(cursor->flags & CURSOR_ON) -+ outl(inl(CURSORXYLOC) | 0x00008000, CURSORXYLOC); -+ -+ return 0; -+ } -+} -+ -+ -+ -+static inline void -+ep93xxfb_palette_write(u_int regno, u_int red, u_int green, -+ u_int blue, u_int trans) -+{ -+ unsigned int cont, i, pal; -+ DPRINTK("ep93xxfb_palette_write - enter\n"); -+ pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); -+ pseudo_palette[regno] = pal; -+ outl( pal, ( COLOR_LUT + ( regno << 2 ))); -+ cont = inl( LUTCONT ); -+ -+ if (( cont & LUTCONT_STAT && cont & LUTCONT_RAM1 ) || -+ ( !( cont & LUTCONT_STAT ) && !( cont&LUTCONT_RAM1 ))) { -+ for ( i = 0; i < 256; i++ ) { -+ outl( pseudo_palette[i], ( COLOR_LUT + ( i << 2 )) ); -+ } -+ outl( cont ^ LUTCONT_RAM1, LUTCONT ); -+ } -+} -+ -+int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, -+ unsigned blue, unsigned transp, -+ struct fb_info *info) -+{ -+ -+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) -+ -+ switch ( info->fix.visual ) -+ { -+ case FB_VISUAL_PSEUDOCOLOR: -+ ep93xxfb_palette_write(regno, red, green, blue, transp); -+ break; -+ case FB_VISUAL_TRUECOLOR: -+ if (regno >= 16) -+ return 1; -+ red = CNVT_TOHW(red, info->var.red.length); -+ green = CNVT_TOHW(green, info->var.green.length); -+ blue = CNVT_TOHW(blue, info->var.blue.length); -+ transp = CNVT_TOHW(transp, info->var.transp.length); -+ ((u32 *)(info->pseudo_palette))[regno] = -+ (red << info->var.red.offset) | -+ (green << info->var.green.offset) | -+ (blue << info->var.blue.offset) | -+ (transp << info->var.transp.offset); -+ break; -+ case FB_VISUAL_DIRECTCOLOR: -+ red = CNVT_TOHW(red, 8); -+ green = CNVT_TOHW(green, 8); -+ blue = CNVT_TOHW(blue, 8); -+ transp = CNVT_TOHW(transp, 8); -+ break; -+ } -+#undef CNVT_TOHW -+ return 0; -+} -+ -+static int ep93xx_pan_display(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ DPRINTK("ep93xx_pan_display - enter\n"); -+ -+ if (var->yoffset < 0 -+ || var->yoffset + var->yres > info->var.yres_virtual -+ || var->xoffset) -+ return -EINVAL; -+ -+ outl(epinfo.fb_phys + info->fix.line_length * var->yoffset -+ , VIDSCRNPAGE); -+ -+ info->var.xoffset = var->xoffset; -+ info->var.yoffset = var->yoffset; -+ -+ DPRINTK("ep93xx_pan_display - exit\n"); -+ return 0; -+} -+ -+ -+static int -+ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ struct fb_var_screeninfo tmp_var; -+ unsigned long pclk; -+ DPRINTK("ep93xxfb_check_var - enter\n"); -+ -+ if( vout != 0) { -+ printk(" ep93xxfb_check_var - vout != 0\n"); -+ return -EINVAL; -+ } -+ -+ memcpy (&tmp_var, var, sizeof (tmp_var)); -+ -+ if( (tmp_var.vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED ) { -+ printk(" ep93xxfb_check_var - unsupported video mode\n"); -+ return -EINVAL; -+ } -+ -+ if( ((tmp_var.xres * tmp_var.yres * tmp_var.bits_per_pixel) / 8) > -+ MAX_FBMEM_SIZE ) { -+ printk(" ep93xxfb_check_var - memory error \n"); -+ return -ENOMEM; -+ } -+ -+ if( ((tmp_var.xres_virtual * tmp_var.yres_virtual * tmp_var.bits_per_pixel) / 8) > -+ MAX_FBMEM_SIZE ) { -+ printk(" ep93xxfb_check_var - memory error \n"); -+ return -ENOMEM; -+ } -+ -+ pclk = 1000 * (1000000000 / tmp_var.pixclock); -+ -+ if( pclk > ep93xx_get_max_video_clk() ) { -+ printk(" ep93xxfb_check_var - pixel clock error %lu\n",pclk); -+ return -EINVAL; -+ } -+ -+ if (var->xres_virtual != var->xres) -+ var->xres_virtual = var->xres; -+ if (var->yres_virtual < var->yres) -+ var->yres_virtual = var->yres; -+ -+ if (var->xoffset < 0) -+ var->xoffset = 0; -+ if (var->yoffset < 0) -+ var->yoffset = 0; -+ -+ switch (tmp_var.bits_per_pixel) { -+ case 8: -+ break; -+ case 16: -+ break; -+ case 24: -+ break; -+ case 32: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ DPRINTK("ep93xxfb_check_var - exit\n"); -+ return 0; -+} -+ -+ -+static int ep93xxfb_set_par(struct fb_info *info) -+{ -+ struct fb_var_screeninfo tmp_var; -+ unsigned long attribs; -+ -+ DPRINTK("ep93xxfb_set_par - enter\n"); -+ -+ if( ep93xxfb_check_var(&info->var,info) < 0 ) -+ return -EINVAL; -+ -+ if( !ep93xxfb_setcol(info,info->var.bits_per_pixel) ) -+ return -EINVAL; -+ -+ -+ info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8; -+ -+ ep93xxfb_blank( 1 , info ); -+ -+ memcpy(&tmp_var,&info->var,sizeof(tmp_var)); -+ -+ epinfo.xres = tmp_var.xres; -+ epinfo.xsync = tmp_var.hsync_len; -+ epinfo.xfp = tmp_var.right_margin; -+ epinfo.xbp = tmp_var.left_margin; -+ epinfo.xtotal = epinfo.xres + epinfo.xsync + -+ epinfo.xfp + epinfo.xbp; -+ -+ epinfo.yres = tmp_var.yres; -+ epinfo.ysync = tmp_var.vsync_len; -+ epinfo.yfp = tmp_var.lower_margin; -+ epinfo.ybp = tmp_var.upper_margin; -+ epinfo.ytotal = epinfo.yres + epinfo.ysync + -+ epinfo.yfp + epinfo.ybp; -+ -+ epinfo.pixclock = tmp_var.pixclock ; -+ epinfo.refresh = 1000 * (1000000000 / tmp_var.pixclock) ; -+ -+ if( epinfo.refresh > ep93xx_get_max_video_clk()) -+ epinfo.refresh = ep93xx_get_max_video_clk(); -+ epinfo.bpp = tmp_var.bits_per_pixel; -+ -+ ep93xxfb_setclk(); -+ ep93xxfb_timing_signal_generation(); -+ -+ // set video memory parameters -+ outl(epinfo.fb_phys, VIDSCRNPAGE); -+ outl(epinfo.yres , SCRNLINES); -+ outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); -+ outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); -+ -+ // set pixel mode -+ ep93xxfb_pixelmod(epinfo.bpp); -+ -+ attribs = 0; -+#ifdef CONFIG_EP93XX_SDCS0 -+ attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+ -+ attribs |= VIDEOATTRIBS_INVCLK; -+ if( tmp_var.sync & FB_SYNC_HOR_HIGH_ACT ) -+ attribs |= VIDEOATTRIBS_HSPOL; -+ if( tmp_var.sync & FB_SYNC_VERT_HIGH_ACT ) -+ attribs |= VIDEOATTRIBS_VCPOL; -+ -+ ep93xxfb_outl(attribs, VIDEOATTRIBS); -+ ep93xxfb_blank( 0 , info ); -+ -+ DPRINTK("ep93xxfb_set_par - exit\n"); -+ -+ return 0; -+} -+ -+ -+static int ep93xxfb_blank(int blank_mode,struct fb_info *info) -+{ -+ unsigned long attribs; -+ DPRINTK("ep93xxfb_blank - enter\n"); -+ attribs = inl(VIDEOATTRIBS); -+ -+#ifdef CONFIG_EP93XX_SDCS0 -+ attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+ -+ if (blank_mode) { -+ if (epinfo.off) -+ (epinfo.off)( 0 ); -+ -+ ep93xxfb_outl(attribs & ~(VIDEOATTRIBS_DATAEN | -+ VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN | -+ VIDEOATTRIBS_EN), VIDEOATTRIBS); -+ } -+ else { -+ if (epinfo.clk_src == CLK_INTERNAL) -+ attribs |= VIDEOATTRIBS_PCLKEN; -+ else -+ attribs &= ~VIDEOATTRIBS_PCLKEN; -+ -+ ep93xxfb_outl(attribs | VIDEOATTRIBS_DATAEN | -+ VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_EN, -+ VIDEOATTRIBS); -+ -+ if (epinfo.configure) -+ (epinfo.configure)( epinfo.automods ); -+ if (epinfo.on) -+ (epinfo.on)( 0 ); -+ } -+ return 0; -+} -+ -+static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma) -+{ -+ unsigned long off, start, len; -+ -+ DPRINTK("ep93xxfb_mmap - enter\n"); -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ start = info->fix.smem_start; -+ len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len; -+ start &= PAGE_MASK; -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ -+ off += start; -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) { -+ DPRINTK("ep93xxfb_mmap error\n"); -+ return -EAGAIN; -+ } -+ -+ DPRINTK("ep93xxfb_mmap - exit\n"); -+ return 0; -+} -+ -+static unsigned long ep93xx_get_pll_frequency(unsigned long pll) -+{ -+ unsigned long fb1, fb2, ipd, ps, freq; -+ -+ if (pll == 1) -+ pll = inl(EP93XX_SYSCON_CLOCK_SET1); -+ else if (pll == 2) -+ pll = inl(EP93XX_SYSCON_CLOCK_SET2); -+ else -+ return 0; -+ -+ ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >> SYSCON_CLKSET1_PLL1_PS_SHIFT; -+ fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT); -+ fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT); -+ ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT); -+ -+ freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps; -+ return freq; -+} -+ -+static int ep93xx_get_max_video_clk() -+{ -+ unsigned long f,freq = 0; -+ -+ freq = 14745600 / 4; -+ f = ep93xx_get_pll_frequency(1) / 4; -+ if ( f > freq ) -+ freq = f; -+ f = ep93xx_get_pll_frequency(2) / 4; -+ if ( f > freq ) -+ freq = f; -+ -+ return freq; -+} -+ -+static int ep93xx_set_video_div(unsigned long freq) -+{ -+ unsigned long pdiv = 0, div = 0, psel = 0, esel = 0; -+ unsigned long err, f, i, j, k; -+ -+ err = -1; -+ -+ for (i = 0; i < 3; i++) { -+ if (i == 0) -+ f = 14745600 * 2; -+ else if (i == 1) -+ f = ep93xx_get_pll_frequency(1) * 2; -+ else -+ f = ep93xx_get_pll_frequency(2) * 2; -+ -+ for (j = 4; j <= 6; j++) { -+ k = f / (freq * j); -+ if (k < 2) -+ continue; -+ -+ if (abs(((f / (j * k))) - freq ) < err ) { -+ pdiv = j - 3; -+ div = k; -+ psel = (i == 2) ? 1 : 0; -+ esel = (i == 0) ? 0 : 1; -+ err = (f / (j * k)) - freq; -+ } -+ } -+ } -+ -+ if (err == -1) -+ return -1; -+ -+ SysconSetLocked(SYSCON_VIDDIV,SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) | -+ (psel ? SYSCON_VIDDIV_PSEL : 0) | -+ (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) | -+ (div << SYSCON_VIDDIV_VDIV_SHIFT) -+ ); -+ -+ return freq + err; -+} -+ -+static void ep93xxfb_pixelmod(int bpp) -+{ -+ unsigned long tmpdata = 0; -+ -+ DPRINTK("ep93xxfb_pixelmod %dbpp -enter\n",bpp); -+ switch(bpp) { -+ case 8: -+ tmpdata = PIXELMODE_P_8BPP | -+ PIXELMODE_S_1PPCMAPPED | -+ PIXELMODE_C_LUT; -+ epinfo.pixformat = PIXEL_FORMAT_8; -+ break; -+ case 16: -+ tmpdata = PIXELMODE_P_16BPP | -+ PIXELMODE_S_1PPCMAPPED | -+ PIXELMODE_C_565; -+ epinfo.pixformat = PIXEL_FORMAT_16; -+ break; -+ case 24: -+ tmpdata = PIXELMODE_P_24BPP | -+ PIXELMODE_S_1PPC | -+ PIXELMODE_C_888; -+ epinfo.pixformat = PIXEL_FORMAT_24; -+ break; -+ case 32: -+ tmpdata = PIXELMODE_P_32BPP | -+ PIXELMODE_S_1PPC | -+ PIXELMODE_C_888; -+ epinfo.pixformat = PIXEL_FORMAT_32; -+ break; -+ default: -+ break; -+ } -+ outl(tmpdata,PIXELMODE); -+} -+ -+static void ep93xxfb_timing_signal_generation(void) -+{ -+ unsigned long vlinestotal,vsyncstart,vsyncstop, -+ vactivestart,vactivestop, -+ vblankstart,vblankstop, -+ vclkstart,vclkstop; -+ -+ unsigned long hclkstotal,hsyncstart,hsyncstop, -+ hactivestart,hactivestop, -+ hblankstart,hblankstop, -+ hclkstart,hclkstop; -+ -+ DPRINTK("ep93xxfb_timing_signal_generation - enter\n"); -+ -+ vlinestotal = epinfo.ytotal - 1; -+ vsyncstart = vlinestotal; -+ vsyncstop = vlinestotal - epinfo.ysync; -+ vblankstart = vlinestotal - epinfo.ysync - epinfo.ybp; -+ vblankstop = epinfo.yfp - 1; -+ vactivestart = vblankstart; -+ vactivestop = vblankstop; -+ vclkstart = vlinestotal; -+ vclkstop = vlinestotal + 1; -+ -+ hclkstotal = epinfo.xtotal - 1; -+ hsyncstart = hclkstotal; -+ hsyncstop = hclkstotal - epinfo.xsync; -+ hblankstart = hclkstotal - epinfo.xsync - epinfo.xbp; -+ hblankstop = epinfo.xfp - 1; -+ hactivestart = hblankstart; -+ hactivestop = hblankstop; -+ hclkstart = hclkstotal ; -+ hclkstop = hclkstotal ; -+ -+ ep93xxfb_outl(0, VIDEOATTRIBS); -+ -+ ep93xxfb_outl( vlinestotal , VLINESTOTAL ); -+ ep93xxfb_outl( vsyncstart + (vsyncstop << 16), VSYNCSTRTSTOP ); -+ ep93xxfb_outl( vactivestart + (vactivestop << 16), VACTIVESTRTSTOP ); -+ ep93xxfb_outl( vblankstart + (vblankstop << 16), VBLANKSTRTSTOP ); -+ ep93xxfb_outl( vclkstart + (vclkstop << 16), VCLKSTRTSTOP ); -+ -+ ep93xxfb_outl( hclkstotal , HCLKSTOTAL ); -+ ep93xxfb_outl( hsyncstart + (hsyncstop << 16), HSYNCSTRTSTOP ); -+ ep93xxfb_outl( hactivestart + (hactivestop << 16) , HACTIVESTRTSTOP ); -+ ep93xxfb_outl( hblankstart + (hblankstop << 16) , HBLANKSTRTSTOP ); -+ ep93xxfb_outl( hclkstart + (hclkstop << 16) , HCLKSTRTSTOP ); -+ -+ ep93xxfb_outl(0, LINECARRY); -+ -+} -+ -+static int ep93xxfb_setcol(struct fb_info *info, int bpp) -+{ -+ -+ DPRINTK("ep93xxfb_setcol %dbpp\n",bpp); -+ switch(bpp) { -+ case 8: -+ info->var.bits_per_pixel = 8; -+ info->var.red.length = 8; -+ info->var.green.length = 8; -+ info->var.blue.length = 8; -+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ break; -+ case 16: -+ info->var.bits_per_pixel = 16; -+ info->var.red.offset = 11; -+ info->var.red.length = 5; -+ info->var.green.offset = 5; -+ info->var.green.length = 6; -+ info->var.blue.offset = 0; -+ info->var.blue.length = 5; -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ break; -+ case 24: -+ info->var.bits_per_pixel = 24; -+ info->var.red.length = 8; -+ info->var.blue.length = 8; -+ info->var.green.length = 8; -+ info->var.red.offset = 16; -+ info->var.green.offset = 8; -+ info->var.blue.offset = 0; -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ break; -+ case 32: -+ info->var.bits_per_pixel = 32; -+ info->var.red.length = 8; -+ info->var.blue.length = 8; -+ info->var.green.length = 8; -+ info->var.transp.length = 0; -+ info->var.red.offset = 16; -+ info->var.green.offset = 8; -+ info->var.blue.offset = 0; -+ info->var.transp.offset = 0; -+ info->fix.visual = FB_VISUAL_TRUECOLOR; -+ break; -+ default: -+ return 0; -+ } -+ return 1; -+} -+ -+static int ep93xxfb_setclk() -+{ -+ unsigned long calc_clk,act_clk; -+ -+ if ( epinfo.clk_src == CLK_INTERNAL ) { -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); -+ calc_clk = epinfo.refresh; -+ act_clk = ep93xx_set_video_div( calc_clk ); -+ if ( act_clk == -1 ) -+ return -ENODEV; -+ -+ epinfo.refresh = act_clk; -+ epinfo.pixclock = 1000000000 / (act_clk / 1000); -+ } -+ else { -+ SysconSetLocked(SYSCON_VIDDIV,0); -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG,inl(EP93XX_SYSCON_DEVICE_CONFIG) | EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); -+ -+ } -+ -+ return 0; -+} -+ -+ -+static void ep93xxfb_get_par(struct fb_info *info) -+{ -+ -+ DPRINTK("ep93xxfb_get_par - enter\n"); -+ epinfo.configure = NULL; -+ epinfo.on = NULL; -+ epinfo.off = NULL; -+ -+ switch( vout ) { -+ case LCD_OUT: -+ epinfo.on = philips_lb064v02_on; -+ epinfo.off = philips_lb064v02_off; -+ -+ case CRT_OUT: -+ epinfo.xres = ep93xxfb_vmods[vmode].hres; -+ epinfo.xsync = ep93xxfb_vmods[vmode].hsync; -+ epinfo.xfp = ep93xxfb_vmods[vmode].hfp; -+ epinfo.xbp = ep93xxfb_vmods[vmode].hbp; -+ epinfo.xtotal = epinfo.xres + epinfo.xsync + -+ epinfo.xfp + epinfo.xbp; -+ -+ epinfo.yres = ep93xxfb_vmods[vmode].vres; -+ epinfo.ysync = ep93xxfb_vmods[vmode].vsync; -+ epinfo.yfp = ep93xxfb_vmods[vmode].vfp; -+ epinfo.ybp = ep93xxfb_vmods[vmode].vbp; -+ epinfo.ytotal = epinfo.yres + epinfo.ysync + -+ epinfo.yfp + epinfo.ybp; -+ -+ epinfo.refresh = ep93xxfb_vmods[vmode].refresh; -+ epinfo.refresh = epinfo.xtotal * epinfo.ytotal * epinfo.refresh; -+ epinfo.pixclock = 1000000000 / ( epinfo.refresh / 1000); -+ epinfo.bpp = depth; -+ -+ epinfo.clk_src = ep93xxfb_vmods[vmode].clk_src; -+ epinfo.clk_edge = ep93xxfb_vmods[vmode].clk_edge; -+ epinfo.pol_blank = ep93xxfb_vmods[vmode].pol_blank; -+ epinfo.pol_xsync = ep93xxfb_vmods[vmode].pol_hsync; -+ epinfo.pol_ysync = ep93xxfb_vmods[vmode].pol_vsync; -+ break; -+ -+ } -+} -+ -+static int ep93xxfb_alloc_videomem(void) -+{ -+ unsigned long adr,size,pgsize; -+ int order; -+ -+ DPRINTK("ep93xxfb_alloc_videomem - enter \n"); -+ -+ epinfo.fb_log = NULL; -+ epinfo.fb_size = PAGE_ALIGN( MAX_FBMEM_SIZE/*ep93xxfb_vmods[vmode].hres * ep93xxfb_vmods[vmode].vres * (depth / 8)*/ ); -+ order = get_order( epinfo.fb_size ); -+ epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order ); -+ -+ if (epinfo.fb_log) { -+ epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log ); -+ adr = (unsigned long)epinfo.fb_log; -+ size = epinfo.fb_size; -+ pgsize = 1 << order; -+ do { -+ adr += pgsize; -+ SetPageReserved(virt_to_page(adr)); -+ } while(size -= pgsize); -+ } -+ else{ -+ printk("%s memory fail \n",__FUNCTION__); -+ return -ENOMEM; -+ } -+ -+ memset(epinfo.fb_log,0x00,epinfo.fb_size); -+ DPRINTK(" fb_log_addres = 0x%x\n",epinfo.fb_log); -+ DPRINTK(" fb_phys_address = 0x%x\n",epinfo.fb_phys); -+ DPRINTK(" fb_size = %lu\n",epinfo.fb_size); -+ DPRINTK(" fb_page_order = %d\n",order); -+ DPRINTK("ep93xxfb_alloc_videomem - exit \n"); -+ return 0; -+} -+ -+static void ep93xxfb_release_videomem(void) -+{ -+ unsigned long adr,size,psize; -+ int order; -+ -+ DPRINTK("ep93xxfb_release_videomem - enter \n"); -+ -+ if (epinfo.fb_log) { -+ order = get_order(epinfo.fb_size); -+ adr = (unsigned long)epinfo.fb_log; -+ size = epinfo.fb_size; -+ psize = 1 << order ; -+ do { -+ adr += psize; -+ ClearPageReserved(virt_to_page(adr)); -+ } while(size -= psize); -+ free_pages((unsigned long)epinfo.fb_log, order ); -+ } -+ -+ -+ DPRINTK("ep93xxfb_release_videomem - exit \n"); -+} -+ -+static void ep93xxfb_setinfo(struct fb_info *info) -+{ -+ -+ info->pseudo_palette = pseudo_palette; -+ info->var.xres = epinfo.xres; -+ info->var.yres = epinfo.yres; -+ info->var.xres_virtual = epinfo.xres; -+ info->var.yres_virtual = epinfo.yres; -+ -+ ep93xxfb_setcol( info, depth ); -+ -+ info->var.activate = FB_ACTIVATE_NOW; -+ info->var.left_margin = epinfo.xbp; -+ info->var.right_margin = epinfo.xfp; -+ info->var.upper_margin = epinfo.ybp; -+ info->var.lower_margin = epinfo.yfp; -+ info->var.hsync_len = epinfo.xsync; -+ info->var.vsync_len = epinfo.ysync; -+ -+ if( epinfo.pol_xsync == POL_HIGH ) -+ info->var.sync |= FB_SYNC_HOR_HIGH_ACT; -+ if( epinfo.pol_ysync == POL_HIGH ) -+ info->var.sync |= FB_SYNC_VERT_HIGH_ACT; -+ -+ info->var.vmode = FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP; -+ info->fix.smem_start = epinfo.fb_phys; -+ info->fix.smem_len = epinfo.fb_size; -+ info->fix.type = FB_TYPE_PACKED_PIXELS; -+ info->fix.line_length = epinfo.xres * (epinfo.bpp / 8); -+ info->screen_base = epinfo.fb_log; -+ info->var.pixclock = epinfo.pixclock; -+ info->fix.ypanstep = 1; -+ info->fix.ywrapstep = 1; -+ -+} -+ -+static int ep93xxfb_config(struct fb_info *info) -+{ -+ unsigned long attribs; -+ -+ DPRINTK("ep93xxfb_config - enter\n"); -+ -+ ep93xxfb_get_par( info ); -+ if( ep93xxfb_alloc_videomem() != 0 ) { -+ printk("Unable to allocate video memory\n"); -+ return -ENOMEM; -+ } -+ -+ if( ep93xxfb_setclk() != 0 ) { -+ printk("Unable to set pixel clock\n"); -+ ep93xxfb_release_videomem(); -+ return -ENODEV; -+ } -+ -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG) |EP93XX_SYSCON_DEVCFG_RasOnP3); -+ ep93xxfb_timing_signal_generation(); -+ -+ /* set video memory parameters */ -+ outl(epinfo.fb_phys, VIDSCRNPAGE); -+ outl(epinfo.yres , SCRNLINES); -+ outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); -+ outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); -+ -+ -+ /* set pixel mode */ -+ ep93xxfb_pixelmod(depth); -+ -+ attribs = 0; -+ -+#ifdef CONFIG_EP93XX_SDCS0 -+ attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+ -+ if(epinfo.clk_edge == EDGE_RISING) -+ attribs |= VIDEOATTRIBS_INVCLK; -+ if(epinfo.pol_blank == POL_HIGH) -+ attribs |= VIDEOATTRIBS_BLKPOL; -+ if(epinfo.pol_xsync == POL_HIGH) -+ attribs |= VIDEOATTRIBS_HSPOL; -+ if(epinfo.pol_ysync == POL_HIGH) -+ attribs |= VIDEOATTRIBS_VCPOL; -+ -+ ep93xxfb_outl(attribs, VIDEOATTRIBS); -+ ep93xxfb_setinfo( info ); -+ -+ if(epinfo.configure) -+ (epinfo.configure)( epinfo.automods ); -+ -+ ep93xxfb_blank( 0 , info ); -+ -+ DPRINTK("ep93xxfb_config - exit\n"); -+ return 0; -+} -+ -+int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg) -+{ -+ struct fb_fillrect fill; -+ struct fb_copyarea cparea; -+ struct fb_image img; -+ struct ep93xx_line line; -+ struct ep93xx_cursor cursor; -+ -+ switch (cmd) { -+ case FBIO_EP93XX_CURSOR: -+ copy_from_user(&cursor, (void *)arg, sizeof(struct ep93xx_cursor)); -+ ep93xxfb_cursor(info,&cursor); -+ break; -+ case FBIO_EP93XX_LINE: -+ copy_from_user(&line, (void *)arg, sizeof(struct ep93xx_line)); -+ ep93xxfb_line(info,&line); -+ break; -+ case FBIO_EP93XX_FILL: -+ copy_from_user(&fill, (void *)arg, sizeof(struct fb_fillrect)); -+ ep93xxfb_fillrect(info,&fill); -+ break; -+ case FBIO_EP93XX_BLIT: -+ copy_from_user(&img, (void *)arg, sizeof(struct fb_image)); -+ ep93xxfb_imageblit(info, &img); -+ break; -+ case FBIO_EP93XX_COPY: -+ copy_from_user(&cparea, (void *)arg, sizeof(struct fb_copyarea)); -+ ep93xxfb_copyarea(info,&cparea); -+ break; -+ default: -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+ -+static struct fb_ops ep93xxfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_setcolreg = ep93xxfb_setcolreg, -+ .fb_check_var = ep93xxfb_check_var, -+ .fb_set_par = ep93xxfb_set_par, -+ .fb_blank = ep93xxfb_blank, -+ .fb_pan_display = ep93xx_pan_display, -+ .fb_fillrect = ep93xxfb_fillrect, -+ .fb_copyarea = ep93xxfb_copyarea, -+ .fb_imageblit = cfb_imageblit, -+ .fb_cursor = ep93xxfb_cursor, -+ .fb_ioctl = ep93xxfb_ioctl, -+ .fb_mmap = ep93xxfb_mmap, -+}; -+ -+ -+static struct resource ep93xxfb_raster_resources = { -+ .start = EP93XX_RASTER_PHYS_BASE, -+ .end = EP93XX_RASTER_PHYS_BASE + 0x1ffff, -+ .flags = IORESOURCE_MEM, -+}; -+ -+ -+static int __init ep93xxfb_probe(struct platform_device *device) -+{ -+ struct fb_info *info = NULL; -+ struct resource *res = NULL; -+ int ret = 0; -+ int arb = 0; -+ -+ DPRINTK("ep93xxfb_probe - enter \n"); -+ -+ -+ if(!device) { -+ printk("error : to_platform_device\n"); -+ return -ENODEV; -+ } -+ res = platform_get_resource( device, IORESOURCE_MEM, 0); -+ if(!res) { -+ printk("error : platform_get_resource \n"); -+ return -ENODEV; -+ } -+ cursor_data = kmalloc( 64 * 64 * 2, GFP_KERNEL ); -+ memset( cursor_data, 0x00, 64 * 64 * 2 ); -+ if(!cursor_data) { -+ printk("Unable to allocate memory for hw_cursor\n"); -+ return -ENOMEM; -+ } -+ if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) -+ return -EBUSY; -+ -+ info = framebuffer_alloc(sizeof(u32) * 256, &device->dev); -+ -+ if(!info) { -+ printk("Unable to allocate memory for frame buffer\n"); -+ return -ENOMEM; -+ } -+ -+ info->flags = FBINFO_DEFAULT; -+ strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); -+ info->fix.mmio_start = res->start; -+ info->fix.mmio_len = res->end - res->start + 1; -+ info->fbops = &ep93xxfb_ops; -+ info->pseudo_palette = info->par; -+ info->state = FBINFO_STATE_RUNNING; -+ -+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { -+ ret = -ENOMEM; -+ goto fbuff; -+ } -+ -+ if ((ret = ep93xxfb_config(info)) < 0) -+ goto clmap; -+ -+ if (register_framebuffer(info) < 0) { -+ printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); -+ ret = -EINVAL; -+ goto clmap; -+ } -+ platform_set_drvdata(device, info); -+ printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, -+ info->var.xres, info->var.yres, info->var.bits_per_pixel); -+ -+ /*change the raster arb to the highest one--Bo*/ -+ arb = inl(EP93XX_SYSCON_BMAR); -+ arb = (arb & 0x3f8) | 0x01; -+ outl(arb,EP93XX_SYSCON_BMAR); -+ -+ DPRINTK("ep93xxfb_probe - exit \n"); -+ return 0; -+ -+clmap: -+ fb_dealloc_cmap(&info->cmap); -+ -+fbuff: -+ framebuffer_release(info); -+ return ret; -+} -+ -+static int ep93xxfb_remove(struct platform_device *device) -+{ -+ struct resource *res; -+ struct fb_info *info; -+ struct ep93xx_cursor cursor; -+ -+ DPRINTK("ep93xxfb_remove - enter \n"); -+ -+ info = platform_get_drvdata(device); -+ -+ ep93xxfb_release_videomem(); -+ -+ res = platform_get_resource( device, IORESOURCE_MEM, 0); -+ release_mem_region(res->start, res->end - res->start + 1); -+ -+ platform_set_drvdata(device, NULL); -+ unregister_framebuffer(info); -+ -+ fb_dealloc_cmap(&info->cmap); -+ framebuffer_release(info); -+ -+ cursor.flags = CURSOR_OFF; -+ ep93xxfb_cursor(info,&cursor); -+ if(cursor_data!=NULL) -+ kfree(cursor_data); -+ -+ ep93xxfb_blank( 1, info ); -+ -+ DPRINTK("ep93xxfb_remove - exit \n"); -+ return 0; -+} -+ -+static void ep93xxfb_platform_release(struct device *device) -+{ -+ DPRINTK("ep93xxfb_platform_release - enter\n"); -+} -+ -+static int ep93xxfb_check_param(void) -+{ -+ -+ switch(vout) { -+ case CRT_OUT: -+ if( vmode >=(sizeof(ep93xxfb_vmods)/sizeof(ep93xxfb_vmods[0]))){ -+ vmode = 1; -+ depth = DEFAULT_BPP; -+ return 0; -+ } -+ break; -+ case LCD_OUT: -+ if( vmode != 0 || depth != 16 ) { -+ vmode = 0; -+ depth = DEFAULT_BPP; -+ return 0; -+ } -+ break; -+ default: -+ vmode = DEFAULT_MODE; -+ depth = DEFAULT_BPP; -+ vout = DEFAULT_OUT; -+ return 0; -+ break; -+ } -+ -+ if(!((depth == 8) || (depth == 16) || (depth == 24) || (depth == 32))) -+ depth = DEFAULT_BPP; -+ -+ return 1; -+} -+ -+int __init ep93xxfb_setup(char *options) -+{ -+ char *opt; -+ -+ DPRINTK("ep93xxfb_setup - %s\n",options); -+ -+ if (!options || !*options) -+ return 0; -+ -+ while ((opt = strsep(&options, ",")) != NULL) { -+ if (!strncmp(opt, "vout=", 5)) -+ vout = simple_strtoul(opt + 5, NULL, 0); -+ else if (!strncmp(opt, "vmode=", 6)) -+ vmode = simple_strtoul(opt + 6, NULL, 0); -+ else if (!strncmp(opt, "depth=", 6)) -+ depth = simple_strtoul(opt + 6, NULL, 0); -+ } -+ ep93xxfb_check_param(); -+ return 0; -+} -+ -+ -+static struct platform_driver ep93xxfb_driver = { -+ .probe = ep93xxfb_probe, -+ .remove = ep93xxfb_remove, -+ .driver = { -+ .name = FBDEV_NAME, -+ }, -+}; -+ -+static struct platform_device ep93xxfb_device = { -+ .name = FBDEV_NAME, -+ .id = -1, -+ .dev = { -+ .release = ep93xxfb_platform_release, -+ }, -+ .num_resources = 1, -+ .resource = &ep93xxfb_raster_resources, -+}; -+ -+int __init ep93xxfb_init(void) -+{ -+ int ret = 0; -+ char *option = NULL; -+ -+ DPRINTK("ep93xxfb_init - enter\n"); -+ -+ if (fb_get_options("ep93xxfb", &option)) -+ return -ENODEV; -+ ep93xxfb_setup(option); -+ -+ -+ if( !ep93xxfb_check_param() ) { -+ printk("Unsupported format \n"); -+ return -1; -+ } -+ /*Add the Hardware accel irq */ -+ outl(0x00000000, BLOCKCTRL); -+ ret = request_irq(IRQ_EP93XX_GRAPHICS, ep93xxfb_irq_handler, IRQF_DISABLED,"graphics",NULL); -+ -+ if (ret != 0) { -+ printk("%s: can't get irq %i, err %d\n",__FUNCTION__, IRQ_EP93XX_GRAPHICS, ret); -+ return -EBUSY; -+ } -+ -+ /*-------------------------------*/ -+ ret = platform_driver_register(&ep93xxfb_driver); -+ -+ if (!ret) { -+ ret = platform_device_register(&ep93xxfb_device); -+ if (ret) -+ platform_driver_unregister(&ep93xxfb_driver); -+ } -+ -+ DPRINTK("ep93xxfb_init - exit\n"); -+ return ret; -+} -+ -+ -+ -+static void __exit ep93xxfb_exit(void) -+{ -+ DPRINTK("ep93xxfb_exit - enter\n"); -+ platform_driver_unregister(&ep93xxfb_driver); -+ platform_device_unregister(&ep93xxfb_device); -+ DPRINTK("ep93xxfb_exit - exit\n"); -+} -+ -+module_init(ep93xxfb_init); -+module_exit(ep93xxfb_exit); -+ -+ -+module_param( vmode, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(vmode, "Specify the video mode number that should be used"); -+module_param( vout , int , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); -+MODULE_PARM_DESC(vout ,"Specify video output (0 = CRT ,1 = LCD )"); -+module_param( depth , int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(depth ,"Color depth (8,16,24,32)"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/video/ep93xxfb.h -@@ -0,0 +1,236 @@ -+#ifndef __EP93XXFB_H__ -+#define __EP93XXFB_H__ -+ -+ -+#define POL_HIGH 1 -+#define POL_LOW 0 -+#define EDGE_RISING 1 -+#define EDGE_FALLING 0 -+#define CLK_INTERNAL 1 -+#define CLK_EXTERNAL 0 -+ -+#define CRT_OUT 0 -+#define LCD_OUT 1 -+#define TV_OUT 2 -+ -+#define MAX_XRES 1280 -+#define MAX_YRES 1024 -+#define MAX_BPP 16 -+#define MAX_FBMEM_SIZE 3686400/*1920000*/ -+ -+#define MAX_XRES_CRT MAX_XRES -+#define MAX_YRES_CRT MAX_YRES -+#define MAX_XRES_SVIDEO 1024 -+#define MAX_YRES_SVIDEO 768 -+ -+#define PIXEL_FORMAT_SHIFT 17 -+#define PIXEL_FORMAT_4 ( 1 << PIXEL_FORMAT_SHIFT ) -+#define PIXEL_FORMAT_8 ( 2 << PIXEL_FORMAT_SHIFT ) -+#define PIXEL_FORMAT_16 ( 4 << PIXEL_FORMAT_SHIFT ) -+#define PIXEL_FORMAT_24 ( 6 << PIXEL_FORMAT_SHIFT ) -+#define PIXEL_FORMAT_32 ( 7 << PIXEL_FORMAT_SHIFT ) -+ -+ -+struct ep93xxfb_videomodes -+{ -+ const char *name; -+ -+ unsigned long hres; // Horizontal Valid -+ unsigned long hfp; // Horizontal Front Porch -+ unsigned long hsync; // Horizontal Sync Width -+ unsigned long hbp; // Horizontal Back Porch -+ -+ unsigned long vres; // Vertical Valid -+ unsigned long vfp; // Vertical Front Porch -+ unsigned long vsync; // Vertical Sync Width -+ unsigned long vbp; // Vertical Back Porch -+ -+ unsigned long refresh; // Vertical Sync Frequency -+ -+ unsigned long clk_src; -+ unsigned long clk_edge; -+ unsigned long pol_blank; -+ unsigned long pol_hsync; -+ unsigned long pol_vsync; -+}; -+ -+ -+struct ep93xxfb_info -+{ -+ -+ -+ dma_addr_t fb_phys; -+ void *fb_log; -+ unsigned long fb_size; -+ unsigned long fb_actsize; -+ -+ unsigned long xtotal; -+ unsigned long ytotal; -+ -+ unsigned int xres; -+ unsigned int xfp; -+ unsigned int xsync; -+ unsigned int xbp; -+ -+ unsigned int yres; -+ unsigned int yfp; -+ unsigned int ysync; -+ unsigned int ybp; -+ unsigned int bpp; -+ -+ unsigned long refresh; -+ unsigned long pixclock; -+ unsigned long pixformat; -+ -+ unsigned int clk_src; -+ unsigned int clk_edge; -+ unsigned int pol_blank; -+ unsigned int pol_xsync; -+ unsigned int pol_ysync; -+ -+ unsigned char automods; -+ -+ void (*configure)(unsigned char value); -+ void (*on)(unsigned char value); -+ void (*off)(unsigned char value); -+}; -+ -+static int ep93xxfb_setclk(void); -+static int ep93xx_get_max_video_clk(void); -+static void ep93xxfb_pixelmod(int bpp); -+static void ep93xxfb_timing_signal_generation(void); -+static int ep93xxfb_blank(int blank_mode,struct fb_info *info); -+ -+#define EE_DELAY_USEC 2 -+#define EE_READ_TIMEOUT 100 -+#define CX25871_DEV_ADDRESS 0x88 -+#define GPIOG_EEDAT 2 -+#define GPIOG_EECLK 1 -+#define CXMODES_COUNT 24 -+ -+struct cx25871_vmodes -+{ -+ -+ const char *name; -+ unsigned char automode; -+ unsigned int hres; -+ unsigned int vres; -+ unsigned int hclktotal; -+ unsigned int vclktotal; -+ unsigned int hblank; -+ unsigned int vblank; -+ unsigned long clkfrequency; -+ -+}; -+ -+ -+int write_reg(unsigned char ucRegAddr, unsigned char ucRegValue); -+void cx25871_on(unsigned char value); -+void cx25871_off(unsigned char value); -+void cx25871_config(unsigned char value); -+ -+static void philips_lb064v02_on(unsigned char value); -+static void philips_lb064v02_off(unsigned char value); -+ -+ -+#define FBIO_EP93XX_CURSOR 0x000046c1 -+#define FBIO_EP93XX_LINE 0x000046c2 -+#define FBIO_EP93XX_FILL 0x000046c3 -+#define FBIO_EP93XX_BLIT 0x000046c4 -+#define FBIO_EP93XX_COPY 0x000046c5 -+ -+ -+#define CURSOR_BLINK 0x00000001 -+#define CURSOR_MOVE 0x00000002 -+#define CURSOR_SETSHAPE 0x00000004 -+#define CURSOR_SETCOLOR 0x00000008 -+#define CURSOR_ON 0x00000010 -+#define CURSOR_OFF 0x00000020 -+ -+ -+/* -+* ioctl(fd, FBIO_EP93XX_CURSOR, ep93xx_cursor *) -+* -+* "data" points to an array of pixels that define the cursor; each row should -+* be a multiple of 32-bit values (i.e. 16 pixels). Each pixel is two bits, -+* where the values are: -+* -+* 00 => transparent 01 => invert 10 => color1 11 => color2 -+* -+* The data is arranged as follows (per word): -+* -+* bits: |31-30|29-28|27-26|25-24|23-22|21-20|19-18|17-16| -+* pixel: | 12 | 13 | 14 | 15 | 8 | 9 | 10 | 11 | -+* bits: |15-14|13-12|11-10| 9-8 | 7-6 | 5-4 | 3-2 | 1-0 | -+* pixel: | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | -+* -+* Regardless of the frame buffer color depth, "color1", "color2", -+* "blinkcolor1", and "blinkcolor2" are 24-bit colors since the cursor is -+* injected into the data stream right before the video DAC. -+* -+* When "blinkrate" is not zero, pixel value 10 will alternate between "color1" -+* and "blinkcolor1" (similar for pixel value 11 and "color2"/"blinkcolor2"). -+* -+* "blinkrate" ranges between 0 and 255. When 0, blinking is disabled. 255 is -+* the fastest blink rate and 1 is the slowest. -+* -+* Both "width" and "height" must be between 1 and 64; it is preferable to have -+* "width" a multiple of 16. -+*/ -+struct ep93xx_cursor { -+ unsigned long flags; -+ unsigned long dx; // Only used if CURSOR_MOVE is set -+ unsigned long dy; // Only used if CURSOR_MOVE is set -+ unsigned long width; // Only used if CURSOR_SETSHAPE is set -+ unsigned long height; // Only used if CURSOR_SETSHAPE is set -+ const char *data; // Only used if CURSOR_SETSHAPE is set -+ unsigned long blinkrate; // Only used if CURSOR_BLINK is set -+ unsigned long color1; // Only used if CURSOR_SETCOLOR is set -+ unsigned long color2; // Only used if CURSOR_SETCOLOR is set -+ unsigned long blinkcolor1; // Only used if CURSOR_SETCOLOR is set -+ unsigned long blinkcolor2; // Only used if CURSOR_SETCOLOR is set -+}; -+ -+ -+/* -+ * The bits in the flags field of ep93xx_line. -+*/ -+/* -+* ioctl(fd, FBIO_EP93XX_LINE, ep93xx_line *) -+* -+* The line starts at ("x1","y1") and ends at ("x2","y2"). This means that -+* when using a pattern, the two coordinates are not transitive (i.e. swapping -+* ("x1","y1") with ("x2","y2") will not necessarily draw the exact same line, -+* pattern-wise). -+* -+* "pattern" is a 2 to 16 bit pattern (since a 1 bit pattern isn't much of a -+* pattern). The lower 16 bits define the pattern (1 being foreground, 0 being -+* background or transparent), and bits 19-16 define the length of the pattern -+* (as pattern length - 1). So, for example, "0xf00ff" defines a 16 bit -+* with the first 8 pixels in the foreground color and the next 8 pixels in the -+* background color or transparent. -+* -+* LINE_PRECISE is used to apply angularly corrected patterns to line. It -+* should only be used when LINE_PATTERN is also set. The pattern will be -+* applied along the length of the line, instead of along the length of the -+* major axis. This may result in the loss of fine details in the pattern, and -+* will take more time to draw the line in most cases. -+*/ -+ -+#define LINE_PATTERN 0x00000001 -+#define LINE_PRECISE 0x00000002 -+#define LINE_BACKGROUND 0x00000004 -+ -+struct ep93xx_line { -+ unsigned long flags; -+ unsigned long x1; -+ unsigned long y1; -+ unsigned long x2; -+ unsigned long y2; -+ unsigned long fgcolor; -+ unsigned long bgcolor; // Only used if LINE_BACKGROUND is set -+ unsigned long pattern; // Only used if LINE_PATTERN is set -+}; -+ -+#endif /* __EP93XXFB_H__ */ -+ ---- /dev/null -+++ b/drivers/video/ep93xxfb_mono.c -@@ -0,0 +1,1281 @@ -+/* -+ * drivers/video/ep93xxfb_mono.c -- grayscale on mono LCD driver for -+ * Cirrus Logic EP93xx. -+ * -+ * Copyright (C) 2007 Cirrus Logic -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ * This driver works for the following two LCD: -+ * SHARP LM121VB1T01 - A dual scan 640x480 monochrome LCD. -+ * HOSIDEN HLM6323 - A single scan 320x240 monochrome LCD. -+ * -+ * And support two gray modes: -+ * 8 levels of gray - Actually is 7 levels of gray. Two of the levels -+ * have the same gray. -+ * 16 levels of gray - Extending the gray levels by switching the LUT -+ * for each frame. -+ * -+ * HW connection for SHARP LM121VB1T01: -+ * P12 <------> LCD_U0 -+ * P8 <------> LCD_U1 -+ * P4 <------> LCD_U2 -+ * P0 <------> LCD_U3 -+ * P14 <------> LCD_L0 -+ * P10 <------> LCD_L1 -+ * P6 <------> LCD_L2 -+ * P2 <------> LCD_L3 -+ * HW connection for HOSIDEN HLM6323: -+ * P12 <------> LCD_0 -+ * P8 <------> LCD_1 -+ * P4 <------> LCD_2 -+ * P0 <------> LCD_3 -+ * -+ */ -+ -+#include <linux/version.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/reboot.h> -+#include <linux/errno.h> -+#include <linux/string.h> -+#include <linux/mm.h> -+#include <linux/delay.h> -+#include <linux/fb.h> -+#include <linux/init.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+#include <linux/dma-mapping.h> -+#include <asm/io.h> -+#include <asm/uaccess.h> -+#include <mach/hardware.h> -+ -+ -+#include <linux/platform_device.h> -+ -+#define CONFIG_EP93XX_SDCS0 -+ -+#undef DEBUG -+#ifdef DEBUG -+#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) -+#else -+#define DPRINTK( fmt, arg... ) -+#endif -+ -+#define FBDEV_NAME "ep93xxfb" -+ -+#define ep93xxfb_lock_outl(value, reg) \ -+{ \ -+ outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); \ -+ outl(value, reg); \ -+ DPRINTK(#reg"=0x%08x\n", (unsigned int)(value)); \ -+} -+ -+#define ep93xxfb_outl(value, reg) \ -+{ \ -+ outl(value, reg); \ -+ DPRINTK(#reg"=0x%08x\n", (unsigned int)(value)); \ -+} -+ -+static unsigned int pseudo_palette[256]; -+ -+struct ep93xxfb_mono_videomodes -+{ -+ const char *name; -+ -+ unsigned long hres; // Horizontal Valid -+ unsigned long vres; // Vertical Valid -+ unsigned int freq; -+ unsigned int dualscan; -+ unsigned int bpp; -+ unsigned int graylevel; -+ -+ void (*configure)(unsigned char value); -+ void (*on)(unsigned char value); -+ void (*off)(unsigned char value); -+}; -+ -+struct ep93xxfb_mono_info -+{ -+ dma_addr_t fb_phys; -+ void *fb_log; -+ unsigned long fb_size; -+ unsigned long fb_actsize; -+ -+ unsigned int xres; -+ unsigned int yres; -+ -+ unsigned int freq; -+ unsigned int dualscan; -+ unsigned int bpp; -+ unsigned int graylevel; -+ -+ void (*configure)(unsigned char value); -+ void (*on)(unsigned char value); -+ void (*off)(unsigned char value); -+}; -+ -+ -+void LM121VB1T01_configure(unsigned char value); -+void HOSIDEN_HLM6323_configure(unsigned char value); -+ -+static int vmode = 1; -+ -+static struct ep93xxfb_mono_info epinfo; -+static struct ep93xxfb_mono_videomodes ep93xxfb_vmods[] = -+{ -+ { -+ "SHARP-LM121VB1T01-8GRAY", -+ 640, 480, 100, -+ 1, //dual scan -+ 4, //4bpp -+ 8, //8-level grayscale -+ LM121VB1T01_configure, -+ NULL, -+ NULL, -+ }, -+ { -+ "SHARP-LM121VB1T01-16GRAY", -+ 640, 480, 120, -+ 1, //dual scan -+ 4, //4bpp -+ 16, //16-level grayscale -+ LM121VB1T01_configure, -+ NULL, -+ NULL, -+ }, -+ { -+ "HOSIDEN HLM6323", -+ 320, 240, 115, -+ 0, //single scan -+ 4, //4bpp -+ 8, //8-level grayscale -+ HOSIDEN_HLM6323_configure, -+ NULL, -+ NULL, -+ }, -+ { -+ "HOSIDEN HLM6323", -+ 320, 240, 115, -+ 0, //single scan -+ 4, //4bpp -+ 16, //16-level grayscale -+ HOSIDEN_HLM6323_configure, -+ NULL, -+ NULL, -+ }, -+}; -+ -+ -+#define EP93XX_GS_OFFSET(lut, frame, pixel) ( (lut) + ( (pixel) << 2) + ((frame) << 5 )) -+ -+static unsigned long DY_LUT[2][16]; -+ -+static unsigned long GSLUT[32] = -+{ -+ 0x00070000, 0x00070000, 0x00070000, 0x00070000, /*0%*/ -+ 0x00078241, 0x00074182, 0x00071428, 0x00072814, /*25%*/ -+ 0x00000412, 0x00000241, 0x00000124, 0x00000000, /*33%*/ -+ 0x0007aa55, 0x000755aa, 0x000755aa, 0x0007aa55, /*50%*/ -+ 0x00000bed, 0x00000dbe, 0x00000edb, 0x00000000, /*66%*/ -+ 0x00077dbe, 0x0007be7d, 0x0007ebd7, 0x0007d7eb, /*75%*/ -+ 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, /*100%*/ -+ 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, -+}; -+ -+static void ep93xxfb_8gray_palette_init(void) -+{ -+ unsigned int cont, i, n; -+ unsigned int frame, pixval, gslut; -+ cont = inl(LUTCONT); -+ for (i=0; i< 16; i++) -+ { -+ n = (i & 0xe) << 4; -+ outl( n, (COLOR_LUT+(i<<2)) ); -+ } -+ for (pixval=0; pixval < 8; pixval++) -+ { -+ for (frame=0; frame < 4; frame++) -+ { -+ gslut = GSLUT[pixval*4 + frame]; -+ outl(gslut,EP93XX_GS_OFFSET(GS_LUT, frame, pixval)); -+ } -+ } -+ outl( cont ^ LUTCONT_RAM1, LUTCONT ); -+} -+ -+static void ep93xxfb_16gray_palette_switch(int index) -+{ -+ unsigned int cont, i, n; -+ cont = inl(LUTCONT); -+ n = index & 0x1; -+ for (i=0; i< 16; i++) -+ { -+ outl( DY_LUT[n][i], (COLOR_LUT+(i<<2)) ); -+ } -+ outl( cont ^ LUTCONT_RAM1, LUTCONT ); -+} -+ -+static void ep93xxfb_16gray_palette_init(void) -+{ -+ int i; -+ unsigned int cont; -+ unsigned int frame, pixval, gslut; -+ int split_table[16][2] = -+ { -+ {0, 0 }, -+ {0, 2 }, -+ {1, 1 }, -+ {3, 0 }, -+ -+ {2, 2 }, -+ {4, 0 }, -+ {3, 2 }, -+ {4, 2 }, -+ -+ {3, 3 }, // {6, 0 }, -+ {3, 4 }, -+ {4, 4 }, -+ {6, 2 }, -+ -+ {5, 5 }, -+ {3, 6 }, -+ {4, 6 }, -+ {6, 6 }, -+ }; -+ -+ cont = inl(LUTCONT); -+ for (i=0; i< 16; i++) -+ { -+ DY_LUT[0][i]=split_table[i][0] << 5; -+ DY_LUT[1][i]=split_table[i][1] << 5; -+ -+ outl( DY_LUT[0][i], (COLOR_LUT+(i<<2)) ); -+ } -+ -+ for (pixval=0; pixval < 8; pixval++) -+ { -+ for (frame=0; frame < 4; frame++) -+ { -+ gslut = GSLUT[pixval*4 + frame]; -+ outl(gslut,EP93XX_GS_OFFSET(GS_LUT, frame, pixval)); -+ outl(gslut,EP93XX_GS_OFFSET(GS_LUT2, frame, pixval)); -+ outl(gslut,EP93XX_GS_OFFSET(GS_LUT3, frame, pixval)); -+ } -+ } -+ outl( cont ^ LUTCONT_RAM1, LUTCONT ); -+} -+ -+static int ep93xxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ struct fb_var_screeninfo tmp_var; -+ DPRINTK("ep93xxfb_check_var - enter\n"); -+ -+ memcpy (&tmp_var, var, sizeof (tmp_var)); -+ -+ if (var->xres_virtual != var->xres) -+ var->xres_virtual = var->xres; -+ if (var->yres_virtual < var->yres) -+ var->yres_virtual = var->yres; -+ -+ if (var->xoffset < 0) -+ var->xoffset = 0; -+ if (var->yoffset < 0) -+ var->yoffset = 0; -+ -+ switch (tmp_var.bits_per_pixel) -+ { -+ case 4: -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ DPRINTK("ep93xxfb_check_var - exit\n"); -+ return 0; -+} -+ -+static int ep93xxfb_set_par(struct fb_info *info) -+{ -+ DPRINTK("ep93xxfb_set_par\n"); -+ switch (info->var.bits_per_pixel) { -+ case 4: -+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+ -+static int ep93xxfb_blank(int blank_mode,struct fb_info *info) -+{ -+ unsigned long attribs; -+ DPRINTK("ep93xxfb_blank - enter\n"); -+ attribs = inl(VIDEOATTRIBS); -+ -+ if (blank_mode) { -+ if (epinfo.off) -+ (epinfo.off)( 0 ); -+ -+ ep93xxfb_lock_outl(attribs & ~(VIDEOATTRIBS_DATAEN | -+ VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_PCLKEN | -+ VIDEOATTRIBS_EN), VIDEOATTRIBS); -+ } -+ else { -+ -+ if (epinfo.configure) -+ (epinfo.configure)( (unsigned char) epinfo.graylevel ); -+ if (epinfo.on) -+ (epinfo.on)( 0 ); -+ } -+ return 0; -+} -+ -+static void ep93xxfb_get_par(struct fb_info *info) -+{ -+ -+ DPRINTK("ep93xxfb_get_par - enter\n"); -+ -+ epinfo.configure = ep93xxfb_vmods[vmode].configure; -+ epinfo.on = ep93xxfb_vmods[vmode].on; -+ epinfo.off = ep93xxfb_vmods[vmode].off; -+ -+ epinfo.freq = ep93xxfb_vmods[vmode].freq; -+ epinfo.dualscan = ep93xxfb_vmods[vmode].dualscan; -+ epinfo.bpp = ep93xxfb_vmods[vmode].bpp; -+ epinfo.graylevel = ep93xxfb_vmods[vmode].graylevel; -+ -+ epinfo.xres = ep93xxfb_vmods[vmode].hres; -+ epinfo.yres = ep93xxfb_vmods[vmode].vres; -+ -+} -+ -+static int ep93xxfb_alloc_videomem(void) -+{ -+ unsigned long adr,size,pgsize; -+ int order; -+ -+ DPRINTK("ep93xxfb_alloc_videomem - enter \n"); -+ -+ epinfo.fb_log = NULL; -+ epinfo.fb_size = epinfo.xres*epinfo.yres*epinfo.bpp/8; -+ order = get_order( epinfo.fb_size ); -+ epinfo.fb_log = (void*) __get_free_pages( GFP_KERNEL, order ); -+ -+ if (epinfo.fb_log) { -+ epinfo.fb_phys = __virt_to_phys((int) epinfo.fb_log ); -+ adr = (unsigned long)epinfo.fb_log; -+ size = epinfo.fb_size; -+ pgsize = 1 << order; -+ do { -+ adr += pgsize; -+ SetPageReserved(virt_to_page(adr)); -+ } while(size -= pgsize); -+ } -+ else -+ return -ENOMEM; -+ -+ memset(epinfo.fb_log,0x00,epinfo.fb_size); -+ -+ DPRINTK(" fb_log_addres = 0x%x\n", (unsigned int)epinfo.fb_log); -+ DPRINTK(" fb_phys_address = 0x%x\n", (unsigned int)epinfo.fb_phys); -+ DPRINTK(" fb_size = %lu\n", (unsigned long)epinfo.fb_size); -+ DPRINTK(" fb_page_order = %d\n", (unsigned int)order); -+ DPRINTK("ep93xxfb_alloc_videomem - exit \n"); -+ return 0; -+} -+ -+static void ep93xxfb_release_videomem(void) -+{ -+ unsigned long adr,size,psize; -+ int order; -+ -+ DPRINTK("ep93xxfb_release_videomem - enter \n"); -+ if (epinfo.fb_log) { -+ order = get_order(epinfo.fb_size); -+ adr = (unsigned long)epinfo.fb_log; -+ size = epinfo.fb_size; -+ psize = 1 << order ; -+ do { -+ adr += psize; -+ ClearPageReserved(virt_to_page(adr)); -+ } while(size -= psize); -+ free_pages((unsigned long)epinfo.fb_log, order ); -+ } -+ DPRINTK("ep93xxfb_release_videomem - exit \n"); -+} -+ -+static void ep93xxfb_setinfo(struct fb_info *info) -+{ -+ -+ DPRINTK("ep93xxfb_setinfo - enter \n"); -+ info->pseudo_palette = pseudo_palette; -+ info->var.xres = epinfo.xres; -+ info->var.yres = epinfo.yres; -+ info->var.xres_virtual = epinfo.xres; -+ info->var.yres_virtual = epinfo.yres; -+ -+ info->var.bits_per_pixel = epinfo.bpp; -+ info->var.red.length = epinfo.bpp; -+ info->var.green.length = epinfo.bpp; -+ info->var.blue.length = epinfo.bpp; -+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ info->var.red.offset = 0; -+ info->var.green.offset =0; -+ info->var.blue.offset = 0; -+ -+ info->fix.smem_start = epinfo.fb_phys; -+ info->fix.smem_len = epinfo.fb_size; -+ info->fix.type = FB_TYPE_PACKED_PIXELS; -+ info->fix.line_length = (epinfo.xres * epinfo.bpp) / 8; -+ info->fix.accel = FB_ACCEL_NONE; -+ info->screen_base = epinfo.fb_log; -+ info->fix.ypanstep = 1; -+ info->fix.ywrapstep = 1; -+ -+ DPRINTK("ep93xxfb_setinfo - exit \n"); -+} -+ -+static int ep93xxfb_config(struct fb_info *info) -+{ -+ DPRINTK("ep93xxfb_config - enter\n"); -+ -+ ep93xxfb_get_par( info ); -+ if( ep93xxfb_alloc_videomem() != 0 ) { -+ printk("Unable to allocate video memory\n"); -+ return -ENOMEM; -+ } -+ -+ /* set video memory parameters */ -+ ep93xxfb_outl(epinfo.fb_phys, VIDSCRNPAGE); -+ if(epinfo.dualscan) -+ { -+ ep93xxfb_outl(epinfo.fb_phys + (epinfo.bpp*epinfo.xres*epinfo.yres/16) -+ , VIDSCRNHPG); -+ } -+ -+ DPRINTK(" fb_phys = 0x%x\n", inl(VIDSCRNPAGE) ); -+ DPRINTK(" fb_phys_hpg = 0x%x\n", inl(VIDSCRNHPG)); -+ -+ ep93xxfb_outl(epinfo.yres , SCRNLINES); -+ ep93xxfb_outl(((epinfo.xres * epinfo.bpp) / 32) - 1, LINELENGTH); -+ ep93xxfb_outl((epinfo.xres * epinfo.bpp) / 32, VLINESTEP); -+ -+ if(epinfo.configure) -+ (epinfo.configure)( (unsigned char) epinfo.graylevel ); -+ -+ ep93xxfb_setinfo( info ); -+ -+ -+ DPRINTK("ep93xxfb_config - exit\n"); -+ return 0; -+} -+ -+static unsigned long ep93xx_get_pll_frequency(unsigned long pll) -+{ -+ unsigned long fb1, fb2, ipd, ps, freq; -+ -+ if (pll == 1) -+ pll = inl(EP93XX_SYSCON_CLOCK_SET1); -+ else if (pll == 2) -+ pll = inl(EP93XX_SYSCON_CLOCK_SET2); -+ else -+ return 0; -+ -+ ps = (pll & SYSCON_CLKSET1_PLL1_PS_MASK) >> SYSCON_CLKSET1_PLL1_PS_SHIFT; -+ fb1 = ((pll & SYSCON_CLKSET1_PLL1_X1FBD1_MASK) >> SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT); -+ fb2 = ((pll & SYSCON_CLKSET1_PLL1_X2FBD2_MASK) >> SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT); -+ ipd = ((pll & SYSCON_CLKSET1_PLL1_X2IPD_MASK) >> SYSCON_CLKSET1_PLL1_X2IPD_SHIFT); -+ -+ freq = (((0x00e10000 * (fb1+1)) / (ipd+1)) * (fb2+1)) >> ps; -+ return freq; -+} -+ -+static int ep93xx_set_video_div(unsigned long freq) -+{ -+ unsigned long pdiv = 0, div = 0, psel = 0, esel = 0; -+ unsigned long err, f, i, j, k; -+ -+ err = -1; -+ -+ for (i = 0; i < 3; i++) { -+ if (i == 0) -+ f = 14745600 * 2; -+ else if (i == 1) -+ f = ep93xx_get_pll_frequency(1) * 2; -+ else -+ f = ep93xx_get_pll_frequency(2) * 2; -+ -+ for (j = 4; j <= 6; j++) { -+ k = f / (freq * j); -+ if (k < 2) -+ continue; -+ -+ if (abs(((f / (j * k))) - freq ) < err ) { -+ pdiv = j - 3; -+ div = k; -+ psel = (i == 2) ? 1 : 0; -+ esel = (i == 0) ? 0 : 1; -+ err = (f / (j * k)) - freq; -+ } -+ } -+ } -+ -+ if (err == -1) -+ return -1; -+ -+ f = SYSCON_VIDDIV_VENA | (esel ? SYSCON_VIDDIV_ESEL : 0) | -+ (psel ? SYSCON_VIDDIV_PSEL : 0) | -+ (pdiv << SYSCON_VIDDIV_PDIV_SHIFT) | -+ (div << SYSCON_VIDDIV_VDIV_SHIFT); -+ outl(0xaa, EP93XX_SYSCON_SWLOCK); -+ outl(f, SYSCON_VIDDIV); -+ -+ return freq + err; -+} -+ -+static int interrupt_hooked = 0; -+static int vs_counter = 0; -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) -+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah) -+#else -+static irqreturn_t ep93xxfb_irq_handler(int i, void *blah, struct pt_regs *regs) -+#endif -+{ -+ -+ outl(RASTER_SWLOCK_VALUE, RASTER_SWLOCK); -+ outl( -+#ifdef CONFIG_EP93XX_SDCS0 -+ (0 << VIDEOATTRIBS_SDSEL_SHIFT) | -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ (1 << VIDEOATTRIBS_SDSEL_SHIFT) | -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ (2 << VIDEOATTRIBS_SDSEL_SHIFT) | -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ (3 << VIDEOATTRIBS_SDSEL_SHIFT) | -+#endif -+ VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | -+ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | -+ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN , -+ VIDEOATTRIBS ); -+ -+ ep93xxfb_16gray_palette_switch(vs_counter++); -+ -+ return IRQ_HANDLED; -+} -+ -+void LM121VB1T01_configure(unsigned char value) -+{ -+ -+ int n; -+ unsigned long attribs; -+ printk("LM121VB1T01_configure\n"); -+ -+ switch(value) -+ { -+ case 8: -+ ep93xxfb_8gray_palette_init(); -+ break; -+ case 16: -+ ep93xxfb_16gray_palette_init(); -+ break; -+ default: -+ return; -+ } -+ -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, (inl(EP93XX_SYSCON_DEVICE_CONFIG) & ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE) | EP93XX_SYSCON_DEVCFG_RasOnP3); -+ -+ ep93xx_set_video_div(epinfo.freq*240*1280); -+ -+ ep93xxfb_lock_outl( 0x00000000 , VIDEOATTRIBS ); -+ -+ n = 240; -+ ep93xxfb_lock_outl( n + 3 , VLINESTOTAL ); -+ ep93xxfb_lock_outl( ((n)<<16) + n+1 , VSYNCSTRTSTOP ); -+ ep93xxfb_lock_outl( ((2)<<16) + n+2 , VACTIVESTRTSTOP ); -+ ep93xxfb_lock_outl( ((3)<<16) + n+3 , VBLANKSTRTSTOP ); -+ ep93xxfb_lock_outl( ((n+3)<<16) + n+3 , VCLKSTRTSTOP ); -+ -+ n = 1280; -+ ep93xxfb_lock_outl( n + 15 , HCLKSTOTAL ); -+ ep93xxfb_lock_outl( ((n+5)<<16) + n+ 14 , HSYNCSTRTSTOP ); -+ ep93xxfb_lock_outl( ((15)<<16) + n + 15 , HACTIVESTRTSTOP ); -+ ep93xxfb_lock_outl( ((n+15)<<16) + 15 , HBLANKSTRTSTOP ); -+ ep93xxfb_lock_outl( ((n)<<16) + n , HCLKSTRTSTOP ); -+ -+ ep93xxfb_lock_outl( 14 , LINECARRY ); -+ -+ attribs = 0; -+ -+#ifdef CONFIG_EP93XX_SDCS0 -+ attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+ -+ switch(value) -+ { -+ case 8: -+ ep93xxfb_lock_outl( PIXELMODE_DSCAN | -+ PIXELMODE_S_8PPC | PIXELMODE_P_4BPP | -+ PIXELMODE_C_GSLUT , PIXELMODE ); -+ -+ ep93xxfb_lock_outl( -+ attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | -+ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | -+ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN , -+ VIDEOATTRIBS ); -+ break; -+ case 16: -+ if(!interrupt_hooked) -+ { -+ request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL); -+ interrupt_hooked = 1; -+ } -+ ep93xxfb_lock_outl( PIXELMODE_DSCAN | -+ PIXELMODE_S_8PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); -+ -+ ep93xxfb_lock_outl( -+ attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | -+ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | -+ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN, -+ VIDEOATTRIBS ); -+ break; -+ default: -+ return; -+ } -+ -+} -+ -+void HOSIDEN_HLM6323_configure(unsigned char value) -+{ -+ int n; -+ unsigned long attribs; -+ -+ printk("HOSIDEN_HLM6323_configure\n"); -+ -+ switch(value) -+ { -+ case 8: -+ ep93xxfb_8gray_palette_init(); -+ break; -+ case 16: -+ ep93xxfb_16gray_palette_init(); -+ break; -+ default: -+ return; -+ } -+ -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, inl(EP93XX_SYSCON_DEVICE_CONFIG) |EP93XX_SYSCON_DEVCFG_RasOnP3); -+ -+ ep93xxfb_lock_outl( 0x00000000 , VIDEOATTRIBS ); -+ -+ ep93xx_set_video_div(epinfo.freq*320*240); -+ mdelay(10); -+ -+ n = 240; -+ ep93xxfb_lock_outl( n + 3 , VLINESTOTAL ); -+ ep93xxfb_lock_outl( ((n+1)<<16) + n +2 , VSYNCSTRTSTOP ); -+ ep93xxfb_lock_outl( ((3)<<16) + n +3 , VACTIVESTRTSTOP ); -+ ep93xxfb_lock_outl( ((3)<<16) + n +3 , VBLANKSTRTSTOP ); -+ ep93xxfb_lock_outl( ((n+3)<<16) + n +3, VCLKSTRTSTOP ); -+ -+ n = 320; -+ ep93xxfb_lock_outl( n + 3, HCLKSTOTAL ); -+ ep93xxfb_lock_outl( ((n+1)<<16) + n+2 , HSYNCSTRTSTOP ); -+ ep93xxfb_lock_outl( ((3)<<16) + n+3 , HACTIVESTRTSTOP ); -+ ep93xxfb_lock_outl( ((3)<<16) + n+3 , HBLANKSTRTSTOP ); -+ ep93xxfb_lock_outl( ((n+3)<<16) + n+3 , HCLKSTRTSTOP ); -+ -+ ep93xxfb_lock_outl( 3 , LINECARRY ); -+ -+ attribs = 0; -+ -+#ifdef CONFIG_EP93XX_SDCS0 -+ attribs |= 0 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS1 -+ attribs |= 1 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS2 -+ attribs |= 2 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+#ifdef CONFIG_EP93XX_SDCS3 -+ attribs |= 3 << VIDEOATTRIBS_SDSEL_SHIFT; -+#endif -+ -+ switch(value) -+ { -+ case 8: -+ ep93xxfb_lock_outl( -+ PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); -+ ep93xxfb_lock_outl( -+ attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | -+ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | -+ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN , -+ VIDEOATTRIBS ); -+ break; -+ case 16: -+ ep93xxfb_lock_outl( -+ PIXELMODE_S_4PPC | PIXELMODE_P_4BPP | PIXELMODE_C_GSLUT, PIXELMODE ); -+ if(!interrupt_hooked) -+ { -+ request_irq(IRQ_EP93XX_VSYNC, ep93xxfb_irq_handler, IRQF_DISABLED, "lut switch interrupt", NULL); -+ interrupt_hooked = 1; -+ } -+ ep93xxfb_lock_outl( -+ attribs | VIDEOATTRIBS_VCPOL | VIDEOATTRIBS_HSPOL | -+ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN | VIDEOATTRIBS_INVCLK | -+ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_EN | VIDEOATTRIBS_INTEN, -+ VIDEOATTRIBS ); -+ break; -+ default: -+ return; -+ } -+} -+ -+#define FB_WRITEL fb_writel -+#define FB_READL fb_readl -+#define LEFT_POS(bpp) (0) -+#define SHIFT_HIGH(val, bits) ((val) << (bits)) -+#define SHIFT_LOW(val, bits) ((val) >> (bits)) -+static inline void color_imageblit(const struct fb_image *image, -+ struct fb_info *p, u8 *dst1, -+ u32 start_index, -+ u32 pitch_index) -+{ -+ /* Draw the penguin */ -+ u32 *dst, *dst2; -+ u32 color = 0, val, shift; -+ int i, n, bpp = p->var.bits_per_pixel; -+ u32 null_bits = 32 - bpp; -+ u32 *palette = (u32 *) p->pseudo_palette; -+ const u8 *src = image->data; -+ -+ dst2 = (u32 *) dst1; -+ for (i = image->height; i--; ) { -+ n = image->width; -+ dst = (u32 *) dst1; -+ shift = 0; -+ val = 0; -+ -+ if (start_index) { -+ u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); -+ val = FB_READL(dst) & start_mask; -+ shift = start_index; -+ } -+ while (n--) { -+ if (p->fix.visual == FB_VISUAL_TRUECOLOR || -+ p->fix.visual == FB_VISUAL_DIRECTCOLOR ) -+ color = palette[*src]; -+ else -+ color = *src; -+ color <<= LEFT_POS(bpp); -+ val |= SHIFT_HIGH(color, shift); -+ if (shift >= null_bits) { -+ FB_WRITEL(val, dst++); -+ -+ val = (shift == null_bits) ? 0 : -+ SHIFT_LOW(color, 32 - shift); -+ } -+ shift += bpp; -+ shift &= (32 - 1); -+ src++; -+ } -+ if (shift) { -+ u32 end_mask = SHIFT_HIGH(~(u32)0, shift); -+ -+ FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); -+ } -+ dst1 += p->fix.line_length; -+ if (pitch_index) { -+ dst2 += p->fix.line_length; -+ dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1)); -+ -+ start_index += pitch_index; -+ start_index &= 32 - 1; -+ } -+ } -+} -+ -+static const int reversebit[]= -+{ -+ 7, 6, 5, 4, 3, 2, 1, 0, -+ 15,14,13,12,11,10, 9, 8, -+ 23,22,21,20,19,18,17,16, -+ 31,30,29,28,27,26,25,24, -+}; -+static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, -+ u8 *dst1, u32 fgcolor, -+ u32 bgcolor, -+ u32 start_index, -+ u32 pitch_index) -+{ -+ u32 shift, color = 0, bpp = p->var.bits_per_pixel; -+ u32 *dst, *dst2; -+ u32 val, pitch = p->fix.line_length; -+ u32 null_bits = 32 - bpp; -+ u32 spitch = (image->width+7)/8; -+ const u8 *src = image->data, *s; -+ u32 i, j, l; -+ -+ dst2 = (u32 *) dst1; -+ fgcolor <<= LEFT_POS(bpp); -+ bgcolor <<= LEFT_POS(bpp); -+ for (i = image->height; i--; ) { -+ shift = val = 0; -+ l = 8; -+ j = image->width; -+ dst = (u32 *) dst1; -+ s = src; -+ -+ /* write leading bits */ -+ if (start_index) { -+ u32 start_mask = ~(SHIFT_HIGH(~(u32)0,start_index)); -+ val = FB_READL(dst) & start_mask; -+ shift = start_index; -+ } -+ -+ while (j--) { -+ l--; -+ color = (*s & (1 << l)) ? fgcolor : bgcolor; -+ val |= SHIFT_HIGH(color, reversebit[shift]); -+ /* Did the bitshift spill bits to the next long? */ -+ if (shift >= null_bits) { -+ FB_WRITEL(val, dst++); -+ val = (shift == null_bits) ? 0 : -+ SHIFT_LOW(color, 32 - reversebit[shift]); -+ } -+ shift += bpp; -+ shift &= (32 - 1); -+ if (!l) { l = 8; s++; }; -+ } -+ -+ /* write trailing bits */ -+ if (shift) { -+ u32 end_mask = SHIFT_HIGH(~(u32)0, shift); -+ -+ FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); -+ } -+ -+ dst1 += pitch; -+ src += spitch; -+ if (pitch_index) { -+ dst2 += pitch; -+ dst1 = (u8 *)((long __force)dst2 & ~(sizeof(u32) - 1)); -+ start_index += pitch_index; -+ start_index &= 32 - 1; -+ } -+ -+ } -+} -+ -+static void ep93xx_imageblit(struct fb_info *p, const struct fb_image *image) -+{ -+ u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; -+ u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; -+ u32 dx = image->dx, dy = image->dy; -+ u8 *dst1; -+ -+ if (p->state != FBINFO_STATE_RUNNING) -+ return; -+ -+ bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); -+ start_index = bitstart & (32 - 1); -+ pitch_index = (p->fix.line_length & (bpl - 1)) * 8; -+ -+ bitstart /= 8; -+ bitstart &= ~(bpl - 1); -+ dst1 = p->screen_base + bitstart; -+ -+ if (p->fbops->fb_sync) -+ p->fbops->fb_sync(p); -+ -+ if (image->depth == 1) { -+ if (p->fix.visual == FB_VISUAL_TRUECOLOR || -+ p->fix.visual == FB_VISUAL_DIRECTCOLOR) { -+ fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; -+ bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; -+ } else { -+ fgcolor = image->fg_color; -+ bgcolor = image->bg_color; -+ } -+ slow_imageblit(image, p, dst1, fgcolor, bgcolor, -+ start_index, pitch_index); -+ } else -+ color_imageblit(image, p, dst1, start_index, pitch_index); -+} -+ -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) -+ -+int ep93xxfb_ioctl(struct fb_info *info,unsigned int cmd, unsigned long arg) -+{ -+ return 0; -+} -+ -+static int ep93xxfb_mmap(struct fb_info *info,struct vm_area_struct *vma) -+{ -+ unsigned long off, start, len; -+ -+ DPRINTK("ep93xxfb_mmap - enter\n"); -+ -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ start = info->fix.smem_start; -+ len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len; -+ start &= PAGE_MASK; -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ return -EINVAL; -+ -+ off += start; -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ -+ vma->vm_flags |= VM_IO; -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, -+ vma->vm_end - vma->vm_start, vma->vm_page_prot)) { -+ DPRINTK("ep93xxfb_mmap error\n"); -+ return -EAGAIN; -+ } -+ -+ DPRINTK("ep93xxfb_mmap - exit\n"); -+ return 0; -+} -+ -+ -+static struct fb_ops ep93xxfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_check_var = ep93xxfb_check_var, -+ .fb_set_par = ep93xxfb_set_par, -+ .fb_blank = ep93xxfb_blank, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ // .fb_imageblit = cfb_imageblit, -+ .fb_imageblit = ep93xx_imageblit, -+ .fb_ioctl = ep93xxfb_ioctl, -+ .fb_mmap = ep93xxfb_mmap, -+}; -+ -+ -+static struct resource ep93xxfb_raster_resources = { -+ .start = EP93XX_RASTER_PHYS_BASE, -+ .end = EP93XX_RASTER_PHYS_BASE + 0x1ffff, -+ .flags = IORESOURCE_MEM, -+}; -+ -+ -+static int __init ep93xxfb_probe(struct platform_device *device) -+{ -+ struct fb_info *info = NULL; -+ struct resource *res = NULL; -+ int ret = 0; -+ int arb = 0; -+ -+ DPRINTK("ep93xxfb_probe - enter \n"); -+ -+ if(!device) { -+ printk("error : to_platform_device\n"); -+ return -ENODEV; -+ } -+ res = platform_get_resource( device, IORESOURCE_MEM, 0); -+ if(!res) { -+ printk("error : platform_get_resource \n"); -+ return -ENODEV; -+ } -+ if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) -+ return -EBUSY; -+ -+ info = framebuffer_alloc(sizeof(u32) * 256, &device->dev); -+ -+ if(!info) { -+ printk("Unable to allocate memory for frame buffer\n"); -+ return -ENOMEM; -+ } -+ -+ info->flags = FBINFO_DEFAULT; -+ strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); -+ info->fix.mmio_start = res->start; -+ info->fix.mmio_len = res->end - res->start + 1; -+ info->fbops = &ep93xxfb_ops; -+ info->pseudo_palette = info->par; -+ info->state = FBINFO_STATE_RUNNING; -+ -+ printk("mmio_start = 0x%08x\n", res->start); -+ printk("mmio_len = 0x%08x\n", res->end - res->start + 1); -+ -+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { -+ ret = -ENOMEM; -+ goto fbuff; -+ } -+ -+ if ((ret = ep93xxfb_config(info)) < 0) -+ goto clmap; -+ -+ if (register_framebuffer(info) < 0) { -+ printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); -+ ret = -EINVAL; -+ goto clmap; -+ } -+ platform_set_drvdata(device, info); -+ printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, -+ info->var.xres, info->var.yres, info->var.bits_per_pixel); -+ -+ /*change the raster arb to the highest one--Bo*/ -+ arb = inl(EP93XX_SYSCON_BMAR); -+ arb = (arb & 0x3f8) | 0x01; -+ ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR); -+ -+ DPRINTK("ep93xxfb_probe - exit \n"); -+ return 0; -+ -+clmap: -+ fb_dealloc_cmap(&info->cmap); -+ -+fbuff: -+ framebuffer_release(info); -+ return ret; -+} -+ -+static int ep93xxfb_remove(struct platform_device *device) -+{ -+ struct resource *res; -+ struct fb_info *info; -+ -+ DPRINTK("ep93xxfb_remove - enter \n"); -+ -+ info = platform_get_drvdata(device); -+ -+ ep93xxfb_release_videomem(); -+ -+ res = platform_get_resource( device, IORESOURCE_MEM, 0); -+ release_mem_region(res->start, res->end - res->start + 1); -+ -+ platform_set_drvdata(device, NULL); -+ unregister_framebuffer(info); -+ -+ fb_dealloc_cmap(&info->cmap); -+ framebuffer_release(info); -+ -+ ep93xxfb_blank( 1, info ); -+ -+ DPRINTK("ep93xxfb_remove - exit \n"); -+ return 0; -+} -+ -+static void ep93xxfb_platform_release(struct device *device) -+{ -+ DPRINTK("ep93xxfb_platform_release - enter\n"); -+} -+ -+ -+static struct platform_driver ep93xxfb_driver = { -+ .probe = ep93xxfb_probe, -+ .remove = ep93xxfb_remove, -+ .driver = { -+ .name = FBDEV_NAME, -+ }, -+}; -+ -+static struct platform_device ep93xxfb_device = { -+ .name = FBDEV_NAME, -+ .id = -1, -+ .dev = { -+ .release = ep93xxfb_platform_release, -+ }, -+ .num_resources = 1, -+ .resource = &ep93xxfb_raster_resources, -+}; -+ -+int __init ep93xxfb_init(void) -+{ -+ int ret = 0; -+ -+ DPRINTK("ep93xxfb_init - enter\n"); -+ -+ ret = platform_driver_register(&ep93xxfb_driver); -+ -+ if (!ret) { -+ ret = platform_device_register(&ep93xxfb_device); -+ if (ret) -+ platform_driver_unregister(&ep93xxfb_driver); -+ } -+ DPRINTK("ep93xxfb_init - exit\n"); -+ return ret; -+} -+ -+static void __exit ep93xxfb_exit(void) -+{ -+ DPRINTK("ep93xxfb_exit - enter\n"); -+ platform_driver_unregister(&ep93xxfb_driver); -+ platform_device_unregister(&ep93xxfb_device); -+ DPRINTK("ep93xxfb_exit - exit\n"); -+} -+ -+#else // LINUX_VERSION_CODE -+ -+ -+int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, -+ unsigned blue, unsigned transp, -+ struct fb_info *info) -+{ -+ return 0; -+} -+static struct fb_ops ep93xxfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_setcolreg = ep93xxfb_setcolreg, -+ .fb_check_var = ep93xxfb_check_var, -+ .fb_set_par = ep93xxfb_set_par, -+ .fb_blank = ep93xxfb_blank, -+ .fb_fillrect = cfb_fillrect, -+ .fb_copyarea = cfb_copyarea, -+ .fb_imageblit = ep93xx_imageblit, -+ .fb_cursor = soft_cursor, -+}; -+ -+static int __init ep93xxfb_probe(struct device *device) -+{ -+ struct platform_device *pdev = to_platform_device(device); -+ struct fb_info *info = NULL; -+ struct resource *res = NULL; -+ int ret = 0; -+ int arb = 0; -+ -+ DPRINTK("ep93xxfb_probe - enter \n"); -+ -+ -+ if(!device) { -+ printk("error : to_platform_device\n"); -+ return -ENODEV; -+ } -+ res = platform_get_resource( pdev, IORESOURCE_MEM, 0); -+ if(!res) { -+ printk("error : platform_get_resource \n"); -+ return -ENODEV; -+ } -+ if (!request_mem_region(res->start,res->end - res->start + 1, FBDEV_NAME )) -+ return -EBUSY; -+ -+ info = framebuffer_alloc(sizeof(u32) * 256, &pdev->dev); -+ -+ if(!info) { -+ printk("Unable to allocate memory for frame buffer\n"); -+ return -ENOMEM; -+ } -+ -+ info->flags = FBINFO_DEFAULT; -+ strncpy(info->fix.id, FBDEV_NAME, sizeof(info->fix.id)); -+ info->fix.mmio_start = res->start; -+ info->fix.mmio_len = res->end - res->start + 1; -+ info->fbops = &ep93xxfb_ops; -+ info->pseudo_palette = info->par; -+ info->state = FBINFO_STATE_RUNNING; -+ -+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { -+ ret = -ENOMEM; -+ goto fbuff; -+ } -+ -+ if ((ret = ep93xxfb_config(info)) < 0) -+ goto clmap; -+ -+ if (register_framebuffer(info) < 0) { -+ printk(KERN_ERR "Unable to register ep93xxfb frame buffer\n"); -+ ret = -EINVAL; -+ goto clmap; -+ } -+ dev_set_drvdata(device, info); -+ printk(KERN_INFO "fb%d: EP93xx frame buffer at %dx%dx%dbpp\n", info->node, -+ info->var.xres, info->var.yres, info->var.bits_per_pixel); -+ -+ /*change the raster arb to the highest one--Bo*/ -+ arb = inl(EP93XX_SYSCON_BMAR); -+ arb = (arb & 0x3f8) | 0x01; -+ ep93xxfb_outl(arb,EP93XX_SYSCON_BMAR); -+ -+ DPRINTK("ep93xxfb_probe - exit \n"); -+ return 0; -+ -+clmap: -+ fb_dealloc_cmap(&info->cmap); -+ -+fbuff: -+ framebuffer_release(info); -+ return ret; -+} -+ -+static int ep93xxfb_remove(struct device *device) -+{ -+ struct platform_device *pdev = to_platform_device(device); -+ struct resource *res; -+ struct fb_info *info; -+ -+ DPRINTK("ep93xxfb_remove - enter \n"); -+ -+ info = dev_get_drvdata(device); -+ -+ ep93xxfb_release_videomem(); -+ -+ res = platform_get_resource( pdev, IORESOURCE_MEM, 0); -+ release_mem_region(res->start, res->end - res->start + 1); -+ -+ dev_set_drvdata(device, NULL); -+ unregister_framebuffer(info); -+ -+ fb_dealloc_cmap(&info->cmap); -+ framebuffer_release(info); -+ -+ ep93xxfb_blank( 1, info ); -+ -+ DPRINTK("ep93xxfb_remove - exit \n"); -+ return 0; -+} -+static struct device_driver ep93xxfb_driver = { -+ .name = FBDEV_NAME, -+ .bus = &platform_bus_type, -+ .probe = ep93xxfb_probe, -+ .remove = ep93xxfb_remove, -+}; -+int __init ep93xxfb_init(void) -+{ -+ DPRINTK("ep93xxfb_init\n"); -+ return driver_register(&ep93xxfb_driver); -+} -+ -+static void __exit ep93xxfb_exit(void) -+{ -+ DPRINTK("ep93xxfb_exit\n"); -+ return driver_unregister(&ep93xxfb_driver); -+} -+ -+int __init ep93xxfb_setup(char *options) -+{ -+ DPRINTK("ep93xxfb_setup\n"); -+ return 0; -+} -+ -+#endif // LINUX_VERSION_CODE -+ -+ -+module_init(ep93xxfb_init); -+module_exit(ep93xxfb_exit); -+MODULE_AUTHOR("John Zheng <yujiang.zheng@cirrus.com>"); -+MODULE_LICENSE("GPL"); -+ ---- a/arch/arm/mach-ep93xx/include/mach/hardware.h -+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h -@@ -7,6 +7,7 @@ - #include "ep93xx-regs.h" - - #define pcibios_assign_all_busses() 0 -+#include "regs_raster.h" - #include "regs_touch.h" - - #include "platform.h" ---- a/arch/arm/mach-ep93xx/include/mach/irqs.h -+++ b/arch/arm/mach-ep93xx/include/mach/irqs.h -@@ -34,7 +34,8 @@ - #define IRQ_EP93XX_UART3TX 28 - #define IRQ_EP93XX_KEY 29 - #define IRQ_EP93XX_TOUCH 30 --#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc -+#define IRQ_EP93XX_GRAPHICS 31 -+#define EP93XX_VIC1_VALID_IRQ_MASK 0xfffffffc - - #define IRQ_EP93XX_EXT0 32 - #define IRQ_EP93XX_EXT1 33 ---- /dev/null -+++ b/arch/arm/mach-ep93xx/include/mach/regs_raster.h -@@ -0,0 +1,347 @@ -+/*============================================================================= -+ * -+ * FILE: regs_raster.h -+ * -+ * DESCRIPTION: ep93xx Raster Engine Register Definition -+ * -+ * Copyright Cirrus Logic, 2001-2003 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ *============================================================================= -+ */ -+#ifndef _REGS_RASTER_H_ -+#define _REGS_RASTER_H_ -+ -+//----------------------------------------------------------------------------- -+// VLINESTOTAL Register Definitions -+//----------------------------------------------------------------------------- -+#define VLINESTOTAL_MASK 0x000007ff -+ -+//----------------------------------------------------------------------------- -+// VSYNCSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define VSYNCSTRTSTOP_STRT_MASK 0x07ff0000 -+#define VSYNCSTRTSTOP_STRT_SHIFT 0 -+#define VSYNCSTRTSTOP_STOP_MASK 0x000007ff -+#define VSYNCSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// VACTIVESTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define VACTIVESTRTSTOP_STRT_MASK 0x07ff0000 -+#define VACTIVESTRTSTOP_STRT_SHIFT 0 -+#define VACTIVESTRTSTOP_STOP_MASK 0x000007ff -+#define VACTIVESTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// VCLKSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define VCLKSTRTSTOP_STRT_MASK 0x07ff0000 -+#define VCLKSTRTSTOP_STRT_SHIFT 0 -+#define VCLKSTRTSTOP_STOP_MASK 0x000007ff -+#define VCLKSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// VBLANKSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define VBLANKSTRTSTOP_STRT_MASK 0x07ff0000 -+#define VBLANKSTRTSTOP_STRT_SHIFT 0 -+#define VBLANKSTRTSTOP_STOP_MASK 0x000007ff -+#define VBLANKSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// HSYNCSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define HSYNCSTRTSTOP_STRT_MASK 0x07ff0000 -+#define HSYNCSTRTSTOP_STRT_SHIFT 0 -+#define HSYNCSTRTSTOP_STOP_MASK 0x000007ff -+#define HSYNCSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// HACTIVESTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define HACTIVESTRTSTOP_STRT_MASK 0x07ff0000 -+#define HACTIVESTRTSTOP_STRT_SHIFT 0 -+#define HACTIVESTRTSTOP_STOP_MASK 0x000007ff -+#define HACTIVESTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// HCLKSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define HCLKSTRTSTOP_STRT_MASK 0x07ff0000 -+#define HCLKSTRTSTOP_STRT_SHIFT 0 -+#define HCLKSTRTSTOP_STOP_MASK 0x000007ff -+#define HCLKSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// BRIGHTNESS Register Definitions -+//----------------------------------------------------------------------------- -+#define BRIGHTNESS_MASK 0x0000ffff -+#define BRIGHTNESS_CNT_MASK 0x000000ff -+#define BRIGHTNESS_CNT_SHIFT 0 -+#define BRIGHTNESS_CMP_MASK 0x0000ff00 -+#define BRIGHTNESS_CMP_SHIFT 8 -+ -+//----------------------------------------------------------------------------- -+// VIDEOATTRIBS Register Definitions -+//----------------------------------------------------------------------------- -+#define VIDEOATTRIBS_MASK 0x001fffff -+#define VIDEOATTRIBS_EN 0x00000001 -+#define VIDEOATTRIBS_PCLKEN 0x00000002 -+#define VIDEOATTRIBS_SYNCEN 0x00000004 -+#define VIDEOATTRIBS_DATAEN 0x00000008 -+#define VIDEOATTRIBS_CSYNC 0x00000010 -+#define VIDEOATTRIBS_VCPOL 0x00000020 -+#define VIDEOATTRIBS_HSPOL 0x00000040 -+#define VIDEOATTRIBS_BLKPOL 0x00000080 -+#define VIDEOATTRIBS_INVCLK 0x00000100 -+#define VIDEOATTRIBS_ACEN 0x00000200 -+#define VIDEOATTRIBS_LCDEN 0x00000400 -+#define VIDEOATTRIBS_CCIREN 0x00001000 -+#define VIDEOATTRIBS_PIFEN 0x00002000 -+#define VIDEOATTRIBS_INTEN 0x00004000 -+#define VIDEOATTRIBS_INT 0x00008000 -+#define VIDEOATTRIBS_INTRLC 0x00010000 -+#define VIDEOATTRIBS_EQUSER 0x00020000 -+#define VIDEOATTRIBS_DHORZ 0x00040000 -+#define VIDEOATTRIBS_DVERT 0x00080000 -+#define VIDEOATTRIBS_BKPXD 0x00100000 -+ -+#define VIDEOATTRIBS_SDSEL_MASK 0x00600000 -+#define VIDEOATTRIBS_SDSEL_SHIFT 21 -+ -+//----------------------------------------------------------------------------- -+// HBLANKSTRTSTOP Register Definitions -+//----------------------------------------------------------------------------- -+#define HBLANKSTRTSTOP_STRT_MASK 0x07ff0000 -+#define HBLANKSTRTSTOP_STRT_SHIFT 0 -+#define HBLANKSTRTSTOP_STOP_MASK 0x000007ff -+#define HBLANKSTRTSTOP_STOP_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// LINECARRY Register Definitions -+//----------------------------------------------------------------------------- -+#define LINECARRY_LCARY_MASK 0x000007ff -+#define LINECARRY_LCARY_SHIFT 0 -+ -+//----------------------------------------------------------------------------- -+// BLINKRATE Register Definitons -+//----------------------------------------------------------------------------- -+#define BLINKRATE_MASK 0x000000ff -+ -+//----------------------------------------------------------------------------- -+// BLINKMASK Register Definitons -+//----------------------------------------------------------------------------- -+#define BLINKMASK_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// VIDSCRNPAGE Register Definitons -+//----------------------------------------------------------------------------- -+#define VIDSCRNPAGE_PAGE_MASK 0x0ffffffc -+ -+//----------------------------------------------------------------------------- -+// VIDSCRNHPG Register Definitons -+//----------------------------------------------------------------------------- -+#define VIDSCRNHPG_MASK 0x0ffffffc -+ -+//----------------------------------------------------------------------------- -+// SCRNLINES Register Definitons -+//----------------------------------------------------------------------------- -+#define SCRNLINES_MASK 0x000007ff -+ -+//----------------------------------------------------------------------------- -+// LINELENGTH Register Definitons -+//----------------------------------------------------------------------------- -+#define LINELENGTH_MASK 0x000007ff -+ -+//----------------------------------------------------------------------------- -+// VLINESTEP Register Definitons -+//----------------------------------------------------------------------------- -+#define VLINESTEP_MASK 0x00000fff -+ -+//----------------------------------------------------------------------------- -+// RASTER_SWLOCK Register Definitons -+//----------------------------------------------------------------------------- -+#define RASTER_SWLOCK_MASK_WR 0xff -+#define RASTER_SWLOCK_MASK_R 0x1 -+#define RASTER_SWLOCK_VALUE 0xaa -+ -+//----------------------------------------------------------------------------- -+// LUTCONT Register Definitions -+//----------------------------------------------------------------------------- -+#define LUTCONT_MASK 0x00000003 -+#define LUTCONT_SWTCH 0x00000001 -+#define LUTCONT_STAT 0x00000002 -+#define LUTCONT_RAM0 0 -+#define LUTCONT_RAM1 1 -+ -+//----------------------------------------------------------------------------- -+// CURSORBLINK1 Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORBLINK1_MASK 0x00ffffff -+//----------------------------------------------------------------------------- -+// CURSORBLINK2 Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORBLINK2_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// CURSORBLINK Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORBLINK_MASK 0x000001ff -+#define CURSORBLINK_RATE_MASK 0x000000ff -+#define CURSORBLINK_RATE_SHIFT 0 -+#define CURSORBLINK_EN 0x00000100 -+ -+//----------------------------------------------------------------------------- -+// BLINKPATRN Register Definitions -+//----------------------------------------------------------------------------- -+#define BLINKPATRN_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// PATRNMASK Register Definitions -+//----------------------------------------------------------------------------- -+#define PATRNMASK_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// BG_OFFSET Register Definitions -+//----------------------------------------------------------------------------- -+#define BG_OFFSET_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// PIXELMODE Register Definitions -+//----------------------------------------------------------------------------- -+#define PIXELMODE_P_MASK 0x00000007 -+#define PIXELMODE_P_MUX_DISABLE 0x00000000 -+#define PIXELMODE_P_4BPP 0x00000001 -+#define PIXELMODE_P_8BPP 0x00000002 -+#define PIXELMODE_P_16BPP 0x00000004 -+#define PIXELMODE_P_24BPP 0x00000006 -+#define PIXELMODE_P_32BPP 0x00000007 -+ -+#define PIXELMODE_S_MASK 0x00000038 -+#define PIXELMODE_S_1PPC 0x00000000 -+#define PIXELMODE_S_1PPCMAPPED 0x00000008 -+#define PIXELMODE_S_2PPC 0x00000010 -+#define PIXELMODE_S_4PPC 0x00000018 -+#define PIXELMODE_S_8PPC 0x00000020 -+#define PIXELMODE_S_223PPC 0x00000028 -+#define PIXELMODE_S_DS223PPC 0x00000030 -+#define PIXELMODE_S_UNDEF 0x00000038 -+ -+#define PIXELMODE_M_MASK 0x000003c0 -+#define PIXELMODE_M_NOBLINK 0x00000000 -+#define PIXELMODE_M_ANDBLINK 0x00000040 -+#define PIXELMODE_M_ORBLINK 0x00000080 -+#define PIXELMODE_M_XORBLINK 0x000000c0 -+#define PIXELMODE_M_BGBLINK 0x00000100 -+#define PIXELMODE_M_OFFSINGBLINK 0x00000140 -+#define PIXELMODE_M_OFF888BLINK 0x00000180 -+#define PIXELMODE_M_DIMBLINK 0x00000300 -+#define PIXELMODE_M_BRTBLINK 0x00000340 -+#define PIXELMODE_M_DIM888BLINK 0x00000380 -+#define PIXELMODE_M_BRT888BLINK 0x000003c0 -+ -+#define PIXELMODE_C_MASK 0x00003c00 -+#define PIXELMODE_C_LUT 0x00000000 -+#define PIXELMODE_C_888 0x00001000 -+#define PIXELMODE_C_565 0x00001400 -+#define PIXELMODE_C_555 0x00001800 -+#define PIXELMODE_C_GSLUT 0x00002000 -+ -+#define PIXELMODE_DSCAN 0x00004000 -+#define PIXELMODE_TRBSW 0x00008000 -+ -+//----------------------------------------------------------------------------- -+//PARLLIFOUT Register Defintions -+//----------------------------------------------------------------------------- -+#define PARLLIFOUT_DAT_MASK 0x0000000f -+#define PARLLIFOUT_DAT_SHIFT 0 -+#define PARLLIFOUT_RD 0x00000010 -+ -+//----------------------------------------------------------------------------- -+//PARLLIFIN Register Defintions -+//----------------------------------------------------------------------------- -+#define PARLLIFIN_DAT_MASK 0x0000000f -+#define PARLLIFIN_DAT_SHIFT 0 -+#define PARLLIFIN_CNT_MASK 0x000f0000 -+#define PARLLIFIN_CNT_SHIFT 16 -+#define PARLLIFIN_ESTRT_MASK 0x00f00000 -+#define PARLLIFIN_ESTRT_SHIFT 20 -+ -+//----------------------------------------------------------------------------- -+// CURSORADRSTART Register Defintions -+//----------------------------------------------------------------------------- -+#define CURSOR_ADR_START_MASK 0xfffffffc -+ -+//----------------------------------------------------------------------------- -+// CURSORADRSTART Register Defintions -+//----------------------------------------------------------------------------- -+#define CURSOR_ADR_RESET_MASK 0xfffffffc -+ -+//----------------------------------------------------------------------------- -+// CURSORCOLOR1 Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORCOLOR1_MASK 0x00ffffff -+//----------------------------------------------------------------------------- -+// CURSORCOLOR2 Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORCOLOR2_MASK 0x00ffffff -+ -+//----------------------------------------------------------------------------- -+// CURSORXYLOC Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORXYLOC_MASK 0x07ff87ff -+#define CURSORXYLOC_XLOC_MASK 0x000007ff -+#define CURSORXYLOC_XLOC_SHIFT 0 -+#define CURSORXYLOC_CEN 0x00008000 -+#define CURSORXYLOC_YLOC_MASK 0x07ff0000 -+#define CURSORXYLOC_YLOC_SHIFT 16 -+ -+//----------------------------------------------------------------------------- -+// CURSOR_DSCAN_LH_YLOC Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSOR_DSCAN_LH_YLOC_MASK 0x000087ff -+ -+#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK 0x000007ff -+#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0 -+#define CURSOR_DSCAN_LH_YLOC_CLHEN 0x00008000 -+ -+//----------------------------------------------------------------------------- -+// CURSORSIZE Register Definitions -+//----------------------------------------------------------------------------- -+#define CURSORSIZE_MASK 0x0000ffff -+ -+#define CURSORSIZE_CWID_MASK 0x00000003 -+#define CURSORSIZE_CWID_SHIFT 0 -+#define CURSORSIZE_CWID_1_WORD 0 -+#define CURSORSIZE_CWID_2_WORD 1 -+#define CURSORSIZE_CWID_3_WORD 2 -+#define CURSORSIZE_CWID_4_WORD 3 -+ -+#define CURSORSIZE_CLINS_MASK 0x000000fc -+#define CURSORSIZE_CLINS_SHIFT 2 -+ -+#define CURSORSIZE_CSTEP_MASK 0x00000300 -+#define CURSORSIZE_CSTEP_SHIFT 8 -+#define CURSORSIZE_CSTEP_1_WORD 0 -+#define CURSORSIZE_CSTEP_2_WORD 1 -+#define CURSORSIZE_CSTEP_3_WORD 2 -+#define CURSORSIZE_CSTEP_4_WORD 3 -+ -+#define CURSORSIZE_DLNS_MASK 0x0000fc00 -+#define CURSORSIZE_DLNS_SHIFT 10 -+ -+#endif /* _REGS_RASTER_H_ */ diff --git a/target/linux/ep93xx/patches-2.6.30/010-ep93xx-snd-ac97.patch b/target/linux/ep93xx/patches-2.6.30/010-ep93xx-snd-ac97.patch deleted file mode 100644 index 36f316be17..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/010-ep93xx-snd-ac97.patch +++ /dev/null @@ -1,3808 +0,0 @@ ---- a/arch/arm/mach-ep93xx/include/mach/hardware.h -+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h -@@ -5,6 +5,7 @@ - #define __ASM_ARCH_HARDWARE_H - - #include "ep93xx-regs.h" -+#include "regs_ac97.h" - - #define pcibios_assign_all_busses() 0 - #include "regs_raster.h" ---- /dev/null -+++ b/arch/arm/mach-ep93xx/include/mach/regs_ac97.h -@@ -0,0 +1,180 @@ -+/*============================================================================= -+ * FILE: regs_ac97.h -+ * -+ * DESCRIPTION: Ac'97 Register Definition -+ * -+ * Copyright Cirrus Logic, 2001-2003 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ *============================================================================= -+ */ -+#ifndef _REGS_AC97_H_ -+#define _REGS_AC97_H_ -+ -+//----------------------------------------------------------------------------- -+// Bit definitionses -+//----------------------------------------------------------------------------- -+#define AC97ISR_RIS 8 -+#define AC97ISR_TIS 4 -+#define AC97ISR_RTIS 2 -+#define AC97ISR_TCIS 1 -+ -+#define AC97RGIS_SLOT1TXCOMPLETE 0x01 -+#define AC97RGIS_SLOT2RXVALID 0x02 -+#define AC97RGIS_GPIOTXCOMPLETE 0x04 -+#define AC97RGIS_GPIOINTRX 0x08 -+#define AC97RGIS_RWIS 0x10 -+#define AC97RGIS_CODECREADY 0x20 -+#define AC97RGIS_SLOT2TXCOMPLETE 0x40 -+ -+#define AC97SR_RXFE 0x0001 -+#define AC97SR_TXFE 0x0002 -+#define AC97SR_RXFF 0x0004 -+#define AC97SR_TXFF 0x0008 -+#define AC97SR_TXBUSY 0x0010 -+#define AC97SR_RXOE 0x0020 -+#define AC97SR_TXUE 0x0040 -+ -+#define AC97GSR_IFE 0x1 -+#define AC97GSR_LOOP 0x2 -+#define AC97GSR_OVERRIDECODECREADY 0x4 -+ -+#define AC97RESET_TIMEDRESET 0x1 -+#define AC97RESET_FORCEDRESET 0x2 -+#define AC97RESET_EFORCER 0x4 -+ -+#define AC97RXCR_REN 0x1 -+ -+#define AC97TXCR_TEN 0x1 -+ -+ -+//**************************************************************************** -+// -+// The Ac97 Codec registers, accessable through the Ac-link. -+// These are not controller registers and are not memory mapped. -+// Includes registers specific to CS4202 (Beavis). -+// -+//**************************************************************************** -+#define AC97_REG_OFFSET_MASK 0x0000007E -+ -+#define AC97_00_RESET 0x00000000 -+#define AC97_02_MASTER_VOL 0x00000002 -+#define AC97_04_HEADPHONE_VOL 0x00000004 -+#define AC97_06_MONO_VOL 0x00000006 -+#define AC97_08_TONE 0x00000008 -+#define AC97_0A_PC_BEEP_VOL 0x0000000A -+#define AC97_0C_PHONE_VOL 0x0000000C -+#define AC97_0E_MIC_VOL 0x0000000E -+#define AC97_10_LINE_IN_VOL 0x00000010 -+#define AC97_12_CD_VOL 0x00000012 -+#define AC97_14_VIDEO_VOL 0x00000014 -+#define AC97_16_AUX_VOL 0x00000016 -+#define AC97_18_PCM_OUT_VOL 0x00000018 -+#define AC97_1A_RECORD_SELECT 0x0000001A -+#define AC97_1C_RECORD_GAIN 0x0000001C -+#define AC97_1E_RESERVED_1E 0x0000001E -+#define AC97_20_GENERAL_PURPOSE 0x00000020 -+#define AC97_22_3D_CONTROL 0x00000022 -+#define AC97_24_MODEM_RATE 0x00000024 -+#define AC97_26_POWERDOWN 0x00000026 -+#define AC97_28_EXT_AUDIO_ID 0x00000028 -+#define AC97_2A_EXT_AUDIO_POWER 0x0000002A -+#define AC97_2C_PCM_FRONT_DAC_RATE 0x0000002C -+#define AC97_2E_PCM_SURR_DAC_RATE 0x0000002E -+#define AC97_30_PCM_LFE_DAC_RATE 0x00000030 -+#define AC97_32_PCM_LR_ADC_RATE 0x00000032 -+#define AC97_34_MIC_ADC_RATE 0x00000034 -+#define AC97_36_6CH_VOL_C_LFE 0x00000036 -+#define AC97_38_6CH_VOL_SURROUND 0x00000038 -+#define AC97_3A_SPDIF_CONTROL 0x0000003A -+#define AC97_3C_EXT_MODEM_ID 0x0000003C -+#define AC97_3E_EXT_MODEM_POWER 0x0000003E -+#define AC97_40_LINE1_CODEC_RATE 0x00000040 -+#define AC97_42_LINE2_CODEC_RATE 0x00000042 -+#define AC97_44_HANDSET_CODEC_RATE 0x00000044 -+#define AC97_46_LINE1_CODEC_LEVEL 0x00000046 -+#define AC97_48_LINE2_CODEC_LEVEL 0x00000048 -+#define AC97_4A_HANDSET_CODEC_LEVEL 0x0000004A -+#define AC97_4C_GPIO_PIN_CONFIG 0x0000004C -+#define AC97_4E_GPIO_PIN_TYPE 0x0000004E -+#define AC97_50_GPIO_PIN_STICKY 0x00000050 -+#define AC97_52_GPIO_PIN_WAKEUP 0x00000052 -+#define AC97_54_GPIO_PIN_STATUS 0x00000054 -+#define AC97_56_RESERVED 0x00000056 -+#define AC97_58_RESERVED 0x00000058 -+#define AC97_5A_CRYSTAL_REV_N_FAB_ID 0x0000005A -+#define AC97_5C_TEST_AND_MISC_CTRL 0x0000005C -+#define AC97_5E_AC_MODE 0x0000005E -+#define AC97_60_MISC_CRYSTAL_CONTROL 0x00000060 -+#define AC97_62_VENDOR_RESERVED 0x00000062 -+#define AC97_64_DAC_SRC_PHASE_INCR 0x00000064 -+#define AC97_66_ADC_SRC_PHASE_INCR 0x00000066 -+#define AC97_68_RESERVED_68 0x00000068 -+#define AC97_6A_SERIAL_PORT_CONTROL 0x0000006A -+#define AC97_6C_VENDOR_RESERVED 0x0000006C -+#define AC97_6E_VENDOR_RESERVED 0x0000006E -+#define AC97_70_BDI_CONFIG 0x00000070 -+#define AC97_72_BDI_WAKEUP 0x00000072 -+#define AC97_74_VENDOR_RESERVED 0x00000074 -+#define AC97_76_CAL_ADDRESS 0x00000076 -+#define AC97_78_CAL_DATA 0x00000078 -+#define AC97_7A_VENDOR_RESERVED 0x0000007A -+#define AC97_7C_VENDOR_ID1 0x0000007C -+#define AC97_7E_VENDOR_ID2 0x0000007E -+ -+ -+#ifndef __ASSEMBLY__ -+ -+// -+// enum type for use with reg AC97_RECORD_SELECT -+// -+typedef enum{ -+ RECORD_MIC = 0x0000, -+ RECORD_CD = 0x0101, -+ RECORD_VIDEO_IN = 0x0202, -+ RECORD_AUX_IN = 0x0303, -+ RECORD_LINE_IN = 0x0404, -+ RECORD_STEREO_MIX = 0x0505, -+ RECORD_MONO_MIX = 0x0606, -+ RECORD_PHONE_IN = 0x0707 -+} Ac97RecordSources; -+ -+#endif /* __ASSEMBLY__ */ -+ -+// -+// Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and -+// AC97_PCM_LR_ADC_RATE. -+// -+#define Ac97_Fs_8000 0x1f40 -+#define Ac97_Fs_11025 0x2b11 -+#define Ac97_Fs_16000 0x3e80 -+#define Ac97_Fs_22050 0x5622 -+#define Ac97_Fs_32000 0x7d00 -+#define Ac97_Fs_44100 0xac44 -+#define Ac97_Fs_48000 0xbb80 -+ -+// -+// RSIZE and TSIZE in AC97RXCR and AC97TXCR -+// -+#define Ac97_SIZE_20 2 -+#define Ac97_SIZE_18 1 -+#define Ac97_SIZE_16 0 -+#define Ac97_SIZE_12 3 -+ -+//============================================================================= -+//============================================================================= -+ -+ -+#endif /* _REGS_AC97_H_ */ ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -11,6 +11,23 @@ menuconfig SND_ARM - - if SND_ARM - -+config SND_EP93XX_AC97 -+ tristate "AC97 driver for the Cirrus EP93xx chip" -+ depends on ARCH_EP93XX && SND -+ select SND_EP93XX_PCM -+ select SND_AC97_CODEC -+ help -+ Say Y here to use AC'97 audio with a Cirrus Logic EP93xx chip. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called snd-ep93xx-ac97. -+ -+config SND_EP93XX_PCM -+ tristate -+ select SND_PCM -+ help -+ Generic PCM module for EP93xx -+ - config SND_ARMAACI - tristate "ARM PrimeCell PL041 AC Link support" - depends on ARM_AMBA ---- a/sound/arm/Makefile -+++ b/sound/arm/Makefile -@@ -5,6 +5,9 @@ - obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o - snd-aaci-objs := aaci.o devdma.o - -+obj-$(CONFIG_SND_EP93XX_AC97) += snd-ep93xx-ac97.o -+snd-ep93xx-ac97-objs := ep93xx-ac97.o -+ - obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o - snd-pxa2xx-pcm-objs := pxa2xx-pcm.o - ---- /dev/null -+++ b/sound/arm/ep93xx-ac97.c -@@ -0,0 +1,3482 @@ -+/* -+ * linux/sound/arm/ep93xx-ac97.c -- ALSA PCM interface for the edb93xx ac97 audio -+ */ -+ -+#include <linux/autoconf.h> -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/delay.h> -+#include <linux/soundcard.h> -+ -+#include <sound/driver.h> -+#include <sound/core.h> -+#include <sound/pcm.h> -+#include <sound/pcm_params.h> -+#include <sound/control.h> -+#include <sound/initval.h> -+#include <sound/ac97_codec.h> -+ -+#include <asm/irq.h> -+#include <asm/semaphore.h> -+#include <asm/hardware.h> -+#include <asm/io.h> -+#include <asm/arch/dma.h> -+#include "ep93xx-ac97.h" -+ -+#define DRIVER_VERSION "01/05/2009" -+#define DRIVER_DESC "EP93xx AC97 Audio driver" -+static int ac_link_enabled = 0; -+static int codec_supported_mixers; -+ -+//#define DEBUG 1 -+#ifdef DEBUG -+#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) -+#else -+#define DPRINTK( fmt, arg... ) -+#endif -+ -+#define WL16 0 -+#define WL24 1 -+ -+#define AUDIO_NAME "ep93xx-ac97" -+#define AUDIO_SAMPLE_RATE_DEFAULT 44100 -+#define AUDIO_DEFAULT_VOLUME 0 -+#define AUDIO_MAX_VOLUME 181 -+#define AUDIO_DEFAULT_DMACHANNELS 3 -+#define PLAYBACK_DEFAULT_DMACHANNELS 3 -+#define CAPTURE_DEFAULT_DMACHANNELS 3 -+ -+#define CHANNEL_FRONT (1<<0) -+#define CHANNEL_REAR (1<<1) -+#define CHANNEL_CENTER_LFE (1<<2) -+ -+static void snd_ep93xx_dma_tx_callback( ep93xx_dma_int_t DMAInt, -+ ep93xx_dma_dev_t device, -+ unsigned int user_data); -+static void snd_ep93xx_dma_rx_callback( ep93xx_dma_int_t DMAInt, -+ ep93xx_dma_dev_t device, -+ unsigned int user_data); -+ -+static const struct snd_pcm_hardware ep93xx_ac97_pcm_hardware = { -+ -+ -+ .info = ( SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE ), -+ .formats = ( SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | -+ SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE | -+ SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | -+ SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE ), -+ .rates = ( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | -+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | -+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | -+ SNDRV_PCM_RATE_48000 ), -+ .rate_min = 8000, -+ .rate_max = 48000, -+ .channels_min = 1,/*2,*/ -+ .channels_max = 2, -+ -+ .period_bytes_min = 1 * 1024, -+ .period_bytes_max = 32 * 1024, -+ .periods_min = 1, -+ .periods_max = 32, -+ .buffer_bytes_max = 32 * 1024, -+ .fifo_size = 0, -+}; -+ -+static audio_stream_t output_stream; -+static audio_stream_t input_stream; -+ -+static audio_state_t audio_state = -+{ -+ .output_stream =&output_stream, -+ .output_dma[0] =DMATx_AAC1, -+ .output_id[0] ="Ac97 out", -+ -+ .input_stream =&input_stream, -+ .input_dma[0] =DMARx_AAC1, -+ .input_id[0] ="Ac97 in", -+ -+ .sem = __SEMAPHORE_INIT(audio_state.sem,1), -+ .codec_set_by_playback = 0, -+ .codec_set_by_capture = 0, -+ .DAC_bit_width =16, -+ .bCompactMode =0, -+}; -+ -+ -+ -+/* -+ * peek -+ * -+ * Reads an AC97 codec register. Returns -1 if there was an error. -+ */ -+static int peek(unsigned int uiAddress) -+{ -+ unsigned int uiAC97RGIS; -+ -+ if( !ac_link_enabled ) -+ { -+ printk("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n"); -+ return -1; -+ } -+ -+ /* -+ * Check to make sure that the address is aligned on a word boundary -+ * and is 7E or less. -+ */ -+ if( ((uiAddress & 0x1)!=0) || (uiAddress > 0x007e)) -+ { -+ return -1; -+ } -+ -+ /* -+ * How it is supposed to work is: -+ * - The ac97 controller sends out a read addr in slot 1. -+ * - In the next frame, the codec will echo that address back in slot 1 -+ * and send the data in slot 2. SLOT2RXVALID will be set to 1. -+ * -+ * Read until SLOT2RXVALID goes to 1. Reading the data in AC97S2DATA -+ * clears SLOT2RXVALID. -+ */ -+ -+ /* -+ * First, delay one frame in case of back to back peeks/pokes. -+ */ -+ mdelay( 1 ); -+ -+ /* -+ * Write the address to AC97S1DATA, delay 1 frame, read the flags. -+ */ -+ outl( uiAddress, AC97S1DATA); -+ udelay( 21 * 4 ); -+ uiAC97RGIS = inl( AC97RGIS ); -+ -+ /* -+ * Return error if we timed out. -+ */ -+ if( ((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0 ) && -+ ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0 ) ) -+ { -+ printk( "ep93xx-ac97 - peek failed reading reg 0x%02x.\n", uiAddress ); -+ return -1; -+ } -+ -+ return ( inl(AC97S2DATA) & 0x000fffff); -+} -+ -+/* -+ * poke -+ * -+ * Writes an AC97 codec Register. Return -1 if error. -+ */ -+static int poke(unsigned int uiAddress, unsigned int uiValue) -+{ -+ unsigned int uiAC97RGIS; -+ -+ if( !ac_link_enabled ) -+ { -+ printk("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n"); -+ return -1; -+ } -+ -+ /* -+ * Check to make sure that the address is align on a word boundary and -+ * is 7E or less. And that the value is a 16 bit value. -+ */ -+ if( ((uiAddress & 0x1)!=0) || (uiAddress > 0x007e)) -+ { -+ printk("ep93xx ac97 poke: address error.\n"); -+ return -1; -+ } -+ -+ /*stop the audio loop from the input to the output directly*/ -+ -+ if((uiAddress==AC97_0E_MIC_VOL)||(uiAddress==AC97_10_LINE_IN_VOL)) -+ { -+ uiValue = (uiValue | 0x8000); -+ -+ } -+ -+ /* -+ * First, delay one frame in case of back to back peeks/pokes. -+ */ -+ mdelay( 1 ); -+ -+ /* -+ * Write the data to AC97S2DATA, then the address to AC97S1DATA. -+ */ -+ outl( uiValue, AC97S2DATA ); -+ outl( uiAddress, AC97S1DATA ); -+ -+ /* -+ * Wait for the tx to complete, get status. -+ */ -+ udelay( 30 );/*21*/ -+ uiAC97RGIS = inl(AC97RGIS); -+ -+ /* -+ * Return error if we timed out. -+ */ -+ if( !(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE) ) -+ { -+ printk( "ep93xx-ac97: poke failed writing reg 0x%02x value 0x%02x.\n", uiAddress, uiValue ); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+ -+/* -+ * When we get to the multichannel case the pre-fill and enable code -+ * will go to the dma driver's start routine. -+ */ -+static void ep93xx_audio_enable( int input_or_output_stream ) -+{ -+ unsigned int uiTemp; -+ -+ DPRINTK("ep93xx_audio_enable :%x\n",input_or_output_stream); -+ -+ /* -+ * Enable the rx or tx channel depending on the value of -+ * input_or_output_stream -+ */ -+ if( input_or_output_stream ) -+ { -+ uiTemp = inl(AC97TXCR1); -+ outl( (uiTemp | AC97TXCR_TEN), AC97TXCR1 ); -+ } -+ else -+ { -+ uiTemp = inl(AC97RXCR1); -+ outl( (uiTemp | AC97RXCR_REN), AC97RXCR1 ); -+ } -+ -+ -+ //DDEBUG("ep93xx_audio_enable - EXIT\n"); -+} -+ -+static void ep93xx_audio_disable( int input_or_output_stream ) -+{ -+ unsigned int uiTemp; -+ -+ DPRINTK("ep93xx_audio_disable\n"); -+ -+ /* -+ * Disable the rx or tx channel depending on the value of -+ * input_or_output_stream -+ */ -+ if( input_or_output_stream ) -+ { -+ uiTemp = inl(AC97TXCR1); -+ outl( (uiTemp & ~AC97TXCR_TEN), AC97TXCR1 ); -+ } -+ else -+ { -+ uiTemp = inl(AC97RXCR1); -+ outl( (uiTemp & ~AC97RXCR_REN), AC97RXCR1 ); -+ } -+ -+ //DDEBUG("ep93xx_audio_disable - EXIT\n"); -+} -+ -+ -+ -+/*=======================================================================================*/ -+/* -+ * ep93xx_setup_src -+ * -+ * Once the ac-link is up and all is good, we want to set the codec to a -+ * usable mode. -+ */ -+static void ep93xx_setup_src(void) -+{ -+ int iTemp; -+ -+ /* -+ * Set the VRA bit to enable the SRC. -+ */ -+ iTemp = peek( AC97_2A_EXT_AUDIO_POWER ); -+ poke( AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1) ); -+ -+ /* -+ * Set the DSRC/ASRC bits to enable the variable rate SRC. -+ */ -+ iTemp = peek( AC97_60_MISC_CRYSTAL_CONTROL ); -+ poke( AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300) ); -+} -+ -+/* -+ * ep93xx_set_samplerate -+ * -+ * lFrequency - Sample Rate in Hz -+ * bCapture - 0 to set Tx sample rate; 1 to set Rx sample rate -+ */ -+static void ep93xx_set_samplerate( long lSampleRate, int bCapture ) -+{ -+ unsigned short usDivider, usPhase; -+ -+ DPRINTK( "ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate ); -+ -+ if( (lSampleRate < 7200) || (lSampleRate > 48000) ) -+ { -+ printk( "ep93xx_set_samplerate - invalid Fs = %d\n", -+ (int)lSampleRate ); -+ return; -+ } -+ -+ /* -+ * Calculate divider and phase increment. -+ * -+ * divider = round( 0x1770000 / lSampleRate ) -+ * Note that usually rounding is done by adding 0.5 to a floating -+ * value and then truncating. To do this without using floating -+ * point, I multiply the fraction by two, do the division, then add one, -+ * then divide the whole by 2 and then truncate. -+ * Same effect, no floating point math. -+ * -+ * Ph incr = trunc( (0x1000000 / usDivider) + 1 ) -+ */ -+ -+ usDivider = (unsigned short)( ((2 * 0x1770000 / lSampleRate) + 1) / 2 ); -+ -+ usPhase = (0x1000000 / usDivider) + 1; -+ -+ /* -+ * Write them in the registers. Spec says divider must be -+ * written after phase incr. -+ */ -+ if(!bCapture) -+ { -+ poke( AC97_2C_PCM_FRONT_DAC_RATE, usDivider); -+ poke( AC97_64_DAC_SRC_PHASE_INCR, usPhase); -+ } -+ else -+ { -+ -+ poke( AC97_32_PCM_LR_ADC_RATE, usDivider); -+ poke( AC97_66_ADC_SRC_PHASE_INCR, usPhase); -+ } -+ -+ DPRINTK( "ep93xx_set_samplerate - phase = %d, divider = %d\n", -+ (unsigned int)usPhase, (unsigned int)usDivider ); -+ -+ /* -+ * We sorta should report the actual samplerate back to the calling -+ * application. But some applications freak out if they don't get -+ * exactly what they asked for. So we fudge and tell them what -+ * they want to hear. -+ */ -+ //audio_samplerate = lSampleRate; -+ -+ DPRINTK( "ep93xx_set_samplerate - EXIT\n" ); -+} -+ -+/* -+ * ep93xx_set_hw_format -+ * -+ * Sets up whether the controller is expecting 20 bit data in 32 bit words -+ * or 16 bit data compacted to have a stereo sample in each 32 bit word. -+ */ -+static void ep93xx_set_hw_format( long format,long channel ) -+{ -+ int bCompactMode; -+ -+ switch( format ) -+ { -+ /* -+ * Here's all the <=16 bit formats. We can squeeze both L and R -+ * into one 32 bit sample so use compact mode. -+ */ -+ case SNDRV_PCM_FORMAT_U8: -+ case SNDRV_PCM_FORMAT_S8: -+ case SNDRV_PCM_FORMAT_S16_LE: -+ case SNDRV_PCM_FORMAT_U16_LE: -+ bCompactMode = 1; -+ break; -+ -+ /* -+ * Add any other >16 bit formats here... -+ */ -+ case SNDRV_PCM_FORMAT_S32_LE: -+ default: -+ bCompactMode = 0; -+ break; -+ } -+ -+ if( bCompactMode ) -+ { -+ DPRINTK("ep93xx_set_hw_format - Setting serial mode to 16 bit compact.\n"); -+ -+ /* -+ * Turn on Compact Mode so we can fit each stereo sample into -+ * a 32 bit word. Twice as efficent for DMA and FIFOs. -+ */ -+ if(channel==2){ -+ outl( 0x00008018, AC97RXCR1 ); -+ outl( 0x00008018, AC97TXCR1 ); -+ } -+ else { -+ outl( 0x00008018, AC97RXCR1 ); -+ outl( 0x00008018, AC97TXCR1 ); -+ } -+ -+ -+ audio_state.DAC_bit_width = 16; -+ audio_state.bCompactMode = 1; -+ } -+ else -+ { -+ DPRINTK("ep93xx_set_hw_format - Setting serial mode to 20 bit non-CM.\n"); -+ -+ /* -+ * Turn off Compact Mode so we can do > 16 bits per channel -+ */ -+ if(channel==2){ -+ outl( 0x00004018, AC97RXCR1 ); -+ outl( 0x00004018, AC97TXCR1 ); -+ } -+ else{ -+ outl( 0x00004018, AC97RXCR1 ); -+ outl( 0x00004018, AC97TXCR1 ); -+ } -+ -+ audio_state.DAC_bit_width = 20; -+ audio_state.bCompactMode = 0; -+ } -+ -+} -+ -+/* -+ * ep93xx_stop_loop -+ * -+ * Once the ac-link is up and all is good, we want to set the codec to a -+ * usable mode. -+ */ -+static void ep93xx_stop_loop(void) -+{ -+ int iTemp; -+ -+ /* -+ * Set the AC97_0E_MIC_VOL MUTE bit to enable the LOOP. -+ */ -+ iTemp = peek( AC97_0E_MIC_VOL ); -+ poke( AC97_0E_MIC_VOL, (iTemp | 0x8000) ); -+ -+ /* -+ * Set the AC97_10_LINE_IN_VOL MUTE bit to enable the LOOP. -+ */ -+ iTemp = peek( AC97_10_LINE_IN_VOL ); -+ poke( AC97_10_LINE_IN_VOL, (iTemp | 0x8000) ); -+} -+ -+/* -+ * ep93xx_init_ac97_controller -+ * -+ * This routine sets up the Ac'97 Controller. -+ */ -+static void ep93xx_init_ac97_controller(void) -+{ -+ unsigned int uiDEVCFG, uiTemp; -+ -+ DPRINTK("ep93xx_init_ac97_controller - enter\n"); -+ -+ /* -+ * Configure the multiplexed Ac'97 pins to be Ac97 not I2s. -+ * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be -+ * SDOUT's for the second and third I2S controller channels. -+ */ -+ uiDEVCFG = inl(EP93XX_SYSCON_DEVICE_CONFIG); -+ -+ uiDEVCFG &= ~(EP93XX_SYSCON_DEVCFG_CONFIG_I2SONAC97 | -+ EP93XX_SYSCON_DEVCFG_A1onG | -+ EP93XX_SYSCON_DEVCFG_A2onG); -+ -+ SysconSetLocked(EP93XX_SYSCON_DEVICE_CONFIG, uiDEVCFG); -+ -+ /* -+ * Disable the AC97 controller internal loopback. -+ * Disable Override codec ready. -+ */ -+ outl( 0, AC97GCR ); -+ -+ /* -+ * Enable the AC97 Link. -+ */ -+ uiTemp = inl(AC97GCR); -+ outl( (uiTemp | AC97GSR_IFE), AC97GCR ); -+ -+ /* -+ * Set the TIMEDRESET bit. Will cause a > 1uSec reset of the ac-link. -+ * This bit is self resetting. -+ */ -+ outl( AC97RESET_TIMEDRESET, AC97RESET ); -+ -+ /* -+ * Delay briefly, but let's not hog the processor. -+ */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout( 5 ); /* 50 mSec */ -+ -+ /* -+ * Read the AC97 status register to see if we've seen a CODECREADY -+ * signal from the AC97 codec. -+ */ -+ if( !(inl(AC97RGIS) & AC97RGIS_CODECREADY)) -+ { -+ printk( "ep93xx-ac97 - FAIL: CODECREADY still low!\n"); -+ return; -+ } -+ -+ /* -+ * Delay for a second, not hogging the processor -+ */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout( HZ ); /* 1 Sec */ -+ -+ /* -+ * Now the Ac-link is up. We can read and write codec registers. -+ */ -+ ac_link_enabled = 1; -+ -+ /* -+ * Set up the rx and tx channels -+ * Set the CM bit, data size=16 bits, enable tx slots 3 & 4. -+ */ -+ ep93xx_set_hw_format( EP93XX_DEFAULT_FORMAT,EP93XX_DEFAULT_NUM_CHANNELS ); -+ -+ DPRINTK( "ep93xx-ac97 -- AC97RXCR1: %08x\n", inl(AC97RXCR1) ); -+ DPRINTK( "ep93xx-ac97 -- AC97TXCR1: %08x\n", inl(AC97TXCR1) ); -+ -+ DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n"); -+ -+} -+ -+#ifdef alsa_ac97_debug -+static void ep93xx_dump_ac97_regs(void) -+{ -+ int i; -+ unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; -+ -+ DPRINTK( "---------------------------------------------\n"); -+ DPRINTK( " : 0 2 4 6 8 A C E\n" ); -+ -+ for( i=0 ; i < 0x80 ; i+=0x10 ) -+ { -+ reg0 = 0xffff & (unsigned int)peek( i ); -+ reg1 = 0xffff & (unsigned int)peek( i + 0x2 ); -+ reg2 = 0xffff & (unsigned int)peek( i + 0x4 ); -+ reg3 = 0xffff & (unsigned int)peek( i + 0x6 ); -+ reg4 = 0xffff & (unsigned int)peek( i + 0x8 ); -+ reg5 = 0xffff & (unsigned int)peek( i + 0xa ); -+ reg6 = 0xffff & (unsigned int)peek( i + 0xc ); -+ reg7 = 0xffff & (unsigned int)peek( i + 0xe ); -+ -+ DPRINTK( " %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n", -+ i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7); -+ } -+ -+ DPRINTK( "---------------------------------------------\n"); -+} -+#endif -+ -+ -+#define supported_mixer(FOO) \ -+ ( (FOO >= 0) && \ -+ (FOO < SOUND_MIXER_NRDEVICES) && \ -+ codec_supported_mixers & (1<<FOO) ) -+ -+/* -+ * Available record sources. -+ * LINE1 refers to AUX in. -+ * IGAIN refers to input gain which means stereo mix. -+ */ -+#define AC97_RECORD_MASK \ -+ (SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\ -+ SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN) -+ -+#define AC97_STEREO_MASK \ -+ (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \ -+ SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO) -+ -+#define AC97_SUPPORTED_MASK \ -+ (AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \ -+ SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \ -+ SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT) -+ -+ -+ -+ -+/* this table has default mixer values for all OSS mixers. */ -+typedef struct { -+ int mixer; -+ unsigned int value; -+} mixer_defaults_t; -+ -+/* -+ * Default mixer settings that are set up during boot. -+ * -+ * These values are 16 bit numbers in which the upper byte is right volume -+ * and the lower byte is left volume or mono volume for mono controls. -+ * -+ * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64). -+ * -+ */ -+static mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] = -+{ -+ /* Outputs */ -+ {SOUND_MIXER_VOLUME, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */ -+ {SOUND_MIXER_ALTPCM, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */ -+ {SOUND_MIXER_PHONEOUT, 0x6464}, /* 0 dB */ /* -46.5dB to 0 dB */ -+ -+ /* PCM playback gain */ -+ {SOUND_MIXER_PCM, 0x4b4b}, /* 0 dB */ /* -34.5dB to +12dB */ -+ -+ /* Record gain */ -+ {SOUND_MIXER_IGAIN, 0x0000}, /* 0 dB */ /* -34.5dB to +12dB */ -+ -+ /* Inputs */ -+ {SOUND_MIXER_MIC, 0x0000}, /* mute */ /* -34.5dB to +12dB */ -+ {SOUND_MIXER_LINE, 0x4b4b}, /* 0 dB */ /* -34.5dB to +12dB */ -+ -+ /* Inputs that are not connected. */ -+ {SOUND_MIXER_SPEAKER, 0x0000}, /* mute */ /* -45dB to 0dB */ -+ {SOUND_MIXER_PHONEIN, 0x0000}, /* mute */ /* -34.5dB to +12dB */ -+ {SOUND_MIXER_CD, 0x0000}, /* mute */ /* -34.5dB to +12dB */ -+ {SOUND_MIXER_VIDEO, 0x0000}, /* mute */ /* -34.5dB to +12dB */ -+ {SOUND_MIXER_LINE1, 0x0000}, /* mute */ /* -34.5dB to +12dB */ -+ -+ {-1,0} /* last entry */ -+}; -+ -+/* table to scale scale from OSS mixer value to AC97 mixer register value */ -+typedef struct { -+ unsigned int offset; -+ int scale; -+} ac97_mixer_hw_t; -+ -+static ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] = -+{ -+ [SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64}, -+ [SOUND_MIXER_BASS] = {0, 0}, -+ [SOUND_MIXER_TREBLE] = {0, 0}, -+ [SOUND_MIXER_SYNTH] = {0, 0}, -+ [SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32}, -+ [SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32}, -+ [SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32}, -+ [SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32}, -+ [SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32}, -+ [SOUND_MIXER_IMIX] = {0, 0}, -+ [SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64}, -+ [SOUND_MIXER_RECLEV] = {0, 0}, -+ [SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16}, -+ [SOUND_MIXER_OGAIN] = {0, 0}, -+ [SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32}, -+ [SOUND_MIXER_LINE2] = {0, 0}, -+ [SOUND_MIXER_LINE3] = {0, 0}, -+ [SOUND_MIXER_DIGITAL1] = {0, 0}, -+ [SOUND_MIXER_DIGITAL2] = {0, 0}, -+ [SOUND_MIXER_DIGITAL3] = {0, 0}, -+ [SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32}, -+ [SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64}, -+ [SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32}, -+ [SOUND_MIXER_RADIO] = {0, 0}, -+ [SOUND_MIXER_MONITOR] = {0, 0}, -+}; -+ -+ -+/* the following tables allow us to go from OSS <-> ac97 quickly. */ -+enum ac97_recsettings -+{ -+ AC97_REC_MIC=0, -+ AC97_REC_CD, -+ AC97_REC_VIDEO, -+ AC97_REC_AUX, -+ AC97_REC_LINE, -+ AC97_REC_STEREO, /* combination of all enabled outputs.. */ -+ AC97_REC_MONO, /*.. or the mono equivalent */ -+ AC97_REC_PHONE -+}; -+ -+static const unsigned int ac97_rm2oss[] = -+{ -+ [AC97_REC_MIC] = SOUND_MIXER_MIC, -+ [AC97_REC_CD] = SOUND_MIXER_CD, -+ [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, -+ [AC97_REC_AUX] = SOUND_MIXER_LINE1, -+ [AC97_REC_LINE] = SOUND_MIXER_LINE, -+ [AC97_REC_STEREO]= SOUND_MIXER_IGAIN, -+ [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN -+}; -+ -+/* indexed by bit position */ -+static const unsigned int ac97_oss_rm[] = -+{ -+ [SOUND_MIXER_MIC] = AC97_REC_MIC, -+ [SOUND_MIXER_CD] = AC97_REC_CD, -+ [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO, -+ [SOUND_MIXER_LINE1] = AC97_REC_AUX, -+ [SOUND_MIXER_LINE] = AC97_REC_LINE, -+ [SOUND_MIXER_IGAIN] = AC97_REC_STEREO, -+ [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE -+}; -+ -+ -+/* -+ * ep93xx_write_mixer -+ * -+ */ -+static void ep93xx_write_mixer -+( -+ int oss_channel, -+ unsigned int left, -+ unsigned int right -+) -+{ -+ u16 val = 0; -+ ac97_mixer_hw_t * mh = &ac97_hw[oss_channel]; -+ -+ DPRINTK("ac97_codec: wrote OSS %2d (ac97 0x%02x), " -+ "l:%2d, r:%2d:", -+ oss_channel, mh->offset, left, right); -+ -+ if( !mh->scale ) -+ { -+ printk( "ep93xx-ac97.c: ep93xx_write_mixer - not a valid OSS channel\n"); -+ return; -+ } -+ -+ if( AC97_STEREO_MASK & (1 << oss_channel) ) -+ { -+ /* stereo mixers */ -+ if (left == 0 && right == 0) -+ { -+ val = 0x8000; -+ } -+ else -+ { -+ if (oss_channel == SOUND_MIXER_IGAIN) -+ { -+ right = (right * mh->scale) / 100; -+ left = (left * mh->scale) / 100; -+ if (right >= mh->scale) -+ right = mh->scale-1; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ } -+ else -+ { -+ right = ((100 - right) * mh->scale) / 100; -+ left = ((100 - left) * mh->scale) / 100; -+ if (right >= mh->scale) -+ right = mh->scale-1; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ } -+ val = (left << 8) | right; -+ } -+ } -+ else if(left == 0) -+ { -+ val = 0x8000; -+ } -+ else if( (oss_channel == SOUND_MIXER_SPEAKER) || -+ (oss_channel == SOUND_MIXER_PHONEIN) || -+ (oss_channel == SOUND_MIXER_PHONEOUT) ) -+ { -+ left = ((100 - left) * mh->scale) / 100; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ val = left; -+ } -+ else if (oss_channel == SOUND_MIXER_MIC) -+ { -+ val = peek( mh->offset) & ~0x801f; -+ left = ((100 - left) * mh->scale) / 100; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ val |= left; -+ } -+ /* -+ * For bass and treble, the low bit is optional. Masking it -+ * lets us avoid the 0xf 'bypass'. -+ * Do a read, modify, write as we have two contols in one reg. -+ */ -+ else if (oss_channel == SOUND_MIXER_BASS) -+ { -+ val = peek( mh->offset) & ~0x0f00; -+ left = ((100 - left) * mh->scale) / 100; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ val |= (left << 8) & 0x0e00; -+ } -+ else if (oss_channel == SOUND_MIXER_TREBLE) -+ { -+ val = peek( mh->offset) & ~0x000f; -+ left = ((100 - left) * mh->scale) / 100; -+ if (left >= mh->scale) -+ left = mh->scale-1; -+ val |= left & 0x000e; -+ } -+ -+ DPRINTK(" 0x%04x", val); -+ -+ poke( mh->offset, val ); -+ -+#ifdef alsa_ac97_debug -+ val = peek( mh->offset ); -+ DEBUG(" -> 0x%04x\n", val); -+#endif -+ -+} -+ -+/* a thin wrapper for write_mixer */ -+static void ep93xx_set_mixer -+( -+ unsigned int oss_mixer, -+ unsigned int val -+) -+{ -+ unsigned int left,right; -+ -+ /* cleanse input a little */ -+ right = ((val >> 8) & 0xff) ; -+ left = (val & 0xff) ; -+ -+ if (right > 100) right = 100; -+ if (left > 100) left = 100; -+ -+ /*mixer_state[oss_mixer] = (right << 8) | left;*/ -+ ep93xx_write_mixer( oss_mixer, left, right); -+} -+ -+static void ep93xx_init_mixer(void) -+{ -+ u16 cap; -+ int i; -+ -+ /* mixer masks */ -+ codec_supported_mixers = AC97_SUPPORTED_MASK; -+ -+ cap = peek( AC97_00_RESET ); -+ if( !(cap & 0x04) ) -+ { -+ codec_supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE); -+ } -+ if( !(cap & 0x10) ) -+ { -+ codec_supported_mixers &= ~SOUND_MASK_ALTPCM; -+ } -+ -+ /* -+ * Detect bit resolution of output volume controls by writing to the -+ * 6th bit (not unmuting yet) -+ */ -+ poke( AC97_02_MASTER_VOL, 0xa020 ); -+ if( peek( AC97_02_MASTER_VOL) != 0xa020 ) -+ { -+ ac97_hw[SOUND_MIXER_VOLUME].scale = 32; -+ } -+ -+ poke( AC97_04_HEADPHONE_VOL, 0xa020 ); -+ if( peek( AC97_04_HEADPHONE_VOL) != 0xa020 ) -+ { -+ ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32; -+ } -+ -+ poke( AC97_06_MONO_VOL, 0x8020 ); -+ if( peek( AC97_06_MONO_VOL) != 0x8020 ) -+ { -+ ac97_hw[AC97_06_MONO_VOL].scale = 32; -+ } -+ -+ /* initialize mixer channel volumes */ -+ for( i = 0; -+ (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1) ; -+ i++ ) -+ { -+ if( !supported_mixer( mixer_defaults[i].mixer) ) -+ { -+ continue; -+ } -+ -+ ep93xx_set_mixer( mixer_defaults[i].mixer, mixer_defaults[i].value); -+ } -+ -+} -+ -+static int ep93xx_set_recsource( int mask ) -+{ -+ unsigned int val; -+ -+ /* Arg contains a bit for each recording source */ -+ if( mask == 0 ) -+ { -+ return 0; -+ } -+ -+ mask &= AC97_RECORD_MASK; -+ -+ if( mask == 0 ) -+ { -+ return -EINVAL; -+ } -+ -+ /* -+ * May have more than one bit set. So clear out currently selected -+ * record source value first (AC97 supports only 1 input) -+ */ -+ val = (1 << ac97_rm2oss[peek( AC97_1A_RECORD_SELECT ) & 0x07]); -+ if (mask != val) -+ mask &= ~val; -+ -+ val = ffs(mask); -+ val = ac97_oss_rm[val-1]; -+ val |= val << 8; /* set both channels */ -+ -+ /* -+ * -+ */ -+ val = peek( AC97_1A_RECORD_SELECT ) & 0x0707; -+ if ((val&0x0404)!=0) -+ val=0x0404; -+ else if((val&0x0000)!=0) -+ val=0x0101; -+ -+ -+ DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val); -+ -+ poke( AC97_1A_RECORD_SELECT, val); -+ -+ return 0; -+} -+ -+/* -+ * ep93xx_init_ac97_codec -+ * -+ * Program up the external Ac97 codec. -+ * -+ */ -+static void ep93xx_init_ac97_codec( void ) -+{ -+ DPRINTK("ep93xx_init_ac97_codec - enter\n"); -+ -+ ep93xx_setup_src(); -+ ep93xx_set_samplerate( AUDIO_SAMPLE_RATE_DEFAULT, 0 ); -+ ep93xx_set_samplerate( AUDIO_SAMPLE_RATE_DEFAULT, 1 ); -+ ep93xx_init_mixer(); -+ -+ DPRINTK("ep93xx_init_ac97_codec - EXIT\n"); -+ -+} -+ -+ -+/* -+ * ep93xx_audio_init -+ * Audio interface -+ */ -+static void ep93xx_audio_init(void) -+{ -+ DPRINTK("ep93xx_audio_init - enter\n"); -+ /* -+ * Init the controller, enable the ac-link. -+ * Initialize the codec. -+ */ -+ ep93xx_init_ac97_controller(); -+ ep93xx_init_ac97_codec(); -+ /*stop the audio loop from the input to the output directly*/ -+ ep93xx_stop_loop(); -+ -+#ifdef alsa_ac97_debug -+ ep93xx_dump_ac97_regs(); -+#endif -+ DPRINTK("ep93xx_audio_init - EXIT\n"); -+} -+ -+/*====================================================================================*/ -+ -+ -+static void print_audio_format( long format ) -+{ -+ switch( format ){ -+ case SNDRV_PCM_FORMAT_S8: -+ DPRINTK( "AFMT_S8\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ DPRINTK( "AFMT_U8\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ DPRINTK( "AFMT_S16_LE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_BE: -+ DPRINTK( "AFMT_S16_BE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ DPRINTK( "AFMT_U16_LE\n" ); -+ break; -+ case SNDRV_PCM_FORMAT_U16_BE: -+ DPRINTK( "AFMT_U16_BE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ DPRINTK( "AFMT_S24_LE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_BE: -+ DPRINTK( "AFMT_S24_BE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ DPRINTK( "AFMT_U24_LE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U24_BE: -+ DPRINTK( "AFMT_U24_BE\n" ); -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ DPRINTK( "AFMT_S24_LE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S32_BE: -+ DPRINTK( "AFMT_S24_BE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U32_LE: -+ DPRINTK( "AFMT_U24_LE\n" ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U32_BE: -+ DPRINTK( "AFMT_U24_BE\n" ); -+ break; -+ default: -+ DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" ); -+ break; -+ } -+} -+ -+static void audio_set_format( audio_stream_t * s, long val ) -+{ -+ DPRINTK( "ep93xx_i2s_audio_set_format enter. Format requested (%d) %d ", -+ (int)val,SNDRV_PCM_FORMAT_S16_LE); -+ print_audio_format( val ); -+ -+ switch( val ){ -+ case SNDRV_PCM_FORMAT_S8: -+ s->audio_format = SNDRV_PCM_FORMAT_S8; -+ s->audio_stream_bitwidth = 8; -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ s->audio_format = SNDRV_PCM_FORMAT_U8; -+ s->audio_stream_bitwidth = 8; -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ case SNDRV_PCM_FORMAT_S16_BE: -+ s->audio_format = SNDRV_PCM_FORMAT_S16_LE; -+ s->audio_stream_bitwidth = 16; -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ case SNDRV_PCM_FORMAT_U16_BE: -+ s->audio_format = SNDRV_PCM_FORMAT_U16_LE; -+ s->audio_stream_bitwidth = 16; -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ case SNDRV_PCM_FORMAT_S24_BE: -+ s->audio_format = SNDRV_PCM_FORMAT_S24_LE; -+ s->audio_stream_bitwidth = 24; -+ break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ case SNDRV_PCM_FORMAT_U24_BE: -+ s->audio_format = SNDRV_PCM_FORMAT_U24_LE; -+ s->audio_stream_bitwidth = 24; -+ break; -+ -+ case SNDRV_PCM_FORMAT_U32_LE: -+ case SNDRV_PCM_FORMAT_U32_BE: -+ case SNDRV_PCM_FORMAT_S32_LE: -+ case SNDRV_PCM_FORMAT_S32_BE: -+ s->audio_format = SNDRV_PCM_FORMAT_S32_LE; -+ s->audio_stream_bitwidth = 32; -+ break; -+ default: -+ DPRINTK( "ep93xx_i2s_Unsupported Audio Format\n" ); -+ break; -+ } -+ -+ DPRINTK( "ep93xx_i2s_audio_set_format EXIT format set to be (%d) ", (int)s->audio_format ); -+ print_audio_format( (long)s->audio_format ); -+} -+ -+static __inline__ unsigned long copy_to_user_S24_LE -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ -+ int total_to_count = to_count; -+ int *user_ptr = (int *)to; /* 32 bit user buffer */ -+ int count; -+ -+ count = 8 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ -+ __put_user( (int)( *dma_buffer_0++ ), user_ptr++ ); -+ __put_user( (int)( *dma_buffer_0++ ), user_ptr++ ); -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (int)( *dma_buffer_1++ ), user_ptr++ ); -+ __put_user( (int)( *dma_buffer_1++ ), user_ptr++ ); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (int)( *dma_buffer_2++ ), user_ptr++ ); -+ __put_user( (int)( *dma_buffer_2++ ), user_ptr++ ); -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U24_LE -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ -+ int total_to_count = to_count; -+ unsigned int * user_ptr = (unsigned int *)to; /* 32 bit user buffer */ -+ int count; -+ -+ count = 8 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned int)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned int)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned int)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_S16_LE -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int total_to_count = to_count; -+ short * user_ptr = (short *)to; /* 16 bit user buffer */ -+ int count; -+ -+ count = 4 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ -+ __put_user( (short)( *dma_buffer_0++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_0++ ), user_ptr++ ); -+ -+ if( stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (short)( *dma_buffer_1++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_1++ ), user_ptr++ ); -+ } -+ -+ if( stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (short)( *dma_buffer_2++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_2++ ), user_ptr++ ); -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U16_LE -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ short * user_ptr = (short *)to; /* 16 bit user buffer */ -+ -+ count = 4 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ -+ __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_S8 -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ char * user_ptr = (char *)to; /* 8 bit user buffer */ -+ -+ count = 2 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (to_count > 0){ -+ -+ __put_user( (char)( *dma_buffer_0 ), user_ptr++ ); -+ dma_buffer_0 += 4; -+ __put_user( (char)( *dma_buffer_0 ), user_ptr++ ); -+ dma_buffer_0 += 4; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (char)( *dma_buffer_1 ), user_ptr++ ); -+ dma_buffer_1 += 4; -+ __put_user( (char)( *dma_buffer_1 ), user_ptr++ ); -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (char)( *dma_buffer_2 ), user_ptr++ ); -+ dma_buffer_2 += 4; -+ __put_user( (char)( *dma_buffer_2 ), user_ptr++ ); -+ dma_buffer_2 += 4; -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U8 -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ char * user_ptr = (char *)to; /* 8 bit user buffer */ -+ -+ count = 2 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (to_count > 0){ -+ -+ __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_0 += 4; -+ __put_user( (char)( *dma_buffer_0 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_0 += 4; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_1 += 4; -+ __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_2 += 4; -+ __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_2 += 4; -+ } -+ to_count -= count; -+ } -+ return total_to_count; -+} -+ -+ -+ -+ -+static __inline__ unsigned long copy_to_user_S16_LE_CM -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ short *dma_buffer_0 = (short *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int total_to_count = to_count; -+ short * user_ptr = (short *)to; /* 16 bit user buffer */ -+ int count; -+ -+ -+ count = 4 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ if(stream->audio_num_channels == 2){ -+ __put_user( (short)( *dma_buffer_0++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_0++ ), user_ptr++ ); -+ to_count -= count; -+ } -+ else{ -+ dma_buffer_0++; -+ __put_user( (short)( *dma_buffer_0++ ), user_ptr++ ); -+ to_count -= 2; -+ } -+ -+ if( stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (short)( *dma_buffer_1++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_1++ ), user_ptr++ ); -+ } -+ -+ if( stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (short)( *dma_buffer_2++ ), user_ptr++ ); -+ __put_user( (short)( *dma_buffer_2++ ), user_ptr++ ); -+ } -+ //to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U16_LE_CM -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ unsigned short * user_ptr = (unsigned short *)to; /* 16 bit user buffer */ -+ -+ count = 4 * stream->dma_num_channels; -+ -+ while (to_count > 0){ -+ -+ if(stream->audio_num_channels == 2){ -+ __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ to_count -= count; -+ } -+ else{ -+ dma_buffer_0++; -+ __put_user( ((unsigned short)( *dma_buffer_0++ )) ^ 0x8000, user_ptr++ ); -+ to_count -= 2; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_1++ )) ^ 0x8000, user_ptr++ ); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ __put_user( ((unsigned short)( *dma_buffer_2++ )) ^ 0x8000, user_ptr++ ); -+ } -+ //to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_S8_CM -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ char * user_ptr = (char *)to; /* 8 bit user buffer */ -+ -+ count = 2 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (to_count > 0){ -+ if(stream->audio_num_channels == 2){ -+ __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ ); -+ //dma_buffer_0 += 4; -+ __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ ); -+ //dma_buffer_0 += 4; -+ to_count -= count; -+ } -+ else{ -+ dma_buffer_0++ ; -+ __put_user( (char)( *dma_buffer_0++ >> 8), user_ptr++ ); -+ -+ to_count -= 1; -+ } -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (char)( *dma_buffer_1 ), user_ptr++ ); -+ dma_buffer_1 += 4; -+ __put_user( (char)( *dma_buffer_1 ), user_ptr++ ); -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (char)( *dma_buffer_2 ), user_ptr++ ); -+ dma_buffer_2 += 4; -+ __put_user( (char)( *dma_buffer_2 ), user_ptr++ ); -+ dma_buffer_2 += 4; -+ } -+ //to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U8_CM -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ unsigned short *dma_buffer_0 = (unsigned short *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ int total_to_count = to_count; -+ char * user_ptr = (char *)to; /* 8 bit user buffer */ -+ -+ count = 2 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (to_count > 0){ -+ if(stream->audio_num_channels == 2){ -+ __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ ); -+ //dma_buffer_0 += 4; -+ __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ ); -+ //dma_buffer_0 += 4; -+ to_count -= count; -+ } -+ else{ -+ dma_buffer_0++; -+ __put_user( (char)( *dma_buffer_0++ >>8) ^ 0x80, user_ptr++ ); -+ //dma_buffer_0 += 4; -+ to_count--; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_1 += 4; -+ __put_user( (char)( *dma_buffer_1 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_2 += 4; -+ __put_user( (char)( *dma_buffer_2 ) ^ 0x80, user_ptr++ ); -+ dma_buffer_2 += 4; -+ } -+ //to_count -= count; -+ } -+ return total_to_count; -+} -+ -+static __inline__ unsigned long copy_to_user_U32 -+( -+ audio_stream_t *stream, -+ const char *to, -+ unsigned long to_count -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ -+ if(__copy_to_user( (char *)to, dma_buffer_0, to_count)) -+ { -+ return -EFAULT; -+ } -+ return to_count; -+} -+ -+static __inline__ int copy_to_user_with_conversion -+( -+ audio_stream_t *stream, -+ const char *to, -+ int toCount, -+ int bCompactMode -+) -+{ -+ int ret = 0; -+ -+ if( toCount == 0 ){ -+ DPRINTK("ep93xx_i2s_copy_to_user_with_conversion - nothing to copy!\n"); -+ } -+ -+ if( bCompactMode == 1 ){ -+ -+ switch( stream->audio_format ){ -+ -+ case SNDRV_PCM_FORMAT_S8: -+ ret = copy_to_user_S8_CM( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ ret = copy_to_user_U8_CM( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ ret = copy_to_user_S16_LE_CM( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ ret = copy_to_user_U16_LE_CM( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ //ret = copy_to_user_S24_LE( stream, to, toCount ); -+ //break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ //ret = copy_to_user_U24_LE( stream, to, toCount ); -+ //break; -+ -+ case SNDRV_PCM_FORMAT_S32_LE: -+ default: -+ DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format ); -+ break; -+ } -+ -+ } -+ else{ -+ -+ switch( stream->audio_format ){ -+ -+ case SNDRV_PCM_FORMAT_S8: -+ ret = copy_to_user_S8( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ ret = copy_to_user_U8( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ ret = copy_to_user_S16_LE( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ ret = copy_to_user_U16_LE( stream, to, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ //ret = copy_to_user_S24_LE( stream, to, toCount ); -+ //break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ //ret = copy_to_user_U24_LE( stream, to, toCount ); -+ //break; -+ DPRINTK( "ep93xx_i2s copy to user unsupported audio format %x\n",stream->audio_format ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S32_LE: -+ -+ //__copy_to_user( (char *)to, from, toCount); -+ ret = copy_to_user_U32( stream, to, toCount ); -+ break; -+ default: -+ DPRINTK( "ep93xx_i2s copy to user unsupported audio format\n" ); -+ break; -+ } -+ -+ } -+ return ret; -+} -+ -+static __inline__ int copy_from_user_S24_LE -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ -+ unsigned int * user_buffer = (unsigned int *)from; -+ unsigned int data; -+ -+ int toCount0 = toCount; -+ count = 8 * stream->dma_num_channels; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = (unsigned int)data; -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = (unsigned int)data; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = (unsigned int)data; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = (unsigned int)data; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = (unsigned int)data; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = (unsigned int)data; -+ } -+ toCount -= count; -+ } -+ return toCount0 / 2; -+} -+ -+static __inline__ int copy_from_user_U24_LE -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ unsigned int * user_buffer = (unsigned int *)from; -+ unsigned int data; -+ -+ int toCount0 = toCount; -+ count = 8 * stream->dma_num_channels; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ } -+ toCount -= count; -+ } -+ return toCount0 / 2; -+} -+ -+static __inline__ int copy_from_user_S16_LE -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ unsigned short *user_buffer = (unsigned short *)from; -+ unsigned short data; -+ -+ int toCount0 = toCount; -+ int count; -+ count = 8 * stream->dma_num_channels; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = data; -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0++ = data; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = data; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = data; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = data; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = data; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 4; -+ } -+ return toCount0 / 2; -+} -+ -+static __inline__ int copy_from_user_U16_LE -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ unsigned short * user_buffer = (unsigned short *)from; -+ unsigned short data; -+ -+ int toCount0 = toCount; -+ count = 8 * stream->dma_num_channels; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 4; -+ } -+ return toCount0 / 2; -+} -+ -+static __inline__ int copy_from_user_S8 -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ unsigned char * user_buffer = (unsigned char *)from; -+ unsigned char data; -+ -+ int toCount0 = toCount; -+ count = 8 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (toCount > 0){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0 = data; -+ dma_buffer_0 += 4; -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0 = data; -+ dma_buffer_0 += 4; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = data; -+ dma_buffer_1 += 4; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = data; -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = data; -+ dma_buffer_2 += 4; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = data; -+ dma_buffer_2 += 4; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 8; -+ } -+ return toCount0 / 4; -+} -+ -+static __inline__ int copy_from_user_U8 -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ unsigned char *user_buffer = (unsigned char *)from; -+ unsigned char data; -+ -+ int toCount0 = toCount; -+ count = 8 * stream->dma_num_channels; -+ -+ dma_buffer_0 ++; -+ dma_buffer_1 ++; -+ dma_buffer_2 ++; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0 = ((unsigned char)data ^ 0x80); -+ dma_buffer_0 += 4; -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0 = ((unsigned char)data ^ 0x80); -+ dma_buffer_0 += 4; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = ((unsigned char)data ^ 0x80); -+ dma_buffer_1 += 4; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = ((unsigned char)data ^ 0x80); -+ dma_buffer_1 += 4; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = ((unsigned char)data ^ 0x80); -+ dma_buffer_2 += 4; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = ((unsigned char)data ^ 0x80); -+ dma_buffer_2 += 4; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 8; -+ } -+ return toCount0 / 4; -+} -+ -+static __inline__ int copy_from_user_S16_LE_CM -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ unsigned int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ unsigned int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ unsigned int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ unsigned short *user_buffer = (unsigned short *)from; -+ short data; -+ unsigned int val; -+ int toCount0 = toCount; -+ int count; -+ count = 4 * stream->dma_num_channels; -+ -+ //printk("count=%x tocount\n",count,toCount); -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_0++ = data; -+ val = (unsigned int)data & 0x0000ffff; -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0++ = ((unsigned int)data << 16) | val; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_1++ = data; -+ val = (unsigned int)data & 0x0000ffff; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1++ = ((unsigned int)data << 16) | val; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_2++ = data; -+ val = (unsigned int)data & 0x0000ffff; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2++ = ((unsigned int)data << 16) | val; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 /2 ; -+ } -+ -+ return toCount0 ; -+} -+ -+static __inline__ int copy_from_user_U16_LE_CM -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ int *dma_buffer_0 = (int *)stream->hwbuf[0]; -+ int *dma_buffer_1 = (int *)stream->hwbuf[1]; -+ int *dma_buffer_2 = (int *)stream->hwbuf[2]; -+ int count; -+ unsigned short * user_buffer = (unsigned short *)from; -+ unsigned short data; -+ unsigned int val; -+ int toCount0 = toCount; -+ count = 4 * stream->dma_num_channels; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ val = (unsigned int)data & 0x0000ffff; -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ //*dma_buffer_0++ = ((unsigned int)data ^ 0x8000); -+ *dma_buffer_0++ = (((unsigned int)data << 16) | val) ^ 0x80008000; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ val = (unsigned int)data & 0x0000ffff; -+ __get_user(data, user_buffer++); -+ //*dma_buffer_1++ = ((unsigned int)data ^ 0x8000); -+ *dma_buffer_1++ = (((unsigned int)data << 16) | val) ^ 0x80008000; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ val = (unsigned int)data & 0x0000ffff; -+ __get_user(data, user_buffer++); -+ //*dma_buffer_2++ = ((unsigned int)data ^ 0x8000); -+ *dma_buffer_2++ = (((unsigned int)data << 16) | val) ^ 0x80008000; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0/2; -+ } -+ return toCount0 ; -+} -+ -+static __inline__ int copy_from_user_S8_CM -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ char *dma_buffer_1 = (char *)stream->hwbuf[1]; -+ char *dma_buffer_2 = (char *)stream->hwbuf[2]; -+ int count; -+ unsigned char * user_buffer = (unsigned char *)from; -+ unsigned char data; -+ int toCount0 = toCount; -+ count = 4 * stream->dma_num_channels; -+ -+ dma_buffer_0++; -+ dma_buffer_1++; -+ dma_buffer_2++; -+ -+ while (toCount > 0){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0 = data; -+ *(dma_buffer_0 +1 ) = 0; -+ dma_buffer_0 += 2; -+ -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0 = data; -+ *(dma_buffer_0 +1 ) = 0; -+ dma_buffer_0 += 2; -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = data; -+ dma_buffer_1 += 2; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = data; -+ dma_buffer_1 += 2; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = data; -+ dma_buffer_2 += 2; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = data; -+ dma_buffer_2 += 2; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 4; -+ } -+ -+ return toCount0 / 2; -+} -+ -+static __inline__ int copy_from_user_U8_CM -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ unsigned char *dma_buffer_0 = (unsigned char *)stream->hwbuf[0]; -+ unsigned char *dma_buffer_1 = (unsigned char *)stream->hwbuf[1]; -+ unsigned char *dma_buffer_2 = (unsigned char *)stream->hwbuf[2]; -+ int count; -+ unsigned char *user_buffer = (unsigned char *)from; -+ unsigned char data; -+ -+ int toCount0 = toCount; -+ count = 4 * stream->dma_num_channels; -+ -+ dma_buffer_0 ++; -+ dma_buffer_1 ++; -+ dma_buffer_2 ++; -+ -+ while (toCount > 0){ -+ -+ __get_user(data, user_buffer++); -+ *dma_buffer_0 = ((unsigned char)data ^ 0x80); -+ *(dma_buffer_0 +1 ) = 0; -+ dma_buffer_0 += 2; -+ -+ if(stream->audio_num_channels == 2){ -+ __get_user(data, user_buffer++); -+ } -+ *dma_buffer_0 = ((unsigned char)data ^ 0x80); -+ *(dma_buffer_0 +1 ) = 0; -+ dma_buffer_0 += 2; -+ -+ -+ if(stream->audio_channels_flag & CHANNEL_REAR ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = ((unsigned char)data ^ 0x80); -+ dma_buffer_1 += 2; -+ __get_user(data, user_buffer++); -+ *dma_buffer_1 = ((unsigned char)data ^ 0x80); -+ dma_buffer_1 += 2; -+ } -+ -+ if(stream->audio_channels_flag & CHANNEL_CENTER_LFE ){ -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = ((unsigned char)data ^ 0x80); -+ dma_buffer_2 += 2; -+ __get_user(data, user_buffer++); -+ *dma_buffer_2 = ((unsigned char)data ^ 0x80); -+ dma_buffer_2 += 2; -+ } -+ toCount -= count; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ return toCount0 / 4; -+ } -+ -+ return toCount0 / 2; -+} -+ -+static int copy_from_user_U32 -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount -+) -+{ -+ char *dma_buffer_0 = (char *)stream->hwbuf[0]; -+ -+ if (copy_from_user( (char *)dma_buffer_0, from, toCount)) -+ { -+ return -EFAULT; -+ } -+ -+ return toCount; -+ -+} -+ -+/* -+ * Returns negative for error -+ * Returns # of bytes transferred out of the from buffer -+ * for success. -+ */ -+static __inline__ int copy_from_user_with_conversion -+( -+ audio_stream_t *stream, -+ const char *from, -+ int toCount, -+ int bCompactMode -+) -+{ -+ int ret = 0; -+// DPRINTK("copy_from_user_with_conversion\n"); -+ if( toCount == 0 ){ -+ DPRINTK("ep93xx_i2s_copy_from_user_with_conversion - nothing to copy!\n"); -+ } -+ -+ if( bCompactMode == 1){ -+ -+ switch( stream->audio_format ){ -+ -+ case SNDRV_PCM_FORMAT_S8: -+ DPRINTK("SNDRV_PCM_FORMAT_S8 CM\n"); -+ ret = copy_from_user_S8_CM( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ DPRINTK("SNDRV_PCM_FORMAT_U8 CM\n"); -+ ret = copy_from_user_U8_CM( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S16_LE CM\n"); -+ ret = copy_from_user_S16_LE_CM( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_U16_LE CM\n"); -+ ret = copy_from_user_U16_LE_CM( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S24_LE CM\n"); -+ //ret = copy_from_user_S24_LE( stream, from, toCount ); -+ //break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_U24_LE CM\n"); -+ //ret = copy_from_user_U24_LE( stream, from, toCount ); -+ //break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S32_LE CM\n"); -+ //break; -+ default: -+ DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" ); -+ break; -+ } -+ } -+ else{ -+ switch( stream->audio_format ){ -+ -+ case SNDRV_PCM_FORMAT_S8: -+ DPRINTK("SNDRV_PCM_FORMAT_S8\n"); -+ ret = copy_from_user_S8( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U8: -+ DPRINTK("SNDRV_PCM_FORMAT_U8\n"); -+ ret = copy_from_user_U8( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S16_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S16_LE\n"); -+ ret = copy_from_user_S16_LE( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_U16_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_U16_LE\n"); -+ ret = copy_from_user_U16_LE( stream, from, toCount ); -+ break; -+ -+ case SNDRV_PCM_FORMAT_S24_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S24_LE\n"); -+ //ret = copy_from_user_S24_LE( stream, from, toCount ); -+ //break; -+ -+ case SNDRV_PCM_FORMAT_U24_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_U24_LE\n"); -+ //ret = copy_from_user_U24_LE( stream, from, toCount ); -+ //break; -+ DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" ); -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ DPRINTK("SNDRV_PCM_FORMAT_S32_LE\n"); -+ ret = copy_from_user_U32( stream, from, toCount ); -+ break; -+ default: -+ DPRINTK( "ep93xx_i2s copy from user unsupported audio format\n" ); -+ break; -+ } -+ } -+ -+ return ret; -+} -+ -+ -+ -+/* -+ * For audio playback, we convert samples of arbitrary format to be 32 bit -+ * for our hardware. We're scaling a user buffer to a dma buffer. So when -+ * report byte counts, we scale them acording to the ratio of DMA sample -+ * size to user buffer sample size. When we report # of DMA fragments, -+ * we don't scale that. So: -+ * -+ * Also adjust the size and number of dma fragments if sample size changed. -+ * -+ * Input format Input sample Output sample size ratio (out:in) -+ * bits channels size (bytes) CM non-CM CM non-CM -+ * 8 stereo 2 4 8 2:1 4:1 -+ * 16 stereo 4 4 8 1:1 2:1 -+ * 24 stereo 6 4 8 X 8:6 not a real case -+ * -+ */ -+static void snd_ep93xx_dma2usr_ratio( audio_stream_t * stream,int bCompactMode ) -+{ -+ unsigned int dma_sample_size, user_sample_size; -+ -+ if(bCompactMode == 1){ -+ dma_sample_size = 4; /* each stereo sample is 2 * 32 bits */ -+ } -+ else{ -+ dma_sample_size = 8; -+ } -+ -+ // If stereo 16 bit, user sample is 4 bytes. -+ // If stereo 8 bit, user sample is 2 bytes. -+ if(stream->audio_num_channels == 1){ -+ user_sample_size = stream->audio_stream_bitwidth / 8; -+ } -+ else{ -+ user_sample_size = stream->audio_stream_bitwidth / 4; -+ } -+ -+ stream->dma2usr_ratio = dma_sample_size / user_sample_size; -+} -+ -+/*---------------------------------------------------------------------------------------------*/ -+ -+static int snd_ep93xx_dma_free(struct snd_pcm_substream *substream ){ -+ -+ -+ audio_state_t *state = substream->private_data; -+ audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_stream:state->input_stream; -+ int i; -+ -+ -+ DPRINTK("snd_ep93xx_dma_free - enter\n"); -+ for( i = 0 ; i < stream->dma_num_channels ;i++ ){ -+ ep93xx_dma_free( stream->dmahandles[i] ); -+ } -+ DPRINTK("snd_ep93xx_dma_free - exit\n"); -+ return 0; -+} -+ -+static int snd_ep93xx_dma_config(struct snd_pcm_substream *substream ){ -+ -+ audio_state_t *state = substream->private_data; -+ audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_stream:state->input_stream; -+ int i,err = 0; -+ -+ DPRINTK("snd_ep93xx_dma_config - enter\n"); -+ -+ for( i = 0 ; i < stream->dma_num_channels ;i++ ){ -+ -+ err = ep93xx_dma_request(&stream->dmahandles[i], -+ stream->devicename, -+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_dma[i]:state->input_dma[i] ); -+ if (err){ -+ printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n"); -+ return err; -+ } -+ err = ep93xx_dma_config( stream->dmahandles[i], -+ IGNORE_CHANNEL_ERROR, -+ 0, -+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ snd_ep93xx_dma_tx_callback:snd_ep93xx_dma_rx_callback, -+ (unsigned int)substream ); -+ if (err){ -+ printk("snd_ep93xx_dma_config - exit ERROR dma request failed\n"); -+ return err; -+ } -+ } -+ -+ DPRINTK("snd_ep93xx_dma_config - enter\n"); -+ return err; -+} -+ -+static void snd_ep93xx_dma_start( audio_state_t * state, audio_stream_t * stream ) -+{ -+ int err,i; -+ -+ DPRINTK("snd_ep93xx_dma_start - enter\n"); -+ -+ for(i = 0 ;i < stream->dma_num_channels;i++) -+ err = ep93xx_dma_start( stream->dmahandles[i], 1,(unsigned int *) stream->dmahandles ); -+ -+ stream->active = 1; -+ -+ DPRINTK("snd_ep93xx_dma_start - exit\n"); -+} -+ -+static void snd_ep93xx_dma_pause( audio_state_t * state, audio_stream_t * stream ) -+{ -+ int i; -+ -+ DPRINTK("snd_ep93xx_dma_pause - enter\n"); -+ -+ for(i = 0 ;i < stream->dma_num_channels;i++) -+ ep93xx_dma_pause( stream->dmahandles[i], 1,(unsigned int *)stream->dmahandles ); -+ -+ stream->active = 0; -+ DPRINTK("snd_ep93xx_dma_pause - exit\n"); -+ -+} -+ -+static void snd_ep93xx_dma_flush( audio_state_t * state, audio_stream_t * stream ){ -+ -+ int i; -+ -+ DPRINTK("snd_ep93xx_dma_flush - enter\n"); -+ -+ for( i = 0 ; i < stream->dma_num_channels ; i++ ) -+ ep93xx_dma_flush( stream->dmahandles[i] ); -+ -+ DPRINTK("snd_ep93xx_dma_flush - exit\n"); -+} -+ -+static void snd_ep93xx_deallocate_buffers( struct snd_pcm_substream *substream, audio_stream_t *stream ) -+{ -+ int i; -+ audio_channel_t *dma_chan; -+ -+ DPRINTK("snd_ep93xx_deallocate_buffers - enter\n"); -+ -+ if( stream->dma_channels ){ -+ -+ for(i = 0;i < stream->dma_num_channels;i++){ -+ -+ dma_chan = &stream->dma_channels[i]; -+ -+ if( dma_chan->area ){ -+ -+ if( dma_chan->audio_buffers ){ -+ -+ kfree(dma_chan->audio_buffers); -+ dma_chan->audio_buffers = NULL; -+ -+ } -+ -+ kfree(dma_chan->area); -+ dma_chan->area = NULL; -+ } -+ } -+ kfree(stream->dma_channels); -+ stream->dma_channels = NULL; -+ } -+ DPRINTK("snd_ep93xx_deallocate_buffers - exit\n"); -+} -+ -+static int snd_ep93xx_allocate_buffers(struct snd_pcm_substream *substream, audio_stream_t *stream) -+{ -+ audio_channel_t *channel; -+ unsigned int size,tmpsize,bufsize,bufextsize; -+ int i,j; -+ -+ -+ DPRINTK("snd_ep93xx_allocate_buffers - enter\n" ); -+ -+ if (stream->dma_channels){ -+ printk("ep93xx_i2s %s BUSY\n",__FUNCTION__); -+ return -EBUSY; -+ } -+ -+ stream->dma_channels = (audio_channel_t *)kmalloc(sizeof(audio_channel_t) * stream->dma_num_channels , GFP_KERNEL); -+ -+ if (!stream->dma_channels){ -+ printk(AUDIO_NAME ": unable to allocate dma_channels memory\n"); -+ return - ENOMEM; -+ } -+ -+ size = ( stream->dmasize / stream->dma_num_channels ) * stream->dma2usr_ratio; -+ -+ for( i = 0; i < stream->dma_num_channels;i++){ -+ channel = &stream->dma_channels[i]; -+ -+ channel->area = kmalloc( size, GFP_DMA ); -+ -+ if(!channel->area){ -+ printk(AUDIO_NAME ": unable to allocate audio memory\n"); -+ return -ENOMEM; -+ } -+ channel->bytes = size; -+ channel->addr = __virt_to_phys((int) channel->area); -+ memset( channel->area, 0, channel->bytes ); -+ -+ bufsize = ( stream->fragsize / stream->dma_num_channels ) * stream->dma2usr_ratio; -+ channel->audio_buff_count = size / bufsize; -+ bufextsize = size % bufsize; -+ -+ if( bufextsize > 0 ){ -+ channel->audio_buff_count++; -+ } -+ -+ channel->audio_buffers = (audio_buf_t *)kmalloc(sizeof(audio_buf_t) * channel->audio_buff_count , GFP_KERNEL); -+ -+ if (!channel->audio_buffers){ -+ printk(AUDIO_NAME ": unable to allocate audio memory\n "); -+ return -ENOMEM; -+ } -+ -+ tmpsize = size; -+ -+ for( j = 0; j < channel->audio_buff_count; j++){ -+ -+ channel->audio_buffers[j].dma_addr = channel->addr + j * bufsize; -+ -+ if( tmpsize >= bufsize ){ -+ tmpsize -= bufsize; -+ channel->audio_buffers[j].bytes = bufsize; -+ channel->audio_buffers[j].reportedbytes = bufsize / stream->dma2usr_ratio; -+ } -+ else{ -+ channel->audio_buffers[j].bytes = bufextsize; -+ channel->audio_buffers[j].reportedbytes = bufextsize / stream->dma2usr_ratio; -+ } -+ } -+ } -+ -+ DPRINTK("snd_ep93xx_allocate_buffers -- exit SUCCESS\n" ); -+ return 0; -+} -+ -+/* -+ * DMA callback functions -+ */ -+ -+static void snd_ep93xx_dma_tx_callback -+( -+ ep93xx_dma_int_t DMAInt, -+ ep93xx_dma_dev_t device, -+ unsigned int user_data -+) -+{ -+ int handle; -+ int i,chan; -+ unsigned int buf_id; -+ -+ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data; -+ audio_state_t *state = (audio_state_t *)(substream->private_data); -+ audio_stream_t *stream = state->output_stream; -+ audio_buf_t *buf; -+ -+ switch( device ) -+ { -+ case DMATx_I2S3: -+ DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S3\n"); -+ i = 2; -+ break; -+ case DMATx_I2S2: -+ DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S2\n"); -+ i = 1; -+ break; -+ case DMATx_I2S1: -+ default: -+ DPRINTK( "snd_ep93xx_dma_tx_callback - DMATx_I2S1\n"); -+ i = 0; -+ break; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ chan = 0; -+ } -+ else{ -+ chan = stream->audio_num_channels / 2 - 1; -+ } -+ handle = stream->dmahandles[i]; -+ -+ if(stream->stopped == 0){ -+ -+ if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){ -+ -+ buf = (audio_buf_t *)buf_id; -+ stream->bytecount += buf->reportedbytes; -+ ep93xx_dma_add_buffer( stream->dmahandles[i], -+ (unsigned int)buf->dma_addr, -+ 0, -+ buf->bytes, -+ 0, -+ (unsigned int) buf ); -+ if(chan == i) -+ snd_pcm_period_elapsed(substream); -+ } -+ } -+} -+ -+static void snd_ep93xx_dma_rx_callback -+( -+ ep93xx_dma_int_t DMAInt, -+ ep93xx_dma_dev_t device, -+ unsigned int user_data -+) -+{ -+ int handle,i,chan; -+ unsigned int buf_id; -+ audio_buf_t *buf; -+ -+ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)user_data; -+ audio_state_t *state = (audio_state_t *)(substream->private_data); -+ audio_stream_t *stream = state->input_stream; -+ -+ switch( device ){ -+ -+ case DMARx_I2S3: -+ DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S3\n"); -+ i = 2; -+ break; -+ case DMARx_I2S2: -+ DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S2\n"); -+ i = 1; -+ break; -+ case DMARx_I2S1: -+ default: -+ DPRINTK( "snd_ep93xx_dma_rx_callback - DMARx_I2S1\n"); -+ i = 0; -+ break; -+ } -+ -+ if(stream->audio_num_channels == 1){ -+ chan = 0; -+ } -+ else{ -+ chan = stream->audio_num_channels / 2 - 1; -+ } -+ handle = stream->dmahandles[i]; -+ -+ if( stream->stopped == 0 ){ -+ -+ if( ep93xx_dma_remove_buffer( handle, &buf_id ) >= 0 ){ -+ -+ buf = (audio_buf_t *)buf_id; -+ stream->bytecount += buf->reportedbytes; -+ ep93xx_dma_add_buffer( stream->dmahandles[i], -+ (unsigned int)buf->dma_addr, -+ 0, -+ buf->bytes, -+ 0, -+ (unsigned int) buf ); -+ if( i == chan ) -+ snd_pcm_period_elapsed(substream); -+ } -+ } -+} -+ -+static int snd_ep93xx_release(struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *)substream->private_data; -+ audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_stream : state->input_stream; -+ -+ DPRINTK("snd_ep93xx_release - enter\n"); -+ -+ down(&state->sem); -+ stream->active = 0; -+ stream->stopped = 0; -+ snd_ep93xx_deallocate_buffers(substream, stream); -+ up(&state->sem); -+ -+ DPRINTK("snd_ep93xx_release - exit\n"); -+ -+ return 0; -+} -+ -+static int ep93xx_ac97_pcm_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ int r; -+ int iTempMasterVol,iTempHeadphoneVol,iTempMonoVol,iTempRecordSelect; -+ /*save the old mixer*/ -+ iTempRecordSelect = peek(AC97_1A_RECORD_SELECT); -+ iTempMasterVol = peek( AC97_02_MASTER_VOL); -+ iTempHeadphoneVol = peek( AC97_04_HEADPHONE_VOL); -+ iTempMonoVol = peek( AC97_06_MONO_VOL); -+ -+ runtime->hw.channels_min = 1; -+ runtime->hw.channels_max = 2; -+ -+ ep93xx_audio_init(); -+ /*ep93xx_init_ac97_controller();*/ -+ -+ /*reset the old output mixer*/ -+ poke( AC97_02_MASTER_VOL, iTempMasterVol); -+ poke( AC97_04_HEADPHONE_VOL,iTempHeadphoneVol ); -+ poke( AC97_06_MONO_VOL, iTempMonoVol); -+ poke( AC97_1A_RECORD_SELECT,iTempRecordSelect); -+ -+ r = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ AC97_RATES_FRONT_DAC : AC97_RATES_ADC; -+ -+ DPRINTK(" ep93xx_ac97_pcm_startup=%x\n",r); -+ -+ return 0; -+} -+ -+ -+static int snd_ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ DPRINTK("snd_ep93xx_pcm_hw_params - enter\n"); -+ return snd_pcm_lib_malloc_pages(substream,params_buffer_bytes(params)); -+} -+ -+static int snd_ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ -+ DPRINTK("snd_ep93xx_pcm_hw_free - enter\n"); -+ return snd_pcm_lib_free_pages(substream); -+} -+ -+/* -+ *snd_ep93xx_pcm_prepare: need to finish these functions as lower -+ *chip_set_sample_format -+ *chip_set_sample_rate -+ *chip_set_channels -+ *chip_set_dma_setup -+ */ -+ -+static int snd_ep93xx_pcm_prepare_playback( struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *) substream->private_data; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->output_stream; -+ -+ DPRINTK("snd_ep93xx_pcm_prepare_playback - enter\n"); -+ -+ ep93xx_audio_disable(1); -+ ep93xx_ac97_pcm_startup(substream); -+ -+ snd_ep93xx_deallocate_buffers(substream,stream); -+ -+ //if(runtime->channels % 2 != 0) -+ // return -1; -+ -+ DPRINTK("The runtime item : \n"); -+ DPRINTK("runtime->dma_addr = 0x%x\n", runtime->dma_addr); -+ DPRINTK("runtime->dma_area = 0x%x\n", runtime->dma_area); -+ DPRINTK("runtime->dma_bytes = %d\n", runtime->dma_bytes); -+ DPRINTK("runtime->frame_bits = %d\n", runtime->frame_bits); -+ DPRINTK("runtime->buffer_size = %d\n", runtime->buffer_size); -+ DPRINTK("runtime->period_size = %d\n", runtime->period_size); -+ DPRINTK("runtime->periods = %d\n", runtime->periods); -+ DPRINTK("runtime->rate = %d\n", runtime->rate); -+ DPRINTK("runtime->format = %d\n", runtime->format); -+ DPRINTK("runtime->channels = %d\n", runtime->channels); -+ -+ /* set requestd format when available */ -+ stream->audio_num_channels = runtime->channels; -+ if(stream->audio_num_channels == 1){ -+ stream->dma_num_channels = 1; -+ } -+ else{ -+ stream->dma_num_channels = runtime->channels / 2; -+ } -+ -+ stream->audio_channels_flag = CHANNEL_FRONT; -+ if(stream->dma_num_channels == 2) -+ stream->audio_channels_flag |= CHANNEL_REAR; -+ if(stream->dma_num_channels == 3) -+ stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE; -+ -+ stream->dmasize = runtime->dma_bytes; -+ stream->nbfrags = runtime->periods; -+ stream->fragsize = frames_to_bytes (runtime, runtime->period_size); -+ stream->bytecount = 0; -+ -+ if( !state->codec_set_by_capture ){ -+ state->codec_set_by_playback = 1; -+ -+ if( stream->audio_rate != runtime->rate ){ -+ ep93xx_set_samplerate( runtime->rate,0 ); -+ } -+ //if( stream->audio_format != runtime->format ){ -+ // snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24)); -+ //} -+ } -+ else{ -+ audio_stream_t *s = state->input_stream; -+ if( runtime->format != s->audio_format) -+ return -1; -+ if( runtime->rate != s->audio_rate ) -+ return -1; -+ } -+ -+ stream->audio_format = runtime->format ; -+ ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels); -+ -+ -+ stream->audio_rate = runtime->rate; -+ audio_set_format( stream, runtime->format ); -+ snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode ); -+ -+ if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){ -+ snd_ep93xx_deallocate_buffers( substream, stream ); -+ return -1; -+ } -+ -+ ep93xx_audio_enable(1); -+ -+ DPRINTK("snd_ep93xx_pcm_prepare_playback - exit\n"); -+ return 0; -+} -+ -+static int snd_ep93xx_pcm_prepare_capture( struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *) substream->private_data; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->input_stream; -+ -+ ep93xx_audio_disable(0); -+ ep93xx_ac97_pcm_startup(substream); -+ -+ snd_ep93xx_deallocate_buffers(substream,stream); -+ -+ //if(runtime->channels % 2 != 0) -+ //return -1; -+ -+ DPRINTK("snd_ep93xx_pcm_prepare_capture - enter\n"); -+ -+// printk("The runtime item : \n"); -+// printk("runtime->dma_addr = 0x%x\n", runtime->dma_addr); -+// printk("runtime->dma_area = 0x%x\n", runtime->dma_area); -+// printk("runtime->dma_bytes = %d\n", runtime->dma_bytes); -+// printk("runtime->frame_bits = %d\n", runtime->frame_bits); -+// printk("runtime->buffer_size = %d\n", runtime->buffer_size); -+// printk("runtime->period_size = %d\n", runtime->period_size); -+// printk("runtime->periods = %d\n", runtime->periods); -+// printk("runtime->rate = %d\n", runtime->rate); -+// printk("runtime->format = %d\n", runtime->format); -+// printk("runtime->channels = %d\n", runtime->channels); -+ -+ /* set requestd format when available */ -+ stream->audio_num_channels = runtime->channels; -+ if(stream->audio_num_channels == 1){ -+ stream->dma_num_channels = 1; -+ } -+ else{ -+ stream->dma_num_channels = runtime->channels / 2; -+ } -+ -+ stream->audio_channels_flag = CHANNEL_FRONT; -+ if(stream->dma_num_channels == 2) -+ stream->audio_channels_flag |= CHANNEL_REAR; -+ if(stream->dma_num_channels == 3) -+ stream->audio_channels_flag |= CHANNEL_REAR | CHANNEL_CENTER_LFE; -+ -+ stream->dmasize = runtime->dma_bytes; -+ stream->nbfrags = runtime->periods; -+ stream->fragsize = frames_to_bytes (runtime, runtime->period_size); -+ stream->bytecount = 0; -+ -+ if( !state->codec_set_by_playback ){ -+ state->codec_set_by_capture = 1; -+ -+ /*rate*/ -+ if( stream->audio_rate != runtime->rate ){ -+ ep93xx_set_samplerate( runtime->rate,1 ); -+ } -+ -+ /*mixer*/ -+ ep93xx_set_recsource(SOUND_MASK_MIC|SOUND_MASK_LINE1 | SOUND_MASK_LINE); -+ poke( AC97_1C_RECORD_GAIN, 0); -+ -+ /*format*/ -+ //if( stream->audio_format != runtime->format ){ -+ // snd_ep93xx_i2s_init((stream->audio_stream_bitwidth == 24)); -+ //} -+ } -+ else{ -+ audio_stream_t *s = state->output_stream; -+ if( runtime->format != s->audio_format) -+ return -1; -+ if( runtime->rate != s->audio_rate ) -+ return -1; -+ } -+ -+ stream->audio_format = runtime->format ; -+ ep93xx_set_hw_format(stream->audio_format,stream->audio_num_channels); -+ -+ -+ stream->audio_rate = runtime->rate; -+ audio_set_format( stream, runtime->format ); -+ snd_ep93xx_dma2usr_ratio( stream,state->bCompactMode ); -+ -+ if( snd_ep93xx_allocate_buffers( substream, stream ) != 0 ){ -+ snd_ep93xx_deallocate_buffers( substream, stream ); -+ return -1; -+ } -+ -+ ep93xx_audio_enable(0); -+ -+ DPRINTK("snd_ep93xx_pcm_prepare_capture - exit\n"); -+ return 0; -+} -+/* -+ *start/stop/pause dma translate -+ */ -+static int snd_ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ audio_state_t *state = (audio_state_t *)substream->private_data; -+ audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_stream:state->input_stream; -+ audio_buf_t *buf; -+ audio_channel_t *dma_channel; -+ int i,count,ret = 0; -+ unsigned long flags; -+ -+ DPRINTK("snd_ep93xx_pcm_triger %d - enter \n",cmd); -+ -+ switch (cmd){ -+ -+ case SNDRV_PCM_TRIGGER_START: -+ -+ snd_ep93xx_dma_config( substream ); -+ -+ stream->stopped = 0; -+ -+ if( !stream->active && !stream->stopped ){ -+ stream->active = 1; -+ snd_ep93xx_dma_start( state, stream ); -+ } -+ -+ local_irq_save(flags); -+ -+ for (i = 0; i < stream->dma_num_channels; i++){ -+ dma_channel = &stream->dma_channels[i]; -+ -+ for(count = 0 ;count < dma_channel->audio_buff_count; count++){ -+ -+ buf = &dma_channel->audio_buffers[count]; -+ ep93xx_dma_add_buffer( stream->dmahandles[i], -+ (unsigned int)buf->dma_addr, -+ 0, -+ buf->bytes, -+ 0, -+ (unsigned int) buf ); -+ } -+ } -+ -+ local_irq_restore(flags); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ stream->stopped = 1; -+ snd_ep93xx_dma_pause( state, stream ); -+ snd_ep93xx_dma_flush( state, stream ); -+ snd_ep93xx_dma_free( substream ); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ break; -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ break; -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ break; -+ -+ default: -+ ret = -EINVAL; -+ } -+ DPRINTK("snd_ep93xx_pcm_triger %d - exit \n",cmd); -+ return ret; -+} -+ -+static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_playback(struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *)(substream->private_data); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->output_stream; -+ snd_pcm_uframes_t pointer = 0; -+ -+ pointer = bytes_to_frames( runtime,stream->bytecount ); -+ -+ if (pointer >= runtime->buffer_size){ -+ pointer = 0; -+ stream->bytecount = 0; -+ } -+ -+ DPRINTK("snd_ep93xx_pcm_pointer_playback - exit\n"); -+ return pointer; -+} -+ -+static snd_pcm_uframes_t snd_ep93xx_pcm_pointer_capture(struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *)(substream->private_data); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->input_stream; -+ snd_pcm_uframes_t pointer = 0; -+ -+ pointer = bytes_to_frames( runtime,stream->bytecount ); -+ -+ if (pointer >= runtime->buffer_size){ -+ pointer = 0; -+ stream->bytecount = 0; -+ } -+ -+ DPRINTK("snd_ep93xx_pcm_pointer_capture - exit\n"); -+ return pointer; -+} -+ -+static int snd_ep93xx_pcm_open(struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = substream->private_data; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? -+ state->output_stream:state->input_stream; -+ -+ DPRINTK("snd_ep93xx_pcm_open - enter\n"); -+ -+ down(&state->sem); -+ -+ runtime->hw = ep93xx_ac97_pcm_hardware; -+ -+ stream->dma_num_channels = AUDIO_DEFAULT_DMACHANNELS; -+ stream->dma_channels = NULL; -+ stream->audio_rate = 0; -+ stream->audio_stream_bitwidth = 0; -+ -+ up(&state->sem); -+ -+ DPRINTK("snd_ep93xx_pcm_open - exit\n"); -+ return 0; -+} -+ -+/* -+ *free the HW dma channel -+ *free the HW dma buffer -+ *free the Hw dma decrotion using function :kfree -+ */ -+static int snd_ep93xx_pcm_close(struct snd_pcm_substream *substream) -+{ -+ audio_state_t *state = (audio_state_t *)(substream->private_data); -+ -+ DPRINTK("snd_ep93xx_pcm_close - enter\n"); -+ -+ snd_ep93xx_release(substream); -+ -+ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) -+ state->codec_set_by_playback = 0; -+ else -+ state->codec_set_by_capture = 0; -+ -+ DPRINTK("snd_ep93xx_pcm_close - exit\n"); -+ return 0; -+} -+ -+static int snd_ep93xx_pcm_copy_playback(struct snd_pcm_substream * substream,int channel, -+ snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count) -+{ -+ -+ audio_state_t *state = (audio_state_t *)substream->private_data; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->output_stream ; -+ audio_channel_t *dma_channel; -+ int i; -+ int tocount = frames_to_bytes(runtime,count); -+ -+ for( i = 0; i < stream->dma_num_channels; i++ ){ -+ -+ dma_channel = &stream->dma_channels[i]; -+ stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels ); -+ -+ } -+ -+ if(copy_from_user_with_conversion(stream ,(const char*)src,(tocount * stream->dma2usr_ratio),state->bCompactMode) <=0 ){ -+ DPRINTK(KERN_ERR "copy_from_user_with_conversion() failed\n"); -+ return -EFAULT; -+ } -+ -+ DPRINTK("snd_ep93xx_pcm_copy_playback - exit\n"); -+ return 0; -+} -+ -+ -+static int snd_ep93xx_pcm_copy_capture(struct snd_pcm_substream * substream,int channel, -+ snd_pcm_uframes_t pos,void __user *src, snd_pcm_uframes_t count) -+{ -+ audio_state_t *state = (audio_state_t *)substream->private_data; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ audio_stream_t *stream = state->input_stream ; -+ audio_channel_t *dma_channel; -+ int i; -+ -+ int tocount = frames_to_bytes(runtime,count); -+ -+ for( i = 0; i < stream->dma_num_channels; i++ ){ -+ -+ dma_channel = &stream->dma_channels[i]; -+ stream->hwbuf[i] = dma_channel->area + ( frames_to_bytes(runtime,pos) * stream->dma2usr_ratio / stream->dma_num_channels ); -+ -+ } -+ -+ if(copy_to_user_with_conversion(stream,(const char*)src,tocount,state->bCompactMode) <=0 ){ -+ -+ DPRINTK(KERN_ERR "copy_to_user_with_conversion() failed\n"); -+ return -EFAULT; -+ } -+ -+ DPRINTK("snd_ep93xx_pcm_copy_capture - exit\n"); -+ return 0; -+} -+ -+/*----------------------------------------------------------------------------------*/ -+static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -+{ -+ int val = -1; -+ /*volatile u32 *reg_addr;*/ -+ -+ DPRINTK(" number of codec:%x reg=%x\n",ac97->num,reg); -+ val=peek(reg); -+ if(val==-1){ -+ printk(KERN_ERR "%s: read error (ac97_reg=%d )val=%x\n", -+ __FUNCTION__, reg, val); -+ return 0; -+ } -+ -+ return val; -+} -+ -+static void ep93xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -+{ -+ /*volatile u32 *reg_addr;*/ -+ int ret; -+ -+ DPRINTK(" number of codec:%x rge=%x val=%x\n",ac97->num,reg,val); -+ ret=poke(reg, val); -+ if(ret!=0){ -+ printk(KERN_ERR "%s: write error (ac97_reg=%d val=%x)\n", -+ __FUNCTION__, reg, val); -+ } -+ -+} -+ -+static void ep93xx_ac97_reset(struct snd_ac97 *ac97) -+{ -+ -+ DPRINTK(" ep93xx_ac97_reset\n"); -+ ep93xx_audio_init(); -+ -+} -+ -+static struct snd_ac97_bus_ops ep93xx_ac97_ops = { -+ .read = ep93xx_ac97_read, -+ .write = ep93xx_ac97_write, -+ .reset = ep93xx_ac97_reset, -+}; -+ -+static struct snd_pcm *ep93xx_ac97_pcm; -+static struct snd_ac97 *ep93xx_ac97_ac97; -+ -+static struct snd_pcm_ops snd_ep93xx_pcm_playback_ops = { -+ .open = snd_ep93xx_pcm_open, -+ .close = snd_ep93xx_pcm_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = snd_ep93xx_pcm_hw_params, -+ .hw_free = snd_ep93xx_pcm_hw_free, -+ .prepare = snd_ep93xx_pcm_prepare_playback, -+ .trigger = snd_ep93xx_pcm_trigger, -+ .pointer = snd_ep93xx_pcm_pointer_playback, -+ .copy = snd_ep93xx_pcm_copy_playback, -+ -+}; -+ -+static struct snd_pcm_ops snd_ep93xx_pcm_capture_ops = { -+ .open = snd_ep93xx_pcm_open, -+ .close = snd_ep93xx_pcm_close, -+ .ioctl = snd_pcm_lib_ioctl, -+ .hw_params = snd_ep93xx_pcm_hw_params, -+ .hw_free = snd_ep93xx_pcm_hw_free, -+ .prepare = snd_ep93xx_pcm_prepare_capture, -+ .trigger = snd_ep93xx_pcm_trigger, -+ .pointer = snd_ep93xx_pcm_pointer_capture, -+ .copy = snd_ep93xx_pcm_copy_capture, -+}; -+ -+/*--------------------------------------------------------------------------*/ -+ -+ -+static int snd_ep93xx_pcm_new(struct snd_card *card, audio_state_t *state, struct snd_pcm **rpcm) -+{ -+ struct snd_pcm *pcm; -+ int play = state->output_stream? 1 : 0;/*SNDRV_PCM_STREAM_PLAYBACK*/ -+ int capt = state->input_stream ? 1 : 0;/*SNDRV_PCM_STREAM_CAPTURE*/ -+ int ret = 0; -+ -+ DPRINTK("snd_ep93xx_pcm_new - enter\n"); -+ -+ /* Register the new pcm device interface */ -+ ret = snd_pcm_new(card, "EP93xx-AC97-PCM", 0, play, capt, &pcm); -+ -+ if (ret){ -+ DPRINTK("%s--%x:card=%x,play=%x,capt=%x,&pcm=%x\n",__FUNCTION__,ret,(int)card,play,capt,(int)pcm); -+ goto out; -+ } -+ -+ /* allocate the pcm(DMA) memory */ -+ ret = snd_pcm_lib_preallocate_pages_for_all(pcm, /*SNDRV_DMA_TYPE_DEV,0,*/SNDRV_DMA_TYPE_CONTINUOUS,snd_dma_continuous_data(GFP_KERNEL),128*1024,128*1024); -+ -+ DPRINTK("The substream item : \n"); -+ DPRINTK("pcm->streams[0].substream->dma_buffer.addr = 0x%x\n", pcm->streams[0].substream->dma_buffer.addr); -+ DPRINTK("pcm->streams[0].substream->dma_buffer.area = 0x%x\n", pcm->streams[0].substream->dma_buffer.area); -+ DPRINTK("pcm->streams[0].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[0].substream->dma_buffer.bytes); -+ DPRINTK("pcm->streams[1].substream->dma_buffer.addr = 0x%x\n", pcm->streams[1].substream->dma_buffer.addr); -+ DPRINTK("pcm->streams[1].substream->dma_buffer.area = 0x%x\n", pcm->streams[1].substream->dma_buffer.area); -+ DPRINTK("pcm->streams[1].substream->dma_buffer.bytes = 0x%x\n", pcm->streams[1].substream->dma_buffer.bytes); -+ -+ pcm->private_data = state; -+ -+ /* seem to free the pcm data struct-->self dma buffer */ -+ pcm->private_free = (void*) snd_pcm_lib_preallocate_free_for_all; -+ -+ /* alsa pcm ops setting for SNDRV_PCM_STREAM_PLAYBACK */ -+ if (play) { -+ int stream = SNDRV_PCM_STREAM_PLAYBACK; -+ snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_playback_ops); -+ } -+ -+ /* alsa pcm ops setting for SNDRV_PCM_STREAM_CAPTURE */ -+ if (capt) { -+ int stream = SNDRV_PCM_STREAM_CAPTURE; -+ snd_pcm_set_ops(pcm, stream, &snd_ep93xx_pcm_capture_ops); -+ } -+ -+ if (rpcm) -+ *rpcm = pcm; -+ DPRINTK("snd_ep93xx_pcm_new - exit\n"); -+out: -+ return ret; -+} -+ -+#ifdef CONFIG_PM -+ -+int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state) -+{ -+ if (card->power_state != SNDRV_CTL_POWER_D3cold) { -+ snd_pcm_suspend_all(ep93xx_ac97_pcm); -+ snd_ac97_suspend(ep93xx_ac97_ac97); -+ snd_power_change_state(card, SNDRV_CTL_POWER_D3cold); -+ } -+ -+ return 0; -+} -+ -+int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state) -+{ -+ if (card->power_state != SNDRV_CTL_POWER_D0) { -+ -+ snd_ac97_resume(ep93xx_ac97_ac97); -+ snd_power_change_state(card, SNDRV_CTL_POWER_D0); -+ } -+ -+ return 0; -+} -+ -+int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level) -+{ -+ struct snd_card *card = platform_get_drvdata(_dev); -+ int ret = 0; -+ -+ if (card && level == SUSPEND_DISABLE) -+ ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold); -+ -+ return ret; -+} -+ -+int ep93xx_ac97_resume(struct platform_device *_dev, u32 level) -+{ -+ struct snd_card *card = platform_get_drvdata(_dev); -+ int ret = 0; -+ -+ if (card && level == RESUME_ENABLE) -+ ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0); -+ -+ return ret; -+} -+ -+#else -+/* -+#define ep93xx_ac97_do_suspend NULL -+#define ep93xx_ac97_do_resume NULL -+#define ep93xx_ac97_suspend NULL -+#define ep93xx_ac97_resume NULL -+*/ -+ -+int ep93xx_ac97_do_suspend(struct snd_card *card, unsigned int state) -+{ -+ return 0; -+} -+ -+int ep93xx_ac97_do_resume(struct snd_card *card, unsigned int state) -+{ -+ return 0; -+} -+ -+int ep93xx_ac97_resume(struct platform_device *_dev, u32 level) -+{ -+ struct snd_card *card = platform_get_drvdata(_dev); -+ int ret = 0; -+ -+ //if (card && level == RESUME_ENABLE) -+ ret = ep93xx_ac97_do_resume(card, SNDRV_CTL_POWER_D0); -+ -+ return ret; -+} -+ -+int ep93xx_ac97_suspend(struct platform_device *_dev, u32 state, u32 level) -+{ -+ struct snd_card *card = platform_get_drvdata(_dev); -+ int ret = 0; -+ -+ //if (card && level == SUSPEND_DISABLE) -+ ret = ep93xx_ac97_do_suspend(card, SNDRV_CTL_POWER_D3cold); -+ -+ return ret; -+} -+ -+#endif -+ -+ -+ -+/* module init & exit */ -+static int __devinit ep93xx_ac97_probe(struct platform_device *dev) -+{ -+ struct snd_card *card; -+ struct snd_ac97_bus *ac97_bus; -+ struct snd_ac97_template ac97_template; -+ int err = -ENOMEM; -+ struct resource *res = NULL; -+ -+ DPRINTK("snd_ep93xx_probe - enter\n"); -+ -+ /* Enable audio early on, give the DAC time to come up. */ -+ res = platform_get_resource( dev, IORESOURCE_MEM, 0); -+ -+ if(!res) { -+ printk("error : platform_get_resource \n"); -+ return -ENODEV; -+ } -+ -+ if (!request_mem_region(res->start,res->end - res->start + 1, "snd-ac97-cs4202" )){ -+ printk("error : request_mem_region\n"); -+ return -EBUSY; -+ } -+ -+ /*enable ac97 codec*/ -+ ep93xx_audio_init(); -+ -+ /* register the soundcard */ -+ card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, -+ THIS_MODULE, 0); -+ if (!card){ -+ printk("AC97: snd_card_new error\n"); -+ goto error; -+ } -+ -+ card->dev = &dev->dev; -+ /*regist the new pcm device*/ -+ err = snd_ep93xx_pcm_new(card, &audio_state, &ep93xx_ac97_pcm); -+ if (err){ -+ printk("AC97: ep93xx_ac97_pcm_new error\n"); -+ goto error; -+ } -+ if (card == NULL) { -+ DPRINTK(KERN_ERR "snd_card_new() failed\n"); -+ goto error; -+ } -+ -+ /*driver name*/ -+ strcpy(card->driver, "CS4202A"); -+ strcpy(card->shortname, "Cirrus Logic AC97 Audio "); -+ strcpy(card->longname, "Cirrus Logic AC97 Audio with CS4202A"); -+ -+ /*regist the new ac97 device*/ -+ err = snd_ac97_bus(card, 0, &ep93xx_ac97_ops, NULL, &ac97_bus); -+ if (err){ -+ printk("AC97: snd_ac97_bus error\n"); -+ goto error; -+ } -+ -+ memset(&ac97_template, 0, sizeof(ac97_template)); -+ err = snd_ac97_mixer(ac97_bus, &ac97_template, &ep93xx_ac97_ac97); -+ if (err){ -+ printk("AC97: snd_ac97_mixer error\n"); -+ goto error; -+ } -+ -+ /**/ -+ ep93xx_audio_init(); -+ /*setting the card device callback*/ -+ //err = snd_card_set_pm_callback(card, ep93xx_ac97_do_suspend,ep93xx_ac97_do_resume, (void*)NULL); -+ //if(err != 0){ -+ // printk("snd_card_set_pm_callback error\n"); -+ //} -+ -+ /*regist the new CARD device*/ -+ err = snd_card_register(card); -+ if (err == 0) { -+ printk( KERN_INFO "Cirrus Logic ep93xx ac97 audio initialized\n" ); -+ platform_set_drvdata(dev,card); -+ DPRINTK("snd_ep93xx_probe - exit\n"); -+ return 0; -+ } -+ -+error: -+ snd_card_free(card); -+ printk("snd_ep93xx_probe - error\n"); -+ return err; -+ -+return 0; -+} -+ -+static int __devexit ep93xx_ac97_remove(struct platform_device *dev) -+{ -+ struct resource *res; -+ struct snd_card *card = platform_get_drvdata(dev); -+ -+ res = platform_get_resource( dev, IORESOURCE_MEM, 0); -+ release_mem_region(res->start, res->end - res->start + 1); -+ -+ DPRINTK("snd_ep93xx_ac97_remove - enter\n"); -+ -+ if (card) { -+ snd_card_free(card); -+ platform_set_drvdata(dev, NULL); -+ } -+ DPRINTK("snd_ep93xx_remove - exit\n"); -+ -+return 0; -+} -+ -+ -+static struct platform_driver ep93xx_ac97_driver = { -+ .probe = ep93xx_ac97_probe, -+ .remove = __devexit_p (ep93xx_ac97_remove), -+ .suspend = ep93xx_ac97_suspend, -+ .resume = ep93xx_ac97_resume, -+ .driver = { -+ .name = "ep93xx-ac97", -+ }, -+}; -+ -+ -+static int __init ep93xx_ac97_init(void) -+{ -+ int ret; -+ -+ DPRINTK(KERN_INFO "%s: version %s\n", DRIVER_DESC, DRIVER_VERSION); -+ DPRINTK("snd_ep93xx_AC97_init - enter\n"); -+ ret = platform_driver_register(&ep93xx_ac97_driver); -+ DPRINTK("snd_ep93xx_AC97_init - exit\n"); -+ return ret; -+} -+ -+static void __exit ep93xx_ac97_exit(void) -+{ -+ DPRINTK("ep93xx_ac97_exit - enter\n"); -+ return platform_driver_unregister(&ep93xx_ac97_driver); -+} -+ -+module_init(ep93xx_ac97_init); -+module_exit(ep93xx_ac97_exit); -+ -+MODULE_DESCRIPTION("Cirrus Logic audio module"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/sound/arm/ep93xx-ac97.h -@@ -0,0 +1,89 @@ -+/* -+ * linux/sound/arm/ep93xx-ac97.h -- ALSA PCM interface for the edb93xx ac97 audio -+ * -+ * Author: Fred Wei -+ * Created: July 19, 2005 -+ * Copyright: Cirrus Logic, Inc. -+ * -+ * 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. -+ */ -+ -+#define EP93XX_DEFAULT_NUM_CHANNELS 2 -+#define EP93XX_DEFAULT_FORMAT SNDRV_PCM_FORMAT_S16_LE -+#define EP93XX_DEFAULT_BIT_WIDTH 16 -+#define MAX_DEVICE_NAME 20 -+ -+/* -+ * Buffer Management -+ */ -+ -+typedef struct { -+ -+ unsigned char *area; /* virtual pointer */ -+ dma_addr_t dma_addr; /* physical address */ -+ size_t bytes; -+ size_t reportedbytes; /* buffer size */ -+ int sent; /* indicates that dma has the buf */ -+ char *start; /* points to actual buffer */ -+ -+} audio_buf_t; -+ -+ -+typedef struct { -+ -+ unsigned char *area; /* virtual pointer */ -+ dma_addr_t addr; /* physical address */ -+ size_t bytes; /* buffer size in bytes */ -+ unsigned char *buff_pos; /* virtual pointer */ -+ audio_buf_t *audio_buffers; /* array of audio buffer structures */ -+ int audio_buff_count; -+ -+ -+} audio_channel_t; -+ -+typedef struct audio_stream_s { -+ -+ /* dma stuff */ -+ int dmahandles[3]; /* handles for dma driver instances */ -+ char devicename[MAX_DEVICE_NAME]; /* string - name of device */ -+ int dma_num_channels; /* 1, 2, or 3 DMA channels */ -+ audio_channel_t *dma_channels; -+ u_int nbfrags; /* nbr of fragments i.e. buffers */ -+ u_int fragsize; /* fragment i.e. buffer size */ -+ u_int dmasize; -+ int bytecount; /* nbr of processed bytes */ -+ int externedbytecount; /* nbr of processed bytes */ -+ volatile int active; /* actually in progress */ -+ volatile int stopped; /* might be active but stopped */ -+ char *hwbuf[3]; -+ long audio_rate; -+ long audio_num_channels; /* Range: 1 to 6 */ -+ int audio_channels_flag; -+ long audio_format; -+ long audio_stream_bitwidth; /* Range: 8, 16, 24 */ -+ int dma2usr_ratio; -+ -+} audio_stream_t; -+ -+ -+/* -+ * State structure for one instance -+ */ -+typedef struct { -+ -+ audio_stream_t *output_stream; -+ audio_stream_t *input_stream; -+ ep93xx_dma_dev_t output_dma[3]; -+ ep93xx_dma_dev_t input_dma[3]; -+ char *output_id[3]; -+ char *input_id[3]; -+ struct semaphore sem; /* to protect against races in attach() */ -+ int codec_set_by_playback; -+ int codec_set_by_capture; -+ int DAC_bit_width; /* 16, 20, 24 bits */ -+ int bCompactMode; /* set if 32bits = a stereo sample */ -+ -+} audio_state_t; -+ diff --git a/target/linux/ep93xx/patches-2.6.30/011-simone-board-def.patch b/target/linux/ep93xx/patches-2.6.30/011-simone-board-def.patch deleted file mode 100644 index d499259adb..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/011-simone-board-def.patch +++ /dev/null @@ -1,1658 +0,0 @@ -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/Kconfig -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/mach-ep93xx/Kconfig 2009-11-26 00:13:04.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/Kconfig 2009-11-26 00:13:15.000000000 +0100 -@@ -88,6 +88,12 @@ - Say 'Y' here if you want your kernel to support the - Contec Hypercontrol Micro9-L board. - -+config MACH_SIM_ONE -+ bool "Support SIM.ONE board " -+ help -+ Say 'Y' here if you want your kernel to support the -+ Simplemachines SIM.ONE board. -+ - config MACH_TS72XX - bool "Support Technologic Systems TS-72xx SBC" - help -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/Makefile -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/mach-ep93xx/Makefile 2009-11-26 00:13:04.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/Makefile 2009-11-26 00:13:15.000000000 +0100 -@@ -16,4 +16,5 @@ - obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o - obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o - obj-$(CONFIG_MACH_MICRO9) += micro9.o -+obj-$(CONFIG_MACH_SIM_ONE) += simone.o - obj-$(CONFIG_MACH_TS72XX) += ts72xx.o -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/Makefile.boot -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/mach-ep93xx/Makefile.boot 2009-11-26 00:13:04.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/Makefile.boot 2009-11-26 00:13:15.000000000 +0100 -@@ -1,2 +1,4 @@ - zreladdr-y := 0x00008000 - params_phys-y := 0x00000100 -+ zreladdr-$(CONFIG_MACH_SIM_ONE) := 0xc0008000 -+params_phys-$(CONFIG_MACH_SIM_ONE) := 0xc0000100 -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/simone.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/simone.c 2009-11-26 00:14:09.000000000 +0100 -@@ -0,0 +1,217 @@ -+/* -+ * arch/arm/mach-ep93xx/simone.c -+ * Simplemachines SIM.ONE support. -+ * -+ * Copyright (C) 2009 Simplemachines -+ * MMC support by Peter Ivanov <ivanovp@gmail.com>, 2007 -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or (at -+ * your option) any later version. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/mm.h> -+#include <linux/sched.h> -+#include <linux/interrupt.h> -+#include <linux/ioport.h> -+#include <linux/mtd/physmap.h> -+#include <linux/platform_device.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/mmc_spi.h> -+#include <linux/mmc/host.h> -+#include <linux/jiffies.h> -+#include <linux/irq.h> -+ -+#include <asm/io.h> -+#include <mach/hardware.h> -+#include <asm/mach-types.h> -+#include <asm/mach/arch.h> -+#include <asm/gpio.h> -+ -+static struct physmap_flash_data simone_flash_data = { -+ .width = 2, -+}; -+ -+static struct resource simone_flash_resource = { -+ .start = 0x60000000, -+ .end = 0x60000000+ SZ_8M - 1, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device simone_flash = { -+ .name = "physmap-flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &simone_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &simone_flash_resource, -+}; -+ -+ -+static struct resource ep93xx_ac97_resources[] = { -+ [0] = { -+ .start = EP93XX_AC97_PHY_BASE, -+ .end = EP93XX_AC97_PHY_BASE + 0x6C, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = NO_IRQ, -+ .end = NO_IRQ, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 ep93xx_ac97_dma_mask = 0xffffffffUL; -+ -+static struct platform_device ep93xx_ac97_device = { -+ .name = "ep93xx-ac97", -+ .id = 0, -+ .num_resources = 2, -+ .resource = ep93xx_ac97_resources, -+ .dev = { -+ .dma_mask = &ep93xx_ac97_dma_mask, -+ .coherent_dma_mask = 0xffffffffUL, -+ }, -+}; -+ -+ -+#ifdef CONFIG_SPI -+static struct resource ep93xx_spi_resources[] = { -+ [0] = { -+ .start = EP93XX_SPI_BASE_PHYS, -+ .end = EP93XX_SPI_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ [1] = { -+ .start = IRQ_EP93XX_SSP, -+ .end = IRQ_EP93XX_SSP, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device ep93xx_spi_device = { -+ .name = "ep93xx-spi", -+ .id = 0, -+ .resource = ep93xx_spi_resources, -+ .num_resources = ARRAY_SIZE(ep93xx_spi_resources), -+}; -+ -+ -+#define EP93XX_MMC_SPI_CARD_PRESENT EP93XX_GPIO_LINE_A(0) -+ -+/* -+ * Initializes SPI system to communicate with MMC/SD card -+ */ -+int ep93xx_mmc_spi_init (struct device *pdev, irqreturn_t (*card_det_irq_handler)(int, void *), -+ void *mmc) -+{ -+ int rv; -+ -+ rv = gpio_request(EP93XX_MMC_SPI_CARD_PRESENT, "ep93xx-mmc-spi"); -+ if (rv) { -+ dev_info(pdev, "failed to request MMC/SD gpio pin\n"); -+ return rv; -+ } -+ -+ gpio_direction_input (EP93XX_MMC_SPI_CARD_PRESENT); -+ -+ if ((rv = request_irq (gpio_to_irq( EP93XX_MMC_SPI_CARD_PRESENT), -+ card_det_irq_handler, -+ IRQF_DISABLED | IRQ_TYPE_EDGE_FALLING, /* flags */ -+ "ep93xx-mmc-spi", /* devname */ -+ mmc /* void *devid */ -+ )) == 0) -+ { -+ dev_info (pdev, "MMC/SD card detection IRQ %i assigned.\n", -+ gpio_to_irq(EP93XX_MMC_SPI_CARD_PRESENT)); -+ } -+ else -+ { -+ dev_err (pdev, "Cannot assign MMC/SD card detection IRQ (%i)!\n", -+ gpio_to_irq(EP93XX_MMC_SPI_CARD_PRESENT)); -+ return rv; -+ } -+ return 0; -+} -+ -+void ep93xx_mmc_spi_exit (struct device *pdev, void *mmc) -+{ -+ free_irq (EP93XX_MMC_SPI_CARD_PRESENT, mmc); -+} -+ -+static struct mmc_spi_platform_data ep93xx_spi_pdata = { -+ .init = &ep93xx_mmc_spi_init, -+ .exit = &ep93xx_mmc_spi_exit, -+ .get_ro = NULL, -+ .detect_delay = 500, /* card detection delay in msec */ -+ .ocr_mask = MMC_VDD_33_34, -+}; -+ -+static struct spi_board_info ep93xx_spi_board_info[] __initdata = { -+ { -+ .modalias = "mmc_spi", -+ .max_speed_hz = 7.4E6, /* max spi clock (SCK) speed in HZ */ -+ .bus_num = 0, -+ .chip_select = 0, -+ .platform_data = (void*) &ep93xx_spi_pdata, -+ .controller_data = NULL, -+ .mode = SPI_MODE_0, -+ } -+}; -+#endif -+static struct ep93xx_eth_data ep93xx_eth_data = { -+ .dev_addr = { 0x00, 0xba, 0xd0, 0x0b, 0xad, 0x00 }, -+}; -+ -+static struct resource ep93xx_eth_resource[] = { -+ { -+ .start = EP93XX_ETHERNET_PHYS_BASE, -+ .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, -+ .flags = IORESOURCE_MEM, -+ }, { -+ .start = IRQ_EP93XX_ETHERNET, -+ .end = IRQ_EP93XX_ETHERNET, -+ .flags = IORESOURCE_IRQ, -+ } -+}; -+ -+static struct platform_device ep93xx_eth_device = { -+ .name = "ep93xx-eth", -+ .id = -1, -+ .dev = { -+ .platform_data = &ep93xx_eth_data, -+ }, -+ .num_resources = ARRAY_SIZE(ep93xx_eth_resource), -+ .resource = ep93xx_eth_resource, -+}; -+ -+static void __init simone_init_machine(void) -+{ -+ ep93xx_init_devices(); -+ /* Switch off the LCD backlight*/ -+ gpio_request(EP93XX_GPIO_LINE_B(5), "lcd"); -+ gpio_direction_output (EP93XX_GPIO_LINE_B(5), 0); -+ platform_device_register(&simone_flash); -+ platform_device_register(&ep93xx_ac97_device); -+ platform_device_register(&ep93xx_eth_device); -+#if defined(CONFIG_SPI_EP93XX) || defined(CONFIG_SPI_EP93XX_MODULE) -+ dev_set_name(&ep93xx_spi_device.dev, "apb:spi"); -+ platform_device_register(&ep93xx_spi_device); -+ spi_register_board_info(ep93xx_spi_board_info,ARRAY_SIZE(ep93xx_spi_board_info)); -+#endif -+} -+ -+MACHINE_START(SIM_ONE, "Simplemachine SimONE Board") -+ /* Maintainer: Nuccio Raciti Simplemachine <nuccio.raciti@gmail.com>*/ -+ .phys_io = EP93XX_APB_PHYS_BASE, -+ .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, -+ .boot_params = 0x00000100, -+ .map_io = ep93xx_map_io, -+ .init_irq = ep93xx_init_irq, -+ .timer = &ep93xx_timer, -+ .init_machine = simone_init_machine, -+MACHINE_END -Index: linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/memory.h -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/mach-ep93xx/include/mach/memory.h 2009-11-26 00:13:04.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/mach-ep93xx/include/mach/memory.h 2009-11-26 00:13:15.000000000 +0100 -@@ -5,6 +5,10 @@ - #ifndef __ASM_ARCH_MEMORY_H - #define __ASM_ARCH_MEMORY_H - -+#if defined(CONFIG_MACH_SIM_ONE) -+#define PHYS_OFFSET UL(0xc0000000) -+#else - #define PHYS_OFFSET UL(0x00000000) -+#endif - - #endif -Index: linux-2.6.30.9/arch/arm/configs/simone_defconfig -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.30.9/arch/arm/configs/simone_defconfig 2009-11-26 00:13:15.000000000 +0100 -@@ -0,0 +1,1380 @@ -+# -+# Automatically generated make config: don't edit -+# Linux kernel version: 2.6.24.7 -+# Tue May 12 17:49:25 2009 -+# -+CONFIG_ARM=y -+CONFIG_SYS_SUPPORTS_APM_EMULATION=y -+# CONFIG_GENERIC_GPIO is not set -+# CONFIG_GENERIC_TIME is not set -+# CONFIG_GENERIC_CLOCKEVENTS is not set -+CONFIG_MMU=y -+# CONFIG_NO_IOPORT is not set -+CONFIG_GENERIC_HARDIRQS=y -+CONFIG_STACKTRACE_SUPPORT=y -+CONFIG_LOCKDEP_SUPPORT=y -+CONFIG_TRACE_IRQFLAGS_SUPPORT=y -+CONFIG_HARDIRQS_SW_RESEND=y -+CONFIG_GENERIC_IRQ_PROBE=y -+CONFIG_RWSEM_GENERIC_SPINLOCK=y -+# CONFIG_ARCH_HAS_ILOG2_U32 is not set -+# CONFIG_ARCH_HAS_ILOG2_U64 is not set -+CONFIG_GENERIC_HWEIGHT=y -+CONFIG_GENERIC_CALIBRATE_DELAY=y -+CONFIG_ZONE_DMA=y -+CONFIG_VECTORS_BASE=0xffff0000 -+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -+ -+# -+# General setup -+# -+CONFIG_EXPERIMENTAL=y -+CONFIG_BROKEN_ON_SMP=y -+CONFIG_LOCK_KERNEL=y -+CONFIG_INIT_ENV_ARG_LIMIT=32 -+CONFIG_LOCALVERSION="" -+CONFIG_LOCALVERSION_AUTO=y -+CONFIG_SWAP=y -+CONFIG_SYSVIPC=y -+CONFIG_SYSVIPC_SYSCTL=y -+# CONFIG_POSIX_MQUEUE is not set -+# CONFIG_BSD_PROCESS_ACCT is not set -+# CONFIG_TASKSTATS is not set -+# CONFIG_USER_NS is not set -+# CONFIG_PID_NS is not set -+# CONFIG_AUDIT is not set -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_LOG_BUF_SHIFT=16 -+# CONFIG_CGROUPS is not set -+CONFIG_FAIR_GROUP_SCHED=y -+CONFIG_FAIR_USER_SCHED=y -+# CONFIG_FAIR_CGROUP_SCHED is not set -+CONFIG_SYSFS_DEPRECATED=y -+# CONFIG_RELAY is not set -+# CONFIG_BLK_DEV_INITRD is not set -+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -+CONFIG_SYSCTL=y -+CONFIG_EMBEDDED=y -+CONFIG_UID16=y -+CONFIG_SYSCTL_SYSCALL=y -+CONFIG_KALLSYMS=y -+# CONFIG_KALLSYMS_EXTRA_PASS is not set -+CONFIG_HOTPLUG=y -+CONFIG_PRINTK=y -+CONFIG_BUG=y -+CONFIG_ELF_CORE=y -+CONFIG_BASE_FULL=y -+CONFIG_FUTEX=y -+CONFIG_ANON_INODES=y -+CONFIG_EPOLL=y -+CONFIG_SIGNALFD=y -+CONFIG_EVENTFD=y -+CONFIG_SHMEM=y -+CONFIG_VM_EVENT_COUNTERS=y -+CONFIG_SLAB=y -+# CONFIG_SLUB is not set -+# CONFIG_SLOB is not set -+CONFIG_SLABINFO=y -+CONFIG_RT_MUTEXES=y -+# CONFIG_TINY_SHMEM is not set -+CONFIG_BASE_SMALL=0 -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODULE_FORCE_UNLOAD=y -+# CONFIG_MODVERSIONS is not set -+# CONFIG_MODULE_SRCVERSION_ALL is not set -+CONFIG_KMOD=y -+CONFIG_BLOCK=y -+# CONFIG_LBD is not set -+# CONFIG_BLK_DEV_IO_TRACE is not set -+# CONFIG_LSF is not set -+# CONFIG_BLK_DEV_BSG is not set -+ -+# -+# IO Schedulers -+# -+CONFIG_IOSCHED_NOOP=y -+# CONFIG_IOSCHED_AS is not set -+CONFIG_IOSCHED_DEADLINE=y -+# CONFIG_IOSCHED_CFQ is not set -+# CONFIG_DEFAULT_AS is not set -+CONFIG_DEFAULT_DEADLINE=y -+# CONFIG_DEFAULT_CFQ is not set -+# CONFIG_DEFAULT_NOOP is not set -+CONFIG_DEFAULT_IOSCHED="deadline" -+ -+# -+# System Type -+# -+# CONFIG_ARCH_AAEC2000 is not set -+# CONFIG_ARCH_INTEGRATOR is not set -+# CONFIG_ARCH_REALVIEW is not set -+# CONFIG_ARCH_VERSATILE is not set -+# CONFIG_ARCH_AT91 is not set -+# CONFIG_ARCH_CLPS7500 is not set -+# CONFIG_ARCH_CLPS711X is not set -+# CONFIG_ARCH_CO285 is not set -+# CONFIG_ARCH_EBSA110 is not set -+CONFIG_ARCH_EP93XX=y -+# CONFIG_ARCH_FOOTBRIDGE is not set -+# CONFIG_ARCH_NETX is not set -+# CONFIG_ARCH_H720X is not set -+# CONFIG_ARCH_IMX is not set -+# CONFIG_ARCH_IOP13XX is not set -+# CONFIG_ARCH_IOP32X is not set -+# CONFIG_ARCH_IOP33X is not set -+# CONFIG_ARCH_IXP23XX is not set -+# CONFIG_ARCH_IXP2000 is not set -+# CONFIG_ARCH_IXP4XX is not set -+# CONFIG_ARCH_L7200 is not set -+# CONFIG_ARCH_KS8695 is not set -+# CONFIG_ARCH_NS9XXX is not set -+# CONFIG_ARCH_MXC is not set -+# CONFIG_ARCH_PNX4008 is not set -+# CONFIG_ARCH_PXA is not set -+# CONFIG_ARCH_RPC is not set -+# CONFIG_ARCH_SA1100 is not set -+# CONFIG_ARCH_S3C2410 is not set -+# CONFIG_ARCH_SHARK is not set -+# CONFIG_ARCH_LH7A40X is not set -+# CONFIG_ARCH_DAVINCI is not set -+# CONFIG_ARCH_OMAP is not set -+ -+# -+# Cirrus EP93xx Implementation Options -+# -+CONFIG_CRUNCH=y -+ -+# -+# EP93xx Platforms -+# -+# CONFIG_MACH_ADSSPHERE is not set -+# CONFIG_MACH_EDB9302 is not set -+# CONFIG_MACH_EDB9302A is not set -+# CONFIG_MACH_EDB9307 is not set -+# CONFIG_MACH_EDB9312 is not set -+# CONFIG_MACH_EDB9315 is not set -+# CONFIG_MACH_EDB9315A is not set -+# CONFIG_MACH_GESBC9312 is not set -+# CONFIG_MACH_MICRO9 is not set -+# CONFIG_MACH_MICRO9H is not set -+# CONFIG_MACH_MICRO9M is not set -+# CONFIG_MACH_MICRO9L is not set -+CONFIG_MACH_SIM_ONE=y -+# CONFIG_MACH_TS72XX is not set -+ -+# -+# Boot options -+# -+ -+# -+# Power management -+# -+ -+# -+# Processor Type -+# -+CONFIG_CPU_32=y -+CONFIG_CPU_ARM920T=y -+CONFIG_CPU_32v4T=y -+CONFIG_CPU_ABRT_EV4T=y -+CONFIG_CPU_CACHE_V4WT=y -+CONFIG_CPU_CACHE_VIVT=y -+CONFIG_CPU_COPY_V4WB=y -+CONFIG_CPU_TLB_V4WBI=y -+CONFIG_CPU_CP15=y -+CONFIG_CPU_CP15_MMU=y -+ -+# -+# Processor Features -+# -+CONFIG_ARM_THUMB=y -+# CONFIG_CPU_ICACHE_DISABLE is not set -+# CONFIG_CPU_DCACHE_DISABLE is not set -+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -+# CONFIG_OUTER_CACHE is not set -+CONFIG_ARM_VIC=y -+ -+# -+# Bus support -+# -+CONFIG_ARM_AMBA=y -+# CONFIG_PCI_SYSCALL is not set -+# CONFIG_ARCH_SUPPORTS_MSI is not set -+# CONFIG_PCCARD is not set -+ -+# -+# Kernel Features -+# -+# CONFIG_TICK_ONESHOT is not set -+CONFIG_PREEMPT=y -+# CONFIG_NO_IDLE_HZ is not set -+CONFIG_HZ=100 -+CONFIG_AEABI=y -+CONFIG_OABI_COMPAT=y -+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -+CONFIG_SELECT_MEMORY_MODEL=y -+CONFIG_FLATMEM_MANUAL=y -+# CONFIG_DISCONTIGMEM_MANUAL is not set -+# CONFIG_SPARSEMEM_MANUAL is not set -+CONFIG_FLATMEM=y -+CONFIG_FLAT_NODE_MEM_MAP=y -+# CONFIG_SPARSEMEM_STATIC is not set -+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -+CONFIG_SPLIT_PTLOCK_CPUS=4096 -+# CONFIG_RESOURCES_64BIT is not set -+CONFIG_ZONE_DMA_FLAG=1 -+CONFIG_BOUNCE=y -+CONFIG_VIRT_TO_BUS=y -+CONFIG_ALIGNMENT_TRAP=y -+ -+# -+# Boot options -+# -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="console=ttyAM0,115200 root=/dev/ram" -+# CONFIG_XIP_KERNEL is not set -+# CONFIG_KEXEC is not set -+ -+# -+# Floating point emulation -+# -+ -+# -+# At least one emulation must be selected -+# -+CONFIG_FPE_NWFPE=y -+CONFIG_FPE_NWFPE_XP=y -+# CONFIG_FPE_FASTFPE is not set -+ -+# -+# Userspace binary formats -+# -+CONFIG_BINFMT_ELF=y -+# CONFIG_BINFMT_AOUT is not set -+# CONFIG_BINFMT_MISC is not set -+# CONFIG_ARTHUR is not set -+ -+# -+# Power management options -+# -+# CONFIG_PM is not set -+CONFIG_SUSPEND_UP_POSSIBLE=y -+ -+# -+# Networking -+# -+CONFIG_NET=y -+ -+# -+# Networking options -+# -+CONFIG_PACKET=y -+CONFIG_PACKET_MMAP=y -+CONFIG_UNIX=y -+CONFIG_XFRM=y -+# CONFIG_XFRM_USER is not set -+# CONFIG_XFRM_SUB_POLICY is not set -+# CONFIG_XFRM_MIGRATE is not set -+CONFIG_NET_KEY=y -+# CONFIG_NET_KEY_MIGRATE is not set -+CONFIG_INET=y -+# CONFIG_IP_MULTICAST is not set -+# CONFIG_IP_ADVANCED_ROUTER is not set -+CONFIG_IP_FIB_HASH=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_BOOTP=y -+# CONFIG_IP_PNP_RARP is not set -+# CONFIG_NET_IPIP is not set -+# CONFIG_NET_IPGRE is not set -+# CONFIG_ARPD is not set -+CONFIG_SYN_COOKIES=y -+# CONFIG_INET_AH is not set -+# CONFIG_INET_ESP is not set -+# CONFIG_INET_IPCOMP is not set -+# CONFIG_INET_XFRM_TUNNEL is not set -+# CONFIG_INET_TUNNEL is not set -+CONFIG_INET_XFRM_MODE_TRANSPORT=y -+CONFIG_INET_XFRM_MODE_TUNNEL=y -+CONFIG_INET_XFRM_MODE_BEET=y -+# CONFIG_INET_LRO is not set -+CONFIG_INET_DIAG=y -+CONFIG_INET_TCP_DIAG=y -+# CONFIG_TCP_CONG_ADVANCED is not set -+CONFIG_TCP_CONG_CUBIC=y -+CONFIG_DEFAULT_TCP_CONG="cubic" -+# CONFIG_TCP_MD5SIG is not set -+CONFIG_IPV6=y -+# CONFIG_IPV6_PRIVACY is not set -+# CONFIG_IPV6_ROUTER_PREF is not set -+# CONFIG_IPV6_OPTIMISTIC_DAD is not set -+# CONFIG_INET6_AH is not set -+# CONFIG_INET6_ESP is not set -+# CONFIG_INET6_IPCOMP is not set -+# CONFIG_IPV6_MIP6 is not set -+# CONFIG_INET6_XFRM_TUNNEL is not set -+# CONFIG_INET6_TUNNEL is not set -+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET6_XFRM_MODE_BEET is not set -+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -+# CONFIG_IPV6_SIT is not set -+# CONFIG_IPV6_TUNNEL is not set -+# CONFIG_IPV6_MULTIPLE_TABLES is not set -+# CONFIG_NETWORK_SECMARK is not set -+# CONFIG_NETFILTER is not set -+# CONFIG_IP_DCCP is not set -+# CONFIG_IP_SCTP is not set -+# CONFIG_TIPC is not set -+# CONFIG_ATM is not set -+# CONFIG_BRIDGE is not set -+# CONFIG_VLAN_8021Q is not set -+# CONFIG_DECNET is not set -+# CONFIG_LLC2 is not set -+# CONFIG_IPX is not set -+# CONFIG_ATALK is not set -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_ECONET is not set -+# CONFIG_WAN_ROUTER is not set -+# CONFIG_NET_SCHED is not set -+CONFIG_NET_SCH_FIFO=y -+ -+# -+# Network testing -+# -+# CONFIG_NET_PKTGEN is not set -+# CONFIG_HAMRADIO is not set -+# CONFIG_IRDA is not set -+# CONFIG_BT is not set -+# CONFIG_AF_RXRPC is not set -+ -+# -+# Wireless -+# -+CONFIG_CFG80211=y -+CONFIG_NL80211=y -+CONFIG_WIRELESS_EXT=y -+CONFIG_MAC80211=m -+CONFIG_MAC80211_RCSIMPLE=y -+# CONFIG_MAC80211_DEBUG is not set -+CONFIG_IEEE80211=m -+# CONFIG_IEEE80211_DEBUG is not set -+CONFIG_IEEE80211_CRYPT_WEP=m -+CONFIG_IEEE80211_CRYPT_CCMP=m -+CONFIG_IEEE80211_CRYPT_TKIP=m -+# CONFIG_IEEE80211_SOFTMAC is not set -+# CONFIG_RFKILL is not set -+# CONFIG_NET_9P is not set -+ -+# -+# Device Drivers -+# -+ -+# -+# Generic Driver Options -+# -+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -+CONFIG_STANDALONE=y -+CONFIG_PREVENT_FIRMWARE_BUILD=y -+# CONFIG_FW_LOADER is not set -+# CONFIG_SYS_HYPERVISOR is not set -+# CONFIG_CONNECTOR is not set -+CONFIG_MTD=y -+# CONFIG_MTD_DEBUG is not set -+# CONFIG_MTD_CONCAT is not set -+CONFIG_MTD_PARTITIONS=y -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_CMDLINE_PARTS is not set -+# CONFIG_MTD_AFS_PARTS is not set -+ -+# -+# User Modules And Translation Layers -+# -+CONFIG_MTD_CHAR=y -+CONFIG_MTD_BLKDEVS=y -+CONFIG_MTD_BLOCK=y -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+# CONFIG_INFTL is not set -+# CONFIG_RFD_FTL is not set -+# CONFIG_SSFDC is not set -+# CONFIG_MTD_OOPS is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+CONFIG_MTD_CFI=y -+# CONFIG_MTD_JEDECPROBE is not set -+CONFIG_MTD_GEN_PROBE=y -+CONFIG_MTD_CFI_ADV_OPTIONS=y -+CONFIG_MTD_CFI_NOSWAP=y -+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -+# CONFIG_MTD_CFI_GEOMETRY is not set -+CONFIG_MTD_MAP_BANK_WIDTH_1=y -+CONFIG_MTD_MAP_BANK_WIDTH_2=y -+CONFIG_MTD_MAP_BANK_WIDTH_4=y -+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -+CONFIG_MTD_CFI_I1=y -+CONFIG_MTD_CFI_I2=y -+# CONFIG_MTD_CFI_I4 is not set -+# CONFIG_MTD_CFI_I8 is not set -+# CONFIG_MTD_OTP is not set -+CONFIG_MTD_CFI_INTELEXT=y -+CONFIG_MTD_CFI_AMDSTD=y -+CONFIG_MTD_CFI_STAA=y -+CONFIG_MTD_CFI_UTIL=y -+CONFIG_MTD_RAM=y -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_COMPLEX_MAPPINGS is not set -+CONFIG_MTD_PHYSMAP=y -+CONFIG_MTD_PHYSMAP_START=0x0 -+CONFIG_MTD_PHYSMAP_LEN=0x0 -+CONFIG_MTD_PHYSMAP_BANKWIDTH=1 -+# CONFIG_MTD_ARM_INTEGRATOR is not set -+# CONFIG_MTD_PLATRAM is not set -+ -+# -+# Self-contained MTD device drivers -+# -+# CONFIG_MTD_DATAFLASH is not set -+# CONFIG_MTD_M25P80 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_PHRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+# CONFIG_MTD_BLOCK2MTD is not set -+ -+# -+# Disk-On-Chip Device Drivers -+# -+# CONFIG_MTD_DOC2000 is not set -+# CONFIG_MTD_DOC2001 is not set -+# CONFIG_MTD_DOC2001PLUS is not set -+# CONFIG_MTD_NAND is not set -+# CONFIG_MTD_ONENAND is not set -+ -+# -+# UBI - Unsorted block images -+# -+# CONFIG_MTD_UBI is not set -+# CONFIG_PARPORT is not set -+CONFIG_BLK_DEV=y -+# CONFIG_BLK_DEV_COW_COMMON is not set -+CONFIG_BLK_DEV_LOOP=y -+# CONFIG_BLK_DEV_CRYPTOLOOP is not set -+CONFIG_BLK_DEV_NBD=y -+# CONFIG_BLK_DEV_UB is not set -+# CONFIG_BLK_DEV_RAM is not set -+# CONFIG_CDROM_PKTCDVD is not set -+# CONFIG_ATA_OVER_ETH is not set -+# CONFIG_MISC_DEVICES is not set -+CONFIG_EEPROM_93CX6=m -+ -+# -+# SCSI device support -+# -+# CONFIG_RAID_ATTRS is not set -+CONFIG_SCSI=y -+CONFIG_SCSI_DMA=y -+# CONFIG_SCSI_TGT is not set -+# CONFIG_SCSI_NETLINK is not set -+# CONFIG_SCSI_PROC_FS is not set -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+CONFIG_BLK_DEV_SD=y -+# 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 is not set -+# CONFIG_CHR_DEV_SCH is not set -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+# CONFIG_SCSI_MULTI_LUN is not set -+# CONFIG_SCSI_CONSTANTS is not set -+# CONFIG_SCSI_LOGGING is not set -+# CONFIG_SCSI_SCAN_ASYNC is not set -+CONFIG_SCSI_WAIT_SCAN=m -+ -+# -+# SCSI Transports -+# -+# CONFIG_SCSI_SPI_ATTRS is not set -+# CONFIG_SCSI_FC_ATTRS is not set -+# CONFIG_SCSI_ISCSI_ATTRS is not set -+# CONFIG_SCSI_SAS_LIBSAS is not set -+# CONFIG_SCSI_SRP_ATTRS is not set -+CONFIG_SCSI_LOWLEVEL=y -+# CONFIG_ISCSI_TCP is not set -+# CONFIG_SCSI_DEBUG is not set -+# CONFIG_ATA is not set -+# CONFIG_MD is not set -+CONFIG_NETDEVICES=y -+# CONFIG_NETDEVICES_MULTIQUEUE is not set -+# CONFIG_DUMMY is not set -+# CONFIG_BONDING is not set -+# CONFIG_MACVLAN is not set -+# CONFIG_EQUALIZER is not set -+# CONFIG_TUN is not set -+# CONFIG_VETH is not set -+# CONFIG_PHYLIB is not set -+CONFIG_NET_ETHERNET=y -+CONFIG_MII=y -+CONFIG_EP93XX_ETH=y -+# CONFIG_AX88796 is not set -+# CONFIG_SMC91X is not set -+# CONFIG_DM9000 is not set -+# CONFIG_IBM_NEW_EMAC_ZMII is not set -+# CONFIG_IBM_NEW_EMAC_RGMII is not set -+# CONFIG_IBM_NEW_EMAC_TAH is not set -+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -+# CONFIG_B44 is not set -+# CONFIG_NETDEV_1000 is not set -+# CONFIG_NETDEV_10000 is not set -+ -+# -+# Wireless LAN -+# -+# CONFIG_WLAN_PRE80211 is not set -+CONFIG_WLAN_80211=y -+# CONFIG_LIBERTAS is not set -+# CONFIG_USB_ZD1201 is not set -+CONFIG_RTL8187=m -+# CONFIG_HOSTAP is not set -+# CONFIG_B43 is not set -+# CONFIG_B43LEGACY is not set -+# CONFIG_RT2X00 is not set -+ -+# -+# USB Network Adapters -+# -+CONFIG_USB_CATC=y -+# CONFIG_USB_KAWETH is not set -+# CONFIG_USB_PEGASUS is not set -+CONFIG_USB_RTL8150=y -+# CONFIG_USB_USBNET is not set -+# CONFIG_WAN is not set -+CONFIG_PPP=m -+# CONFIG_PPP_MULTILINK is not set -+# CONFIG_PPP_FILTER is not set -+# CONFIG_PPP_ASYNC is not set -+CONFIG_PPP_SYNC_TTY=m -+# CONFIG_PPP_DEFLATE is not set -+CONFIG_PPP_BSDCOMP=m -+# CONFIG_PPP_MPPE is not set -+CONFIG_PPPOE=m -+# CONFIG_PPPOL2TP is not set -+# CONFIG_SLIP is not set -+CONFIG_SLHC=m -+# CONFIG_SHAPER is not set -+# CONFIG_NETCONSOLE is not set -+# CONFIG_NETPOLL is not set -+# CONFIG_NET_POLL_CONTROLLER is not set -+# CONFIG_ISDN is not set -+ -+# -+# Input device support -+# -+CONFIG_INPUT=y -+# CONFIG_INPUT_FF_MEMLESS is not set -+# CONFIG_INPUT_POLLDEV is not set -+ -+# -+# Userland interfaces -+# -+CONFIG_INPUT_MOUSEDEV=y -+CONFIG_INPUT_MOUSEDEV_PSAUX=y -+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -+# CONFIG_INPUT_JOYDEV is not set -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_EVBUG is not set -+ -+# -+# Input Device Drivers -+# -+CONFIG_INPUT_KEYBOARD=y -+CONFIG_KEYBOARD_ATKBD=y -+# CONFIG_KEYBOARD_SUNKBD is not set -+# CONFIG_KEYBOARD_LKKBD is not set -+# CONFIG_KEYBOARD_XTKBD is not set -+# CONFIG_KEYBOARD_NEWTON is not set -+# CONFIG_KEYBOARD_STOWAWAY is not set -+CONFIG_INPUT_MOUSE=y -+CONFIG_MOUSE_PS2=y -+CONFIG_MOUSE_PS2_ALPS=y -+# CONFIG_MOUSE_PS2_LOGIPS2PP is not set -+# CONFIG_MOUSE_PS2_SYNAPTICS is not set -+# CONFIG_MOUSE_PS2_LIFEBOOK is not set -+# CONFIG_MOUSE_PS2_TRACKPOINT is not set -+# CONFIG_MOUSE_PS2_TOUCHKIT is not set -+# CONFIG_MOUSE_SERIAL is not set -+# CONFIG_MOUSE_APPLETOUCH is not set -+# CONFIG_MOUSE_VSXXXAA is not set -+# CONFIG_INPUT_JOYSTICK is not set -+# CONFIG_INPUT_TABLET is not set -+CONFIG_INPUT_TOUCHSCREEN=y -+# CONFIG_TOUCHSCREEN_ADS7846 is not set -+# CONFIG_TOUCHSCREEN_FUJITSU is not set -+# CONFIG_TOUCHSCREEN_GUNZE is not set -+# CONFIG_TOUCHSCREEN_ELO is not set -+# CONFIG_TOUCHSCREEN_MTOUCH is not set -+# CONFIG_TOUCHSCREEN_MK712 is not set -+# CONFIG_TOUCHSCREEN_PENMOUNT is not set -+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set -+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set -+# CONFIG_TOUCHSCREEN_UCB1400 is not set -+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set -+CONFIG_TOUCHSCREEN_EP93XX=y -+# CONFIG_INPUT_MISC is not set -+ -+# -+# Hardware I/O ports -+# -+CONFIG_SERIO=y -+# CONFIG_SERIO_SERPORT is not set -+# CONFIG_SERIO_AMBAKMI is not set -+CONFIG_SERIO_LIBPS2=y -+# CONFIG_SERIO_RAW is not set -+# CONFIG_GAMEPORT is not set -+ -+# -+# Character devices -+# -+CONFIG_VT=y -+CONFIG_VT_CONSOLE=y -+CONFIG_HW_CONSOLE=y -+# CONFIG_VT_HW_CONSOLE_BINDING is not set -+# CONFIG_SERIAL_NONSTANDARD is not set -+ -+# -+# Serial drivers -+# -+# CONFIG_SERIAL_8250 is not set -+ -+# -+# Non-8250 serial port support -+# -+CONFIG_SERIAL_AMBA_PL010=y -+CONFIG_SERIAL_AMBA_PL010_CONSOLE=y -+# CONFIG_SERIAL_AMBA_PL011 is not set -+CONFIG_SERIAL_CORE=y -+CONFIG_SERIAL_CORE_CONSOLE=y -+CONFIG_UNIX98_PTYS=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_IPMI_HANDLER is not set -+# CONFIG_HW_RANDOM is not set -+# CONFIG_NVRAM is not set -+# CONFIG_R3964 is not set -+# CONFIG_RAW_DRIVER is not set -+# CONFIG_TCG_TPM is not set -+CONFIG_I2C=y -+CONFIG_I2C_BOARDINFO=y -+CONFIG_I2C_CHARDEV=y -+ -+# -+# I2C Algorithms -+# -+CONFIG_I2C_ALGOBIT=y -+# CONFIG_I2C_ALGOPCF is not set -+# CONFIG_I2C_ALGOPCA is not set -+ -+# -+# I2C Hardware Bus support -+# -+CONFIG_I2C_EP93XX=y -+# CONFIG_I2C_OCORES is not set -+# CONFIG_I2C_PARPORT_LIGHT is not set -+# CONFIG_I2C_SIMTEC is not set -+# CONFIG_I2C_TAOS_EVM is not set -+# CONFIG_I2C_STUB is not set -+# CONFIG_I2C_TINY_USB is not set -+ -+# -+# Miscellaneous I2C Chip support -+# -+CONFIG_SENSORS_DS1337=y -+# CONFIG_SENSORS_DS1374 is not set -+# CONFIG_DS1682 is not set -+# CONFIG_SENSORS_EEPROM is not set -+# CONFIG_SENSORS_PCF8574 is not set -+# CONFIG_SENSORS_PCA9539 is not set -+# CONFIG_SENSORS_PCF8591 is not set -+# CONFIG_SENSORS_MAX6875 is not set -+# CONFIG_SENSORS_TSL2550 is not set -+# CONFIG_I2C_DEBUG_CORE is not set -+# CONFIG_I2C_DEBUG_ALGO is not set -+# CONFIG_I2C_DEBUG_BUS is not set -+# CONFIG_I2C_DEBUG_CHIP is not set -+ -+# -+# SPI support -+# -+CONFIG_SPI=y -+CONFIG_SPI_MASTER=y -+ -+# -+# SPI Master Controller Drivers -+# -+CONFIG_SPI_BITBANG=y -+CONFIG_SPI_EP93XX=y -+ -+# -+# SPI Protocol Masters -+# -+# CONFIG_SPI_AT25 is not set -+# CONFIG_SPI_SPIDEV is not set -+# CONFIG_SPI_TLE62X0 is not set -+# CONFIG_W1 is not set -+# CONFIG_POWER_SUPPLY is not set -+# CONFIG_HWMON is not set -+CONFIG_WATCHDOG=y -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+ -+# -+# Watchdog Device Drivers -+# -+# CONFIG_SOFT_WATCHDOG is not set -+CONFIG_EP93XX_WATCHDOG=y -+ -+# -+# USB-based Watchdog Cards -+# -+# CONFIG_USBPCWATCHDOG is not set -+ -+# -+# Sonics Silicon Backplane -+# -+CONFIG_SSB_POSSIBLE=y -+# CONFIG_SSB is not set -+ -+# -+# Multifunction device drivers -+# -+# CONFIG_MFD_SM501 is not set -+ -+# -+# Multimedia devices -+# -+# CONFIG_VIDEO_DEV is not set -+# CONFIG_DVB_CORE is not set -+# CONFIG_DAB is not set -+ -+# -+# Graphics support -+# -+# CONFIG_VGASTATE is not set -+CONFIG_VIDEO_OUTPUT_CONTROL=y -+CONFIG_FB=y -+# CONFIG_FIRMWARE_EDID is not set -+# CONFIG_FB_DDC is not set -+CONFIG_FB_CFB_FILLRECT=y -+CONFIG_FB_CFB_COPYAREA=y -+CONFIG_FB_CFB_IMAGEBLIT=y -+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -+# CONFIG_FB_SYS_FILLRECT is not set -+# CONFIG_FB_SYS_COPYAREA is not set -+# CONFIG_FB_SYS_IMAGEBLIT is not set -+# CONFIG_FB_SYS_FOPS is not set -+CONFIG_FB_DEFERRED_IO=y -+# CONFIG_FB_SVGALIB is not set -+# CONFIG_FB_MACMODES is not set -+# CONFIG_FB_BACKLIGHT is not set -+# CONFIG_FB_MODE_HELPERS is not set -+# CONFIG_FB_TILEBLITTING is not set -+ -+# -+# Frame buffer hardware drivers -+# -+CONFIG_FB_EP93XX=y -+# CONFIG_FB_EP93XX_MONO is not set -+# CONFIG_FB_ARMCLCD is not set -+# CONFIG_FB_S1D13XXX is not set -+# CONFIG_FB_VIRTUAL is not set -+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -+ -+# -+# Display device support -+# -+# CONFIG_DISPLAY_SUPPORT is not set -+ -+# -+# Console display driver support -+# -+# CONFIG_VGA_CONSOLE is not set -+CONFIG_DUMMY_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -+CONFIG_FONTS=y -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+# CONFIG_FONT_6x11 is not set -+# CONFIG_FONT_7x14 is not set -+# CONFIG_FONT_PEARL_8x8 is not set -+# CONFIG_FONT_ACORN_8x8 is not set -+# CONFIG_FONT_MINI_4x6 is not set -+# CONFIG_FONT_SUN8x16 is not set -+# CONFIG_FONT_SUN12x22 is not set -+# CONFIG_FONT_10x18 is not set -+CONFIG_LOGO=y -+CONFIG_LOGO_LINUX_MONO=y -+CONFIG_LOGO_LINUX_VGA16=y -+CONFIG_LOGO_LINUX_CLUT224=y -+ -+# -+# Sound -+# -+CONFIG_SOUND=y -+ -+# -+# Advanced Linux Sound Architecture -+# -+CONFIG_SND=y -+CONFIG_SND_TIMER=y -+CONFIG_SND_PCM=y -+# CONFIG_SND_SEQUENCER is not set -+CONFIG_SND_OSSEMUL=y -+CONFIG_SND_MIXER_OSS=y -+CONFIG_SND_PCM_OSS=y -+CONFIG_SND_PCM_OSS_PLUGINS=y -+# CONFIG_SND_DYNAMIC_MINORS is not set -+# CONFIG_SND_SUPPORT_OLD_API is not set -+# CONFIG_SND_VERBOSE_PROCFS is not set -+# CONFIG_SND_VERBOSE_PRINTK is not set -+# CONFIG_SND_DEBUG is not set -+ -+# -+# Generic devices -+# -+CONFIG_SND_AC97_CODEC=y -+# CONFIG_SND_DUMMY is not set -+# CONFIG_SND_MTPAV is not set -+# CONFIG_SND_SERIAL_U16550 is not set -+# CONFIG_SND_MPU401 is not set -+ -+# -+# ALSA ARM devices -+# -+CONFIG_SND_EP93XX_AC97=y -+CONFIG_SND_EP93XX_PCM=y -+# CONFIG_SND_ARMAACI is not set -+ -+# -+# SPI devices -+# -+ -+# -+# USB devices -+# -+# CONFIG_SND_USB_AUDIO is not set -+# CONFIG_SND_USB_CAIAQ is not set -+ -+# -+# System on Chip audio support -+# -+# CONFIG_SND_SOC is not set -+ -+# -+# SoC Audio support for SuperH -+# -+ -+# -+# Open Sound System -+# -+# CONFIG_SOUND_PRIME is not set -+CONFIG_AC97_BUS=y -+CONFIG_HID_SUPPORT=y -+CONFIG_HID=y -+# CONFIG_HID_DEBUG is not set -+# CONFIG_HIDRAW is not set -+ -+# -+# USB Input Devices -+# -+CONFIG_USB_HID=y -+# CONFIG_USB_HIDINPUT_POWERBOOK is not set -+# CONFIG_HID_FF is not set -+# CONFIG_USB_HIDDEV is not set -+CONFIG_USB_SUPPORT=y -+CONFIG_USB_ARCH_HAS_HCD=y -+CONFIG_USB_ARCH_HAS_OHCI=y -+# CONFIG_USB_ARCH_HAS_EHCI is not set -+CONFIG_USB=y -+# CONFIG_USB_DEBUG is not set -+ -+# -+# Miscellaneous USB options -+# -+CONFIG_USB_DEVICEFS=y -+CONFIG_USB_DEVICE_CLASS=y -+CONFIG_USB_DYNAMIC_MINORS=y -+# CONFIG_USB_OTG is not set -+ -+# -+# USB Host Controller Drivers -+# -+# CONFIG_USB_ISP116X_HCD is not set -+CONFIG_USB_OHCI_HCD=y -+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -+CONFIG_USB_OHCI_LITTLE_ENDIAN=y -+# CONFIG_USB_SL811_HCD is not set -+# CONFIG_USB_R8A66597_HCD is not set -+ -+# -+# USB Device Class drivers -+# -+CONFIG_USB_ACM=m -+CONFIG_USB_PRINTER=m -+ -+# -+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -+# -+ -+# -+# may also be needed; see USB_STORAGE Help for more information -+# -+CONFIG_USB_STORAGE=y -+# CONFIG_USB_STORAGE_DEBUG is not set -+# CONFIG_USB_STORAGE_DATAFAB is not set -+# CONFIG_USB_STORAGE_FREECOM is not set -+# CONFIG_USB_STORAGE_ISD200 is not set -+# CONFIG_USB_STORAGE_DPCM is not set -+# CONFIG_USB_STORAGE_USBAT 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_STORAGE_ALAUDA is not set -+# CONFIG_USB_STORAGE_ONETOUCH is not set -+# CONFIG_USB_STORAGE_KARMA is not set -+# CONFIG_USB_LIBUSUAL is not set -+ -+# -+# USB Imaging devices -+# -+# CONFIG_USB_MDC800 is not set -+# CONFIG_USB_MICROTEK is not set -+# CONFIG_USB_MON is not set -+ -+# -+# USB port drivers -+# -+ -+# -+# USB Serial Converter support -+# -+CONFIG_USB_SERIAL=y -+CONFIG_USB_SERIAL_CONSOLE=y -+# CONFIG_USB_SERIAL_GENERIC is not set -+# CONFIG_USB_SERIAL_AIRCABLE is not set -+# CONFIG_USB_SERIAL_AIRPRIME is not set -+# CONFIG_USB_SERIAL_ARK3116 is not set -+# CONFIG_USB_SERIAL_BELKIN is not set -+# CONFIG_USB_SERIAL_CH341 is not set -+# CONFIG_USB_SERIAL_WHITEHEAT is not set -+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -+# CONFIG_USB_SERIAL_CP2101 is not set -+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set -+# CONFIG_USB_SERIAL_EMPEG is not set -+# CONFIG_USB_SERIAL_FTDI_SIO is not set -+# CONFIG_USB_SERIAL_FUNSOFT is not set -+# CONFIG_USB_SERIAL_VISOR is not set -+# CONFIG_USB_SERIAL_IPAQ is not set -+# CONFIG_USB_SERIAL_IR is not set -+# CONFIG_USB_SERIAL_EDGEPORT is not set -+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -+# CONFIG_USB_SERIAL_GARMIN is not set -+# CONFIG_USB_SERIAL_IPW is not set -+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -+# CONFIG_USB_SERIAL_KEYSPAN is not set -+# CONFIG_USB_SERIAL_KLSI is not set -+# CONFIG_USB_SERIAL_KOBIL_SCT is not set -+# CONFIG_USB_SERIAL_MCT_U232 is not set -+# CONFIG_USB_SERIAL_MOS7720 is not set -+# CONFIG_USB_SERIAL_MOS7840 is not set -+# CONFIG_USB_SERIAL_NAVMAN is not set -+CONFIG_USB_SERIAL_PL2303=y -+# CONFIG_USB_SERIAL_OTI6858 is not set -+# CONFIG_USB_SERIAL_HP4X is not set -+# CONFIG_USB_SERIAL_SAFE is not set -+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set -+# CONFIG_USB_SERIAL_TI is not set -+# CONFIG_USB_SERIAL_CYBERJACK is not set -+# CONFIG_USB_SERIAL_XIRCOM is not set -+# CONFIG_USB_SERIAL_OPTION is not set -+# CONFIG_USB_SERIAL_OMNINET is not set -+# CONFIG_USB_SERIAL_DEBUG is not set -+ -+# -+# USB Miscellaneous drivers -+# -+# CONFIG_USB_EMI62 is not set -+# CONFIG_USB_EMI26 is not set -+# CONFIG_USB_ADUTUX is not set -+# CONFIG_USB_AUERSWALD is not set -+# CONFIG_USB_RIO500 is not set -+# CONFIG_USB_LEGOTOWER is not set -+# CONFIG_USB_LCD is not set -+# CONFIG_USB_BERRY_CHARGE is not set -+# CONFIG_USB_LED is not set -+# CONFIG_USB_CYPRESS_CY7C63 is not set -+# CONFIG_USB_CYTHERM is not set -+# CONFIG_USB_PHIDGET is not set -+# CONFIG_USB_IDMOUSE is not set -+# CONFIG_USB_FTDI_ELAN is not set -+# CONFIG_USB_APPLEDISPLAY is not set -+# CONFIG_USB_LD is not set -+# CONFIG_USB_TRANCEVIBRATOR is not set -+# CONFIG_USB_IOWARRIOR is not set -+# CONFIG_USB_TEST is not set -+ -+# -+# USB DSL modem support -+# -+ -+# -+# USB Gadget Support -+# -+# CONFIG_USB_GADGET is not set -+CONFIG_MMC=y -+# CONFIG_MMC_DEBUG is not set -+# CONFIG_MMC_UNSAFE_RESUME is not set -+ -+# -+# MMC/SD Card Drivers -+# -+CONFIG_MMC_BLOCK=y -+CONFIG_MMC_BLOCK_BOUNCE=y -+# CONFIG_SDIO_UART is not set -+ -+# -+# MMC/SD Host Controller Drivers -+# -+# CONFIG_MMC_ARMMMCI is not set -+CONFIG_MMC_SPI=y -+# -+# SimOne LCD support -+# -+CONFIG_LCD_LINUX=m -+CONFIG_LCD_HD44780=m -+# -+# CONFIG_NEW_LEDS is not set -+CONFIG_RTC_LIB=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_HCTOSYS=y -+CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -+# CONFIG_RTC_DEBUG is not set -+ -+# -+# RTC interfaces -+# -+CONFIG_RTC_INTF_SYSFS=y -+CONFIG_RTC_INTF_PROC=y -+CONFIG_RTC_INTF_DEV=y -+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -+# CONFIG_RTC_DRV_TEST is not set -+ -+# -+# I2C RTC drivers -+# -+CONFIG_RTC_DRV_DS1307=y -+# CONFIG_RTC_DRV_DS1374 is not set -+# CONFIG_RTC_DRV_DS1672 is not set -+# CONFIG_RTC_DRV_MAX6900 is not set -+# CONFIG_RTC_DRV_RS5C372 is not set -+# CONFIG_RTC_DRV_ISL1208 is not set -+# CONFIG_RTC_DRV_X1205 is not set -+# CONFIG_RTC_DRV_PCF8563 is not set -+# CONFIG_RTC_DRV_PCF8583 is not set -+# CONFIG_RTC_DRV_M41T80 is not set -+ -+# -+# SPI RTC drivers -+# -+# CONFIG_RTC_DRV_RS5C348 is not set -+# CONFIG_RTC_DRV_MAX6902 is not set -+ -+# -+# Platform RTC drivers -+# -+# CONFIG_RTC_DRV_CMOS is not set -+# CONFIG_RTC_DRV_DS1553 is not set -+# CONFIG_RTC_DRV_STK17TA8 is not set -+# CONFIG_RTC_DRV_DS1742 is not set -+# CONFIG_RTC_DRV_M48T86 is not set -+# CONFIG_RTC_DRV_M48T59 is not set -+# CONFIG_RTC_DRV_V3020 is not set -+ -+# -+# on-CPU RTC drivers -+# -+CONFIG_RTC_DRV_EP93XX=y -+CONFIG_RTC_DRV_EP93XX_DS1337=y -+# CONFIG_RTC_DRV_PL031 is not set -+ -+# -+# File systems -+# -+CONFIG_EXT2_FS=y -+CONFIG_EXT2_FS_XATTR=y -+CONFIG_EXT2_FS_POSIX_ACL=y -+CONFIG_EXT2_FS_SECURITY=y -+# CONFIG_EXT2_FS_XIP is not set -+CONFIG_EXT3_FS=y -+# CONFIG_EXT3_FS_XATTR is not set -+# CONFIG_EXT4DEV_FS is not set -+CONFIG_JBD=y -+CONFIG_FS_MBCACHE=y -+# CONFIG_REISERFS_FS is not set -+# CONFIG_JFS_FS is not set -+CONFIG_FS_POSIX_ACL=y -+# CONFIG_XFS_FS is not set -+# CONFIG_GFS2_FS is not set -+# CONFIG_OCFS2_FS is not set -+# CONFIG_MINIX_FS is not set -+CONFIG_ROMFS_FS=y -+CONFIG_INOTIFY=y -+CONFIG_INOTIFY_USER=y -+# CONFIG_QUOTA is not set -+CONFIG_DNOTIFY=y -+# CONFIG_AUTOFS_FS is not set -+CONFIG_AUTOFS4_FS=y -+# CONFIG_FUSE_FS is not set -+ -+# -+# CD-ROM/DVD Filesystems -+# -+CONFIG_ISO9660_FS=y -+CONFIG_JOLIET=y -+# CONFIG_ZISOFS is not set -+CONFIG_UDF_FS=y -+CONFIG_UDF_NLS=y -+ -+# -+# DOS/FAT/NT Filesystems -+# -+CONFIG_FAT_FS=y -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_CODEPAGE=437 -+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -+# CONFIG_NTFS_FS is not set -+ -+# -+# Pseudo filesystems -+# -+CONFIG_PROC_FS=y -+CONFIG_PROC_SYSCTL=y -+CONFIG_SYSFS=y -+CONFIG_TMPFS=y -+# CONFIG_TMPFS_POSIX_ACL is not set -+# CONFIG_HUGETLB_PAGE is not set -+# CONFIG_CONFIGFS_FS is not set -+ -+# -+# Miscellaneous filesystems -+# -+# CONFIG_ADFS_FS is not set -+# CONFIG_AFFS_FS is not set -+# CONFIG_HFS_FS is not set -+# CONFIG_HFSPLUS_FS is not set -+# CONFIG_BEFS_FS is not set -+# CONFIG_BFS_FS is not set -+# CONFIG_EFS_FS is not set -+CONFIG_JFFS2_FS=y -+CONFIG_JFFS2_FS_DEBUG=0 -+CONFIG_JFFS2_FS_WRITEBUFFER=y -+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -+# CONFIG_JFFS2_SUMMARY is not set -+# CONFIG_JFFS2_FS_XATTR is not set -+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -+CONFIG_JFFS2_ZLIB=y -+# CONFIG_JFFS2_LZO is not set -+CONFIG_JFFS2_RTIME=y -+# CONFIG_JFFS2_RUBIN is not set -+# CONFIG_CRAMFS is not set -+# CONFIG_VXFS_FS is not set -+# CONFIG_HPFS_FS is not set -+# CONFIG_QNX4FS_FS is not set -+# CONFIG_SYSV_FS is not set -+# CONFIG_UFS_FS is not set -+CONFIG_NETWORK_FILESYSTEMS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3=y -+# CONFIG_NFS_V3_ACL is not set -+# CONFIG_NFS_V4 is not set -+# CONFIG_NFS_DIRECTIO is not set -+# CONFIG_NFSD is not set -+CONFIG_ROOT_NFS=y -+CONFIG_LOCKD=y -+CONFIG_LOCKD_V4=y -+CONFIG_NFS_COMMON=y -+CONFIG_SUNRPC=y -+# CONFIG_SUNRPC_BIND34 is not set -+# CONFIG_RPCSEC_GSS_KRB5 is not set -+# CONFIG_RPCSEC_GSS_SPKM3 is not set -+# CONFIG_SMB_FS is not set -+# CONFIG_CIFS is not set -+# CONFIG_NCP_FS is not set -+# CONFIG_CODA_FS is not set -+# CONFIG_AFS_FS is not set -+ -+# -+# Partition Types -+# -+CONFIG_PARTITION_ADVANCED=y -+# CONFIG_ACORN_PARTITION is not set -+# CONFIG_OSF_PARTITION is not set -+# CONFIG_AMIGA_PARTITION is not set -+# CONFIG_ATARI_PARTITION is not set -+# CONFIG_MAC_PARTITION is not set -+CONFIG_MSDOS_PARTITION=y -+# CONFIG_BSD_DISKLABEL is not set -+# CONFIG_MINIX_SUBPARTITION is not set -+# CONFIG_SOLARIS_X86_PARTITION is not set -+# CONFIG_UNIXWARE_DISKLABEL is not set -+# CONFIG_LDM_PARTITION is not set -+# CONFIG_SGI_PARTITION is not set -+# CONFIG_ULTRIX_PARTITION is not set -+# CONFIG_SUN_PARTITION is not set -+# CONFIG_KARMA_PARTITION is not set -+# CONFIG_EFI_PARTITION is not set -+# CONFIG_SYSV68_PARTITION is not set -+CONFIG_NLS=y -+CONFIG_NLS_DEFAULT="iso8859-1" -+CONFIG_NLS_CODEPAGE_437=y -+# CONFIG_NLS_CODEPAGE_737 is not set -+# CONFIG_NLS_CODEPAGE_775 is not set -+# CONFIG_NLS_CODEPAGE_850 is not set -+# CONFIG_NLS_CODEPAGE_852 is not set -+# CONFIG_NLS_CODEPAGE_855 is not set -+# CONFIG_NLS_CODEPAGE_857 is not set -+# CONFIG_NLS_CODEPAGE_860 is not set -+# CONFIG_NLS_CODEPAGE_861 is not set -+# CONFIG_NLS_CODEPAGE_862 is not set -+# CONFIG_NLS_CODEPAGE_863 is not set -+# CONFIG_NLS_CODEPAGE_864 is not set -+# CONFIG_NLS_CODEPAGE_865 is not set -+# CONFIG_NLS_CODEPAGE_866 is not set -+# CONFIG_NLS_CODEPAGE_869 is not set -+# CONFIG_NLS_CODEPAGE_936 is not set -+# CONFIG_NLS_CODEPAGE_950 is not set -+# CONFIG_NLS_CODEPAGE_932 is not set -+# CONFIG_NLS_CODEPAGE_949 is not set -+# CONFIG_NLS_CODEPAGE_874 is not set -+# CONFIG_NLS_ISO8859_8 is not set -+# CONFIG_NLS_CODEPAGE_1250 is not set -+# CONFIG_NLS_CODEPAGE_1251 is not set -+# CONFIG_NLS_ASCII is not set -+CONFIG_NLS_ISO8859_1=y -+# CONFIG_NLS_ISO8859_2 is not set -+# CONFIG_NLS_ISO8859_3 is not set -+# CONFIG_NLS_ISO8859_4 is not set -+# CONFIG_NLS_ISO8859_5 is not set -+# CONFIG_NLS_ISO8859_6 is not set -+# CONFIG_NLS_ISO8859_7 is not set -+# CONFIG_NLS_ISO8859_9 is not set -+# CONFIG_NLS_ISO8859_13 is not set -+# CONFIG_NLS_ISO8859_14 is not set -+# CONFIG_NLS_ISO8859_15 is not set -+# CONFIG_NLS_KOI8_R is not set -+# CONFIG_NLS_KOI8_U is not set -+# CONFIG_NLS_UTF8 is not set -+# CONFIG_DLM is not set -+# CONFIG_INSTRUMENTATION is not set -+ -+# -+# Kernel hacking -+# -+# CONFIG_PRINTK_TIME is not set -+# CONFIG_ENABLE_WARN_DEPRECATED is not set -+# CONFIG_ENABLE_MUST_CHECK is not set -+# CONFIG_MAGIC_SYSRQ is not set -+# CONFIG_UNUSED_SYMBOLS is not set -+# CONFIG_DEBUG_FS is not set -+# CONFIG_HEADERS_CHECK is not set -+# CONFIG_DEBUG_KERNEL is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+CONFIG_FRAME_POINTER=y -+# CONFIG_SAMPLES is not set -+CONFIG_DEBUG_USER=y -+ -+# -+# Security options -+# -+# CONFIG_KEYS is not set -+# CONFIG_SECURITY is not set -+# CONFIG_SECURITY_FILE_CAPABILITIES is not set -+CONFIG_CRYPTO=y -+CONFIG_CRYPTO_ALGAPI=y -+CONFIG_CRYPTO_BLKCIPHER=y -+CONFIG_CRYPTO_MANAGER=y -+# CONFIG_CRYPTO_HMAC is not set -+# CONFIG_CRYPTO_XCBC is not set -+# CONFIG_CRYPTO_NULL is not set -+# CONFIG_CRYPTO_MD4 is not set -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_SHA1=y -+# CONFIG_CRYPTO_SHA256 is not set -+# CONFIG_CRYPTO_SHA512 is not set -+# CONFIG_CRYPTO_WP512 is not set -+# CONFIG_CRYPTO_TGR192 is not set -+# CONFIG_CRYPTO_GF128MUL is not set -+CONFIG_CRYPTO_ECB=m -+CONFIG_CRYPTO_CBC=m -+CONFIG_CRYPTO_PCBC=y -+# CONFIG_CRYPTO_LRW is not set -+# CONFIG_CRYPTO_XTS is not set -+# CONFIG_CRYPTO_CRYPTD is not set -+CONFIG_CRYPTO_DES=y -+# CONFIG_CRYPTO_FCRYPT is not set -+# CONFIG_CRYPTO_BLOWFISH is not set -+# CONFIG_CRYPTO_TWOFISH is not set -+# CONFIG_CRYPTO_SERPENT is not set -+CONFIG_CRYPTO_AES=y -+# CONFIG_CRYPTO_CAST5 is not set -+# CONFIG_CRYPTO_CAST6 is not set -+# CONFIG_CRYPTO_TEA is not set -+CONFIG_CRYPTO_ARC4=y -+# CONFIG_CRYPTO_KHAZAD is not set -+# CONFIG_CRYPTO_ANUBIS is not set -+# CONFIG_CRYPTO_SEED is not set -+# CONFIG_CRYPTO_DEFLATE is not set -+CONFIG_CRYPTO_MICHAEL_MIC=y -+# CONFIG_CRYPTO_CRC32C is not set -+# CONFIG_CRYPTO_CAMELLIA is not set -+# CONFIG_CRYPTO_TEST is not set -+# CONFIG_CRYPTO_AUTHENC is not set -+# CONFIG_CRYPTO_HW is not set -+ -+# -+# Library routines -+# -+CONFIG_BITREVERSE=y -+# CONFIG_CRC_CCITT is not set -+# CONFIG_CRC16 is not set -+CONFIG_CRC_ITU_T=y -+CONFIG_CRC32=y -+CONFIG_CRC7=y -+CONFIG_LIBCRC32C=y -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=y -+CONFIG_PLIST=y -+CONFIG_HAS_IOMEM=y -+CONFIG_HAS_IOPORT=y -+CONFIG_HAS_DMA=y diff --git a/target/linux/ep93xx/patches-2.6.30/012-ep93xx-cpuinfo.patch b/target/linux/ep93xx/patches-2.6.30/012-ep93xx-cpuinfo.patch deleted file mode 100644 index d2845c910a..0000000000 --- a/target/linux/ep93xx/patches-2.6.30/012-ep93xx-cpuinfo.patch +++ /dev/null @@ -1,32 +0,0 @@ -Index: linux-2.6.30.9/arch/arm/kernel/setup.c -=================================================================== ---- linux-2.6.30.9.orig/arch/arm/kernel/setup.c 2009-11-24 21:00:10.000000000 +0100 -+++ linux-2.6.30.9/arch/arm/kernel/setup.c 2009-11-24 21:00:46.000000000 +0100 -@@ -42,6 +42,10 @@ - #include <asm/traps.h> - #include <asm/unwind.h> - -+#if defined(CONFIG_ARCH_EP93XX) -+#include <mach/ep93xx-regs.h> -+#endif -+ - #include "compat.h" - #include "atags.h" - -@@ -844,9 +848,16 @@ - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); -+#if defined(CONFIG_ARCH_EP93XX) -+ seq_printf(m, "Revision\t: %04x\n", -+ *((unsigned int *)EP93XX_SYSCON_CHIP_ID) >> 28); -+ seq_printf(m, "Serial\t\t: %016x\n", -+ *((unsigned int *)EP93XX_SECURITY_UNIQID)); -+#else - seq_printf(m, "Revision\t: %04x\n", system_rev); - seq_printf(m, "Serial\t\t: %08x%08x\n", - system_serial_high, system_serial_low); -+#endif - - return 0; - } diff --git a/target/linux/ep93xx/patches-2.6.36/001-ep93xx_cpuinfo.patch b/target/linux/ep93xx/patches-2.6.36/001-ep93xx_cpuinfo.patch deleted file mode 100644 index 171787e879..0000000000 --- a/target/linux/ep93xx/patches-2.6.36/001-ep93xx_cpuinfo.patch +++ /dev/null @@ -1,59 +0,0 @@ -This patch puts the EP93xx chip revision and unique ID into /proc/cpuinfo. -This is necessary to be able to set a unique MAC address for DHCP purposes -by adding a line to /etc/network/interfaces: - -# Generate a unique locally-assigned MAC address from the CPU serial number -pre-up ifconfig eth0 hw ether `sed -n 's/^Serial.* 000000/02/p' /proc/cpuinfo` - -It uses the chip revision reading code in the ep93xx-chip-revision patch. - -Really, this is wrong, since /proc/cpuinfo should report the revision and -serial number of the ARM920T processor, while these are the rev and serial -of the EP93xx SoC. In a future kernel (>2.6.34) there may be a new file -/proc/socinfo for this information. - - -martinwguy 14 May 2010 - ---- a/arch/arm/kernel/setup.c -+++ b/arch/arm/kernel/setup.c -@@ -47,6 +47,12 @@ - #include <asm/traps.h> - #include <asm/unwind.h> - -+#if defined(CONFIG_ARCH_EP93XX) -+#include <mach/io.h> -+#include <mach/ep93xx-regs.h> -+#include <mach/platform.h> -+#endif -+ - #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) - #include "compat.h" - #endif -@@ -953,9 +959,16 @@ static int c_show(struct seq_file *m, vo - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); -+#if defined(CONFIG_ARCH_EP93XX) -+ seq_printf(m, "Revision\t: %04x\n", -+ ep93xx_chip_revision()); -+ seq_printf(m, "Serial\t\t: %016x\n", -+ *((unsigned int *)EP93XX_SECURITY_UNIQID)); -+#else - seq_printf(m, "Revision\t: %04x\n", system_rev); - seq_printf(m, "Serial\t\t: %08x%08x\n", - system_serial_high, system_serial_low); -+#endif - - return 0; - } ---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -@@ -97,6 +97,8 @@ - #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) - - #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) -+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) - - #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) - #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) diff --git a/target/linux/ep93xx/patches-2.6.36/002-mmc_spi_fix_sdhc.patch b/target/linux/ep93xx/patches-2.6.36/002-mmc_spi_fix_sdhc.patch deleted file mode 100644 index 4c12b85181..0000000000 --- a/target/linux/ep93xx/patches-2.6.36/002-mmc_spi_fix_sdhc.patch +++ /dev/null @@ -1,74 +0,0 @@ -This patch makes SDHC cards work with the mmc_spi driver. - -The problem is that they fail when reading the last block of the card using -a multi-block read. This is because on SDHC the multiple block read has to be -stopped with an explicit STOP command, which needs to be sent to the card -while the incoming transfer is in progress. -The 2.6.3[45] mmc-spi driver sends it after the last block transfer, so the -SDHC card continues reading past the end of the card. -This patch works around this by using single-block reads if we're reading the -last blocks of the card. - -martinwguy, 14 May 2010 - -Date: Thu, 29 Apr 2010 21:30:36 +0300 -From: Mika Westerberg <mika.westerberg@iki.fi> -To: Martin Guy <martinwguy@gmail.com> - -On Wed, Apr 21, 2010 at 02:10:08AM +0100, Martin Guy wrote: -> -> the SDHC cards I have don't work at all, spewing tons of: -> mmcblk0: error -38 sending status comand -> mmcblk0: error -38 sending read/write command, response 0x4, card status 0xff04 -> end_request: I/O error, dev mmcblk0, sector 7744509 - -I bought today a new 4GB SDHC card and with that I get similar -errors that you are getting. I hacked around quick fix which seems -to work in my case. I'm wondering whether you could check if it -helps with your SDHC card as well? - -This problem is easy to reproduce, just read last sector of the -card (I wrote simple C program but running fdisk -l does the same). - -Patch is below. - -Thanks, -MW - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Thu, 29 Apr 2010 21:14:32 +0300 -Subject: [PATCH] mmc_block: use single block reads for last block on SPI - -Some SD-cards fail when doing multiblock read for last block with SPI host. Real -reason is not known but as workaround we can perform this last read using -multiple single block reads. - -Signed-off-by: Mika Westerberg <mika.westerberg@iki.fi> ---- - drivers/mmc/card/block.c | 19 +++++++++++++++++++ - 1 files changed, 19 insertions(+), 0 deletions(-) - ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -351,6 +351,22 @@ static int mmc_blk_issue_rw_rq(struct mm - if (brq.data.blocks > card->host->max_blk_count) - brq.data.blocks = card->host->max_blk_count; - -+ if (mmc_host_is_spi(card->host)) { -+ /* -+ * Some SD-cards fail when we are reading last block -+ * with multiblock read. In these cases we automatically -+ * use single block reads. This only happens on SPI -+ * hosts. -+ */ -+ if (rq_data_dir(req) == READ && brq.data.blocks > 1) { -+ sector_t s = blk_rq_pos(req) + brq.data.blocks; -+ -+ if (s >= get_capacity(md->disk)) { -+ disable_multi = 1; -+ } -+ } -+ } -+ - /* - * After a read error, we redo the request one sector at a time - * in order to accurately determine which sectors can be read diff --git a/target/linux/ep93xx/patches-2.6.36/003-ep93xx_touchscreen.patch b/target/linux/ep93xx/patches-2.6.36/003-ep93xx_touchscreen.patch deleted file mode 100644 index 09cae7aa0c..0000000000 --- a/target/linux/ep93xx/patches-2.6.36/003-ep93xx_touchscreen.patch +++ /dev/null @@ -1,1060 +0,0 @@ ---- - arch/arm/mach-ep93xx/include/mach/hardware.h | 1 - arch/arm/mach-ep93xx/include/mach/regs_touch.h | 95 ++ - drivers/input/touchscreen/Kconfig | 5 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/ep93xx_ts.c | 1117 +++++++++++++++++++++++++ - drivers/input/touchscreen/ep93xx_ts.h | 53 + - 6 files changed, 1272 insertions(+) - ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -153,6 +153,15 @@ config TOUCHSCREEN_EETI - To compile this driver as a module, choose M here: the - module will be called eeti_ts. - -+config TOUCHSCREEN_EP93XX -+ tristate "EP93xx Touchscreen" -+ depends on ARM && INPUT && ARCH_EP93XX -+ help -+ Say Y here to enable support for EP93xx touch screen. -+ -+ To compile this driver as a module, choose M here: -+ the module will be called ep93xx_ts. -+ - config TOUCHSCREEN_FUJITSU - tristate "Fujitsu serial touchscreen" - select SERIO ---- a/drivers/input/touchscreen/Makefile -+++ b/drivers/input/touchscreen/Makefile -@@ -21,6 +21,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += h - obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o - obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o - obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -+obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o - obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o - obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o - obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o ---- /dev/null -+++ b/drivers/input/touchscreen/ep93xx_ts.c -@@ -0,0 +1,1020 @@ -+/* -+ * linux/drivers/input/touchscreen/ep93xx_ts.c -+ * -+ * Copyright (C) 2003-2004 Cirrus Corp. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/wait.h> -+#include <linux/fs.h> -+#include <linux/sched.h> -+#include <linux/poll.h> -+#include <linux/miscdevice.h> -+#include <linux/init.h> -+#include <linux/compiler.h> -+#include <linux/timer.h> -+#include <linux/interrupt.h> -+#include <linux/syscalls.h> -+#include <linux/input.h> -+#include <asm/irq.h> -+#include <mach/hardware.h> -+#include <asm/io.h> -+ -+/* This stuff should be in ep93xx-regs.h */ -+#define EP93XX_TOUCHSCREEN_REG(x) (EP93XX_TOUCHSCREEN_BASE + (x)) -+/* R/W touchscreen controller setup control register. */ -+#define EP93XX_TOUCHSCREEN_SETUP EP93XX_TOUCHSCREEN_REG(0x00) -+/* R/W touchscreen controller max/min register. */ -+#define EP93XX_TOUCHSCREEN_XYMAXMIN EP93XX_TOUCHSCREEN_REG(0x04) -+/* R touchscreen controller result register. */ -+#define EP93XX_TOUCHSCREEN_XYRESULT EP93XX_TOUCHSCREEN_REG(0x08) -+/* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define EP93XX_TOUCHSCREEN_DISCHARGE EP93XX_TOUCHSCREEN_REG(0x0C) -+#define EP93XX_TOUCHSCREEN_XSAMPLE EP93XX_TOUCHSCREEN_REG(0x10) -+#define EP93XX_TOUCHSCREEN_YSAMPLE EP93XX_TOUCHSCREEN_REG(0x14) -+#define EP93XX_TOUCHSCREEN_DIRECT EP93XX_TOUCHSCREEN_REG(0x18) -+#define EP93XX_TOUCHSCREEN_DETECT EP93XX_TOUCHSCREEN_REG(0x1C) -+/* NA R/W touchscreen software lock register. */ -+#define EP93XX_TOUCHSCREEN_SWLOCK EP93XX_TOUCHSCREEN_REG(0x20) -+/* R/W touchscreen setup control register #2. */ -+#define EP93XX_TOUCHSCREEN_SETUP2 EP93XX_TOUCHSCREEN_REG(0x24) -+ -+/* These are duplicated in mach-ep93xx/core.c */ -+#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -+#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -+#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -+#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -+#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -+ -+/* -+ * Register bit definitions -+ */ -+#define TSSETUP_SDLY_MASK 0x000003FF -+#define TSSETUP_SDLY_SHIFT 0 -+#define TSSETUP_NSMP_4 0x00000000 -+#define TSSETUP_NSMP_8 0x00000400 -+#define TSSETUP_NSMP_16 0x00000800 -+#define TSSETUP_NSMP_32 0x00000C00 -+#define TSSETUP_NSMP_MASK 0x00000C00 -+#define TSSETUP_DEV_4 0x00000000 -+#define TSSETUP_DEV_8 0x00001000 -+#define TSSETUP_DEV_12 0x00002000 -+#define TSSETUP_DEV_16 0x00003000 -+#define TSSETUP_DEV_24 0x00004000 -+#define TSSETUP_DEV_32 0x00005000 -+#define TSSETUP_DEV_64 0x00006000 -+#define TSSETUP_DEV_128 0x00007000 -+#define TSSETUP_ENABLE 0x00008000 -+#define TSSETUP_DLY_MASK 0x03FF0000 -+#define TSSETUP_DLY_SHIFT 16 -+#define TSSETUP_TDTCT 0x80000000 -+ -+#define TSMAXMIN_XMIN_MASK 0x000000FF -+#define TSMAXMIN_XMIN_SHIFT 0 -+#define TSMAXMIN_YMIN_MASK 0x0000FF00 -+#define TSMAXMIN_YMIN_SHIFT 8 -+#define TSMAXMIN_XMAX_MASK 0x00FF0000 -+#define TSMAXMIN_XMAX_SHIFT 16 -+#define TSMAXMIN_YMAX_MASK 0xFF000000 -+#define TSMAXMIN_YMAX_SHIFT 24 -+ -+#define TSXYRESULT_X_MASK 0x00000FFF -+#define TSXYRESULT_X_SHIFT 0 -+#define TSXYRESULT_AD_MASK 0x0000FFFF -+#define TSXYRESULT_AD_SHIFT 0 -+#define TSXYRESULT_Y_MASK 0x0FFF0000 -+#define TSXYRESULT_Y_SHIFT 16 -+#define TSXYRESULT_SDR 0x80000000 -+ -+#define TSX_SAMPLE_MASK 0x00003FFF -+#define TSX_SAMPLE_SHIFT 0x00 -+#define TSY_SAMPLE_MASK 0x3FFF0000 -+#define TSY_SAMPLE_SHIFT 0x10 -+ -+#define TSSETUP2_TINT 0x00000001 -+#define TSSETUP2_NICOR 0x00000002 -+#define TSSETUP2_PINT 0x00000004 -+#define TSSETUP2_PENSTS 0x00000008 -+#define TSSETUP2_PINTEN 0x00000010 -+#define TSSETUP2_DEVINT 0x00000020 -+#define TSSETUP2_DINTEN 0x00000040 -+#define TSSETUP2_DTMEN 0x00000080 -+#define TSSETUP2_DISDEV 0x00000100 -+#define TSSETUP2_NSIGND 0x00000200 -+#define TSSETUP2_S28EN 0x00000400 -+#define TSSETUP2_RINTEN 0x00000800 -+ -+#define TSXYRESULT_SDR 0x80000000 -+ -+/* -+ * These are used as trigger levels to know when we have pen up/down. -+ * The rules: -+ * 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these -+ * are Inverse pressure. -+ * 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up. -+ * 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down. -+ */ -+#define TS_HEAVY_INV_PRESSURE 0xFE0 /* C00 */ -+#define TS_LIGHT_INV_PRESSURE 0xFFF /* e00 */ -+ -+/* -+ * If the x, y, or inverse pressure changes more than these values -+ * between two succeeding points, the point is not reported. -+ */ -+#define TS_MAX_VALID_XY_CHANGE 0x300 -+#define TS_MAX_VALID_PRESSURE_CHANGE 0x100 -+ -+/* -+ * This is the minimum Z1 Value that is valid. -+ */ -+#define MIN_Z1_VALUE 0x50 -+ -+/* -+ * Settling delay for taking each ADC measurement. Increase this -+ * if ts is jittery. -+ */ -+#define EP93XX_TS_ADC_DELAY_USEC 2000 -+ -+/* -+ * Delay between TS points. -+ */ -+#define EP93XX_TS_PER_POINT_DELAY_USEC 10000 -+ -+/* -+ * A few more macros... -+ */ -+#define TSSETUP_DEFAULT (TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \ -+ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \ -+ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK)) -+ -+#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND) -+ -+/* -+ * For now, we use one of the minor numbers from the local/experimental -+ * range. -+ */ -+#define EP93XX_TS_MINOR 240 -+ -+/* -+ * Static Declarations -+ */ -+static unsigned int guiLastX, guiLastY; -+static unsigned int guiLastInvPressure; -+ -+struct TouchScreenSample -+{ -+ int currentX; -+ int currentY; -+ int currentButton; -+ int currentPressure; -+ struct timeval currentTime; -+}; -+ -+/* -+ * This must match the structure in tslib. -+ */ -+struct ts_sample { -+ int x; -+ int y; -+ unsigned int pressure; -+ struct timeval tv; -+}; -+ -+static struct TouchScreenSample gSample; -+static int bFreshTouchData; -+static int bCurrentPenDown; -+ -+static DECLARE_WAIT_QUEUE_HEAD(queue); -+static DECLARE_MUTEX(open_sem); -+static spinlock_t event_buffer_lock = SPIN_LOCK_UNLOCKED; -+static struct fasync_struct *ep93xx_fasync; -+ -+/* -+ * Typedef Declarations -+ */ -+typedef enum { -+ TS_MODE_UN_INITIALIZED, -+ TS_MODE_HARDWARE_SCAN, -+ TS_MODE_SOFT_SCAN -+} ts_mode_t; -+ -+static ts_mode_t gScanningMode; -+ -+typedef enum{ -+ TS_STATE_STOPPED = 0, -+ TS_STATE_Z1, -+ TS_STATE_Z2, -+ TS_STATE_Y, -+ TS_STATE_X, -+ TS_STATE_DONE -+} ts_states_t; -+ -+typedef struct -+{ -+ unsigned int uiX; -+ unsigned int uiY; -+ unsigned int uiZ1; -+ unsigned int uiZ2; -+ ts_states_t state; -+} ts_struct_t; -+ -+static ts_struct_t sTouch; -+ -+/* -+ * From the spec, here's how to set up the touch screen's switch registers. -+ */ -+typedef struct -+{ -+ unsigned int uiDetect; -+ unsigned int uiDischarge; -+ unsigned int uiXSample; -+ unsigned int uiYSample; -+ unsigned int uiSwitchZ1; -+ unsigned int uiSwitchZ2; -+}SwitchStructType; -+ -+/* -+ * Here's the switch settings for a 4-wire touchscreen. See the spec -+ * for how to handle a 4, 7, or 8-wire. -+ */ -+const static SwitchStructType sSwitchSettings = -+/* s28en=0 */ -+/* TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2 */ -+ {0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608}; -+ -+/* -+ * Function declarations -+ */ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch); -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id); -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id); -+static void ee93xx_ts_evt_add(int button, int dX, int dY, int Pressure); -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, -+ size_t count, loff_t *l); -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait); -+static int ep93xx_ts_open(struct inode *inode, struct file *filp); -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on); -+static int ep93xx_ts_release(struct inode *inode, struct file *filp); -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos); -+static void ep93xx_ts_setup(void); -+static void ep93xx_ts_shutdown(void); -+int __init ep93xx_ts_init(void); -+void __exit ep93xx_ts_exit(void); -+static unsigned int CalculateInvPressure(void); -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff); -+static void TS_Soft_Scan_Mode(void); -+static void TS_Hardware_Scan_Mode(void); -+static void ProcessPointData(void); -+static void Set_Timer2_uSec(unsigned int Delay_mSec); -+static void Stop_Timer2(void); -+ -+/* -+ * ep93xx_ts_isr -+ */ -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id) -+{ -+ /* -+ * Note that we don't clear the interrupt here. The interrupt -+ * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE -+ * bit is cleared. -+ */ -+ -+ /* -+ * Set the ts to manual polling mode and schedule a callback. -+ * That way we can return from the isr in a reasonable amount of -+ * time and process the touch in the callback after a brief delay. -+ */ -+ TS_Soft_Scan_Mode(); -+ -+ return(IRQ_HANDLED); -+} -+ -+/* -+ * Save the current ts 'event' in an atomic fashion. -+ */ -+static void ee93xx_ts_evt_add(int buttons, int iX, int iY, int iPressure) -+{ -+ /* -+ * Note the event, but use spinlocks to keep it from getting -+ * halfway read if we get interrupted. -+ */ -+ -+ spin_lock(&event_buffer_lock); -+ -+ gSample.currentX = iX; -+ gSample.currentY = iY; -+ gSample.currentButton = buttons; -+ gSample.currentPressure = iPressure; -+ bFreshTouchData = 1; -+ do_gettimeofday(&gSample.currentTime); -+ -+ spin_unlock(&event_buffer_lock); -+ -+ kill_fasync(&ep93xx_fasync, SIGIO, POLL_IN); -+ wake_up_interruptible(&queue); -+} -+ -+ -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) -+{ -+ unsigned short data[3]; -+ struct ts_sample ts_data; -+ int iReturn = -EFAULT; -+ -+ if (!bFreshTouchData) -+ { -+ iReturn = 0; -+ } -+ else if (count == sizeof(data)) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ data[0] = gSample.currentX; -+ data[1] = gSample.currentY; -+ data[2] = gSample.currentButton; -+ -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, data, sizeof data)) -+ return -EFAULT; -+ -+ count -= sizeof(data); -+ -+ /* return the # of bytes that got read */ -+ iReturn = sizeof(data) ; -+ } -+ else if (count == sizeof(struct ts_sample) ) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ ts_data.x = gSample.currentX; -+ ts_data.y = gSample.currentY; -+ ts_data.pressure = gSample.currentPressure; -+ ts_data.tv = gSample.currentTime; -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, &ts_data, sizeof(struct ts_sample))) -+ { -+ iReturn = -EFAULT; -+ } -+ else -+ { -+ count -= sizeof(ts_data); -+ iReturn = sizeof(ts_data); -+ } -+ } -+ -+ return iReturn; -+} -+ -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait) -+{ -+ poll_wait(filp, &queue, wait); -+ -+ if (bFreshTouchData) -+ { -+ return POLLIN | POLLRDNORM; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_open(struct inode *inode, struct file *filp) -+{ -+ if (down_trylock(&open_sem)) -+ { -+ return -EBUSY; -+ } -+ -+ ep93xx_ts_setup(); -+ -+ return 0; -+} -+ -+/* -+ * Asynchronous I/O support. -+ */ -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on) -+{ -+ int retval; -+ -+ retval = fasync_helper(fd, filp, on, &ep93xx_fasync); -+ if (retval < 0) -+ { -+ return retval; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_release(struct inode *inode, struct file *filp) -+{ -+ Stop_Timer2(); -+ -+ /* -+ * Call our async I/O support to request that this file -+ * cease to be used for async I/O. -+ */ -+ ep93xx_ts_fasync(-1, filp, 0); -+ -+ ep93xx_ts_shutdown(); -+ -+ up(&open_sem); -+ -+ return 0; -+} -+ -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ -+static int ep93xx_ts_ioctl(struct inode *inode, struct file *file, uint command, ulong u) -+{ -+ static const int version = EV_VERSION; -+ static const u_int32_t bit =(1 << EV_ABS); -+ static const u_int32_t absbit = (1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_PRESSURE); -+ int iReturn ; -+ int i = 0; -+ -+ switch(command) -+ { -+ case EVIOCGVERSION: -+ i = copy_to_user((void __user *)u, (void *)version, sizeof(version)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(0,sizeof(u_int32_t) * 8) : -+ i = copy_to_user((void __user *)u, (void *)bit, sizeof(bit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(EV_ABS, sizeof(absbit) * 8): -+ i = copy_to_user((void __user *)u, (void *)absbit, sizeof(absbit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ default: -+ iReturn = -1; -+ break; -+ } -+ -+ return iReturn; -+} -+ -+static struct file_operations ep93xx_ts_fops = { -+ owner: THIS_MODULE, -+ read: ep93xx_ts_read, -+ write: ep93xx_ts_write, -+ poll: ep93xx_ts_poll, -+ open: ep93xx_ts_open, -+ unlocked_ioctl: ep93xx_ts_ioctl, -+ release: ep93xx_ts_release, -+ fasync: ep93xx_ts_fasync, -+}; -+ -+static struct miscdevice ep93xx_ts_miscdev = -+{ -+ EP93XX_TS_MINOR, -+ "ep93xx_ts", -+ &ep93xx_ts_fops -+}; -+ -+void ep93xx_ts_setup(void) -+{ -+ unsigned int uiKTDIV, uiTSXYMaxMin; -+ -+ /* -+ * Set the TSEN bit in KTDIV so that we are enabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV |= EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+ /* -+ * Program the EP93XX_TOUCHSCREEN_SETUP and TSSetup2 registers. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Set the the touch settings. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DISCHARGE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ1, EP93XX_TOUCHSCREEN_XSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ2, EP93XX_TOUCHSCREEN_YSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDetect, EP93XX_TOUCHSCREEN_DETECT); -+ -+ /* -+ * X,YMin set to 0x40 = have to drag that many pixels for a new irq. -+ * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the -+ * time scan limit. -+ */ -+ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK; -+ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK; -+ __raw_writel(uiTSXYMaxMin, EP93XX_TOUCHSCREEN_XYMAXMIN); -+ -+ bCurrentPenDown = 0; -+ bFreshTouchData = 0; -+ guiLastX = 0; -+ guiLastY = 0; -+ guiLastInvPressure = 0xffffff; -+ -+ /* -+ * Enable the touch screen scanning engine. -+ */ -+ TS_Hardware_Scan_Mode(); -+} -+ -+/* -+ * ep93xx_ts_shutdown -+ * -+ */ -+static void -+ep93xx_ts_shutdown(void) -+{ -+ unsigned int uiKTDIV; -+ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Disable the scanning engine. -+ */ -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Clear the TSEN bit in KTDIV so that we are disabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV &= ~EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+} /* ep93xx_ts_shutdown */ -+ -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id) -+{ -+ switch(sTouch.state) -+ { -+ case TS_STATE_STOPPED: -+ TS_Hardware_Scan_Mode(); -+ break; -+ -+ /* -+ * Get the Z1 value for pressure measurement and set up -+ * the switch register for getting the Z2 measurement. -+ */ -+ case TS_STATE_Z1: -+ Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC); -+ sTouch.uiZ1 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2); -+ sTouch.state = TS_STATE_Z2; -+ break; -+ -+ /* -+ * Get the Z2 value for pressure measurement and set up -+ * the switch register for getting the Y measurement. -+ */ -+ case TS_STATE_Z2: -+ sTouch.uiZ2 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiYSample); -+ sTouch.state = TS_STATE_Y; -+ break; -+ -+ /* -+ * Get the Y value and set up the switch register for -+ * getting the X measurement. -+ */ -+ case TS_STATE_Y: -+ sTouch.uiY = ADCGetData(4, 20); -+ ep93xx_ts_set_direct(sSwitchSettings.uiXSample); -+ sTouch.state = TS_STATE_X; -+ break; -+ -+ /* -+ * Read the X value. This is the last of the 4 adc values -+ * we need so we continue on to process the data. -+ */ -+ case TS_STATE_X: -+ Stop_Timer2(); -+ -+ sTouch.uiX = ADCGetData(4, 20); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ sTouch.state = TS_STATE_DONE; -+ -+ /* -+ * Process this set of ADC readings. -+ */ -+ ProcessPointData(); -+ -+ break; -+ -+ /* -+ * Shouldn't get here. But if we do, we can recover... -+ */ -+ case TS_STATE_DONE: -+ TS_Hardware_Scan_Mode(); -+ break; -+ } -+ -+ /* -+ * Clear the timer2 interrupt. -+ */ -+ __raw_writel(1, EP93XX_TIMER2_CLEAR); -+ return(IRQ_HANDLED); -+} -+ -+/*--------------------------------------------------------------------- -+ * ProcessPointData -+ * -+ * This routine processes the ADC data into usable point data and then -+ * puts the driver into hw or sw scanning mode before returning. -+ * -+ * We calculate inverse pressure (lower number = more pressure) then -+ * do a hystheresis with the two pressure values 'light' and 'heavy'. -+ * -+ * If we are above the light, we have pen up. -+ * If we are below the heavy we have pen down. -+ * As long as the pressure stays below the light, pen stays down. -+ * When we get above the light again, pen goes back up. -+ * -+ */ -+static void ProcessPointData(void) -+{ -+ int bValidPoint = 0; -+ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff; -+ unsigned int uiInvPressure; -+ -+ /* -+ * Calculate the current pressure. -+ */ -+ uiInvPressure = CalculateInvPressure(); -+ -+ /* -+ * If pen pressure is so light that it is greater than the 'max' setting -+ * then we consider this to be a pen up. -+ */ -+ if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) -+ { -+ bCurrentPenDown = 0; -+ ee93xx_ts_evt_add(0, guiLastX, guiLastY, 0); -+ TS_Hardware_Scan_Mode(); -+ return; -+ } -+ -+ /* -+ * Hysteresis: -+ * If the pen pressure is hard enough to be less than the 'min' OR -+ * the pen is already down and is still less than the 'max'... -+ */ -+ if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) || -+ (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) -+ { -+ if (bCurrentPenDown) -+ { -+ /* -+ * If pen was previously down, check the difference between -+ * the last sample and this one... if the difference between -+ * samples is too great, ignore the sample. -+ */ -+ uiXDiff = abs(guiLastX - sTouch.uiX); -+ uiYDiff = abs(guiLastY - sTouch.uiY); -+ uiInvPressureDiff = abs(guiLastInvPressure - uiInvPressure); -+ -+ if (uiXDiff < TS_MAX_VALID_XY_CHANGE -+ && uiYDiff < TS_MAX_VALID_XY_CHANGE -+ && uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE) -+ { -+ bValidPoint = 1; -+ } -+ } -+ else -+ { -+ bValidPoint = 1; -+ } -+ -+ /* -+ * If either the pen was put down or dragged make a note of it. -+ */ -+ if (bValidPoint) -+ { -+ guiLastX = sTouch.uiX; -+ guiLastY = sTouch.uiY; -+ guiLastInvPressure = uiInvPressure; -+ bCurrentPenDown = 1; -+ ee93xx_ts_evt_add(1, sTouch.uiX, sTouch.uiY, -+ 0x7000000 / uiInvPressure); -+ } -+ -+ TS_Soft_Scan_Mode(); -+ return; -+ } -+ -+ TS_Hardware_Scan_Mode(); -+} -+ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch) -+{ -+ unsigned int uiResult; -+ -+ /* -+ * Set the switch settings in the direct register. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(uiADCSwitch, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ /* -+ * Read and throw away the first sample. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+} -+ -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff) -+{ -+ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, uiAve; -+ -+ do -+ { -+ /* -+ * Initialize our values. -+ */ -+ uiLowest = 0xfffffff; -+ uiHighest = 0; -+ uiSum = 0; -+ -+ for (uiCount = 0; uiCount < uiSamples; uiCount++) -+ { -+ /* -+ * Read the touch screen four more times and average. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+ uiValue = (uiResult & TSXYRESULT_AD_MASK) >> TSXYRESULT_AD_SHIFT; -+ uiValue = ((uiValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1)) & TSXYRESULT_X_MASK; -+ -+ /* -+ * Add up the values. -+ */ -+ uiSum += uiValue; -+ -+ /* -+ * Get the lowest and highest values. -+ */ -+ if (uiValue < uiLowest) -+ { -+ uiLowest = uiValue; -+ } -+ if (uiValue > uiHighest) -+ { -+ uiHighest = uiValue; -+ } -+ } -+ } while ((uiHighest - uiLowest) > uiMaxDiff); -+ -+ /* -+ * Calculate the Average value. -+ */ -+ uiAve = uiSum / uiSamples; -+ -+ return uiAve; -+} -+ -+/* -+ * CalculateInvPressure -+ * -+ * Is the Touch Valid. Touch is not valid if the X or Y value is not -+ * in range and the pressure is not enough. -+ * -+ * Touch resistance can be measured by the following formula: -+ * -+ * Rx * X * Z2 -+ * Rtouch = --------- * (-- - 1) -+ * 4096 Z1 -+ * -+ * This is simplified in the ration of Rtouch to Rx. The lower the value, the -+ * higher the pressure. -+ * -+ * Z2 -+ * InvPressure = X * (-- - 1) -+ * Z1 -+ */ -+static unsigned int CalculateInvPressure(void) -+{ -+ unsigned int uiInvPressure; -+ -+ /* -+ * Check to see if the point is valid. -+ */ -+ if (sTouch.uiZ1 < MIN_Z1_VALUE) -+ { -+ uiInvPressure = 0x10000; -+ } -+ -+ /* -+ * Can omit the pressure calculation if you need to get rid of the division. -+ */ -+ else -+ { -+ uiInvPressure = ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX; -+ } -+ -+ return uiInvPressure; -+} -+ -+/* -+ * TS_Hardware_Scan_Mode -+ * -+ * Enables the ep93xx ts scanning engine so that when the pen goes down -+ * we will get an interrupt. -+ */ -+static void TS_Hardware_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ /* -+ * Disable the soft scanning engine. -+ */ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Clear the TIN (Touchscreen INactive) bit so we can go to -+ * automatic scanning mode. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg & ~EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ -+ /* -+ * Enable the touch screen scanning state machine by setting -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT | TSSETUP_ENABLE, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the flag to show that we are in interrupt mode. -+ */ -+ gScanningMode = TS_MODE_HARDWARE_SCAN; -+ -+ /* -+ * Initialize EP93XX_TOUCHSCREEN_SETUP2 register. -+ */ -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+} -+ -+/* -+ * TS_Soft_Scan_Mode -+ * -+ * Sets the touch screen to manual polling mode. -+ */ -+static void TS_Soft_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ if (gScanningMode != TS_MODE_SOFT_SCAN) -+ { -+ /* -+ * Disable the touch screen scanning state machine by clearing -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the TIN bit so we can do manual touchscreen polling. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg | EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ } -+ -+ /* -+ * Set the switch register up for the first ADC reading -+ */ -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1); -+ -+ /* -+ * Initialize our software state machine to know which ADC -+ * reading to take -+ */ -+ sTouch.state = TS_STATE_Z1; -+ -+ /* -+ * Set the timer so after a mSec or two settling delay it will -+ * take the first ADC reading. -+ */ -+ Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC); -+ -+ /* -+ * Note that we are in sw scanning mode not hw scanning mode. -+ */ -+ gScanningMode = TS_MODE_SOFT_SCAN; -+ -+} -+ -+static void Set_Timer2_uSec(unsigned int uiDelay_uSec) -+{ -+ unsigned int uiClockTicks; -+ -+ /* -+ * Stop timer 2 -+ */ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+ -+ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000; -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_LOAD); -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_VALUE); -+ -+ /* -+ * Set up Timer 2 for 508 kHz clock and periodic mode. -+ */ -+ __raw_writel(0xC8, EP93XX_TIMER2_CONTROL); -+ -+} -+ -+static void Stop_Timer2(void) -+{ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+} -+ -+/* -+ * Initialization and exit routines -+ */ -+int __init ep93xx_ts_init(void) -+{ -+ int retval; -+ -+ retval = request_irq(IRQ_EP93XX_TOUCH, ep93xx_ts_isr, -+ IRQF_DISABLED, "ep93xx_ts", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n"); -+ return retval; -+ } -+ -+ retval = request_irq(IRQ_EP93XX_TIMER2, ep93xx_timer2_isr, -+ IRQF_DISABLED, "ep93xx_timer2", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n"); -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ return retval; -+ } -+ -+ misc_register(&ep93xx_ts_miscdev); -+ -+ sTouch.state = TS_STATE_STOPPED; -+ gScanningMode = TS_MODE_UN_INITIALIZED; -+ -+ printk(KERN_NOTICE "ep93xx touchscreen driver configured for 4-wire operation\n"); -+ -+ return 0; -+} -+ -+void __exit ep93xx_ts_exit(void) -+{ -+ Stop_Timer2(); -+ -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ free_irq(IRQ_EP93XX_TIMER2, 0); -+ -+ misc_deregister(&ep93xx_ts_miscdev); -+} -+ -+module_init(ep93xx_ts_init); -+module_exit(ep93xx_ts_exit); -+ -+MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver"); -+MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ep93xx/patches-2.6.36/004-simone_add_mmc_spi.patch b/target/linux/ep93xx/patches-2.6.36/004-simone_add_mmc_spi.patch deleted file mode 100644 index 52199baef9..0000000000 --- a/target/linux/ep93xx/patches-2.6.36/004-simone_add_mmc_spi.patch +++ /dev/null @@ -1,179 +0,0 @@ -This enables the mmc-over-spi driver for the Sim.One board, based on Mika's -patch, which used a GPIO for chip select in stead of the default SFRMOUT pin. -I've modified it to use the usual SFRMOUT; if you've modified your Sim.One -board to use a GPIO instead, uncomment and modify -// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -in the source file. - -martinwguy, 14 May 2010 - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Wed, 28 Apr 2010 08:42:46 +0300 -Subject: [PATCH] ep93xx: simone: added board specific SPI support for MMC/SD cards - -This includes setting up EGPIOs 0 and 9 for card detection and chip select -respectively. - ---- a/arch/arm/mach-ep93xx/simone.c -+++ b/arch/arm/mach-ep93xx/simone.c -@@ -18,12 +18,16 @@ - #include <linux/kernel.h> - #include <linux/init.h> - #include <linux/platform_device.h> -+#include <linux/mmc/host.h> - #include <linux/gpio.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/mmc_spi.h> - #include <linux/i2c.h> - #include <linux/i2c-gpio.h> - - #include <mach/hardware.h> - #include <mach/fb.h> -+#include <mach/ep93xx_spi.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -38,6 +42,135 @@ static struct ep93xxfb_mach_info __initd - .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, - }; - -+/* -+ * GPIO lines used for MMC card detection. -+ */ -+#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 -+ -+/* -+ * If you have hacked your Sim.One to use a GPIO as SD card chip select -+ * (SD pin 1), uncomment the following line. -+ * The example, EGPIO15, is on TP17 near the CPU. -+ */ -+// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -+ -+/* -+ * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal, -+ * you can leave these empty and pass NULL as .controller_data. -+ */ -+ -+#ifdef MMC_CHIP_SELECT_GPIO -+static int simone_mmc_spi_setup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ int err; -+ -+ err = gpio_request(gpio, spi->modalias); -+ if (err) -+ return err; -+ -+ err = gpio_direction_output(gpio, 1); -+ if (err) { -+ gpio_free(gpio); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static void simone_mmc_spi_cleanup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ -+ gpio_set_value(gpio, 1); -+ gpio_direction_input(gpio); -+ gpio_free(gpio); -+} -+ -+static void simone_mmc_spi_cs_control(struct spi_device *spi, int value) -+{ -+ gpio_set_value(MMC_CHIP_SELECT_GPIO, value); -+} -+ -+static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = { -+ .setup = simone_mmc_spi_setup, -+ .cleanup = simone_mmc_spi_cleanup, -+ .cs_control = simone_mmc_spi_cs_control, -+}; -+#endif -+ -+/* -+ * MMC card detection GPIO setup. -+ */ -+static int simone_mmc_spi_init(struct device *dev, -+ irqreturn_t (*irq_handler)(int, void *), void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ int irq, err; -+ -+ err = gpio_request(gpio, dev_name(dev)); -+ if (err) -+ return err; -+ -+ err = gpio_direction_input(gpio); -+ if (err) -+ goto fail; -+ -+ irq = gpio_to_irq(gpio); -+ if (irq < 0) -+ goto fail; -+ -+ err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING, -+ "MMC card detect", mmc); -+ if (err) -+ goto fail; -+ -+ printk(KERN_INFO "%s: using irq %d for MMC card detection\n", -+ dev_name(dev), irq); -+ -+ return 0; -+fail: -+ gpio_free(gpio); -+ return err; -+} -+ -+static void simone_mmc_spi_exit(struct device *dev, void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ -+ free_irq(gpio_to_irq(gpio), mmc); -+ gpio_free(gpio); -+} -+ -+static struct mmc_spi_platform_data simone_mmc_spi_data = { -+ .init = simone_mmc_spi_init, -+ .exit = simone_mmc_spi_exit, -+ .detect_delay = 500, -+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, -+}; -+ -+static struct spi_board_info simone_spi_devices[] __initdata = { -+ { -+ .modalias = "mmc_spi", -+#ifdef MMC_CHIP_SELECT_GPIO -+ .controller_data = &simone_mmc_spi_ops, -+#endif -+ .platform_data = &simone_mmc_spi_data, -+ /* -+ * We use 10 MHz even though the maximum is 3.7 MHz. The driver -+ * will limit it automatically to max. frequency. -+ */ -+ .max_speed_hz = 10 * 1000 * 1000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = SPI_MODE_3, -+ }, -+}; -+ -+static struct ep93xx_spi_info simone_spi_info __initdata = { -+ .num_chipselect = ARRAY_SIZE(simone_spi_devices), -+}; -+ - static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { - .sda_pin = EP93XX_GPIO_LINE_EEDAT, - .sda_is_open_drain = 0, -@@ -61,6 +194,8 @@ static void __init simone_init_machine(v - ep93xx_register_fb(&simone_fb_info); - ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, - ARRAY_SIZE(simone_i2c_board_info)); -+ ep93xx_register_spi(&simone_spi_info, simone_spi_devices, -+ ARRAY_SIZE(simone_spi_devices)); - } - - MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") diff --git a/target/linux/ep93xx/patches-2.6.37/001-ep93xx_cpuinfo.patch b/target/linux/ep93xx/patches-2.6.37/001-ep93xx_cpuinfo.patch deleted file mode 100644 index 68099c5b60..0000000000 --- a/target/linux/ep93xx/patches-2.6.37/001-ep93xx_cpuinfo.patch +++ /dev/null @@ -1,59 +0,0 @@ -This patch puts the EP93xx chip revision and unique ID into /proc/cpuinfo. -This is necessary to be able to set a unique MAC address for DHCP purposes -by adding a line to /etc/network/interfaces: - -# Generate a unique locally-assigned MAC address from the CPU serial number -pre-up ifconfig eth0 hw ether `sed -n 's/^Serial.* 000000/02/p' /proc/cpuinfo` - -It uses the chip revision reading code in the ep93xx-chip-revision patch. - -Really, this is wrong, since /proc/cpuinfo should report the revision and -serial number of the ARM920T processor, while these are the rev and serial -of the EP93xx SoC. In a future kernel (>2.6.34) there may be a new file -/proc/socinfo for this information. - - -martinwguy 14 May 2010 - ---- a/arch/arm/kernel/setup.c -+++ b/arch/arm/kernel/setup.c -@@ -48,6 +48,12 @@ - #include <asm/traps.h> - #include <asm/unwind.h> - -+#if defined(CONFIG_ARCH_EP93XX) -+#include <mach/io.h> -+#include <mach/ep93xx-regs.h> -+#include <mach/platform.h> -+#endif -+ - #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) - #include "compat.h" - #endif -@@ -989,9 +995,16 @@ static int c_show(struct seq_file *m, vo - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); -+#if defined(CONFIG_ARCH_EP93XX) -+ seq_printf(m, "Revision\t: %04x\n", -+ ep93xx_chip_revision()); -+ seq_printf(m, "Serial\t\t: %016x\n", -+ *((unsigned int *)EP93XX_SECURITY_UNIQID)); -+#else - seq_printf(m, "Revision\t: %04x\n", system_rev); - seq_printf(m, "Serial\t\t: %08x%08x\n", - system_serial_high, system_serial_low); -+#endif - - return 0; - } ---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -@@ -97,6 +97,8 @@ - #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) - - #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) -+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) - - #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) - #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) diff --git a/target/linux/ep93xx/patches-2.6.37/002-mmc_spi_fix_sdhc.patch b/target/linux/ep93xx/patches-2.6.37/002-mmc_spi_fix_sdhc.patch deleted file mode 100644 index 5211e00c49..0000000000 --- a/target/linux/ep93xx/patches-2.6.37/002-mmc_spi_fix_sdhc.patch +++ /dev/null @@ -1,74 +0,0 @@ -This patch makes SDHC cards work with the mmc_spi driver. - -The problem is that they fail when reading the last block of the card using -a multi-block read. This is because on SDHC the multiple block read has to be -stopped with an explicit STOP command, which needs to be sent to the card -while the incoming transfer is in progress. -The 2.6.3[45] mmc-spi driver sends it after the last block transfer, so the -SDHC card continues reading past the end of the card. -This patch works around this by using single-block reads if we're reading the -last blocks of the card. - -martinwguy, 14 May 2010 - -Date: Thu, 29 Apr 2010 21:30:36 +0300 -From: Mika Westerberg <mika.westerberg@iki.fi> -To: Martin Guy <martinwguy@gmail.com> - -On Wed, Apr 21, 2010 at 02:10:08AM +0100, Martin Guy wrote: -> -> the SDHC cards I have don't work at all, spewing tons of: -> mmcblk0: error -38 sending status comand -> mmcblk0: error -38 sending read/write command, response 0x4, card status 0xff04 -> end_request: I/O error, dev mmcblk0, sector 7744509 - -I bought today a new 4GB SDHC card and with that I get similar -errors that you are getting. I hacked around quick fix which seems -to work in my case. I'm wondering whether you could check if it -helps with your SDHC card as well? - -This problem is easy to reproduce, just read last sector of the -card (I wrote simple C program but running fdisk -l does the same). - -Patch is below. - -Thanks, -MW - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Thu, 29 Apr 2010 21:14:32 +0300 -Subject: [PATCH] mmc_block: use single block reads for last block on SPI - -Some SD-cards fail when doing multiblock read for last block with SPI host. Real -reason is not known but as workaround we can perform this last read using -multiple single block reads. - -Signed-off-by: Mika Westerberg <mika.westerberg@iki.fi> ---- - drivers/mmc/card/block.c | 19 +++++++++++++++++++ - 1 files changed, 19 insertions(+), 0 deletions(-) - ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -366,6 +366,22 @@ static int mmc_blk_issue_rw_rq(struct mm - if (brq.data.blocks > card->host->max_blk_count) - brq.data.blocks = card->host->max_blk_count; - -+ if (mmc_host_is_spi(card->host)) { -+ /* -+ * Some SD-cards fail when we are reading last block -+ * with multiblock read. In these cases we automatically -+ * use single block reads. This only happens on SPI -+ * hosts. -+ */ -+ if (rq_data_dir(req) == READ && brq.data.blocks > 1) { -+ sector_t s = blk_rq_pos(req) + brq.data.blocks; -+ -+ if (s >= get_capacity(md->disk)) { -+ disable_multi = 1; -+ } -+ } -+ } -+ - /* - * After a read error, we redo the request one sector at a time - * in order to accurately determine which sectors can be read diff --git a/target/linux/ep93xx/patches-2.6.37/003-ep93xx_touchscreen.patch b/target/linux/ep93xx/patches-2.6.37/003-ep93xx_touchscreen.patch deleted file mode 100644 index b6b34cd7ee..0000000000 --- a/target/linux/ep93xx/patches-2.6.37/003-ep93xx_touchscreen.patch +++ /dev/null @@ -1,1061 +0,0 @@ ---- - arch/arm/mach-ep93xx/include/mach/hardware.h | 1 - arch/arm/mach-ep93xx/include/mach/regs_touch.h | 95 ++ - drivers/input/touchscreen/Kconfig | 5 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/ep93xx_ts.c | 1117 +++++++++++++++++++++++++ - drivers/input/touchscreen/ep93xx_ts.h | 53 + - 6 files changed, 1272 insertions(+) - ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -165,6 +165,15 @@ config TOUCHSCREEN_EETI - To compile this driver as a module, choose M here: the - module will be called eeti_ts. - -+config TOUCHSCREEN_EP93XX -+ tristate "EP93xx Touchscreen" -+ depends on ARM && INPUT && ARCH_EP93XX -+ help -+ Say Y here to enable support for EP93xx touch screen. -+ -+ To compile this driver as a module, choose M here: -+ the module will be called ep93xx_ts. -+ - config TOUCHSCREEN_FUJITSU - tristate "Fujitsu serial touchscreen" - select SERIO ---- a/drivers/input/touchscreen/Makefile -+++ b/drivers/input/touchscreen/Makefile -@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += h - obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o - obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o - obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -+obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o - obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o - obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o - obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o ---- /dev/null -+++ b/drivers/input/touchscreen/ep93xx_ts.c -@@ -0,0 +1,1021 @@ -+/* -+ * linux/drivers/input/touchscreen/ep93xx_ts.c -+ * -+ * Copyright (C) 2003-2004 Cirrus Corp. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/wait.h> -+#include <linux/fs.h> -+#include <linux/sched.h> -+#include <linux/poll.h> -+#include <linux/miscdevice.h> -+#include <linux/init.h> -+#include <linux/compiler.h> -+#include <linux/timer.h> -+#include <linux/interrupt.h> -+#include <linux/syscalls.h> -+#include <linux/input.h> -+#include <linux/semaphore.h> -+#include <asm/irq.h> -+#include <mach/hardware.h> -+#include <asm/io.h> -+ -+/* This stuff should be in ep93xx-regs.h */ -+#define EP93XX_TOUCHSCREEN_REG(x) (EP93XX_TOUCHSCREEN_BASE + (x)) -+/* R/W touchscreen controller setup control register. */ -+#define EP93XX_TOUCHSCREEN_SETUP EP93XX_TOUCHSCREEN_REG(0x00) -+/* R/W touchscreen controller max/min register. */ -+#define EP93XX_TOUCHSCREEN_XYMAXMIN EP93XX_TOUCHSCREEN_REG(0x04) -+/* R touchscreen controller result register. */ -+#define EP93XX_TOUCHSCREEN_XYRESULT EP93XX_TOUCHSCREEN_REG(0x08) -+/* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define EP93XX_TOUCHSCREEN_DISCHARGE EP93XX_TOUCHSCREEN_REG(0x0C) -+#define EP93XX_TOUCHSCREEN_XSAMPLE EP93XX_TOUCHSCREEN_REG(0x10) -+#define EP93XX_TOUCHSCREEN_YSAMPLE EP93XX_TOUCHSCREEN_REG(0x14) -+#define EP93XX_TOUCHSCREEN_DIRECT EP93XX_TOUCHSCREEN_REG(0x18) -+#define EP93XX_TOUCHSCREEN_DETECT EP93XX_TOUCHSCREEN_REG(0x1C) -+/* NA R/W touchscreen software lock register. */ -+#define EP93XX_TOUCHSCREEN_SWLOCK EP93XX_TOUCHSCREEN_REG(0x20) -+/* R/W touchscreen setup control register #2. */ -+#define EP93XX_TOUCHSCREEN_SETUP2 EP93XX_TOUCHSCREEN_REG(0x24) -+ -+/* These are duplicated in mach-ep93xx/core.c */ -+#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -+#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -+#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -+#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -+#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -+ -+/* -+ * Register bit definitions -+ */ -+#define TSSETUP_SDLY_MASK 0x000003FF -+#define TSSETUP_SDLY_SHIFT 0 -+#define TSSETUP_NSMP_4 0x00000000 -+#define TSSETUP_NSMP_8 0x00000400 -+#define TSSETUP_NSMP_16 0x00000800 -+#define TSSETUP_NSMP_32 0x00000C00 -+#define TSSETUP_NSMP_MASK 0x00000C00 -+#define TSSETUP_DEV_4 0x00000000 -+#define TSSETUP_DEV_8 0x00001000 -+#define TSSETUP_DEV_12 0x00002000 -+#define TSSETUP_DEV_16 0x00003000 -+#define TSSETUP_DEV_24 0x00004000 -+#define TSSETUP_DEV_32 0x00005000 -+#define TSSETUP_DEV_64 0x00006000 -+#define TSSETUP_DEV_128 0x00007000 -+#define TSSETUP_ENABLE 0x00008000 -+#define TSSETUP_DLY_MASK 0x03FF0000 -+#define TSSETUP_DLY_SHIFT 16 -+#define TSSETUP_TDTCT 0x80000000 -+ -+#define TSMAXMIN_XMIN_MASK 0x000000FF -+#define TSMAXMIN_XMIN_SHIFT 0 -+#define TSMAXMIN_YMIN_MASK 0x0000FF00 -+#define TSMAXMIN_YMIN_SHIFT 8 -+#define TSMAXMIN_XMAX_MASK 0x00FF0000 -+#define TSMAXMIN_XMAX_SHIFT 16 -+#define TSMAXMIN_YMAX_MASK 0xFF000000 -+#define TSMAXMIN_YMAX_SHIFT 24 -+ -+#define TSXYRESULT_X_MASK 0x00000FFF -+#define TSXYRESULT_X_SHIFT 0 -+#define TSXYRESULT_AD_MASK 0x0000FFFF -+#define TSXYRESULT_AD_SHIFT 0 -+#define TSXYRESULT_Y_MASK 0x0FFF0000 -+#define TSXYRESULT_Y_SHIFT 16 -+#define TSXYRESULT_SDR 0x80000000 -+ -+#define TSX_SAMPLE_MASK 0x00003FFF -+#define TSX_SAMPLE_SHIFT 0x00 -+#define TSY_SAMPLE_MASK 0x3FFF0000 -+#define TSY_SAMPLE_SHIFT 0x10 -+ -+#define TSSETUP2_TINT 0x00000001 -+#define TSSETUP2_NICOR 0x00000002 -+#define TSSETUP2_PINT 0x00000004 -+#define TSSETUP2_PENSTS 0x00000008 -+#define TSSETUP2_PINTEN 0x00000010 -+#define TSSETUP2_DEVINT 0x00000020 -+#define TSSETUP2_DINTEN 0x00000040 -+#define TSSETUP2_DTMEN 0x00000080 -+#define TSSETUP2_DISDEV 0x00000100 -+#define TSSETUP2_NSIGND 0x00000200 -+#define TSSETUP2_S28EN 0x00000400 -+#define TSSETUP2_RINTEN 0x00000800 -+ -+#define TSXYRESULT_SDR 0x80000000 -+ -+/* -+ * These are used as trigger levels to know when we have pen up/down. -+ * The rules: -+ * 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these -+ * are Inverse pressure. -+ * 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up. -+ * 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down. -+ */ -+#define TS_HEAVY_INV_PRESSURE 0xFE0 /* C00 */ -+#define TS_LIGHT_INV_PRESSURE 0xFFF /* e00 */ -+ -+/* -+ * If the x, y, or inverse pressure changes more than these values -+ * between two succeeding points, the point is not reported. -+ */ -+#define TS_MAX_VALID_XY_CHANGE 0x300 -+#define TS_MAX_VALID_PRESSURE_CHANGE 0x100 -+ -+/* -+ * This is the minimum Z1 Value that is valid. -+ */ -+#define MIN_Z1_VALUE 0x50 -+ -+/* -+ * Settling delay for taking each ADC measurement. Increase this -+ * if ts is jittery. -+ */ -+#define EP93XX_TS_ADC_DELAY_USEC 2000 -+ -+/* -+ * Delay between TS points. -+ */ -+#define EP93XX_TS_PER_POINT_DELAY_USEC 10000 -+ -+/* -+ * A few more macros... -+ */ -+#define TSSETUP_DEFAULT (TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \ -+ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \ -+ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK)) -+ -+#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND) -+ -+/* -+ * For now, we use one of the minor numbers from the local/experimental -+ * range. -+ */ -+#define EP93XX_TS_MINOR 240 -+ -+/* -+ * Static Declarations -+ */ -+static unsigned int guiLastX, guiLastY; -+static unsigned int guiLastInvPressure; -+ -+struct TouchScreenSample -+{ -+ int currentX; -+ int currentY; -+ int currentButton; -+ int currentPressure; -+ struct timeval currentTime; -+}; -+ -+/* -+ * This must match the structure in tslib. -+ */ -+struct ts_sample { -+ int x; -+ int y; -+ unsigned int pressure; -+ struct timeval tv; -+}; -+ -+static struct TouchScreenSample gSample; -+static int bFreshTouchData; -+static int bCurrentPenDown; -+ -+static DECLARE_WAIT_QUEUE_HEAD(queue); -+static DEFINE_SEMAPHORE(open_sem); -+static spinlock_t event_buffer_lock = SPIN_LOCK_UNLOCKED; -+static struct fasync_struct *ep93xx_fasync; -+ -+/* -+ * Typedef Declarations -+ */ -+typedef enum { -+ TS_MODE_UN_INITIALIZED, -+ TS_MODE_HARDWARE_SCAN, -+ TS_MODE_SOFT_SCAN -+} ts_mode_t; -+ -+static ts_mode_t gScanningMode; -+ -+typedef enum{ -+ TS_STATE_STOPPED = 0, -+ TS_STATE_Z1, -+ TS_STATE_Z2, -+ TS_STATE_Y, -+ TS_STATE_X, -+ TS_STATE_DONE -+} ts_states_t; -+ -+typedef struct -+{ -+ unsigned int uiX; -+ unsigned int uiY; -+ unsigned int uiZ1; -+ unsigned int uiZ2; -+ ts_states_t state; -+} ts_struct_t; -+ -+static ts_struct_t sTouch; -+ -+/* -+ * From the spec, here's how to set up the touch screen's switch registers. -+ */ -+typedef struct -+{ -+ unsigned int uiDetect; -+ unsigned int uiDischarge; -+ unsigned int uiXSample; -+ unsigned int uiYSample; -+ unsigned int uiSwitchZ1; -+ unsigned int uiSwitchZ2; -+}SwitchStructType; -+ -+/* -+ * Here's the switch settings for a 4-wire touchscreen. See the spec -+ * for how to handle a 4, 7, or 8-wire. -+ */ -+const static SwitchStructType sSwitchSettings = -+/* s28en=0 */ -+/* TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2 */ -+ {0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608}; -+ -+/* -+ * Function declarations -+ */ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch); -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id); -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id); -+static void ee93xx_ts_evt_add(int button, int dX, int dY, int Pressure); -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, -+ size_t count, loff_t *l); -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait); -+static int ep93xx_ts_open(struct inode *inode, struct file *filp); -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on); -+static int ep93xx_ts_release(struct inode *inode, struct file *filp); -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos); -+static void ep93xx_ts_setup(void); -+static void ep93xx_ts_shutdown(void); -+int __init ep93xx_ts_init(void); -+void __exit ep93xx_ts_exit(void); -+static unsigned int CalculateInvPressure(void); -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff); -+static void TS_Soft_Scan_Mode(void); -+static void TS_Hardware_Scan_Mode(void); -+static void ProcessPointData(void); -+static void Set_Timer2_uSec(unsigned int Delay_mSec); -+static void Stop_Timer2(void); -+ -+/* -+ * ep93xx_ts_isr -+ */ -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id) -+{ -+ /* -+ * Note that we don't clear the interrupt here. The interrupt -+ * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE -+ * bit is cleared. -+ */ -+ -+ /* -+ * Set the ts to manual polling mode and schedule a callback. -+ * That way we can return from the isr in a reasonable amount of -+ * time and process the touch in the callback after a brief delay. -+ */ -+ TS_Soft_Scan_Mode(); -+ -+ return(IRQ_HANDLED); -+} -+ -+/* -+ * Save the current ts 'event' in an atomic fashion. -+ */ -+static void ee93xx_ts_evt_add(int buttons, int iX, int iY, int iPressure) -+{ -+ /* -+ * Note the event, but use spinlocks to keep it from getting -+ * halfway read if we get interrupted. -+ */ -+ -+ spin_lock(&event_buffer_lock); -+ -+ gSample.currentX = iX; -+ gSample.currentY = iY; -+ gSample.currentButton = buttons; -+ gSample.currentPressure = iPressure; -+ bFreshTouchData = 1; -+ do_gettimeofday(&gSample.currentTime); -+ -+ spin_unlock(&event_buffer_lock); -+ -+ kill_fasync(&ep93xx_fasync, SIGIO, POLL_IN); -+ wake_up_interruptible(&queue); -+} -+ -+ -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) -+{ -+ unsigned short data[3]; -+ struct ts_sample ts_data; -+ int iReturn = -EFAULT; -+ -+ if (!bFreshTouchData) -+ { -+ iReturn = 0; -+ } -+ else if (count == sizeof(data)) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ data[0] = gSample.currentX; -+ data[1] = gSample.currentY; -+ data[2] = gSample.currentButton; -+ -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, data, sizeof data)) -+ return -EFAULT; -+ -+ count -= sizeof(data); -+ -+ /* return the # of bytes that got read */ -+ iReturn = sizeof(data) ; -+ } -+ else if (count == sizeof(struct ts_sample) ) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ ts_data.x = gSample.currentX; -+ ts_data.y = gSample.currentY; -+ ts_data.pressure = gSample.currentPressure; -+ ts_data.tv = gSample.currentTime; -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, &ts_data, sizeof(struct ts_sample))) -+ { -+ iReturn = -EFAULT; -+ } -+ else -+ { -+ count -= sizeof(ts_data); -+ iReturn = sizeof(ts_data); -+ } -+ } -+ -+ return iReturn; -+} -+ -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait) -+{ -+ poll_wait(filp, &queue, wait); -+ -+ if (bFreshTouchData) -+ { -+ return POLLIN | POLLRDNORM; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_open(struct inode *inode, struct file *filp) -+{ -+ if (down_trylock(&open_sem)) -+ { -+ return -EBUSY; -+ } -+ -+ ep93xx_ts_setup(); -+ -+ return 0; -+} -+ -+/* -+ * Asynchronous I/O support. -+ */ -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on) -+{ -+ int retval; -+ -+ retval = fasync_helper(fd, filp, on, &ep93xx_fasync); -+ if (retval < 0) -+ { -+ return retval; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_release(struct inode *inode, struct file *filp) -+{ -+ Stop_Timer2(); -+ -+ /* -+ * Call our async I/O support to request that this file -+ * cease to be used for async I/O. -+ */ -+ ep93xx_ts_fasync(-1, filp, 0); -+ -+ ep93xx_ts_shutdown(); -+ -+ up(&open_sem); -+ -+ return 0; -+} -+ -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ -+static int ep93xx_ts_ioctl(struct inode *inode, struct file *file, uint command, ulong u) -+{ -+ static const int version = EV_VERSION; -+ static const u_int32_t bit =(1 << EV_ABS); -+ static const u_int32_t absbit = (1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_PRESSURE); -+ int iReturn ; -+ int i = 0; -+ -+ switch(command) -+ { -+ case EVIOCGVERSION: -+ i = copy_to_user((void __user *)u, (void *)version, sizeof(version)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(0,sizeof(u_int32_t) * 8) : -+ i = copy_to_user((void __user *)u, (void *)bit, sizeof(bit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(EV_ABS, sizeof(absbit) * 8): -+ i = copy_to_user((void __user *)u, (void *)absbit, sizeof(absbit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ default: -+ iReturn = -1; -+ break; -+ } -+ -+ return iReturn; -+} -+ -+static struct file_operations ep93xx_ts_fops = { -+ owner: THIS_MODULE, -+ read: ep93xx_ts_read, -+ write: ep93xx_ts_write, -+ poll: ep93xx_ts_poll, -+ open: ep93xx_ts_open, -+ unlocked_ioctl: ep93xx_ts_ioctl, -+ release: ep93xx_ts_release, -+ fasync: ep93xx_ts_fasync, -+}; -+ -+static struct miscdevice ep93xx_ts_miscdev = -+{ -+ EP93XX_TS_MINOR, -+ "ep93xx_ts", -+ &ep93xx_ts_fops -+}; -+ -+void ep93xx_ts_setup(void) -+{ -+ unsigned int uiKTDIV, uiTSXYMaxMin; -+ -+ /* -+ * Set the TSEN bit in KTDIV so that we are enabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV |= EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+ /* -+ * Program the EP93XX_TOUCHSCREEN_SETUP and TSSetup2 registers. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Set the the touch settings. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DISCHARGE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ1, EP93XX_TOUCHSCREEN_XSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ2, EP93XX_TOUCHSCREEN_YSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDetect, EP93XX_TOUCHSCREEN_DETECT); -+ -+ /* -+ * X,YMin set to 0x40 = have to drag that many pixels for a new irq. -+ * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the -+ * time scan limit. -+ */ -+ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK; -+ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK; -+ __raw_writel(uiTSXYMaxMin, EP93XX_TOUCHSCREEN_XYMAXMIN); -+ -+ bCurrentPenDown = 0; -+ bFreshTouchData = 0; -+ guiLastX = 0; -+ guiLastY = 0; -+ guiLastInvPressure = 0xffffff; -+ -+ /* -+ * Enable the touch screen scanning engine. -+ */ -+ TS_Hardware_Scan_Mode(); -+} -+ -+/* -+ * ep93xx_ts_shutdown -+ * -+ */ -+static void -+ep93xx_ts_shutdown(void) -+{ -+ unsigned int uiKTDIV; -+ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Disable the scanning engine. -+ */ -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Clear the TSEN bit in KTDIV so that we are disabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV &= ~EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+} /* ep93xx_ts_shutdown */ -+ -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id) -+{ -+ switch(sTouch.state) -+ { -+ case TS_STATE_STOPPED: -+ TS_Hardware_Scan_Mode(); -+ break; -+ -+ /* -+ * Get the Z1 value for pressure measurement and set up -+ * the switch register for getting the Z2 measurement. -+ */ -+ case TS_STATE_Z1: -+ Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC); -+ sTouch.uiZ1 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2); -+ sTouch.state = TS_STATE_Z2; -+ break; -+ -+ /* -+ * Get the Z2 value for pressure measurement and set up -+ * the switch register for getting the Y measurement. -+ */ -+ case TS_STATE_Z2: -+ sTouch.uiZ2 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiYSample); -+ sTouch.state = TS_STATE_Y; -+ break; -+ -+ /* -+ * Get the Y value and set up the switch register for -+ * getting the X measurement. -+ */ -+ case TS_STATE_Y: -+ sTouch.uiY = ADCGetData(4, 20); -+ ep93xx_ts_set_direct(sSwitchSettings.uiXSample); -+ sTouch.state = TS_STATE_X; -+ break; -+ -+ /* -+ * Read the X value. This is the last of the 4 adc values -+ * we need so we continue on to process the data. -+ */ -+ case TS_STATE_X: -+ Stop_Timer2(); -+ -+ sTouch.uiX = ADCGetData(4, 20); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ sTouch.state = TS_STATE_DONE; -+ -+ /* -+ * Process this set of ADC readings. -+ */ -+ ProcessPointData(); -+ -+ break; -+ -+ /* -+ * Shouldn't get here. But if we do, we can recover... -+ */ -+ case TS_STATE_DONE: -+ TS_Hardware_Scan_Mode(); -+ break; -+ } -+ -+ /* -+ * Clear the timer2 interrupt. -+ */ -+ __raw_writel(1, EP93XX_TIMER2_CLEAR); -+ return(IRQ_HANDLED); -+} -+ -+/*--------------------------------------------------------------------- -+ * ProcessPointData -+ * -+ * This routine processes the ADC data into usable point data and then -+ * puts the driver into hw or sw scanning mode before returning. -+ * -+ * We calculate inverse pressure (lower number = more pressure) then -+ * do a hystheresis with the two pressure values 'light' and 'heavy'. -+ * -+ * If we are above the light, we have pen up. -+ * If we are below the heavy we have pen down. -+ * As long as the pressure stays below the light, pen stays down. -+ * When we get above the light again, pen goes back up. -+ * -+ */ -+static void ProcessPointData(void) -+{ -+ int bValidPoint = 0; -+ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff; -+ unsigned int uiInvPressure; -+ -+ /* -+ * Calculate the current pressure. -+ */ -+ uiInvPressure = CalculateInvPressure(); -+ -+ /* -+ * If pen pressure is so light that it is greater than the 'max' setting -+ * then we consider this to be a pen up. -+ */ -+ if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) -+ { -+ bCurrentPenDown = 0; -+ ee93xx_ts_evt_add(0, guiLastX, guiLastY, 0); -+ TS_Hardware_Scan_Mode(); -+ return; -+ } -+ -+ /* -+ * Hysteresis: -+ * If the pen pressure is hard enough to be less than the 'min' OR -+ * the pen is already down and is still less than the 'max'... -+ */ -+ if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) || -+ (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) -+ { -+ if (bCurrentPenDown) -+ { -+ /* -+ * If pen was previously down, check the difference between -+ * the last sample and this one... if the difference between -+ * samples is too great, ignore the sample. -+ */ -+ uiXDiff = abs(guiLastX - sTouch.uiX); -+ uiYDiff = abs(guiLastY - sTouch.uiY); -+ uiInvPressureDiff = abs(guiLastInvPressure - uiInvPressure); -+ -+ if (uiXDiff < TS_MAX_VALID_XY_CHANGE -+ && uiYDiff < TS_MAX_VALID_XY_CHANGE -+ && uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE) -+ { -+ bValidPoint = 1; -+ } -+ } -+ else -+ { -+ bValidPoint = 1; -+ } -+ -+ /* -+ * If either the pen was put down or dragged make a note of it. -+ */ -+ if (bValidPoint) -+ { -+ guiLastX = sTouch.uiX; -+ guiLastY = sTouch.uiY; -+ guiLastInvPressure = uiInvPressure; -+ bCurrentPenDown = 1; -+ ee93xx_ts_evt_add(1, sTouch.uiX, sTouch.uiY, -+ 0x7000000 / uiInvPressure); -+ } -+ -+ TS_Soft_Scan_Mode(); -+ return; -+ } -+ -+ TS_Hardware_Scan_Mode(); -+} -+ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch) -+{ -+ unsigned int uiResult; -+ -+ /* -+ * Set the switch settings in the direct register. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(uiADCSwitch, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ /* -+ * Read and throw away the first sample. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+} -+ -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff) -+{ -+ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, uiAve; -+ -+ do -+ { -+ /* -+ * Initialize our values. -+ */ -+ uiLowest = 0xfffffff; -+ uiHighest = 0; -+ uiSum = 0; -+ -+ for (uiCount = 0; uiCount < uiSamples; uiCount++) -+ { -+ /* -+ * Read the touch screen four more times and average. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+ uiValue = (uiResult & TSXYRESULT_AD_MASK) >> TSXYRESULT_AD_SHIFT; -+ uiValue = ((uiValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1)) & TSXYRESULT_X_MASK; -+ -+ /* -+ * Add up the values. -+ */ -+ uiSum += uiValue; -+ -+ /* -+ * Get the lowest and highest values. -+ */ -+ if (uiValue < uiLowest) -+ { -+ uiLowest = uiValue; -+ } -+ if (uiValue > uiHighest) -+ { -+ uiHighest = uiValue; -+ } -+ } -+ } while ((uiHighest - uiLowest) > uiMaxDiff); -+ -+ /* -+ * Calculate the Average value. -+ */ -+ uiAve = uiSum / uiSamples; -+ -+ return uiAve; -+} -+ -+/* -+ * CalculateInvPressure -+ * -+ * Is the Touch Valid. Touch is not valid if the X or Y value is not -+ * in range and the pressure is not enough. -+ * -+ * Touch resistance can be measured by the following formula: -+ * -+ * Rx * X * Z2 -+ * Rtouch = --------- * (-- - 1) -+ * 4096 Z1 -+ * -+ * This is simplified in the ration of Rtouch to Rx. The lower the value, the -+ * higher the pressure. -+ * -+ * Z2 -+ * InvPressure = X * (-- - 1) -+ * Z1 -+ */ -+static unsigned int CalculateInvPressure(void) -+{ -+ unsigned int uiInvPressure; -+ -+ /* -+ * Check to see if the point is valid. -+ */ -+ if (sTouch.uiZ1 < MIN_Z1_VALUE) -+ { -+ uiInvPressure = 0x10000; -+ } -+ -+ /* -+ * Can omit the pressure calculation if you need to get rid of the division. -+ */ -+ else -+ { -+ uiInvPressure = ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX; -+ } -+ -+ return uiInvPressure; -+} -+ -+/* -+ * TS_Hardware_Scan_Mode -+ * -+ * Enables the ep93xx ts scanning engine so that when the pen goes down -+ * we will get an interrupt. -+ */ -+static void TS_Hardware_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ /* -+ * Disable the soft scanning engine. -+ */ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Clear the TIN (Touchscreen INactive) bit so we can go to -+ * automatic scanning mode. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg & ~EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ -+ /* -+ * Enable the touch screen scanning state machine by setting -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT | TSSETUP_ENABLE, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the flag to show that we are in interrupt mode. -+ */ -+ gScanningMode = TS_MODE_HARDWARE_SCAN; -+ -+ /* -+ * Initialize EP93XX_TOUCHSCREEN_SETUP2 register. -+ */ -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+} -+ -+/* -+ * TS_Soft_Scan_Mode -+ * -+ * Sets the touch screen to manual polling mode. -+ */ -+static void TS_Soft_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ if (gScanningMode != TS_MODE_SOFT_SCAN) -+ { -+ /* -+ * Disable the touch screen scanning state machine by clearing -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the TIN bit so we can do manual touchscreen polling. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg | EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ } -+ -+ /* -+ * Set the switch register up for the first ADC reading -+ */ -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1); -+ -+ /* -+ * Initialize our software state machine to know which ADC -+ * reading to take -+ */ -+ sTouch.state = TS_STATE_Z1; -+ -+ /* -+ * Set the timer so after a mSec or two settling delay it will -+ * take the first ADC reading. -+ */ -+ Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC); -+ -+ /* -+ * Note that we are in sw scanning mode not hw scanning mode. -+ */ -+ gScanningMode = TS_MODE_SOFT_SCAN; -+ -+} -+ -+static void Set_Timer2_uSec(unsigned int uiDelay_uSec) -+{ -+ unsigned int uiClockTicks; -+ -+ /* -+ * Stop timer 2 -+ */ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+ -+ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000; -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_LOAD); -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_VALUE); -+ -+ /* -+ * Set up Timer 2 for 508 kHz clock and periodic mode. -+ */ -+ __raw_writel(0xC8, EP93XX_TIMER2_CONTROL); -+ -+} -+ -+static void Stop_Timer2(void) -+{ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+} -+ -+/* -+ * Initialization and exit routines -+ */ -+int __init ep93xx_ts_init(void) -+{ -+ int retval; -+ -+ retval = request_irq(IRQ_EP93XX_TOUCH, ep93xx_ts_isr, -+ IRQF_DISABLED, "ep93xx_ts", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n"); -+ return retval; -+ } -+ -+ retval = request_irq(IRQ_EP93XX_TIMER2, ep93xx_timer2_isr, -+ IRQF_DISABLED, "ep93xx_timer2", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n"); -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ return retval; -+ } -+ -+ misc_register(&ep93xx_ts_miscdev); -+ -+ sTouch.state = TS_STATE_STOPPED; -+ gScanningMode = TS_MODE_UN_INITIALIZED; -+ -+ printk(KERN_NOTICE "ep93xx touchscreen driver configured for 4-wire operation\n"); -+ -+ return 0; -+} -+ -+void __exit ep93xx_ts_exit(void) -+{ -+ Stop_Timer2(); -+ -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ free_irq(IRQ_EP93XX_TIMER2, 0); -+ -+ misc_deregister(&ep93xx_ts_miscdev); -+} -+ -+module_init(ep93xx_ts_init); -+module_exit(ep93xx_ts_exit); -+ -+MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver"); -+MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ep93xx/patches-2.6.37/004-simone_add_mmc_spi.patch b/target/linux/ep93xx/patches-2.6.37/004-simone_add_mmc_spi.patch deleted file mode 100644 index 511d012b86..0000000000 --- a/target/linux/ep93xx/patches-2.6.37/004-simone_add_mmc_spi.patch +++ /dev/null @@ -1,179 +0,0 @@ -This enables the mmc-over-spi driver for the Sim.One board, based on Mika's -patch, which used a GPIO for chip select in stead of the default SFRMOUT pin. -I've modified it to use the usual SFRMOUT; if you've modified your Sim.One -board to use a GPIO instead, uncomment and modify -// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -in the source file. - -martinwguy, 14 May 2010 - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Wed, 28 Apr 2010 08:42:46 +0300 -Subject: [PATCH] ep93xx: simone: added board specific SPI support for MMC/SD cards - -This includes setting up EGPIOs 0 and 9 for card detection and chip select -respectively. - ---- a/arch/arm/mach-ep93xx/simone.c -+++ b/arch/arm/mach-ep93xx/simone.c -@@ -18,12 +18,16 @@ - #include <linux/kernel.h> - #include <linux/init.h> - #include <linux/platform_device.h> -+#include <linux/mmc/host.h> - #include <linux/gpio.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/mmc_spi.h> - #include <linux/i2c.h> - #include <linux/i2c-gpio.h> - - #include <mach/hardware.h> - #include <mach/fb.h> -+#include <mach/ep93xx_spi.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -38,6 +42,135 @@ static struct ep93xxfb_mach_info __initd - .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, - }; - -+/* -+ * GPIO lines used for MMC card detection. -+ */ -+#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 -+ -+/* -+ * If you have hacked your Sim.One to use a GPIO as SD card chip select -+ * (SD pin 1), uncomment the following line. -+ * The example, EGPIO15, is on TP17 near the CPU. -+ */ -+// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -+ -+/* -+ * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal, -+ * you can leave these empty and pass NULL as .controller_data. -+ */ -+ -+#ifdef MMC_CHIP_SELECT_GPIO -+static int simone_mmc_spi_setup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ int err; -+ -+ err = gpio_request(gpio, spi->modalias); -+ if (err) -+ return err; -+ -+ err = gpio_direction_output(gpio, 1); -+ if (err) { -+ gpio_free(gpio); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static void simone_mmc_spi_cleanup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ -+ gpio_set_value(gpio, 1); -+ gpio_direction_input(gpio); -+ gpio_free(gpio); -+} -+ -+static void simone_mmc_spi_cs_control(struct spi_device *spi, int value) -+{ -+ gpio_set_value(MMC_CHIP_SELECT_GPIO, value); -+} -+ -+static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = { -+ .setup = simone_mmc_spi_setup, -+ .cleanup = simone_mmc_spi_cleanup, -+ .cs_control = simone_mmc_spi_cs_control, -+}; -+#endif -+ -+/* -+ * MMC card detection GPIO setup. -+ */ -+static int simone_mmc_spi_init(struct device *dev, -+ irqreturn_t (*irq_handler)(int, void *), void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ int irq, err; -+ -+ err = gpio_request(gpio, dev_name(dev)); -+ if (err) -+ return err; -+ -+ err = gpio_direction_input(gpio); -+ if (err) -+ goto fail; -+ -+ irq = gpio_to_irq(gpio); -+ if (irq < 0) -+ goto fail; -+ -+ err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING, -+ "MMC card detect", mmc); -+ if (err) -+ goto fail; -+ -+ printk(KERN_INFO "%s: using irq %d for MMC card detection\n", -+ dev_name(dev), irq); -+ -+ return 0; -+fail: -+ gpio_free(gpio); -+ return err; -+} -+ -+static void simone_mmc_spi_exit(struct device *dev, void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ -+ free_irq(gpio_to_irq(gpio), mmc); -+ gpio_free(gpio); -+} -+ -+static struct mmc_spi_platform_data simone_mmc_spi_data = { -+ .init = simone_mmc_spi_init, -+ .exit = simone_mmc_spi_exit, -+ .detect_delay = 500, -+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, -+}; -+ -+static struct spi_board_info simone_spi_devices[] __initdata = { -+ { -+ .modalias = "mmc_spi", -+#ifdef MMC_CHIP_SELECT_GPIO -+ .controller_data = &simone_mmc_spi_ops, -+#endif -+ .platform_data = &simone_mmc_spi_data, -+ /* -+ * We use 10 MHz even though the maximum is 3.7 MHz. The driver -+ * will limit it automatically to max. frequency. -+ */ -+ .max_speed_hz = 10 * 1000 * 1000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = SPI_MODE_3, -+ }, -+}; -+ -+static struct ep93xx_spi_info simone_spi_info __initdata = { -+ .num_chipselect = ARRAY_SIZE(simone_spi_devices), -+}; -+ - static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { - .sda_pin = EP93XX_GPIO_LINE_EEDAT, - .sda_is_open_drain = 0, -@@ -61,6 +194,8 @@ static void __init simone_init_machine(v - ep93xx_register_fb(&simone_fb_info); - ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, - ARRAY_SIZE(simone_i2c_board_info)); -+ ep93xx_register_spi(&simone_spi_info, simone_spi_devices, -+ ARRAY_SIZE(simone_spi_devices)); - ep93xx_register_ac97(); - } - diff --git a/target/linux/ep93xx/patches-2.6.38/001-ep93xx_cpuinfo.patch b/target/linux/ep93xx/patches-2.6.38/001-ep93xx_cpuinfo.patch deleted file mode 100644 index 1f0c5e67d8..0000000000 --- a/target/linux/ep93xx/patches-2.6.38/001-ep93xx_cpuinfo.patch +++ /dev/null @@ -1,59 +0,0 @@ -This patch puts the EP93xx chip revision and unique ID into /proc/cpuinfo. -This is necessary to be able to set a unique MAC address for DHCP purposes -by adding a line to /etc/network/interfaces: - -# Generate a unique locally-assigned MAC address from the CPU serial number -pre-up ifconfig eth0 hw ether `sed -n 's/^Serial.* 000000/02/p' /proc/cpuinfo` - -It uses the chip revision reading code in the ep93xx-chip-revision patch. - -Really, this is wrong, since /proc/cpuinfo should report the revision and -serial number of the ARM920T processor, while these are the rev and serial -of the EP93xx SoC. In a future kernel (>2.6.34) there may be a new file -/proc/socinfo for this information. - - -martinwguy 14 May 2010 - ---- a/arch/arm/kernel/setup.c -+++ b/arch/arm/kernel/setup.c -@@ -48,6 +48,12 @@ - #include <asm/traps.h> - #include <asm/unwind.h> - -+#if defined(CONFIG_ARCH_EP93XX) -+#include <mach/io.h> -+#include <mach/ep93xx-regs.h> -+#include <mach/platform.h> -+#endif -+ - #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) - #include "compat.h" - #endif -@@ -986,9 +992,16 @@ static int c_show(struct seq_file *m, vo - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); -+#if defined(CONFIG_ARCH_EP93XX) -+ seq_printf(m, "Revision\t: %04x\n", -+ ep93xx_chip_revision()); -+ seq_printf(m, "Serial\t\t: %016x\n", -+ *((unsigned int *)EP93XX_SECURITY_UNIQID)); -+#else - seq_printf(m, "Revision\t: %04x\n", system_rev); - seq_printf(m, "Serial\t\t: %08x%08x\n", - system_serial_high, system_serial_low); -+#endif - - return 0; - } ---- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h -@@ -97,6 +97,8 @@ - #define EP93XX_I2S_BASE EP93XX_APB_IOMEM(0x00020000) - - #define EP93XX_SECURITY_BASE EP93XX_APB_IOMEM(0x00030000) -+#define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) -+#define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) - - #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) - #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) diff --git a/target/linux/ep93xx/patches-2.6.38/002-mmc_spi_fix_sdhc.patch b/target/linux/ep93xx/patches-2.6.38/002-mmc_spi_fix_sdhc.patch deleted file mode 100644 index 5211e00c49..0000000000 --- a/target/linux/ep93xx/patches-2.6.38/002-mmc_spi_fix_sdhc.patch +++ /dev/null @@ -1,74 +0,0 @@ -This patch makes SDHC cards work with the mmc_spi driver. - -The problem is that they fail when reading the last block of the card using -a multi-block read. This is because on SDHC the multiple block read has to be -stopped with an explicit STOP command, which needs to be sent to the card -while the incoming transfer is in progress. -The 2.6.3[45] mmc-spi driver sends it after the last block transfer, so the -SDHC card continues reading past the end of the card. -This patch works around this by using single-block reads if we're reading the -last blocks of the card. - -martinwguy, 14 May 2010 - -Date: Thu, 29 Apr 2010 21:30:36 +0300 -From: Mika Westerberg <mika.westerberg@iki.fi> -To: Martin Guy <martinwguy@gmail.com> - -On Wed, Apr 21, 2010 at 02:10:08AM +0100, Martin Guy wrote: -> -> the SDHC cards I have don't work at all, spewing tons of: -> mmcblk0: error -38 sending status comand -> mmcblk0: error -38 sending read/write command, response 0x4, card status 0xff04 -> end_request: I/O error, dev mmcblk0, sector 7744509 - -I bought today a new 4GB SDHC card and with that I get similar -errors that you are getting. I hacked around quick fix which seems -to work in my case. I'm wondering whether you could check if it -helps with your SDHC card as well? - -This problem is easy to reproduce, just read last sector of the -card (I wrote simple C program but running fdisk -l does the same). - -Patch is below. - -Thanks, -MW - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Thu, 29 Apr 2010 21:14:32 +0300 -Subject: [PATCH] mmc_block: use single block reads for last block on SPI - -Some SD-cards fail when doing multiblock read for last block with SPI host. Real -reason is not known but as workaround we can perform this last read using -multiple single block reads. - -Signed-off-by: Mika Westerberg <mika.westerberg@iki.fi> ---- - drivers/mmc/card/block.c | 19 +++++++++++++++++++ - 1 files changed, 19 insertions(+), 0 deletions(-) - ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -366,6 +366,22 @@ static int mmc_blk_issue_rw_rq(struct mm - if (brq.data.blocks > card->host->max_blk_count) - brq.data.blocks = card->host->max_blk_count; - -+ if (mmc_host_is_spi(card->host)) { -+ /* -+ * Some SD-cards fail when we are reading last block -+ * with multiblock read. In these cases we automatically -+ * use single block reads. This only happens on SPI -+ * hosts. -+ */ -+ if (rq_data_dir(req) == READ && brq.data.blocks > 1) { -+ sector_t s = blk_rq_pos(req) + brq.data.blocks; -+ -+ if (s >= get_capacity(md->disk)) { -+ disable_multi = 1; -+ } -+ } -+ } -+ - /* - * After a read error, we redo the request one sector at a time - * in order to accurately determine which sectors can be read diff --git a/target/linux/ep93xx/patches-2.6.38/003-ep93xx_touchscreen.patch b/target/linux/ep93xx/patches-2.6.38/003-ep93xx_touchscreen.patch deleted file mode 100644 index b6b34cd7ee..0000000000 --- a/target/linux/ep93xx/patches-2.6.38/003-ep93xx_touchscreen.patch +++ /dev/null @@ -1,1061 +0,0 @@ ---- - arch/arm/mach-ep93xx/include/mach/hardware.h | 1 - arch/arm/mach-ep93xx/include/mach/regs_touch.h | 95 ++ - drivers/input/touchscreen/Kconfig | 5 - drivers/input/touchscreen/Makefile | 1 - drivers/input/touchscreen/ep93xx_ts.c | 1117 +++++++++++++++++++++++++ - drivers/input/touchscreen/ep93xx_ts.h | 53 + - 6 files changed, 1272 insertions(+) - ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -165,6 +165,15 @@ config TOUCHSCREEN_EETI - To compile this driver as a module, choose M here: the - module will be called eeti_ts. - -+config TOUCHSCREEN_EP93XX -+ tristate "EP93xx Touchscreen" -+ depends on ARM && INPUT && ARCH_EP93XX -+ help -+ Say Y here to enable support for EP93xx touch screen. -+ -+ To compile this driver as a module, choose M here: -+ the module will be called ep93xx_ts. -+ - config TOUCHSCREEN_FUJITSU - tristate "Fujitsu serial touchscreen" - select SERIO ---- a/drivers/input/touchscreen/Makefile -+++ b/drivers/input/touchscreen/Makefile -@@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += h - obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o - obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o - obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o -+obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o - obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o - obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o - obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o ---- /dev/null -+++ b/drivers/input/touchscreen/ep93xx_ts.c -@@ -0,0 +1,1021 @@ -+/* -+ * linux/drivers/input/touchscreen/ep93xx_ts.c -+ * -+ * Copyright (C) 2003-2004 Cirrus Corp. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/delay.h> -+#include <linux/wait.h> -+#include <linux/fs.h> -+#include <linux/sched.h> -+#include <linux/poll.h> -+#include <linux/miscdevice.h> -+#include <linux/init.h> -+#include <linux/compiler.h> -+#include <linux/timer.h> -+#include <linux/interrupt.h> -+#include <linux/syscalls.h> -+#include <linux/input.h> -+#include <linux/semaphore.h> -+#include <asm/irq.h> -+#include <mach/hardware.h> -+#include <asm/io.h> -+ -+/* This stuff should be in ep93xx-regs.h */ -+#define EP93XX_TOUCHSCREEN_REG(x) (EP93XX_TOUCHSCREEN_BASE + (x)) -+/* R/W touchscreen controller setup control register. */ -+#define EP93XX_TOUCHSCREEN_SETUP EP93XX_TOUCHSCREEN_REG(0x00) -+/* R/W touchscreen controller max/min register. */ -+#define EP93XX_TOUCHSCREEN_XYMAXMIN EP93XX_TOUCHSCREEN_REG(0x04) -+/* R touchscreen controller result register. */ -+#define EP93XX_TOUCHSCREEN_XYRESULT EP93XX_TOUCHSCREEN_REG(0x08) -+/* LOCKED R/W touchscreen Switch Matrix control register. */ -+#define EP93XX_TOUCHSCREEN_DISCHARGE EP93XX_TOUCHSCREEN_REG(0x0C) -+#define EP93XX_TOUCHSCREEN_XSAMPLE EP93XX_TOUCHSCREEN_REG(0x10) -+#define EP93XX_TOUCHSCREEN_YSAMPLE EP93XX_TOUCHSCREEN_REG(0x14) -+#define EP93XX_TOUCHSCREEN_DIRECT EP93XX_TOUCHSCREEN_REG(0x18) -+#define EP93XX_TOUCHSCREEN_DETECT EP93XX_TOUCHSCREEN_REG(0x1C) -+/* NA R/W touchscreen software lock register. */ -+#define EP93XX_TOUCHSCREEN_SWLOCK EP93XX_TOUCHSCREEN_REG(0x20) -+/* R/W touchscreen setup control register #2. */ -+#define EP93XX_TOUCHSCREEN_SETUP2 EP93XX_TOUCHSCREEN_REG(0x24) -+ -+/* These are duplicated in mach-ep93xx/core.c */ -+#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) -+#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) -+#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) -+#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) -+#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) -+ -+/* -+ * Register bit definitions -+ */ -+#define TSSETUP_SDLY_MASK 0x000003FF -+#define TSSETUP_SDLY_SHIFT 0 -+#define TSSETUP_NSMP_4 0x00000000 -+#define TSSETUP_NSMP_8 0x00000400 -+#define TSSETUP_NSMP_16 0x00000800 -+#define TSSETUP_NSMP_32 0x00000C00 -+#define TSSETUP_NSMP_MASK 0x00000C00 -+#define TSSETUP_DEV_4 0x00000000 -+#define TSSETUP_DEV_8 0x00001000 -+#define TSSETUP_DEV_12 0x00002000 -+#define TSSETUP_DEV_16 0x00003000 -+#define TSSETUP_DEV_24 0x00004000 -+#define TSSETUP_DEV_32 0x00005000 -+#define TSSETUP_DEV_64 0x00006000 -+#define TSSETUP_DEV_128 0x00007000 -+#define TSSETUP_ENABLE 0x00008000 -+#define TSSETUP_DLY_MASK 0x03FF0000 -+#define TSSETUP_DLY_SHIFT 16 -+#define TSSETUP_TDTCT 0x80000000 -+ -+#define TSMAXMIN_XMIN_MASK 0x000000FF -+#define TSMAXMIN_XMIN_SHIFT 0 -+#define TSMAXMIN_YMIN_MASK 0x0000FF00 -+#define TSMAXMIN_YMIN_SHIFT 8 -+#define TSMAXMIN_XMAX_MASK 0x00FF0000 -+#define TSMAXMIN_XMAX_SHIFT 16 -+#define TSMAXMIN_YMAX_MASK 0xFF000000 -+#define TSMAXMIN_YMAX_SHIFT 24 -+ -+#define TSXYRESULT_X_MASK 0x00000FFF -+#define TSXYRESULT_X_SHIFT 0 -+#define TSXYRESULT_AD_MASK 0x0000FFFF -+#define TSXYRESULT_AD_SHIFT 0 -+#define TSXYRESULT_Y_MASK 0x0FFF0000 -+#define TSXYRESULT_Y_SHIFT 16 -+#define TSXYRESULT_SDR 0x80000000 -+ -+#define TSX_SAMPLE_MASK 0x00003FFF -+#define TSX_SAMPLE_SHIFT 0x00 -+#define TSY_SAMPLE_MASK 0x3FFF0000 -+#define TSY_SAMPLE_SHIFT 0x10 -+ -+#define TSSETUP2_TINT 0x00000001 -+#define TSSETUP2_NICOR 0x00000002 -+#define TSSETUP2_PINT 0x00000004 -+#define TSSETUP2_PENSTS 0x00000008 -+#define TSSETUP2_PINTEN 0x00000010 -+#define TSSETUP2_DEVINT 0x00000020 -+#define TSSETUP2_DINTEN 0x00000040 -+#define TSSETUP2_DTMEN 0x00000080 -+#define TSSETUP2_DISDEV 0x00000100 -+#define TSSETUP2_NSIGND 0x00000200 -+#define TSSETUP2_S28EN 0x00000400 -+#define TSSETUP2_RINTEN 0x00000800 -+ -+#define TSXYRESULT_SDR 0x80000000 -+ -+/* -+ * These are used as trigger levels to know when we have pen up/down. -+ * The rules: -+ * 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these -+ * are Inverse pressure. -+ * 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up. -+ * 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down. -+ */ -+#define TS_HEAVY_INV_PRESSURE 0xFE0 /* C00 */ -+#define TS_LIGHT_INV_PRESSURE 0xFFF /* e00 */ -+ -+/* -+ * If the x, y, or inverse pressure changes more than these values -+ * between two succeeding points, the point is not reported. -+ */ -+#define TS_MAX_VALID_XY_CHANGE 0x300 -+#define TS_MAX_VALID_PRESSURE_CHANGE 0x100 -+ -+/* -+ * This is the minimum Z1 Value that is valid. -+ */ -+#define MIN_Z1_VALUE 0x50 -+ -+/* -+ * Settling delay for taking each ADC measurement. Increase this -+ * if ts is jittery. -+ */ -+#define EP93XX_TS_ADC_DELAY_USEC 2000 -+ -+/* -+ * Delay between TS points. -+ */ -+#define EP93XX_TS_PER_POINT_DELAY_USEC 10000 -+ -+/* -+ * A few more macros... -+ */ -+#define TSSETUP_DEFAULT (TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \ -+ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \ -+ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK)) -+ -+#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND) -+ -+/* -+ * For now, we use one of the minor numbers from the local/experimental -+ * range. -+ */ -+#define EP93XX_TS_MINOR 240 -+ -+/* -+ * Static Declarations -+ */ -+static unsigned int guiLastX, guiLastY; -+static unsigned int guiLastInvPressure; -+ -+struct TouchScreenSample -+{ -+ int currentX; -+ int currentY; -+ int currentButton; -+ int currentPressure; -+ struct timeval currentTime; -+}; -+ -+/* -+ * This must match the structure in tslib. -+ */ -+struct ts_sample { -+ int x; -+ int y; -+ unsigned int pressure; -+ struct timeval tv; -+}; -+ -+static struct TouchScreenSample gSample; -+static int bFreshTouchData; -+static int bCurrentPenDown; -+ -+static DECLARE_WAIT_QUEUE_HEAD(queue); -+static DEFINE_SEMAPHORE(open_sem); -+static spinlock_t event_buffer_lock = SPIN_LOCK_UNLOCKED; -+static struct fasync_struct *ep93xx_fasync; -+ -+/* -+ * Typedef Declarations -+ */ -+typedef enum { -+ TS_MODE_UN_INITIALIZED, -+ TS_MODE_HARDWARE_SCAN, -+ TS_MODE_SOFT_SCAN -+} ts_mode_t; -+ -+static ts_mode_t gScanningMode; -+ -+typedef enum{ -+ TS_STATE_STOPPED = 0, -+ TS_STATE_Z1, -+ TS_STATE_Z2, -+ TS_STATE_Y, -+ TS_STATE_X, -+ TS_STATE_DONE -+} ts_states_t; -+ -+typedef struct -+{ -+ unsigned int uiX; -+ unsigned int uiY; -+ unsigned int uiZ1; -+ unsigned int uiZ2; -+ ts_states_t state; -+} ts_struct_t; -+ -+static ts_struct_t sTouch; -+ -+/* -+ * From the spec, here's how to set up the touch screen's switch registers. -+ */ -+typedef struct -+{ -+ unsigned int uiDetect; -+ unsigned int uiDischarge; -+ unsigned int uiXSample; -+ unsigned int uiYSample; -+ unsigned int uiSwitchZ1; -+ unsigned int uiSwitchZ2; -+}SwitchStructType; -+ -+/* -+ * Here's the switch settings for a 4-wire touchscreen. See the spec -+ * for how to handle a 4, 7, or 8-wire. -+ */ -+const static SwitchStructType sSwitchSettings = -+/* s28en=0 */ -+/* TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2 */ -+ {0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608}; -+ -+/* -+ * Function declarations -+ */ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch); -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id); -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id); -+static void ee93xx_ts_evt_add(int button, int dX, int dY, int Pressure); -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, -+ size_t count, loff_t *l); -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait); -+static int ep93xx_ts_open(struct inode *inode, struct file *filp); -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on); -+static int ep93xx_ts_release(struct inode *inode, struct file *filp); -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, -+ size_t count, loff_t *ppos); -+static void ep93xx_ts_setup(void); -+static void ep93xx_ts_shutdown(void); -+int __init ep93xx_ts_init(void); -+void __exit ep93xx_ts_exit(void); -+static unsigned int CalculateInvPressure(void); -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff); -+static void TS_Soft_Scan_Mode(void); -+static void TS_Hardware_Scan_Mode(void); -+static void ProcessPointData(void); -+static void Set_Timer2_uSec(unsigned int Delay_mSec); -+static void Stop_Timer2(void); -+ -+/* -+ * ep93xx_ts_isr -+ */ -+static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id) -+{ -+ /* -+ * Note that we don't clear the interrupt here. The interrupt -+ * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE -+ * bit is cleared. -+ */ -+ -+ /* -+ * Set the ts to manual polling mode and schedule a callback. -+ * That way we can return from the isr in a reasonable amount of -+ * time and process the touch in the callback after a brief delay. -+ */ -+ TS_Soft_Scan_Mode(); -+ -+ return(IRQ_HANDLED); -+} -+ -+/* -+ * Save the current ts 'event' in an atomic fashion. -+ */ -+static void ee93xx_ts_evt_add(int buttons, int iX, int iY, int iPressure) -+{ -+ /* -+ * Note the event, but use spinlocks to keep it from getting -+ * halfway read if we get interrupted. -+ */ -+ -+ spin_lock(&event_buffer_lock); -+ -+ gSample.currentX = iX; -+ gSample.currentY = iY; -+ gSample.currentButton = buttons; -+ gSample.currentPressure = iPressure; -+ bFreshTouchData = 1; -+ do_gettimeofday(&gSample.currentTime); -+ -+ spin_unlock(&event_buffer_lock); -+ -+ kill_fasync(&ep93xx_fasync, SIGIO, POLL_IN); -+ wake_up_interruptible(&queue); -+} -+ -+ -+static ssize_t ep93xx_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) -+{ -+ unsigned short data[3]; -+ struct ts_sample ts_data; -+ int iReturn = -EFAULT; -+ -+ if (!bFreshTouchData) -+ { -+ iReturn = 0; -+ } -+ else if (count == sizeof(data)) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ data[0] = gSample.currentX; -+ data[1] = gSample.currentY; -+ data[2] = gSample.currentButton; -+ -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, data, sizeof data)) -+ return -EFAULT; -+ -+ count -= sizeof(data); -+ -+ /* return the # of bytes that got read */ -+ iReturn = sizeof(data) ; -+ } -+ else if (count == sizeof(struct ts_sample) ) -+ { -+ spin_lock_irq(&event_buffer_lock); -+ bFreshTouchData = 0; -+ ts_data.x = gSample.currentX; -+ ts_data.y = gSample.currentY; -+ ts_data.pressure = gSample.currentPressure; -+ ts_data.tv = gSample.currentTime; -+ spin_unlock_irq(&event_buffer_lock); -+ -+ if (copy_to_user(buf, &ts_data, sizeof(struct ts_sample))) -+ { -+ iReturn = -EFAULT; -+ } -+ else -+ { -+ count -= sizeof(ts_data); -+ iReturn = sizeof(ts_data); -+ } -+ } -+ -+ return iReturn; -+} -+ -+static unsigned int ep93xx_ts_poll(struct file *filp, poll_table *wait) -+{ -+ poll_wait(filp, &queue, wait); -+ -+ if (bFreshTouchData) -+ { -+ return POLLIN | POLLRDNORM; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_open(struct inode *inode, struct file *filp) -+{ -+ if (down_trylock(&open_sem)) -+ { -+ return -EBUSY; -+ } -+ -+ ep93xx_ts_setup(); -+ -+ return 0; -+} -+ -+/* -+ * Asynchronous I/O support. -+ */ -+static int ep93xx_ts_fasync(int fd, struct file *filp, int on) -+{ -+ int retval; -+ -+ retval = fasync_helper(fd, filp, on, &ep93xx_fasync); -+ if (retval < 0) -+ { -+ return retval; -+ } -+ -+ return 0; -+} -+ -+static int ep93xx_ts_release(struct inode *inode, struct file *filp) -+{ -+ Stop_Timer2(); -+ -+ /* -+ * Call our async I/O support to request that this file -+ * cease to be used for async I/O. -+ */ -+ ep93xx_ts_fasync(-1, filp, 0); -+ -+ ep93xx_ts_shutdown(); -+ -+ up(&open_sem); -+ -+ return 0; -+} -+ -+static ssize_t ep93xx_ts_write(struct file *file, const char *buffer, size_t count, -+ loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ -+static int ep93xx_ts_ioctl(struct inode *inode, struct file *file, uint command, ulong u) -+{ -+ static const int version = EV_VERSION; -+ static const u_int32_t bit =(1 << EV_ABS); -+ static const u_int32_t absbit = (1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_PRESSURE); -+ int iReturn ; -+ int i = 0; -+ -+ switch(command) -+ { -+ case EVIOCGVERSION: -+ i = copy_to_user((void __user *)u, (void *)version, sizeof(version)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(0,sizeof(u_int32_t) * 8) : -+ i = copy_to_user((void __user *)u, (void *)bit, sizeof(bit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ -+ case EVIOCGBIT(EV_ABS, sizeof(absbit) * 8): -+ i = copy_to_user((void __user *)u, (void *)absbit, sizeof(absbit)); -+ iReturn = i ? -EFAULT : 0; -+ break; -+ default: -+ iReturn = -1; -+ break; -+ } -+ -+ return iReturn; -+} -+ -+static struct file_operations ep93xx_ts_fops = { -+ owner: THIS_MODULE, -+ read: ep93xx_ts_read, -+ write: ep93xx_ts_write, -+ poll: ep93xx_ts_poll, -+ open: ep93xx_ts_open, -+ unlocked_ioctl: ep93xx_ts_ioctl, -+ release: ep93xx_ts_release, -+ fasync: ep93xx_ts_fasync, -+}; -+ -+static struct miscdevice ep93xx_ts_miscdev = -+{ -+ EP93XX_TS_MINOR, -+ "ep93xx_ts", -+ &ep93xx_ts_fops -+}; -+ -+void ep93xx_ts_setup(void) -+{ -+ unsigned int uiKTDIV, uiTSXYMaxMin; -+ -+ /* -+ * Set the TSEN bit in KTDIV so that we are enabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV |= EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+ /* -+ * Program the EP93XX_TOUCHSCREEN_SETUP and TSSetup2 registers. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Set the the touch settings. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DISCHARGE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ1, EP93XX_TOUCHSCREEN_XSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiSwitchZ2, EP93XX_TOUCHSCREEN_YSAMPLE); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDetect, EP93XX_TOUCHSCREEN_DETECT); -+ -+ /* -+ * X,YMin set to 0x40 = have to drag that many pixels for a new irq. -+ * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the -+ * time scan limit. -+ */ -+ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK; -+ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK; -+ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK; -+ __raw_writel(uiTSXYMaxMin, EP93XX_TOUCHSCREEN_XYMAXMIN); -+ -+ bCurrentPenDown = 0; -+ bFreshTouchData = 0; -+ guiLastX = 0; -+ guiLastY = 0; -+ guiLastInvPressure = 0xffffff; -+ -+ /* -+ * Enable the touch screen scanning engine. -+ */ -+ TS_Hardware_Scan_Mode(); -+} -+ -+/* -+ * ep93xx_ts_shutdown -+ * -+ */ -+static void -+ep93xx_ts_shutdown(void) -+{ -+ unsigned int uiKTDIV; -+ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Disable the scanning engine. -+ */ -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP); -+ __raw_writel(0, EP93XX_TOUCHSCREEN_SETUP2); -+ -+ /* -+ * Clear the TSEN bit in KTDIV so that we are disabling the clock -+ * for the touchscreen. -+ */ -+ uiKTDIV = __raw_readl(EP93XX_SYSCON_KEYTCHCLKDIV); -+ uiKTDIV &= ~EP93XX_SYSCON_KEYTCHCLKDIV_TSEN; -+ ep93xx_syscon_swlocked_write(uiKTDIV, EP93XX_SYSCON_KEYTCHCLKDIV); -+ -+} /* ep93xx_ts_shutdown */ -+ -+static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id) -+{ -+ switch(sTouch.state) -+ { -+ case TS_STATE_STOPPED: -+ TS_Hardware_Scan_Mode(); -+ break; -+ -+ /* -+ * Get the Z1 value for pressure measurement and set up -+ * the switch register for getting the Z2 measurement. -+ */ -+ case TS_STATE_Z1: -+ Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC); -+ sTouch.uiZ1 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2); -+ sTouch.state = TS_STATE_Z2; -+ break; -+ -+ /* -+ * Get the Z2 value for pressure measurement and set up -+ * the switch register for getting the Y measurement. -+ */ -+ case TS_STATE_Z2: -+ sTouch.uiZ2 = ADCGetData(2, 200); -+ ep93xx_ts_set_direct(sSwitchSettings.uiYSample); -+ sTouch.state = TS_STATE_Y; -+ break; -+ -+ /* -+ * Get the Y value and set up the switch register for -+ * getting the X measurement. -+ */ -+ case TS_STATE_Y: -+ sTouch.uiY = ADCGetData(4, 20); -+ ep93xx_ts_set_direct(sSwitchSettings.uiXSample); -+ sTouch.state = TS_STATE_X; -+ break; -+ -+ /* -+ * Read the X value. This is the last of the 4 adc values -+ * we need so we continue on to process the data. -+ */ -+ case TS_STATE_X: -+ Stop_Timer2(); -+ -+ sTouch.uiX = ADCGetData(4, 20); -+ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(sSwitchSettings.uiDischarge, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ sTouch.state = TS_STATE_DONE; -+ -+ /* -+ * Process this set of ADC readings. -+ */ -+ ProcessPointData(); -+ -+ break; -+ -+ /* -+ * Shouldn't get here. But if we do, we can recover... -+ */ -+ case TS_STATE_DONE: -+ TS_Hardware_Scan_Mode(); -+ break; -+ } -+ -+ /* -+ * Clear the timer2 interrupt. -+ */ -+ __raw_writel(1, EP93XX_TIMER2_CLEAR); -+ return(IRQ_HANDLED); -+} -+ -+/*--------------------------------------------------------------------- -+ * ProcessPointData -+ * -+ * This routine processes the ADC data into usable point data and then -+ * puts the driver into hw or sw scanning mode before returning. -+ * -+ * We calculate inverse pressure (lower number = more pressure) then -+ * do a hystheresis with the two pressure values 'light' and 'heavy'. -+ * -+ * If we are above the light, we have pen up. -+ * If we are below the heavy we have pen down. -+ * As long as the pressure stays below the light, pen stays down. -+ * When we get above the light again, pen goes back up. -+ * -+ */ -+static void ProcessPointData(void) -+{ -+ int bValidPoint = 0; -+ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff; -+ unsigned int uiInvPressure; -+ -+ /* -+ * Calculate the current pressure. -+ */ -+ uiInvPressure = CalculateInvPressure(); -+ -+ /* -+ * If pen pressure is so light that it is greater than the 'max' setting -+ * then we consider this to be a pen up. -+ */ -+ if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) -+ { -+ bCurrentPenDown = 0; -+ ee93xx_ts_evt_add(0, guiLastX, guiLastY, 0); -+ TS_Hardware_Scan_Mode(); -+ return; -+ } -+ -+ /* -+ * Hysteresis: -+ * If the pen pressure is hard enough to be less than the 'min' OR -+ * the pen is already down and is still less than the 'max'... -+ */ -+ if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) || -+ (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) -+ { -+ if (bCurrentPenDown) -+ { -+ /* -+ * If pen was previously down, check the difference between -+ * the last sample and this one... if the difference between -+ * samples is too great, ignore the sample. -+ */ -+ uiXDiff = abs(guiLastX - sTouch.uiX); -+ uiYDiff = abs(guiLastY - sTouch.uiY); -+ uiInvPressureDiff = abs(guiLastInvPressure - uiInvPressure); -+ -+ if (uiXDiff < TS_MAX_VALID_XY_CHANGE -+ && uiYDiff < TS_MAX_VALID_XY_CHANGE -+ && uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE) -+ { -+ bValidPoint = 1; -+ } -+ } -+ else -+ { -+ bValidPoint = 1; -+ } -+ -+ /* -+ * If either the pen was put down or dragged make a note of it. -+ */ -+ if (bValidPoint) -+ { -+ guiLastX = sTouch.uiX; -+ guiLastY = sTouch.uiY; -+ guiLastInvPressure = uiInvPressure; -+ bCurrentPenDown = 1; -+ ee93xx_ts_evt_add(1, sTouch.uiX, sTouch.uiY, -+ 0x7000000 / uiInvPressure); -+ } -+ -+ TS_Soft_Scan_Mode(); -+ return; -+ } -+ -+ TS_Hardware_Scan_Mode(); -+} -+ -+static void ep93xx_ts_set_direct(unsigned int uiADCSwitch) -+{ -+ unsigned int uiResult; -+ -+ /* -+ * Set the switch settings in the direct register. -+ */ -+ __raw_writel(0xaa, EP93XX_TOUCHSCREEN_SWLOCK); -+ __raw_writel(uiADCSwitch, EP93XX_TOUCHSCREEN_DIRECT); -+ -+ /* -+ * Read and throw away the first sample. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+} -+ -+static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff) -+{ -+ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, uiAve; -+ -+ do -+ { -+ /* -+ * Initialize our values. -+ */ -+ uiLowest = 0xfffffff; -+ uiHighest = 0; -+ uiSum = 0; -+ -+ for (uiCount = 0; uiCount < uiSamples; uiCount++) -+ { -+ /* -+ * Read the touch screen four more times and average. -+ */ -+ do { -+ uiResult = __raw_readl(EP93XX_TOUCHSCREEN_XYRESULT); -+ } while (!(uiResult & TSXYRESULT_SDR)); -+ -+ uiValue = (uiResult & TSXYRESULT_AD_MASK) >> TSXYRESULT_AD_SHIFT; -+ uiValue = ((uiValue >> 4) + ((1 + TSXYRESULT_X_MASK)>>1)) & TSXYRESULT_X_MASK; -+ -+ /* -+ * Add up the values. -+ */ -+ uiSum += uiValue; -+ -+ /* -+ * Get the lowest and highest values. -+ */ -+ if (uiValue < uiLowest) -+ { -+ uiLowest = uiValue; -+ } -+ if (uiValue > uiHighest) -+ { -+ uiHighest = uiValue; -+ } -+ } -+ } while ((uiHighest - uiLowest) > uiMaxDiff); -+ -+ /* -+ * Calculate the Average value. -+ */ -+ uiAve = uiSum / uiSamples; -+ -+ return uiAve; -+} -+ -+/* -+ * CalculateInvPressure -+ * -+ * Is the Touch Valid. Touch is not valid if the X or Y value is not -+ * in range and the pressure is not enough. -+ * -+ * Touch resistance can be measured by the following formula: -+ * -+ * Rx * X * Z2 -+ * Rtouch = --------- * (-- - 1) -+ * 4096 Z1 -+ * -+ * This is simplified in the ration of Rtouch to Rx. The lower the value, the -+ * higher the pressure. -+ * -+ * Z2 -+ * InvPressure = X * (-- - 1) -+ * Z1 -+ */ -+static unsigned int CalculateInvPressure(void) -+{ -+ unsigned int uiInvPressure; -+ -+ /* -+ * Check to see if the point is valid. -+ */ -+ if (sTouch.uiZ1 < MIN_Z1_VALUE) -+ { -+ uiInvPressure = 0x10000; -+ } -+ -+ /* -+ * Can omit the pressure calculation if you need to get rid of the division. -+ */ -+ else -+ { -+ uiInvPressure = ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX; -+ } -+ -+ return uiInvPressure; -+} -+ -+/* -+ * TS_Hardware_Scan_Mode -+ * -+ * Enables the ep93xx ts scanning engine so that when the pen goes down -+ * we will get an interrupt. -+ */ -+static void TS_Hardware_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ /* -+ * Disable the soft scanning engine. -+ */ -+ sTouch.state = TS_STATE_STOPPED; -+ Stop_Timer2(); -+ -+ /* -+ * Clear the TIN (Touchscreen INactive) bit so we can go to -+ * automatic scanning mode. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg & ~EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ -+ /* -+ * Enable the touch screen scanning state machine by setting -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT | TSSETUP_ENABLE, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the flag to show that we are in interrupt mode. -+ */ -+ gScanningMode = TS_MODE_HARDWARE_SCAN; -+ -+ /* -+ * Initialize EP93XX_TOUCHSCREEN_SETUP2 register. -+ */ -+ __raw_writel(TSSETUP2_DEFAULT, EP93XX_TOUCHSCREEN_SETUP2); -+ -+} -+ -+/* -+ * TS_Soft_Scan_Mode -+ * -+ * Sets the touch screen to manual polling mode. -+ */ -+static void TS_Soft_Scan_Mode(void) -+{ -+ unsigned int uiDevCfg; -+ -+ if (gScanningMode != TS_MODE_SOFT_SCAN) -+ { -+ /* -+ * Disable the touch screen scanning state machine by clearing -+ * the ENABLE bit. -+ */ -+ __raw_writel(TSSETUP_DEFAULT, EP93XX_TOUCHSCREEN_SETUP); -+ -+ /* -+ * Set the TIN bit so we can do manual touchscreen polling. -+ */ -+ uiDevCfg = __raw_readl(EP93XX_SYSCON_DEVCFG); -+ ep93xx_syscon_swlocked_write(uiDevCfg | EP93XX_SYSCON_DEVCFG_TIN, -+ EP93XX_SYSCON_DEVCFG); -+ } -+ -+ /* -+ * Set the switch register up for the first ADC reading -+ */ -+ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1); -+ -+ /* -+ * Initialize our software state machine to know which ADC -+ * reading to take -+ */ -+ sTouch.state = TS_STATE_Z1; -+ -+ /* -+ * Set the timer so after a mSec or two settling delay it will -+ * take the first ADC reading. -+ */ -+ Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC); -+ -+ /* -+ * Note that we are in sw scanning mode not hw scanning mode. -+ */ -+ gScanningMode = TS_MODE_SOFT_SCAN; -+ -+} -+ -+static void Set_Timer2_uSec(unsigned int uiDelay_uSec) -+{ -+ unsigned int uiClockTicks; -+ -+ /* -+ * Stop timer 2 -+ */ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+ -+ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000; -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_LOAD); -+ __raw_writel(uiClockTicks, EP93XX_TIMER2_VALUE); -+ -+ /* -+ * Set up Timer 2 for 508 kHz clock and periodic mode. -+ */ -+ __raw_writel(0xC8, EP93XX_TIMER2_CONTROL); -+ -+} -+ -+static void Stop_Timer2(void) -+{ -+ __raw_writel(0, EP93XX_TIMER2_CONTROL); -+} -+ -+/* -+ * Initialization and exit routines -+ */ -+int __init ep93xx_ts_init(void) -+{ -+ int retval; -+ -+ retval = request_irq(IRQ_EP93XX_TOUCH, ep93xx_ts_isr, -+ IRQF_DISABLED, "ep93xx_ts", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get touchscreen IRQ\n"); -+ return retval; -+ } -+ -+ retval = request_irq(IRQ_EP93XX_TIMER2, ep93xx_timer2_isr, -+ IRQF_DISABLED, "ep93xx_timer2", 0); -+ if (retval) -+ { -+ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n"); -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ return retval; -+ } -+ -+ misc_register(&ep93xx_ts_miscdev); -+ -+ sTouch.state = TS_STATE_STOPPED; -+ gScanningMode = TS_MODE_UN_INITIALIZED; -+ -+ printk(KERN_NOTICE "ep93xx touchscreen driver configured for 4-wire operation\n"); -+ -+ return 0; -+} -+ -+void __exit ep93xx_ts_exit(void) -+{ -+ Stop_Timer2(); -+ -+ free_irq(IRQ_EP93XX_TOUCH, 0); -+ free_irq(IRQ_EP93XX_TIMER2, 0); -+ -+ misc_deregister(&ep93xx_ts_miscdev); -+} -+ -+module_init(ep93xx_ts_init); -+module_exit(ep93xx_ts_exit); -+ -+MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver"); -+MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx"); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ep93xx/patches-2.6.38/004-simone_add_mmc_spi.patch b/target/linux/ep93xx/patches-2.6.38/004-simone_add_mmc_spi.patch deleted file mode 100644 index 511d012b86..0000000000 --- a/target/linux/ep93xx/patches-2.6.38/004-simone_add_mmc_spi.patch +++ /dev/null @@ -1,179 +0,0 @@ -This enables the mmc-over-spi driver for the Sim.One board, based on Mika's -patch, which used a GPIO for chip select in stead of the default SFRMOUT pin. -I've modified it to use the usual SFRMOUT; if you've modified your Sim.One -board to use a GPIO instead, uncomment and modify -// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -in the source file. - -martinwguy, 14 May 2010 - -From: Mika Westerberg <mika.westerberg@iki.fi> -Date: Wed, 28 Apr 2010 08:42:46 +0300 -Subject: [PATCH] ep93xx: simone: added board specific SPI support for MMC/SD cards - -This includes setting up EGPIOs 0 and 9 for card detection and chip select -respectively. - ---- a/arch/arm/mach-ep93xx/simone.c -+++ b/arch/arm/mach-ep93xx/simone.c -@@ -18,12 +18,16 @@ - #include <linux/kernel.h> - #include <linux/init.h> - #include <linux/platform_device.h> -+#include <linux/mmc/host.h> - #include <linux/gpio.h> -+#include <linux/spi/spi.h> -+#include <linux/spi/mmc_spi.h> - #include <linux/i2c.h> - #include <linux/i2c-gpio.h> - - #include <mach/hardware.h> - #include <mach/fb.h> -+#include <mach/ep93xx_spi.h> - - #include <asm/mach-types.h> - #include <asm/mach/arch.h> -@@ -38,6 +42,135 @@ static struct ep93xxfb_mach_info __initd - .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, - }; - -+/* -+ * GPIO lines used for MMC card detection. -+ */ -+#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 -+ -+/* -+ * If you have hacked your Sim.One to use a GPIO as SD card chip select -+ * (SD pin 1), uncomment the following line. -+ * The example, EGPIO15, is on TP17 near the CPU. -+ */ -+// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 -+ -+/* -+ * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal, -+ * you can leave these empty and pass NULL as .controller_data. -+ */ -+ -+#ifdef MMC_CHIP_SELECT_GPIO -+static int simone_mmc_spi_setup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ int err; -+ -+ err = gpio_request(gpio, spi->modalias); -+ if (err) -+ return err; -+ -+ err = gpio_direction_output(gpio, 1); -+ if (err) { -+ gpio_free(gpio); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static void simone_mmc_spi_cleanup(struct spi_device *spi) -+{ -+ unsigned int gpio = MMC_CHIP_SELECT_GPIO; -+ -+ gpio_set_value(gpio, 1); -+ gpio_direction_input(gpio); -+ gpio_free(gpio); -+} -+ -+static void simone_mmc_spi_cs_control(struct spi_device *spi, int value) -+{ -+ gpio_set_value(MMC_CHIP_SELECT_GPIO, value); -+} -+ -+static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = { -+ .setup = simone_mmc_spi_setup, -+ .cleanup = simone_mmc_spi_cleanup, -+ .cs_control = simone_mmc_spi_cs_control, -+}; -+#endif -+ -+/* -+ * MMC card detection GPIO setup. -+ */ -+static int simone_mmc_spi_init(struct device *dev, -+ irqreturn_t (*irq_handler)(int, void *), void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ int irq, err; -+ -+ err = gpio_request(gpio, dev_name(dev)); -+ if (err) -+ return err; -+ -+ err = gpio_direction_input(gpio); -+ if (err) -+ goto fail; -+ -+ irq = gpio_to_irq(gpio); -+ if (irq < 0) -+ goto fail; -+ -+ err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING, -+ "MMC card detect", mmc); -+ if (err) -+ goto fail; -+ -+ printk(KERN_INFO "%s: using irq %d for MMC card detection\n", -+ dev_name(dev), irq); -+ -+ return 0; -+fail: -+ gpio_free(gpio); -+ return err; -+} -+ -+static void simone_mmc_spi_exit(struct device *dev, void *mmc) -+{ -+ unsigned int gpio = MMC_CARD_DETECT_GPIO; -+ -+ free_irq(gpio_to_irq(gpio), mmc); -+ gpio_free(gpio); -+} -+ -+static struct mmc_spi_platform_data simone_mmc_spi_data = { -+ .init = simone_mmc_spi_init, -+ .exit = simone_mmc_spi_exit, -+ .detect_delay = 500, -+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, -+}; -+ -+static struct spi_board_info simone_spi_devices[] __initdata = { -+ { -+ .modalias = "mmc_spi", -+#ifdef MMC_CHIP_SELECT_GPIO -+ .controller_data = &simone_mmc_spi_ops, -+#endif -+ .platform_data = &simone_mmc_spi_data, -+ /* -+ * We use 10 MHz even though the maximum is 3.7 MHz. The driver -+ * will limit it automatically to max. frequency. -+ */ -+ .max_speed_hz = 10 * 1000 * 1000, -+ .bus_num = 0, -+ .chip_select = 0, -+ .mode = SPI_MODE_3, -+ }, -+}; -+ -+static struct ep93xx_spi_info simone_spi_info __initdata = { -+ .num_chipselect = ARRAY_SIZE(simone_spi_devices), -+}; -+ - static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { - .sda_pin = EP93XX_GPIO_LINE_EEDAT, - .sda_is_open_drain = 0, -@@ -61,6 +194,8 @@ static void __init simone_init_machine(v - ep93xx_register_fb(&simone_fb_info); - ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, - ARRAY_SIZE(simone_i2c_board_info)); -+ ep93xx_register_spi(&simone_spi_info, simone_spi_devices, -+ ARRAY_SIZE(simone_spi_devices)); - ep93xx_register_ac97(); - } - |