aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch')
-rw-r--r--target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch10488
1 files changed, 10488 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch b/target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch
new file mode 100644
index 000000000..b5211d9ca
--- /dev/null
+++ b/target/linux/brcm2708/patches-3.3/0500-rpi-patches-geaf792a-9efb4705.patch
@@ -0,0 +1,10488 @@
+--- a/arch/arm/configs/bcmrpi_cutdown_defconfig
++++ b/arch/arm/configs/bcmrpi_cutdown_defconfig
+@@ -1,1307 +1,436 @@
+-#
+-# Automatically generated file; DO NOT EDIT.
+-# Linux/arm 3.1.9 Kernel Configuration
+-#
+-CONFIG_ARM=y
+-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+-CONFIG_GENERIC_GPIO=y
+-# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+-CONFIG_GENERIC_CLOCKEVENTS=y
+-CONFIG_KTIME_SCALAR=y
+-CONFIG_HAVE_PROC_CPU=y
+-CONFIG_STACKTRACE_SUPPORT=y
+-CONFIG_HAVE_LATENCYTOP_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_CPU_IDLE_WAIT=y
+-CONFIG_GENERIC_HWEIGHT=y
+-CONFIG_GENERIC_CALIBRATE_DELAY=y
+-CONFIG_NEED_DMA_MAP_STATE=y
+-CONFIG_VECTORS_BASE=0xffff0000
+-# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+-CONFIG_HAVE_IRQ_WORK=y
+-
+-#
+-# General setup
+-#
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_BROKEN_ON_SMP=y
+-CONFIG_INIT_ENV_ARG_LIMIT=32
+-CONFIG_CROSS_COMPILE=""
+-CONFIG_LOCALVERSION=""
+ # CONFIG_LOCALVERSION_AUTO is not set
+-CONFIG_HAVE_KERNEL_GZIP=y
+-CONFIG_HAVE_KERNEL_LZMA=y
+-CONFIG_HAVE_KERNEL_LZO=y
+-CONFIG_KERNEL_GZIP=y
+-# CONFIG_KERNEL_LZMA is not set
+-# CONFIG_KERNEL_LZO is not set
+-CONFIG_DEFAULT_HOSTNAME="(none)"
+-CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
+-CONFIG_SYSVIPC_SYSCTL=y
+ CONFIG_POSIX_MQUEUE=y
+-CONFIG_POSIX_MQUEUE_SYSCTL=y
+-# CONFIG_BSD_PROCESS_ACCT is not set
+-# CONFIG_FHANDLE is not set
+-# CONFIG_TASKSTATS is not set
+-# CONFIG_AUDIT is not set
+-CONFIG_HAVE_GENERIC_HARDIRQS=y
+-
+-#
+-# IRQ subsystem
+-#
+-CONFIG_GENERIC_HARDIRQS=y
+-CONFIG_HAVE_SPARSE_IRQ=y
+-CONFIG_GENERIC_IRQ_SHOW=y
+-# CONFIG_SPARSE_IRQ is not set
+-
+-#
+-# RCU Subsystem
+-#
+-CONFIG_TINY_RCU=y
+-# CONFIG_PREEMPT_RCU is not set
+-# CONFIG_RCU_TRACE is not set
+-# CONFIG_TREE_RCU_TRACE is not set
+ CONFIG_IKCONFIG=y
+ CONFIG_IKCONFIG_PROC=y
+-CONFIG_LOG_BUF_SHIFT=17
+-# CONFIG_CGROUPS is not set
+-# CONFIG_NAMESPACES is not set
+-# CONFIG_SCHED_AUTOGROUP is not set
+-# CONFIG_SYSFS_DEPRECATED is not set
+-# CONFIG_RELAY is not set
+-# CONFIG_BLK_DEV_INITRD is not set
+-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+-CONFIG_SYSCTL=y
+-CONFIG_ANON_INODES=y
+-CONFIG_EXPERT=y
+ # CONFIG_UID16 is not set
+-CONFIG_SYSCTL_SYSCALL=y
+ # CONFIG_KALLSYMS is not set
+-CONFIG_HOTPLUG=y
+-CONFIG_PRINTK=y
+-CONFIG_BUG=y
+-# CONFIG_ELF_CORE is not set
+-CONFIG_BASE_FULL=y
+-CONFIG_FUTEX=y
+-CONFIG_EPOLL=y
+-CONFIG_SIGNALFD=y
+-CONFIG_TIMERFD=y
+-CONFIG_EVENTFD=y
+-CONFIG_SHMEM=y
+-CONFIG_AIO=y
+ CONFIG_EMBEDDED=y
+-CONFIG_HAVE_PERF_EVENTS=y
+-CONFIG_PERF_USE_VMALLOC=y
+-
+-#
+-# Kernel Performance Events And Counters
+-#
+-# CONFIG_PERF_EVENTS is not set
+-# CONFIG_PERF_COUNTERS is not set
+ # CONFIG_VM_EVENT_COUNTERS is not set
+ # CONFIG_COMPAT_BRK is not set
+ CONFIG_SLAB=y
+-# CONFIG_SLUB is not set
+-# CONFIG_SLOB is not set
+-# CONFIG_PROFILING is not set
+-CONFIG_HAVE_OPROFILE=y
+-# CONFIG_KPROBES is not set
+-CONFIG_HAVE_KPROBES=y
+-CONFIG_HAVE_KRETPROBES=y
+-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+-CONFIG_HAVE_CLK=y
+-CONFIG_HAVE_DMA_API_DEBUG=y
+-
+-#
+-# GCOV-based kernel profiling
+-#
+-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+-CONFIG_SLABINFO=y
+-CONFIG_RT_MUTEXES=y
+-CONFIG_BASE_SMALL=0
+ CONFIG_MODULES=y
+-# CONFIG_MODULE_FORCE_LOAD is not set
+ CONFIG_MODULE_UNLOAD=y
+-# CONFIG_MODULE_FORCE_UNLOAD is not set
+ CONFIG_MODVERSIONS=y
+ CONFIG_MODULE_SRCVERSION_ALL=y
+-CONFIG_BLOCK=y
+-CONFIG_LBDAF=y
+ # CONFIG_BLK_DEV_BSG is not set
+-# CONFIG_BLK_DEV_BSGLIB is not set
+-# CONFIG_BLK_DEV_INTEGRITY is not set
+-
+-#
+-# IO Schedulers
+-#
+-CONFIG_IOSCHED_NOOP=y
+-CONFIG_IOSCHED_DEADLINE=y
+-CONFIG_IOSCHED_CFQ=y
+-# CONFIG_DEFAULT_DEADLINE is not set
+-CONFIG_DEFAULT_CFQ=y
+-# CONFIG_DEFAULT_NOOP is not set
+-CONFIG_DEFAULT_IOSCHED="cfq"
+-# CONFIG_INLINE_SPIN_TRYLOCK is not set
+-# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+-# CONFIG_INLINE_SPIN_LOCK is not set
+-# CONFIG_INLINE_SPIN_LOCK_BH is not set
+-# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+-# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+-CONFIG_INLINE_SPIN_UNLOCK=y
+-# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+-CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+-# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+-# CONFIG_INLINE_READ_TRYLOCK is not set
+-# CONFIG_INLINE_READ_LOCK is not set
+-# CONFIG_INLINE_READ_LOCK_BH is not set
+-# CONFIG_INLINE_READ_LOCK_IRQ is not set
+-# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+-CONFIG_INLINE_READ_UNLOCK=y
+-# CONFIG_INLINE_READ_UNLOCK_BH is not set
+-CONFIG_INLINE_READ_UNLOCK_IRQ=y
+-# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+-# CONFIG_INLINE_WRITE_TRYLOCK is not set
+-# CONFIG_INLINE_WRITE_LOCK is not set
+-# CONFIG_INLINE_WRITE_LOCK_BH is not set
+-# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+-# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+-CONFIG_INLINE_WRITE_UNLOCK=y
+-# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+-CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+-# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+-# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+-CONFIG_FREEZER=y
+-
+-#
+-# System Type
+-#
+-CONFIG_MMU=y
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_VEXPRESS is not set
+-# CONFIG_ARCH_AT91 is not set
+-# CONFIG_ARCH_BCMRING is not set
+-# CONFIG_ARCH_CLPS711X is not set
+-# CONFIG_ARCH_CNS3XXX is not set
+-# CONFIG_ARCH_GEMINI is not set
+-# CONFIG_ARCH_PRIMA2 is not set
+-# CONFIG_ARCH_EBSA110 is not set
+-# CONFIG_ARCH_EP93XX is not set
+-# CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_MXC is not set
+-# CONFIG_ARCH_MXS is not set
+-# CONFIG_ARCH_NETX is not set
+-# CONFIG_ARCH_H720X 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_DOVE is not set
+-# CONFIG_ARCH_KIRKWOOD is not set
+-# CONFIG_ARCH_LPC32XX is not set
+-# CONFIG_ARCH_MV78XX0 is not set
+-# CONFIG_ARCH_ORION5X is not set
+-# CONFIG_ARCH_MMP is not set
+-# CONFIG_ARCH_KS8695 is not set
+-# CONFIG_ARCH_W90X900 is not set
+-# CONFIG_ARCH_NUC93X is not set
+-# CONFIG_ARCH_TEGRA is not set
+-# CONFIG_ARCH_PNX4008 is not set
+-# CONFIG_ARCH_PXA is not set
+-# CONFIG_ARCH_MSM is not set
+-# CONFIG_ARCH_SHMOBILE is not set
+-# CONFIG_ARCH_RPC is not set
+-# CONFIG_ARCH_SA1100 is not set
+-# CONFIG_ARCH_S3C2410 is not set
+-# CONFIG_ARCH_S3C64XX is not set
+-# CONFIG_ARCH_S5P64X0 is not set
+-# CONFIG_ARCH_S5PC100 is not set
+-# CONFIG_ARCH_S5PV210 is not set
+-# CONFIG_ARCH_EXYNOS4 is not set
+-# CONFIG_ARCH_SHARK is not set
+-# CONFIG_ARCH_TCC_926 is not set
+-# CONFIG_ARCH_U300 is not set
+-# CONFIG_ARCH_U8500 is not set
+-# CONFIG_ARCH_NOMADIK is not set
+-# CONFIG_ARCH_DAVINCI is not set
+-# CONFIG_ARCH_OMAP is not set
+-# CONFIG_PLAT_SPEAR is not set
+ CONFIG_ARCH_BCM2708=y
+-# CONFIG_ARCH_VT8500 is not set
+-# CONFIG_ARCH_ZYNQ is not set
+-
+-#
+-# System MMU
+-#
+-
+-#
+-# Broadcom BCM2708 Implementations
+-#
+-CONFIG_MACH_BCM2708=y
+-CONFIG_BCM2708_GPIO=y
+-CONFIG_BCM2708_VCMEM=y
+-
+-#
+-# Processor Type
+-#
+-CONFIG_CPU_V6=y
+-CONFIG_CPU_32v6=y
+-CONFIG_CPU_ABRT_EV6=y
+-CONFIG_CPU_PABRT_V6=y
+-CONFIG_CPU_CACHE_V6=y
+-CONFIG_CPU_CACHE_VIPT=y
+-CONFIG_CPU_COPY_V6=y
+-CONFIG_CPU_TLB_V6=y
+-CONFIG_CPU_HAS_ASID=y
+-CONFIG_CPU_CP15=y
+-CONFIG_CPU_CP15_MMU=y
+-CONFIG_CPU_USE_DOMAINS=y
+-
+-#
+-# Processor Features
+-#
+-CONFIG_ARM_THUMB=y
+-# CONFIG_CPU_ICACHE_DISABLE is not set
+-# CONFIG_CPU_DCACHE_DISABLE is not set
+-# CONFIG_CPU_BPREDICT_DISABLE is not set
+-CONFIG_ARM_L1_CACHE_SHIFT=5
+-CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+-CONFIG_CPU_HAS_PMU=y
+-CONFIG_ARM_ERRATA_411920=y
+-# CONFIG_ARM_ERRATA_364296 is not set
+-
+-#
+-# 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=y
+ CONFIG_NO_HZ=y
+-# CONFIG_HIGH_RES_TIMERS is not set
+-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+-CONFIG_VMSPLIT_3G=y
+-# CONFIG_VMSPLIT_2G is not set
+-# CONFIG_VMSPLIT_1G is not set
+-CONFIG_PAGE_OFFSET=0xC0000000
+-CONFIG_PREEMPT_NONE=y
+-# CONFIG_PREEMPT_VOLUNTARY is not set
+-# CONFIG_PREEMPT is not set
+-CONFIG_HZ=100
++CONFIG_HIGH_RES_TIMERS=y
+ CONFIG_AEABI=y
+-CONFIG_OABI_COMPAT=y
+-# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+-# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+-CONFIG_HAVE_ARCH_PFN_VALID=y
+-# CONFIG_HIGHMEM is not set
+-CONFIG_SELECT_MEMORY_MODEL=y
+-CONFIG_FLATMEM_MANUAL=y
+-CONFIG_FLATMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+-CONFIG_HAVE_MEMBLOCK=y
+-CONFIG_PAGEFLAGS_EXTENDED=y
+-CONFIG_SPLIT_PTLOCK_CPUS=4
+-# CONFIG_COMPACTION is not set
+-# CONFIG_PHYS_ADDR_T_64BIT is not set
+-CONFIG_ZONE_DMA_FLAG=0
+-CONFIG_VIRT_TO_BUS=y
+-# CONFIG_KSM is not set
+-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+-CONFIG_NEED_PER_CPU_KM=y
+-# CONFIG_CLEANCACHE is not set
+-CONFIG_FORCE_MAX_ZONEORDER=11
+-CONFIG_ALIGNMENT_TRAP=y
+-# CONFIG_UACCESS_WITH_MEMCPY is not set
+-# CONFIG_SECCOMP is not set
+-# CONFIG_CC_STACKPROTECTOR is not set
+-# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+-
+-#
+-# Boot options
+-#
+-# CONFIG_USE_OF is not set
+ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
+-CONFIG_CMDLINE_FROM_BOOTLOADER=y
+-# CONFIG_CMDLINE_EXTEND is not set
+-# CONFIG_CMDLINE_FORCE is not set
+-# CONFIG_XIP_KERNEL is not set
+-# CONFIG_KEXEC is not set
+-# CONFIG_CRASH_DUMP is not set
+-# CONFIG_AUTO_ZRELADDR is not set
+-
+-#
+-# CPU Power Management
+-#
+ CONFIG_CPU_IDLE=y
+-CONFIG_CPU_IDLE_GOV_LADDER=y
+-CONFIG_CPU_IDLE_GOV_MENU=y
+-
+-#
+-# Floating point emulation
+-#
+-
+-#
+-# At least one emulation must be selected
+-#
+-# CONFIG_FPE_NWFPE is not set
+-# CONFIG_FPE_FASTFPE is not set
+ CONFIG_VFP=y
+-
+-#
+-# Userspace binary formats
+-#
+-CONFIG_BINFMT_ELF=y
+-CONFIG_HAVE_AOUT=y
+-# CONFIG_BINFMT_AOUT is not set
+-# CONFIG_BINFMT_MISC is not set
+-
+-#
+-# Power management options
+-#
+-CONFIG_SUSPEND=y
+-CONFIG_SUSPEND_FREEZER=y
+-CONFIG_PM_SLEEP=y
+-# CONFIG_PM_RUNTIME is not set
+-CONFIG_PM=y
+-# CONFIG_PM_DEBUG is not set
+-# CONFIG_APM_EMULATION is not set
+-CONFIG_PM_CLK=y
+-CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_BINFMT_MISC=m
+ CONFIG_NET=y
+-
+-#
+-# Networking options
+-#
+ CONFIG_PACKET=y
+ CONFIG_UNIX=y
+-CONFIG_XFRM=y
+ CONFIG_XFRM_USER=y
+-# CONFIG_XFRM_SUB_POLICY is not set
+-# CONFIG_XFRM_MIGRATE is not set
+-# CONFIG_XFRM_STATISTICS is not set
+ CONFIG_NET_KEY=m
+-# CONFIG_NET_KEY_MIGRATE is not set
+ CONFIG_INET=y
+ CONFIG_IP_MULTICAST=y
+-# CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
+-# CONFIG_IP_PNP_BOOTP is not set
+ CONFIG_IP_PNP_RARP=y
+-# CONFIG_NET_IPIP is not set
+-# CONFIG_NET_IPGRE_DEMUX is not set
+-# CONFIG_IP_MROUTE 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 is not set
+ # CONFIG_INET_XFRM_MODE_TUNNEL is not set
+ # CONFIG_INET_XFRM_MODE_BEET is not set
+ # CONFIG_INET_LRO is not set
+ # CONFIG_INET_DIAG is not set
+-# 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 is not set
+-# CONFIG_NETWORK_SECMARK is not set
+-# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+-# CONFIG_NETFILTER is not set
+-# CONFIG_IP_DCCP is not set
+-# CONFIG_IP_SCTP is not set
+-# CONFIG_RDS is not set
+-# CONFIG_TIPC is not set
+-# CONFIG_ATM is not set
+-# CONFIG_L2TP is not set
+-# CONFIG_BRIDGE is not set
+-# CONFIG_NET_DSA 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_PHONET is not set
+-# CONFIG_IEEE802154 is not set
+-# CONFIG_NET_SCHED is not set
+-# CONFIG_DCB is not set
+-CONFIG_DNS_RESOLVER=y
+-# CONFIG_BATMAN_ADV is not set
+-
+-#
+-# Network testing
+-#
+ CONFIG_NET_PKTGEN=m
+-# CONFIG_HAMRADIO is not set
+-# CONFIG_CAN is not set
+-# CONFIG_IRDA is not set
+-# CONFIG_BT is not set
+-# CONFIG_AF_RXRPC is not set
+-CONFIG_WIRELESS=y
+-CONFIG_WEXT_CORE=y
+-CONFIG_WEXT_PROC=y
+-CONFIG_CFG80211=y
+-# CONFIG_NL80211_TESTMODE is not set
+-# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+-# CONFIG_CFG80211_REG_DEBUG is not set
+-CONFIG_CFG80211_DEFAULT_PS=y
+-# CONFIG_CFG80211_INTERNAL_REGDB is not set
+-CONFIG_CFG80211_WEXT=y
+-CONFIG_WIRELESS_EXT_SYSFS=y
+-# CONFIG_LIB80211 is not set
+-# CONFIG_MAC80211 is not set
+-# CONFIG_WIMAX is not set
+-# CONFIG_RFKILL is not set
+-# CONFIG_NET_9P is not set
+-# CONFIG_CAIF is not set
+-# CONFIG_CEPH_LIB is not set
+-# CONFIG_NFC is not set
+-
+-#
+-# Device Drivers
+-#
+-
+-#
+-# Generic Driver Options
+-#
+-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+-# CONFIG_DEVTMPFS is not set
+-CONFIG_STANDALONE=y
+-CONFIG_PREVENT_FIRMWARE_BUILD=y
+-CONFIG_FW_LOADER=y
+-CONFIG_FIRMWARE_IN_KERNEL=y
+-CONFIG_EXTRA_FIRMWARE=""
+-# CONFIG_DEBUG_DRIVER is not set
+-# CONFIG_DEBUG_DEVRES is not set
+-# CONFIG_SYS_HYPERVISOR is not set
+-# CONFIG_CONNECTOR is not set
+-# CONFIG_MTD is not set
+-# CONFIG_PARPORT is not set
+-CONFIG_BLK_DEV=y
+-# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_IRDA=m
++CONFIG_IRLAN=m
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRTTY_SIR=m
++CONFIG_KINGSUN_DONGLE=m
++CONFIG_KSDAZZLE_DONGLE=m
++CONFIG_KS959_DONGLE=m
++CONFIG_USB_IRDA=m
++CONFIG_SIGMATEL_FIR=m
++CONFIG_MCS_FIR=m
++CONFIG_BT=m
++CONFIG_BT_L2CAP=y
++CONFIG_BT_SCO=y
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_MRVL=m
++CONFIG_BT_MRVL_SDIO=m
++CONFIG_BT_ATH3K=m
++CONFIG_CFG80211=m
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_MESH=y
++CONFIG_WIMAX=m
++CONFIG_NET_9P=m
++CONFIG_NFC=m
++CONFIG_NFC_PN533=m
++CONFIG_DEVTMPFS=y
+ CONFIG_BLK_DEV_LOOP=y
+-CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+-
+-#
+-# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+-#
+-# CONFIG_BLK_DEV_NBD is not set
+-# CONFIG_BLK_DEV_UB is not set
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
+ CONFIG_BLK_DEV_RAM=y
+-CONFIG_BLK_DEV_RAM_COUNT=16
+-CONFIG_BLK_DEV_RAM_SIZE=4096
+-# CONFIG_BLK_DEV_XIP is not set
+-# CONFIG_CDROM_PKTCDVD is not set
+-# CONFIG_ATA_OVER_ETH is not set
+-# CONFIG_MG_DISK is not set
+-# CONFIG_BLK_DEV_RBD is not set
+-# CONFIG_SENSORS_LIS3LV02D is not set
++CONFIG_CDROM_PKTCDVD=m
+ CONFIG_MISC_DEVICES=y
+-# CONFIG_ENCLOSURE_SERVICES is not set
+-# CONFIG_C2PORT is not set
+-
+-#
+-# EEPROM support
+-#
+-# CONFIG_EEPROM_93CX6 is not set
+-# CONFIG_IWMC3200TOP is not set
+-
+-#
+-# Texas Instruments shared transport line discipline
+-#
+-# CONFIG_TI_ST is not set
+-CONFIG_BCM2708_VCHIQ=y
+-CONFIG_HAVE_IDE=y
+-# CONFIG_IDE is not set
+-
+-#
+-# SCSI device support
+-#
+-CONFIG_SCSI_MOD=y
+-# 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=m
+-# CONFIG_CHR_DEV_ST is not set
+-# CONFIG_CHR_DEV_OSST is not set
++CONFIG_BLK_DEV_SD=y
+ CONFIG_BLK_DEV_SR=m
+-# CONFIG_BLK_DEV_SR_VENDOR is not set
+-# CONFIG_CHR_DEV_SG is not set
+-# CONFIG_CHR_DEV_SCH is not set
+ CONFIG_SCSI_MULTI_LUN=y
+-# 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_ATTRS is not set
+-# CONFIG_SCSI_SAS_LIBSAS is not set
+-# CONFIG_SCSI_SRP_ATTRS is not set
+ # CONFIG_SCSI_LOWLEVEL is not set
+-# CONFIG_SCSI_DH is not set
+-# CONFIG_SCSI_OSD_INITIATOR is not set
+-# CONFIG_ATA is not set
+-# CONFIG_MD is not set
+-# CONFIG_TARGET_CORE is not set
+ CONFIG_NETDEVICES=y
+-# CONFIG_DUMMY is not set
+-# CONFIG_BONDING is not set
+-# CONFIG_MACVLAN is not set
+-# CONFIG_EQUALIZER is not set
+ CONFIG_TUN=m
+-# CONFIG_VETH is not set
+-CONFIG_MII=y
+ CONFIG_PHYLIB=m
+-
+-#
+-# MII PHY device drivers
+-#
+-# CONFIG_MARVELL_PHY is not set
+-# CONFIG_DAVICOM_PHY is not set
+-# CONFIG_QSEMI_PHY is not set
+-# CONFIG_LXT_PHY is not set
+-# CONFIG_CICADA_PHY is not set
+-# CONFIG_VITESSE_PHY is not set
+-# CONFIG_SMSC_PHY is not set
+-# CONFIG_BROADCOM_PHY is not set
+-# CONFIG_ICPLUS_PHY is not set
+-# CONFIG_REALTEK_PHY is not set
+-# CONFIG_NATIONAL_PHY is not set
+-# CONFIG_STE10XP is not set
+-# CONFIG_LSI_ET1011C_PHY is not set
+-# CONFIG_MICREL_PHY is not set
+ CONFIG_MDIO_BITBANG=m
+-# CONFIG_MDIO_GPIO is not set
+ CONFIG_NET_ETHERNET=y
+-CONFIG_AX88796=m
+-# CONFIG_AX88796_93CX6 is not set
+-# CONFIG_SMC91X is not set
+-# CONFIG_DM9000 is not set
+-# CONFIG_ETHOC is not set
+-# CONFIG_SMC911X is not set
+-# CONFIG_SMSC911X is not set
+-# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+-# CONFIG_B44 is not set
+-# CONFIG_KS8851_MLL is not set
+-# CONFIG_FTMAC100 is not set
+ # CONFIG_NETDEV_1000 is not set
+ # CONFIG_NETDEV_10000 is not set
+-# CONFIG_WLAN is not set
+-
+-#
+-# Enable WiMAX (Networking options) to see the WiMAX drivers
+-#
+-
+-#
+-# USB Network Adapters
+-#
+-# CONFIG_USB_CATC is not set
+-# CONFIG_USB_KAWETH is not set
+-# CONFIG_USB_PEGASUS is not set
+-# CONFIG_USB_RTL8150 is not set
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_AT76C50X_USB=m
++CONFIG_USB_ZD1201=m
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_RTL8187=m
++CONFIG_MAC80211_HWSIM=m
++CONFIG_ATH_COMMON=m
++CONFIG_ATH9K=m
++CONFIG_ATH9K_HTC=m
++CONFIG_CARL9170=m
++CONFIG_B43=m
++CONFIG_B43LEGACY=m
++CONFIG_HOSTAP=m
++CONFIG_IWM=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT53XX=y
++CONFIG_RTL8192CU=m
++CONFIG_WL1251=m
++CONFIG_WL12XX_MENU=m
++CONFIG_ZD1211RW=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_WIMAX_I2400M_USB=m
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
+ CONFIG_USB_USBNET=y
+ CONFIG_USB_NET_AX8817X=m
+-# CONFIG_USB_NET_CDCETHER is not set
+-# CONFIG_USB_NET_CDC_EEM is not set
+-CONFIG_USB_NET_CDC_NCM=y
+-# CONFIG_USB_NET_DM9601 is not set
+-# CONFIG_USB_NET_SMSC75XX is not set
++CONFIG_USB_NET_CDCETHER=m
++CONFIG_USB_NET_CDC_EEM=m
++CONFIG_USB_NET_DM9601=m
++CONFIG_USB_NET_SMSC75XX=m
+ CONFIG_USB_NET_SMSC95XX=y
+-# CONFIG_USB_NET_GL620A is not set
+-# CONFIG_USB_NET_NET1080 is not set
+-# CONFIG_USB_NET_PLUSB is not set
+-# CONFIG_USB_NET_MCS7830 is not set
+-# CONFIG_USB_NET_RNDIS_HOST is not set
+-# CONFIG_USB_NET_CDC_SUBSET is not set
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_KC2190=y
+ # CONFIG_USB_NET_ZAURUS is not set
+-# CONFIG_USB_NET_CX82310_ETH is not set
+-# CONFIG_USB_NET_KALMIA is not set
+-# CONFIG_USB_NET_INT51X1 is not set
+-# CONFIG_USB_IPHETH is not set
+-# CONFIG_USB_SIERRA_NET is not set
+-# CONFIG_WAN is not set
+-
+-#
+-# CAIF transport drivers
+-#
+-# CONFIG_PPP is not set
+-# CONFIG_SLIP 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
+-# CONFIG_PHONE is not set
+-
+-#
+-# Input device support
+-#
+-CONFIG_INPUT=y
+-# CONFIG_INPUT_FF_MEMLESS is not set
+-# CONFIG_INPUT_POLLDEV is not set
+-# CONFIG_INPUT_SPARSEKMAP is not set
+-
+-#
+-# Userland interfaces
+-#
+-CONFIG_INPUT_MOUSEDEV=y
++CONFIG_USB_NET_CX82310_ETH=m
++CONFIG_USB_NET_KALMIA=m
++CONFIG_USB_NET_INT51X1=m
++CONFIG_USB_IPHETH=m
++CONFIG_USB_SIERRA_NET=m
++CONFIG_USB_VL600=m
++CONFIG_PPP=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_NETCONSOLE=m
++CONFIG_INPUT_POLLDEV=m
+ # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+-# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_JOYDEV=m
+ CONFIG_INPUT_EVDEV=m
+-# CONFIG_INPUT_EVBUG is not set
+-
+-#
+-# Input Device Drivers
+-#
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+-# CONFIG_INPUT_JOYSTICK is not set
+-# CONFIG_INPUT_TABLET is not set
+-# CONFIG_INPUT_TOUCHSCREEN is not set
+ CONFIG_INPUT_MISC=y
+-# CONFIG_INPUT_AD714X is not set
+-# CONFIG_INPUT_ATI_REMOTE is not set
+-# CONFIG_INPUT_ATI_REMOTE2 is not set
+-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+-# CONFIG_INPUT_POWERMATE is not set
+-# CONFIG_INPUT_YEALINK is not set
+-# CONFIG_INPUT_CM109 is not set
++CONFIG_INPUT_AD714X=m
++CONFIG_INPUT_ATI_REMOTE=m
++CONFIG_INPUT_ATI_REMOTE2=m
++CONFIG_INPUT_KEYSPAN_REMOTE=m
++CONFIG_INPUT_POWERMATE=m
++CONFIG_INPUT_YEALINK=m
++CONFIG_INPUT_CM109=m
+ CONFIG_INPUT_UINPUT=m
+-# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+-# CONFIG_INPUT_ADXL34X is not set
+-# CONFIG_INPUT_CMA3000 is not set
+-
+-#
+-# Hardware I/O ports
+-#
++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
++CONFIG_INPUT_ADXL34X=m
++CONFIG_INPUT_CMA3000=m
+ CONFIG_SERIO=m
+-CONFIG_SERIO_SERPORT=m
+-# CONFIG_SERIO_AMBAKMI is not set
+-# CONFIG_SERIO_LIBPS2 is not set
+ CONFIG_SERIO_RAW=m
+-# CONFIG_SERIO_ALTERA_PS2 is not set
+-# CONFIG_SERIO_PS2MULT is not set
+ CONFIG_GAMEPORT=m
+ CONFIG_GAMEPORT_NS558=m
+ CONFIG_GAMEPORT_L4=m
+-
+-#
+-# Character devices
+-#
+-CONFIG_VT=y
+-CONFIG_CONSOLE_TRANSLATIONS=y
+-CONFIG_VT_CONSOLE=y
+-CONFIG_HW_CONSOLE=y
+ CONFIG_VT_HW_CONSOLE_BINDING=y
+-CONFIG_UNIX98_PTYS=y
+-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+ # CONFIG_LEGACY_PTYS is not set
+-# CONFIG_SERIAL_NONSTANDARD is not set
+-# CONFIG_N_GSM is not set
+-# CONFIG_TRACE_SINK is not set
+ # CONFIG_DEVKMEM is not set
+-
+-#
+-# Serial drivers
+-#
+-# CONFIG_SERIAL_8250 is not set
+-
+-#
+-# Non-8250 serial port support
+-#
+-# CONFIG_SERIAL_AMBA_PL010 is not set
+ CONFIG_SERIAL_AMBA_PL011=y
+ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+-CONFIG_SERIAL_CORE=y
+-CONFIG_SERIAL_CORE_CONSOLE=y
+-# CONFIG_SERIAL_TIMBERDALE is not set
+-# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+-# CONFIG_SERIAL_ALTERA_UART is not set
+-# CONFIG_SERIAL_XILINX_PS_UART is not set
+-# CONFIG_TTY_PRINTK is not set
+-# CONFIG_HVC_DCC is not set
+-# CONFIG_IPMI_HANDLER is not set
+ # CONFIG_HW_RANDOM is not set
+-# CONFIG_R3964 is not set
+ CONFIG_RAW_DRIVER=y
+-CONFIG_MAX_RAW_DEVS=256
+-# CONFIG_TCG_TPM is not set
+-# CONFIG_RAMOOPS is not set
+-# CONFIG_I2C is not set
+-# CONFIG_SPI is not set
+-
+-#
+-# PPS support
+-#
+-# CONFIG_PPS is not set
+-
+-#
+-# PPS generators support
+-#
+-
+-#
+-# PTP clock support
+-#
+-
+-#
+-# Enable Device Drivers -> PPS to see the PTP clock options.
+-#
+-CONFIG_ARCH_REQUIRE_GPIOLIB=y
+-CONFIG_GPIOLIB=y
+-# CONFIG_DEBUG_GPIO is not set
+ CONFIG_GPIO_SYSFS=y
+-
+-#
+-# Memory mapped GPIO drivers:
+-#
+-# CONFIG_GPIO_GENERIC_PLATFORM is not set
+-# CONFIG_GPIO_IT8761E is not set
+-# CONFIG_GPIO_PL061 is not set
+-
+-#
+-# I2C GPIO expanders:
+-#
+-
+-#
+-# PCI GPIO expanders:
+-#
+-
+-#
+-# SPI GPIO expanders:
+-#
+-
+-#
+-# AC97 GPIO expanders:
+-#
+-
+-#
+-# MODULbus GPIO expanders:
+-#
+-# CONFIG_W1 is not set
+-# CONFIG_POWER_SUPPLY is not set
+ # CONFIG_HWMON is not set
+-# CONFIG_THERMAL is not set
+-# CONFIG_WATCHDOG is not set
+-CONFIG_SSB_POSSIBLE=y
+-
+-#
+-# Sonics Silicon Backplane
+-#
+-# CONFIG_SSB is not set
+-CONFIG_BCMA_POSSIBLE=y
+-
+-#
+-# Broadcom specific AMBA
+-#
+-# CONFIG_BCMA is not set
++CONFIG_WATCHDOG=y
++CONFIG_BCM2708_WDT=m
+ # CONFIG_MFD_SUPPORT is not set
+-# CONFIG_REGULATOR is not set
+-# CONFIG_MEDIA_SUPPORT is not set
+-
+-#
+-# Graphics support
+-#
+-# CONFIG_DRM is not set
+-# CONFIG_VGASTATE is not set
+-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ CONFIG_FB=y
+-# CONFIG_FIRMWARE_EDID is not set
+-# CONFIG_FB_DDC is not set
+-# CONFIG_FB_BOOT_VESA_SUPPORT 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_FOREIGN_ENDIAN is not set
+-# CONFIG_FB_SYS_FOPS is not set
+-# CONFIG_FB_WMT_GE_ROPS is not set
+-# 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_BCM2708=y
+-# CONFIG_FB_ARMCLCD is not set
+-# CONFIG_FB_S1D13XXX is not set
+-# CONFIG_FB_UDL is not set
+-# CONFIG_FB_VIRTUAL is not set
+-# CONFIG_FB_METRONOME is not set
+-# CONFIG_FB_BROADSHEET is not set
+-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+-
+-#
+-# Display device support
+-#
+-# CONFIG_DISPLAY_SUPPORT is not set
+-
+-#
+-# Console display driver support
+-#
+-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 is not set
+-CONFIG_FONT_8x8=y
+-CONFIG_FONT_8x16=y
+ CONFIG_LOGO=y
+ # CONFIG_LOGO_LINUX_MONO is not set
+ # CONFIG_LOGO_LINUX_VGA16 is not set
+-CONFIG_LOGO_LINUX_CLUT224=y
+-# CONFIG_SOUND is not set
+-CONFIG_HID_SUPPORT=y
+-CONFIG_HID=y
+-# CONFIG_HIDRAW is not set
+-
+-#
+-# USB Input Devices
+-#
+-CONFIG_USB_HID=y
++CONFIG_SOUND=y
++CONFIG_SND=m
++CONFIG_SND_SEQUENCER=m
++CONFIG_SND_SEQ_DUMMY=m
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_SEQUENCER_OSS=y
++CONFIG_SND_HRTIMER=m
++CONFIG_SND_DUMMY=m
++CONFIG_SND_ALOOP=m
++CONFIG_SND_VIRMIDI=m
++CONFIG_SND_MTPAV=m
++CONFIG_SND_SERIAL_U16550=m
++CONFIG_SND_MPU401=m
++CONFIG_SND_BCM2835=m
++CONFIG_SND_USB_AUDIO=m
++CONFIG_SND_USB_UA101=m
++CONFIG_SND_USB_CAIAQ=m
++CONFIG_SND_USB_6FIRE=m
++CONFIG_SOUND_PRIME=m
+ CONFIG_HID_PID=y
+ CONFIG_USB_HIDDEV=y
+-
+-#
+-# Special HID drivers
+-#
+ CONFIG_HID_A4TECH=m
+-# CONFIG_HID_ACRUX is not set
++CONFIG_HID_ACRUX=m
+ CONFIG_HID_APPLE=m
+ CONFIG_HID_BELKIN=m
+ CONFIG_HID_CHERRY=m
+ CONFIG_HID_CHICONY=m
+ CONFIG_HID_CYPRESS=m
+ CONFIG_HID_DRAGONRISE=m
+-# CONFIG_DRAGONRISE_FF is not set
+-# CONFIG_HID_EMS_FF is not set
++CONFIG_HID_EMS_FF=m
++CONFIG_HID_ELECOM=m
+ CONFIG_HID_EZKEY=m
+-# CONFIG_HID_HOLTEK is not set
+-# CONFIG_HID_KEYTOUCH is not set
++CONFIG_HID_HOLTEK=m
++CONFIG_HID_KEYTOUCH=m
+ CONFIG_HID_KYE=m
+-# CONFIG_HID_UCLOGIC is not set
+-# CONFIG_HID_WALTOP is not set
++CONFIG_HID_UCLOGIC=m
++CONFIG_HID_WALTOP=m
+ CONFIG_HID_GYRATION=m
+ CONFIG_HID_TWINHAN=m
+ CONFIG_HID_KENSINGTON=m
+-# CONFIG_HID_LCPOWER is not set
++CONFIG_HID_LCPOWER=m
+ CONFIG_HID_LOGITECH=m
+-# CONFIG_LOGITECH_FF is not set
+-# CONFIG_LOGIRUMBLEPAD2_FF is not set
+-# CONFIG_LOGIG940_FF is not set
+-# CONFIG_LOGIWII_FF is not set
++CONFIG_HID_MAGICMOUSE=m
+ CONFIG_HID_MICROSOFT=m
+ CONFIG_HID_MONTEREY=m
+-# CONFIG_HID_MULTITOUCH is not set
+-# CONFIG_HID_NTRIG is not set
++CONFIG_HID_MULTITOUCH=m
++CONFIG_HID_NTRIG=m
+ CONFIG_HID_ORTEK=m
+ CONFIG_HID_PANTHERLORD=m
+-# CONFIG_PANTHERLORD_FF is not set
+ CONFIG_HID_PETALYNX=m
+-# CONFIG_HID_PICOLCD is not set
+-# CONFIG_HID_QUANTA is not set
+-# CONFIG_HID_ROCCAT is not set
++CONFIG_HID_PICOLCD=m
++CONFIG_HID_QUANTA=m
++CONFIG_HID_ROCCAT=m
+ CONFIG_HID_SAMSUNG=m
+ CONFIG_HID_SONY=m
+-# CONFIG_HID_SPEEDLINK is not set
++CONFIG_HID_SPEEDLINK=m
+ CONFIG_HID_SUNPLUS=m
+ CONFIG_HID_GREENASIA=m
+-# CONFIG_GREENASIA_FF is not set
+ CONFIG_HID_SMARTJOYPLUS=m
+-# CONFIG_SMARTJOYPLUS_FF is not set
+ CONFIG_HID_TOPSEED=m
+ CONFIG_HID_THRUSTMASTER=m
+-# CONFIG_THRUSTMASTER_FF is not set
++CONFIG_HID_WACOM=m
++CONFIG_HID_WIIMOTE=m
+ CONFIG_HID_ZEROPLUS=m
+-# CONFIG_ZEROPLUS_FF is not set
+-# CONFIG_HID_ZYDACRON is not set
+-CONFIG_USB_SUPPORT=y
+-CONFIG_USB_ARCH_HAS_HCD=y
+-# CONFIG_USB_ARCH_HAS_OHCI is not set
+-# CONFIG_USB_ARCH_HAS_EHCI is not set
++CONFIG_HID_ZYDACRON=m
+ CONFIG_USB=y
+-# CONFIG_USB_DEBUG is not set
+ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+-
+-#
+-# Miscellaneous USB options
+-#
+-# CONFIG_USB_DEVICEFS is not set
+-CONFIG_USB_DEVICE_CLASS=y
+-# CONFIG_USB_DYNAMIC_MINORS is not set
+-# CONFIG_USB_OTG_WHITELIST is not set
+-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+ CONFIG_USB_MON=m
+-# CONFIG_USB_WUSB is not set
+-# CONFIG_USB_WUSB_CBAF is not set
+-
+-#
+-# USB Host Controller Drivers
+-#
+-# CONFIG_USB_C67X00_HCD is not set
+-# CONFIG_USB_OXU210HP_HCD is not set
+-# CONFIG_USB_ISP116X_HCD is not set
+-# CONFIG_USB_ISP1760_HCD is not set
+-# CONFIG_USB_ISP1362_HCD is not set
+-# CONFIG_USB_SL811_HCD is not set
+-# CONFIG_USB_R8A66597_HCD is not set
+-# CONFIG_USB_HWA_HCD is not set
+ CONFIG_USB_DWCOTG=y
+-
+-#
+-# USB Device Class drivers
+-#
+-# CONFIG_USB_ACM is not set
+-# CONFIG_USB_PRINTER is not set
+-# CONFIG_USB_WDM is not set
+-# CONFIG_USB_TMC is not set
+-
+-#
+-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+-#
+-
+-#
+-# also be needed; see USB_STORAGE Help for more info
+-#
+ CONFIG_USB_STORAGE=y
+-# CONFIG_USB_STORAGE_DEBUG is not set
+-# CONFIG_USB_STORAGE_REALTEK 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_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_STORAGE_CYPRESS_ATACB is not set
+-# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+-# CONFIG_USB_UAS is not set
++CONFIG_USB_STORAGE_REALTEK=m
++CONFIG_USB_STORAGE_DATAFAB=m
++CONFIG_USB_STORAGE_FREECOM=m
++CONFIG_USB_STORAGE_ISD200=m
++CONFIG_USB_STORAGE_USBAT=m
++CONFIG_USB_STORAGE_SDDR09=m
++CONFIG_USB_STORAGE_SDDR55=m
++CONFIG_USB_STORAGE_JUMPSHOT=m
++CONFIG_USB_STORAGE_ALAUDA=m
++CONFIG_USB_STORAGE_ONETOUCH=m
++CONFIG_USB_STORAGE_KARMA=m
++CONFIG_USB_STORAGE_CYPRESS_ATACB=m
++CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=y
+ CONFIG_USB_LIBUSUAL=y
+-
+-#
+-# USB Imaging devices
+-#
+-# CONFIG_USB_MDC800 is not set
+-# CONFIG_USB_MICROTEK is not set
+-
+-#
+-# USB port drivers
+-#
+-# CONFIG_USB_SERIAL 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_SEVSEG is not set
+-# CONFIG_USB_RIO500 is not set
+-# CONFIG_USB_LEGOTOWER is not set
+-# CONFIG_USB_LCD is not set
+-# CONFIG_USB_LED is not set
+-# CONFIG_USB_CYPRESS_CY7C63 is not set
+-# CONFIG_USB_CYTHERM 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
+-# CONFIG_USB_ISIGHTFW is not set
+-# CONFIG_USB_YUREX is not set
+-# CONFIG_USB_GADGET is not set
+-
+-#
+-# OTG and related infrastructure
+-#
+-# CONFIG_USB_GPIO_VBUS is not set
+-# CONFIG_USB_ULPI is not set
+-# CONFIG_NOP_USB_XCEIV is not set
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++CONFIG_USB_SERIAL=m
++CONFIG_USB_SERIAL_GENERIC=y
++CONFIG_USB_SERIAL_AIRCABLE=m
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_FUNSOFT=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_MOTOROLA=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_HP4X=m
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SIEMENS_MPI=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
++CONFIG_USB_SERIAL_ZIO=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_DEBUG=m
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_LED=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
+ CONFIG_MMC=y
+-# CONFIG_MMC_DEBUG is not set
+-# CONFIG_MMC_UNSAFE_RESUME is not set
+-# CONFIG_MMC_CLKGATE is not set
+-
+-#
+-# MMC/SD/SDIO Card Drivers
+-#
+-CONFIG_MMC_BLOCK=y
+-CONFIG_MMC_BLOCK_MINORS=8
+-CONFIG_MMC_BLOCK_BOUNCE=y
+-# CONFIG_SDIO_UART is not set
+-# CONFIG_MMC_TEST is not set
+-
+-#
+-# MMC/SD/SDIO Host Controller Drivers
+-#
+-# CONFIG_MMC_ARMMMCI is not set
+ CONFIG_MMC_SDHCI=y
+-CONFIG_MMC_SDHCI_IO_ACCESSORS=y
+ CONFIG_MMC_SDHCI_PLTFM=y
+-# CONFIG_MMC_SDHCI_PXAV3 is not set
+-# CONFIG_MMC_SDHCI_PXAV2 is not set
+ CONFIG_MMC_SDHCI_BCM2708=y
+ CONFIG_MMC_SDHCI_BCM2708_DMA=y
+-# CONFIG_MMC_BCM2708 is not set
+-# CONFIG_MMC_DW is not set
+-# CONFIG_MMC_VUB300 is not set
+-# CONFIG_MMC_USHC is not set
+-# CONFIG_MEMSTICK is not set
+-CONFIG_NEW_LEDS=y
+-CONFIG_LEDS_CLASS=y
+-
+-#
+-# LED drivers
+-#
+ CONFIG_LEDS_GPIO=y
+-# CONFIG_LEDS_LT3593 is not set
+-CONFIG_LEDS_TRIGGERS=y
+-
+-#
+-# LED Triggers
+-#
+ CONFIG_LEDS_TRIGGER_TIMER=m
+ CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+-# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+-# CONFIG_LEDS_TRIGGER_GPIO is not set
+ CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+-
+-#
+-# iptables trigger is under Netfilter config (LED target)
+-#
+-# CONFIG_ACCESSIBILITY is not set
+-CONFIG_RTC_LIB=y
+-# CONFIG_RTC_CLASS is not set
+-# CONFIG_DMADEVICES is not set
+-# CONFIG_AUXDISPLAY is not set
+-# CONFIG_UIO is not set
+-
+-#
+-# Virtio drivers
+-#
+-# CONFIG_VIRTIO_BALLOON is not set
+-# CONFIG_STAGING is not set
+-CONFIG_CLKDEV_LOOKUP=y
++CONFIG_UIO=m
++CONFIG_UIO_PDRV=m
++CONFIG_UIO_PDRV_GENIRQ=m
+ # CONFIG_IOMMU_SUPPORT is not set
+-# CONFIG_VIRT_DRIVERS is not set
+-
+-#
+-# File systems
+-#
+-CONFIG_EXT2_FS=m
+-CONFIG_EXT2_FS_XATTR=y
+-CONFIG_EXT2_FS_POSIX_ACL=y
+-CONFIG_EXT2_FS_SECURITY=y
+-CONFIG_EXT2_FS_XIP=y
+-CONFIG_EXT3_FS=y
+-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+-CONFIG_EXT3_FS_XATTR=y
+-CONFIG_EXT3_FS_POSIX_ACL=y
+-CONFIG_EXT3_FS_SECURITY=y
+-CONFIG_EXT4_FS=m
+-CONFIG_EXT4_FS_XATTR=y
++CONFIG_EXT4_FS=y
+ CONFIG_EXT4_FS_POSIX_ACL=y
+ CONFIG_EXT4_FS_SECURITY=y
+-# CONFIG_EXT4_DEBUG is not set
+-CONFIG_FS_XIP=y
+-CONFIG_JBD=y
+-CONFIG_JBD2=m
+-CONFIG_FS_MBCACHE=y
+-# CONFIG_REISERFS_FS is not set
+-# CONFIG_JFS_FS is not set
+-# CONFIG_XFS_FS is not set
+-# CONFIG_GFS2_FS is not set
+-# CONFIG_OCFS2_FS is not set
+-# CONFIG_BTRFS_FS is not set
+-# CONFIG_NILFS2_FS is not set
+-CONFIG_FS_POSIX_ACL=y
+-CONFIG_FILE_LOCKING=y
+-CONFIG_FSNOTIFY=y
+-CONFIG_DNOTIFY=y
+-CONFIG_INOTIFY_USER=y
+-# CONFIG_FANOTIFY is not set
+-# CONFIG_QUOTA is not set
+-# CONFIG_QUOTACTL is not set
++CONFIG_REISERFS_FS=m
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
++CONFIG_JFS_FS=m
++CONFIG_JFS_POSIX_ACL=y
++CONFIG_JFS_SECURITY=y
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++CONFIG_GFS2_FS=m
++CONFIG_OCFS2_FS=m
++CONFIG_BTRFS_FS=m
++CONFIG_BTRFS_FS_POSIX_ACL=y
++CONFIG_NILFS2_FS=m
+ CONFIG_AUTOFS4_FS=y
+ CONFIG_FUSE_FS=m
+ CONFIG_CUSE=m
+-
+-#
+-# Caches
+-#
+ CONFIG_FSCACHE=y
+-# CONFIG_FSCACHE_STATS is not set
+-# CONFIG_FSCACHE_HISTOGRAM is not set
+-# CONFIG_FSCACHE_DEBUG is not set
+-# CONFIG_FSCACHE_OBJECT_LIST is not set
+ CONFIG_CACHEFILES=y
+-# CONFIG_CACHEFILES_DEBUG is not set
+-# CONFIG_CACHEFILES_HISTOGRAM is not set
+-
+-#
+-# CD-ROM/DVD Filesystems
+-#
+ CONFIG_ISO9660_FS=m
+ CONFIG_JOLIET=y
+ CONFIG_ZISOFS=y
+ CONFIG_UDF_FS=m
+-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="ascii"
+ CONFIG_NTFS_FS=m
+-# CONFIG_NTFS_DEBUG is not set
+-# CONFIG_NTFS_RW is not set
+-
+-#
+-# Pseudo filesystems
+-#
+-CONFIG_PROC_FS=y
+-CONFIG_PROC_SYSCTL=y
+-CONFIG_PROC_PAGE_MONITOR=y
+-CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
+-# CONFIG_TMPFS_POSIX_ACL is not set
+-# CONFIG_TMPFS_XATTR is not set
+-# CONFIG_HUGETLB_PAGE is not set
++CONFIG_TMPFS_POSIX_ACL=y
+ CONFIG_CONFIGFS_FS=y
+-CONFIG_MISC_FILESYSTEMS=y
+-# CONFIG_ADFS_FS is not set
+-# CONFIG_AFFS_FS is not set
+-# CONFIG_ECRYPT_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_LOGFS is not set
+-# CONFIG_CRAMFS is not set
+-# CONFIG_SQUASHFS is not set
+-# CONFIG_VXFS_FS is not set
+-# CONFIG_MINIX_FS is not set
+-# CONFIG_OMFS_FS is not set
+-# CONFIG_HPFS_FS is not set
+-# CONFIG_QNX4FS_FS is not set
+-# CONFIG_ROMFS_FS is not set
+-# CONFIG_PSTORE is not set
+-# CONFIG_SYSV_FS is not set
+-# CONFIG_UFS_FS is not set
+-CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_SQUASHFS=m
++CONFIG_SQUASHFS_XATTR=y
++CONFIG_SQUASHFS_LZO=y
++CONFIG_SQUASHFS_XZ=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ CONFIG_NFS_V3_ACL=y
+ CONFIG_NFS_V4=y
+-# CONFIG_NFS_V4_1 is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFS_FSCACHE=y
+-# CONFIG_NFS_USE_LEGACY_DNS is not set
+-CONFIG_NFS_USE_KERNEL_DNS=y
+-# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+-# CONFIG_NFSD is not set
+-CONFIG_LOCKD=y
+-CONFIG_LOCKD_V4=y
+-CONFIG_NFS_ACL_SUPPORT=y
+-CONFIG_NFS_COMMON=y
+-CONFIG_SUNRPC=y
+-CONFIG_SUNRPC_GSS=y
+-# CONFIG_CEPH_FS is not set
+ CONFIG_CIFS=m
+-# CONFIG_CIFS_STATS is not set
+ CONFIG_CIFS_WEAK_PW_HASH=y
+-# CONFIG_CIFS_UPCALL is not set
+ CONFIG_CIFS_XATTR=y
+ CONFIG_CIFS_POSIX=y
+-# CONFIG_CIFS_DEBUG2 is not set
+-# CONFIG_CIFS_DFS_UPCALL is not set
+-# CONFIG_CIFS_FSCACHE is not set
+-# CONFIG_CIFS_ACL is not set
+-# CONFIG_NCP_FS is not set
+-# CONFIG_CODA_FS is not set
+-# CONFIG_AFS_FS is not set
+-
+-#
+-# Partition Types
+-#
++CONFIG_9P_FS=m
+ 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=y
+-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=y
+-# CONFIG_SYSV68_PARTITION is not set
+-CONFIG_NLS=y
+ CONFIG_NLS_DEFAULT="utf8"
+ CONFIG_NLS_CODEPAGE_437=y
+ CONFIG_NLS_CODEPAGE_737=m
+@@ -1341,218 +470,25 @@ CONFIG_NLS_ISO8859_15=m
+ CONFIG_NLS_KOI8_R=m
+ CONFIG_NLS_KOI8_U=m
+ CONFIG_NLS_UTF8=m
+-# CONFIG_DLM is not set
+-
+-#
+-# Kernel hacking
+-#
+-# CONFIG_PRINTK_TIME is not set
+-CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+-CONFIG_ENABLE_WARN_DEPRECATED=y
+-CONFIG_ENABLE_MUST_CHECK=y
+-CONFIG_FRAME_WARN=1024
+-# CONFIG_MAGIC_SYSRQ is not set
+-# CONFIG_STRIP_ASM_SYMS is not set
+-# CONFIG_UNUSED_SYMBOLS is not set
+-# CONFIG_DEBUG_FS is not set
+-# CONFIG_HEADERS_CHECK is not set
+-# CONFIG_DEBUG_SECTION_MISMATCH is not set
+-CONFIG_DEBUG_KERNEL=y
+-# CONFIG_DEBUG_SHIRQ is not set
+-# CONFIG_LOCKUP_DETECTOR is not set
+-# CONFIG_HARDLOCKUP_DETECTOR is not set
+-# CONFIG_DETECT_HUNG_TASK is not set
+ # CONFIG_SCHED_DEBUG is not set
+-# CONFIG_SCHEDSTATS is not set
+-# CONFIG_TIMER_STATS is not set
+-# CONFIG_DEBUG_OBJECTS is not set
+-# CONFIG_DEBUG_SLAB is not set
+-# CONFIG_DEBUG_KMEMLEAK is not set
+-# CONFIG_DEBUG_RT_MUTEXES is not set
+-# CONFIG_RT_MUTEX_TESTER is not set
+-# CONFIG_DEBUG_SPINLOCK is not set
+-# CONFIG_DEBUG_MUTEXES is not set
+-# CONFIG_DEBUG_LOCK_ALLOC is not set
+-# CONFIG_PROVE_LOCKING is not set
+-# CONFIG_SPARSE_RCU_POINTER is not set
+-# CONFIG_LOCK_STAT is not set
+-# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+-# CONFIG_DEBUG_STACK_USAGE is not set
+-# CONFIG_DEBUG_KOBJECT is not set
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+-# CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_VM is not set
+-# CONFIG_DEBUG_WRITECOUNT is not set
+-# CONFIG_DEBUG_MEMORY_INIT is not set
+-# CONFIG_DEBUG_LIST is not set
+-# CONFIG_TEST_LIST_SORT is not set
+-# CONFIG_DEBUG_SG is not set
+-# CONFIG_DEBUG_NOTIFIERS is not set
+-# CONFIG_DEBUG_CREDENTIALS is not set
+-CONFIG_FRAME_POINTER=y
+-# CONFIG_BOOT_PRINTK_DELAY is not set
+-# CONFIG_RCU_TORTURE_TEST is not set
+-# CONFIG_BACKTRACE_SELF_TEST is not set
+-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+-# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+-# CONFIG_FAULT_INJECTION is not set
+-# CONFIG_LATENCYTOP is not set
+-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+-# CONFIG_DEBUG_PAGEALLOC is not set
+-CONFIG_HAVE_FUNCTION_TRACER=y
+-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+-CONFIG_HAVE_DYNAMIC_FTRACE=y
+-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+-CONFIG_HAVE_C_RECORDMCOUNT=y
+-CONFIG_TRACING_SUPPORT=y
+ # CONFIG_FTRACE is not set
+-# CONFIG_DMA_API_DEBUG is not set
+-# CONFIG_ATOMIC64_SELFTEST is not set
+-# CONFIG_SAMPLES is not set
+-CONFIG_HAVE_ARCH_KGDB=y
+-# CONFIG_KGDB is not set
+-# CONFIG_TEST_KSTRTOX is not set
+-# CONFIG_STRICT_DEVMEM is not set
+ # CONFIG_ARM_UNWIND is not set
+-# CONFIG_DEBUG_USER is not set
+-# CONFIG_DEBUG_LL is not set
+-# CONFIG_OC_ETM is not set
+-
+-#
+-# Security options
+-#
+-CONFIG_KEYS=y
+-# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+-# CONFIG_SECURITY_DMESG_RESTRICT is not set
+-# CONFIG_SECURITY is not set
+-# CONFIG_SECURITYFS is not set
+-CONFIG_DEFAULT_SECURITY_DAC=y
+-CONFIG_DEFAULT_SECURITY=""
+-CONFIG_CRYPTO=y
+-
+-#
+-# Crypto core or helper
+-#
+-CONFIG_CRYPTO_ALGAPI=y
+-CONFIG_CRYPTO_ALGAPI2=y
+-CONFIG_CRYPTO_AEAD=m
+-CONFIG_CRYPTO_AEAD2=y
+-CONFIG_CRYPTO_BLKCIPHER=y
+-CONFIG_CRYPTO_BLKCIPHER2=y
+-CONFIG_CRYPTO_HASH=y
+-CONFIG_CRYPTO_HASH2=y
+-CONFIG_CRYPTO_RNG=m
+-CONFIG_CRYPTO_RNG2=y
+-CONFIG_CRYPTO_PCOMP2=y
+-CONFIG_CRYPTO_MANAGER=y
+-CONFIG_CRYPTO_MANAGER2=y
+-CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+-# CONFIG_CRYPTO_GF128MUL is not set
+-# CONFIG_CRYPTO_NULL is not set
+-CONFIG_CRYPTO_WORKQUEUE=y
+-# CONFIG_CRYPTO_CRYPTD is not set
+ CONFIG_CRYPTO_AUTHENC=m
+-# CONFIG_CRYPTO_TEST is not set
+-
+-#
+-# Authenticated Encryption with Associated Data
+-#
+-# CONFIG_CRYPTO_CCM is not set
+-# CONFIG_CRYPTO_GCM is not set
+ CONFIG_CRYPTO_SEQIV=m
+-
+-#
+-# Block modes
+-#
+ CONFIG_CRYPTO_CBC=y
+-# CONFIG_CRYPTO_CTR is not set
+-# CONFIG_CRYPTO_CTS is not set
+-CONFIG_CRYPTO_ECB=m
+-# CONFIG_CRYPTO_LRW is not set
+-# CONFIG_CRYPTO_PCBC is not set
+-# CONFIG_CRYPTO_XTS is not set
+-
+-#
+-# Hash modes
+-#
+ CONFIG_CRYPTO_HMAC=y
+ CONFIG_CRYPTO_XCBC=m
+-# CONFIG_CRYPTO_VMAC is not set
+-
+-#
+-# Digest
+-#
+-CONFIG_CRYPTO_CRC32C=y
+-# CONFIG_CRYPTO_GHASH is not set
+-CONFIG_CRYPTO_MD4=m
+ CONFIG_CRYPTO_MD5=y
+-CONFIG_CRYPTO_MICHAEL_MIC=m
+-# CONFIG_CRYPTO_RMD128 is not set
+-# CONFIG_CRYPTO_RMD160 is not set
+-# CONFIG_CRYPTO_RMD256 is not set
+-# CONFIG_CRYPTO_RMD320 is not set
+ CONFIG_CRYPTO_SHA1=y
+ CONFIG_CRYPTO_SHA256=m
+ CONFIG_CRYPTO_SHA512=m
+ CONFIG_CRYPTO_TGR192=m
+ CONFIG_CRYPTO_WP512=m
+-
+-#
+-# Ciphers
+-#
+-# CONFIG_CRYPTO_AES is not set
+-# CONFIG_CRYPTO_ANUBIS is not set
+-CONFIG_CRYPTO_ARC4=m
+-# CONFIG_CRYPTO_BLOWFISH is not set
+-# CONFIG_CRYPTO_CAMELLIA is not set
+ CONFIG_CRYPTO_CAST5=m
+-# CONFIG_CRYPTO_CAST6 is not set
+ CONFIG_CRYPTO_DES=y
+-# CONFIG_CRYPTO_FCRYPT is not set
+-# CONFIG_CRYPTO_KHAZAD is not set
+-# CONFIG_CRYPTO_SALSA20 is not set
+-# CONFIG_CRYPTO_SEED is not set
+-# CONFIG_CRYPTO_SERPENT is not set
+-# CONFIG_CRYPTO_TEA is not set
+-# CONFIG_CRYPTO_TWOFISH is not set
+-
+-#
+-# Compression
+-#
+ CONFIG_CRYPTO_DEFLATE=m
+-# CONFIG_CRYPTO_ZLIB is not set
+-# CONFIG_CRYPTO_LZO is not set
+-
+-#
+-# Random Number Generation
+-#
+ # CONFIG_CRYPTO_ANSI_CPRNG is not set
+-# CONFIG_CRYPTO_USER_API_HASH is not set
+-# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+ # CONFIG_CRYPTO_HW is not set
+-# CONFIG_BINARY_PRINTF is not set
+-
+-#
+-# Library routines
+-#
+-CONFIG_BITREVERSE=y
+-CONFIG_CRC_CCITT=m
+-CONFIG_CRC16=y
+-# CONFIG_CRC_T10DIF is not set
+ CONFIG_CRC_ITU_T=y
+-CONFIG_CRC32=y
+-# CONFIG_CRC7 is not set
+ CONFIG_LIBCRC32C=y
+-# CONFIG_CRC8 is not set
+-CONFIG_ZLIB_INFLATE=m
+-CONFIG_ZLIB_DEFLATE=m
+-# CONFIG_XZ_DEC is not set
+-# CONFIG_XZ_DEC_BCJ is not set
+-CONFIG_HAS_IOMEM=y
+-CONFIG_HAS_IOPORT=y
+-CONFIG_HAS_DMA=y
+-CONFIG_NLATTR=y
+-CONFIG_GENERIC_ATOMIC64=y
+-# CONFIG_AVERAGE is not set
+-# CONFIG_CORDIC is not set
+--- /dev/null
++++ b/arch/arm/configs/bcmrpi_defconfig
+@@ -0,0 +1,530 @@
++CONFIG_EXPERIMENTAL=y
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_FHANDLE=y
++CONFIG_AUDIT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_CGROUP_FREEZER=y
++CONFIG_CGROUP_DEVICE=y
++CONFIG_CGROUP_CPUACCT=y
++CONFIG_RESOURCE_COUNTERS=y
++CONFIG_BLK_CGROUP=y
++CONFIG_NAMESPACES=y
++CONFIG_SCHED_AUTOGROUP=y
++CONFIG_EMBEDDED=y
++# CONFIG_COMPAT_BRK is not set
++CONFIG_SLAB=y
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=m
++CONFIG_KPROBES=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_BLK_DEV_THROTTLING=y
++CONFIG_CFQ_GROUP_IOSCHED=y
++CONFIG_ARCH_BCM2708=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_AEABI=y
++CONFIG_SECCOMP=y
++CONFIG_CC_STACKPROTECTOR=y
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
++CONFIG_KEXEC=y
++CONFIG_CPU_IDLE=y
++CONFIG_VFP=y
++CONFIG_BINFMT_MISC=m
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_XFRM_USER=y
++CONFIG_NET_KEY=m
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_NET_PKTGEN=m
++CONFIG_IRDA=m
++CONFIG_IRLAN=m
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRTTY_SIR=m
++CONFIG_KINGSUN_DONGLE=m
++CONFIG_KSDAZZLE_DONGLE=m
++CONFIG_KS959_DONGLE=m
++CONFIG_USB_IRDA=m
++CONFIG_SIGMATEL_FIR=m
++CONFIG_MCS_FIR=m
++CONFIG_BT=m
++CONFIG_BT_L2CAP=y
++CONFIG_BT_SCO=y
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_MRVL=m
++CONFIG_BT_MRVL_SDIO=m
++CONFIG_BT_ATH3K=m
++CONFIG_CFG80211=m
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_MESH=y
++CONFIG_WIMAX=m
++CONFIG_NET_9P=m
++CONFIG_NFC=m
++CONFIG_NFC_PN533=m
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_MISC_DEVICES=y
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++CONFIG_BLK_DEV_SD=y
++CONFIG_BLK_DEV_SR=m
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_LOWLEVEL is not set
++CONFIG_MD=y
++CONFIG_NETDEVICES=y
++CONFIG_TUN=m
++CONFIG_PHYLIB=m
++CONFIG_MDIO_BITBANG=m
++CONFIG_NET_ETHERNET=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_AT76C50X_USB=m
++CONFIG_USB_ZD1201=m
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_RTL8187=m
++CONFIG_MAC80211_HWSIM=m
++CONFIG_ATH_COMMON=m
++CONFIG_ATH9K=m
++CONFIG_ATH9K_HTC=m
++CONFIG_CARL9170=m
++CONFIG_B43=m
++CONFIG_B43LEGACY=m
++CONFIG_HOSTAP=m
++CONFIG_IWM=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT53XX=y
++CONFIG_RTL8192CU=m
++CONFIG_WL1251=m
++CONFIG_WL12XX_MENU=m
++CONFIG_ZD1211RW=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_WIMAX_I2400M_USB=m
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=m
++CONFIG_USB_NET_CDCETHER=m
++CONFIG_USB_NET_CDC_EEM=m
++CONFIG_USB_NET_DM9601=m
++CONFIG_USB_NET_SMSC75XX=m
++CONFIG_USB_NET_SMSC95XX=y
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_KC2190=y
++# CONFIG_USB_NET_ZAURUS is not set
++CONFIG_USB_NET_CX82310_ETH=m
++CONFIG_USB_NET_KALMIA=m
++CONFIG_USB_NET_INT51X1=m
++CONFIG_USB_IPHETH=m
++CONFIG_USB_SIERRA_NET=m
++CONFIG_USB_VL600=m
++CONFIG_PPP=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_NETCONSOLE=m
++CONFIG_INPUT_POLLDEV=m
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_AD714X=m
++CONFIG_INPUT_ATI_REMOTE=m
++CONFIG_INPUT_ATI_REMOTE2=m
++CONFIG_INPUT_KEYSPAN_REMOTE=m
++CONFIG_INPUT_POWERMATE=m
++CONFIG_INPUT_YEALINK=m
++CONFIG_INPUT_CM109=m
++CONFIG_INPUT_UINPUT=m
++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
++CONFIG_INPUT_ADXL34X=m
++CONFIG_INPUT_CMA3000=m
++CONFIG_SERIO=m
++CONFIG_SERIO_RAW=m
++CONFIG_GAMEPORT=m
++CONFIG_GAMEPORT_NS558=m
++CONFIG_GAMEPORT_L4=m
++CONFIG_VT_HW_CONSOLE_BINDING=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_DEVKMEM is not set
++CONFIG_SERIAL_AMBA_PL011=y
++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
++# CONFIG_HW_RANDOM is not set
++CONFIG_RAW_DRIVER=y
++CONFIG_GPIO_SYSFS=y
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_BCM2708_WDT=m
++# CONFIG_MFD_SUPPORT is not set
++CONFIG_FB=y
++CONFIG_FB_BCM2708=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_SOUND=y
++CONFIG_SND=m
++CONFIG_SND_SEQUENCER=m
++CONFIG_SND_SEQ_DUMMY=m
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_SEQUENCER_OSS=y
++CONFIG_SND_HRTIMER=m
++CONFIG_SND_DUMMY=m
++CONFIG_SND_ALOOP=m
++CONFIG_SND_VIRMIDI=m
++CONFIG_SND_MTPAV=m
++CONFIG_SND_SERIAL_U16550=m
++CONFIG_SND_MPU401=m
++CONFIG_SND_BCM2835=m
++CONFIG_SND_USB_AUDIO=m
++CONFIG_SND_USB_UA101=m
++CONFIG_SND_USB_CAIAQ=m
++CONFIG_SND_USB_6FIRE=m
++CONFIG_SOUND_PRIME=m
++CONFIG_HID_PID=y
++CONFIG_USB_HIDDEV=y
++CONFIG_HID_A4TECH=m
++CONFIG_HID_ACRUX=m
++CONFIG_HID_APPLE=m
++CONFIG_HID_BELKIN=m
++CONFIG_HID_CHERRY=m
++CONFIG_HID_CHICONY=m
++CONFIG_HID_CYPRESS=m
++CONFIG_HID_DRAGONRISE=m
++CONFIG_HID_EMS_FF=m
++CONFIG_HID_ELECOM=m
++CONFIG_HID_EZKEY=m
++CONFIG_HID_HOLTEK=m
++CONFIG_HID_KEYTOUCH=m
++CONFIG_HID_KYE=m
++CONFIG_HID_UCLOGIC=m
++CONFIG_HID_WALTOP=m
++CONFIG_HID_GYRATION=m
++CONFIG_HID_TWINHAN=m
++CONFIG_HID_KENSINGTON=m
++CONFIG_HID_LCPOWER=m
++CONFIG_HID_LOGITECH=m
++CONFIG_HID_MAGICMOUSE=m
++CONFIG_HID_MICROSOFT=m
++CONFIG_HID_MONTEREY=m
++CONFIG_HID_MULTITOUCH=m
++CONFIG_HID_NTRIG=m
++CONFIG_HID_ORTEK=m
++CONFIG_HID_PANTHERLORD=m
++CONFIG_HID_PETALYNX=m
++CONFIG_HID_PICOLCD=m
++CONFIG_HID_QUANTA=m
++CONFIG_HID_ROCCAT=m
++CONFIG_HID_SAMSUNG=m
++CONFIG_HID_SONY=m
++CONFIG_HID_SPEEDLINK=m
++CONFIG_HID_SUNPLUS=m
++CONFIG_HID_GREENASIA=m
++CONFIG_HID_SMARTJOYPLUS=m
++CONFIG_HID_TOPSEED=m
++CONFIG_HID_THRUSTMASTER=m
++CONFIG_HID_WACOM=m
++CONFIG_HID_WIIMOTE=m
++CONFIG_HID_ZEROPLUS=m
++CONFIG_HID_ZYDACRON=m
++CONFIG_USB=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++CONFIG_USB_MON=m
++CONFIG_USB_DWCOTG=y
++CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE_REALTEK=m
++CONFIG_USB_STORAGE_DATAFAB=m
++CONFIG_USB_STORAGE_FREECOM=m
++CONFIG_USB_STORAGE_ISD200=m
++CONFIG_USB_STORAGE_USBAT=m
++CONFIG_USB_STORAGE_SDDR09=m
++CONFIG_USB_STORAGE_SDDR55=m
++CONFIG_USB_STORAGE_JUMPSHOT=m
++CONFIG_USB_STORAGE_ALAUDA=m
++CONFIG_USB_STORAGE_ONETOUCH=m
++CONFIG_USB_STORAGE_KARMA=m
++CONFIG_USB_STORAGE_CYPRESS_ATACB=m
++CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=y
++CONFIG_USB_LIBUSUAL=y
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++CONFIG_USB_SERIAL=m
++CONFIG_USB_SERIAL_GENERIC=y
++CONFIG_USB_SERIAL_AIRCABLE=m
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_FUNSOFT=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_MOTOROLA=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_HP4X=m
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SIEMENS_MPI=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
++CONFIG_USB_SERIAL_ZIO=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_DEBUG=m
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_LED=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_MMC=y
++CONFIG_MMC_SDHCI=y
++CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SDHCI_BCM2708=y
++CONFIG_MMC_SDHCI_BCM2708_DMA=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_TRIGGER_TIMER=m
++CONFIG_LEDS_TRIGGER_HEARTBEAT=m
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
++CONFIG_UIO=m
++CONFIG_UIO_PDRV=m
++CONFIG_UIO_PDRV_GENIRQ=m
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_POSIX_ACL=y
++CONFIG_EXT4_FS_SECURITY=y
++CONFIG_REISERFS_FS=m
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
++CONFIG_JFS_FS=m
++CONFIG_JFS_POSIX_ACL=y
++CONFIG_JFS_SECURITY=y
++CONFIG_JFS_STATISTICS=y
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++CONFIG_GFS2_FS=m
++CONFIG_OCFS2_FS=m
++CONFIG_BTRFS_FS=m
++CONFIG_BTRFS_FS_POSIX_ACL=y
++CONFIG_NILFS2_FS=m
++CONFIG_FANOTIFY=y
++CONFIG_AUTOFS4_FS=y
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++CONFIG_FSCACHE=y
++CONFIG_FSCACHE_STATS=y
++CONFIG_FSCACHE_HISTOGRAM=y
++CONFIG_CACHEFILES=y
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++CONFIG_NTFS_FS=m
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_CONFIGFS_FS=y
++CONFIG_SQUASHFS=m
++CONFIG_SQUASHFS_XATTR=y
++CONFIG_SQUASHFS_LZO=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_ROOT_NFS=y
++CONFIG_NFS_FSCACHE=y
++CONFIG_CIFS=m
++CONFIG_CIFS_WEAK_PW_HASH=y
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++CONFIG_9P_FS=m
++CONFIG_9P_FS_POSIX_ACL=y
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
++CONFIG_EFI_PARTITION=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++CONFIG_PRINTK_TIME=y
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_TIMER_STATS=y
++CONFIG_DEBUG_STACK_USAGE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_BOOT_PRINTK_DELAY=y
++CONFIG_LATENCYTOP=y
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_IRQSOFF_TRACER=y
++CONFIG_SCHED_TRACER=y
++CONFIG_STACK_TRACER=y
++CONFIG_BLK_DEV_IO_TRACE=y
++CONFIG_FUNCTION_PROFILER=y
++CONFIG_KGDB=y
++CONFIG_KGDB_KDB=y
++CONFIG_KDB_KEYBOARD=y
++CONFIG_STRICT_DEVMEM=y
++CONFIG_CRYPTO_AUTHENC=m
++CONFIG_CRYPTO_SEQIV=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_HMAC=y
++CONFIG_CRYPTO_XCBC=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_WP512=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++CONFIG_CRC_ITU_T=y
++CONFIG_LIBCRC32C=y
+--- /dev/null
++++ b/arch/arm/configs/bcmrpi_emergency_defconfig
+@@ -0,0 +1,532 @@
++CONFIG_EXPERIMENTAL=y
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_FHANDLE=y
++CONFIG_AUDIT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../target_fs"
++CONFIG_CGROUP_FREEZER=y
++CONFIG_CGROUP_DEVICE=y
++CONFIG_CGROUP_CPUACCT=y
++CONFIG_RESOURCE_COUNTERS=y
++CONFIG_BLK_CGROUP=y
++CONFIG_NAMESPACES=y
++CONFIG_SCHED_AUTOGROUP=y
++CONFIG_EMBEDDED=y
++# CONFIG_COMPAT_BRK is not set
++CONFIG_SLAB=y
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=m
++CONFIG_KPROBES=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODVERSIONS=y
++CONFIG_MODULE_SRCVERSION_ALL=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_BLK_DEV_THROTTLING=y
++CONFIG_CFQ_GROUP_IOSCHED=y
++CONFIG_ARCH_BCM2708=y
++CONFIG_NO_HZ=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_AEABI=y
++CONFIG_SECCOMP=y
++CONFIG_CC_STACKPROTECTOR=y
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait"
++CONFIG_KEXEC=y
++CONFIG_CPU_IDLE=y
++CONFIG_VFP=y
++CONFIG_BINFMT_MISC=m
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_XFRM_USER=y
++CONFIG_NET_KEY=m
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_RARP=y
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_NET_PKTGEN=m
++CONFIG_IRDA=m
++CONFIG_IRLAN=m
++CONFIG_IRCOMM=m
++CONFIG_IRDA_ULTRA=y
++CONFIG_IRDA_CACHE_LAST_LSAP=y
++CONFIG_IRDA_FAST_RR=y
++CONFIG_IRTTY_SIR=m
++CONFIG_KINGSUN_DONGLE=m
++CONFIG_KSDAZZLE_DONGLE=m
++CONFIG_KS959_DONGLE=m
++CONFIG_USB_IRDA=m
++CONFIG_SIGMATEL_FIR=m
++CONFIG_MCS_FIR=m
++CONFIG_BT=m
++CONFIG_BT_L2CAP=y
++CONFIG_BT_SCO=y
++CONFIG_BT_RFCOMM=m
++CONFIG_BT_RFCOMM_TTY=y
++CONFIG_BT_BNEP=m
++CONFIG_BT_BNEP_MC_FILTER=y
++CONFIG_BT_BNEP_PROTO_FILTER=y
++CONFIG_BT_HIDP=m
++CONFIG_BT_HCIBTUSB=m
++CONFIG_BT_HCIBCM203X=m
++CONFIG_BT_HCIBPA10X=m
++CONFIG_BT_HCIBFUSB=m
++CONFIG_BT_HCIVHCI=m
++CONFIG_BT_MRVL=m
++CONFIG_BT_MRVL_SDIO=m
++CONFIG_BT_ATH3K=m
++CONFIG_CFG80211=m
++CONFIG_MAC80211=m
++CONFIG_MAC80211_RC_PID=y
++CONFIG_MAC80211_MESH=y
++CONFIG_WIMAX=m
++CONFIG_NET_9P=m
++CONFIG_NFC=m
++CONFIG_NFC_PN533=m
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_CRYPTOLOOP=m
++CONFIG_BLK_DEV_NBD=m
++CONFIG_BLK_DEV_RAM=y
++CONFIG_CDROM_PKTCDVD=m
++CONFIG_MISC_DEVICES=y
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++CONFIG_BLK_DEV_SD=y
++CONFIG_BLK_DEV_SR=m
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_LOWLEVEL is not set
++CONFIG_MD=y
++CONFIG_NETDEVICES=y
++CONFIG_TUN=m
++CONFIG_PHYLIB=m
++CONFIG_MDIO_BITBANG=m
++CONFIG_NET_ETHERNET=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++CONFIG_LIBERTAS_THINFIRM=m
++CONFIG_LIBERTAS_THINFIRM_USB=m
++CONFIG_AT76C50X_USB=m
++CONFIG_USB_ZD1201=m
++CONFIG_USB_NET_RNDIS_WLAN=m
++CONFIG_RTL8187=m
++CONFIG_MAC80211_HWSIM=m
++CONFIG_ATH_COMMON=m
++CONFIG_ATH9K=m
++CONFIG_ATH9K_HTC=m
++CONFIG_CARL9170=m
++CONFIG_B43=m
++CONFIG_B43LEGACY=m
++CONFIG_HOSTAP=m
++CONFIG_IWM=m
++CONFIG_LIBERTAS=m
++CONFIG_LIBERTAS_USB=m
++CONFIG_LIBERTAS_SDIO=m
++CONFIG_P54_COMMON=m
++CONFIG_P54_USB=m
++CONFIG_RT2X00=m
++CONFIG_RT2500USB=m
++CONFIG_RT73USB=m
++CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT53XX=y
++CONFIG_RTL8192CU=m
++CONFIG_WL1251=m
++CONFIG_WL12XX_MENU=m
++CONFIG_ZD1211RW=m
++CONFIG_MWIFIEX=m
++CONFIG_MWIFIEX_SDIO=m
++CONFIG_WIMAX_I2400M_USB=m
++CONFIG_USB_CATC=m
++CONFIG_USB_KAWETH=m
++CONFIG_USB_PEGASUS=m
++CONFIG_USB_RTL8150=m
++CONFIG_USB_USBNET=y
++CONFIG_USB_NET_AX8817X=m
++CONFIG_USB_NET_CDCETHER=m
++CONFIG_USB_NET_CDC_EEM=m
++CONFIG_USB_NET_DM9601=m
++CONFIG_USB_NET_SMSC75XX=m
++CONFIG_USB_NET_SMSC95XX=y
++CONFIG_USB_NET_GL620A=m
++CONFIG_USB_NET_NET1080=m
++CONFIG_USB_NET_PLUSB=m
++CONFIG_USB_NET_MCS7830=m
++CONFIG_USB_NET_CDC_SUBSET=m
++CONFIG_USB_ALI_M5632=y
++CONFIG_USB_AN2720=y
++CONFIG_USB_KC2190=y
++# CONFIG_USB_NET_ZAURUS is not set
++CONFIG_USB_NET_CX82310_ETH=m
++CONFIG_USB_NET_KALMIA=m
++CONFIG_USB_NET_INT51X1=m
++CONFIG_USB_IPHETH=m
++CONFIG_USB_SIERRA_NET=m
++CONFIG_USB_VL600=m
++CONFIG_PPP=m
++CONFIG_PPP_ASYNC=m
++CONFIG_PPP_SYNC_TTY=m
++CONFIG_PPP_DEFLATE=m
++CONFIG_PPP_BSDCOMP=m
++CONFIG_SLIP=m
++CONFIG_SLIP_COMPRESSED=y
++CONFIG_NETCONSOLE=m
++CONFIG_INPUT_POLLDEV=m
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_JOYDEV=m
++CONFIG_INPUT_EVDEV=m
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_AD714X=m
++CONFIG_INPUT_ATI_REMOTE=m
++CONFIG_INPUT_ATI_REMOTE2=m
++CONFIG_INPUT_KEYSPAN_REMOTE=m
++CONFIG_INPUT_POWERMATE=m
++CONFIG_INPUT_YEALINK=m
++CONFIG_INPUT_CM109=m
++CONFIG_INPUT_UINPUT=m
++CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
++CONFIG_INPUT_ADXL34X=m
++CONFIG_INPUT_CMA3000=m
++CONFIG_SERIO=m
++CONFIG_SERIO_RAW=m
++CONFIG_GAMEPORT=m
++CONFIG_GAMEPORT_NS558=m
++CONFIG_GAMEPORT_L4=m
++CONFIG_VT_HW_CONSOLE_BINDING=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_DEVKMEM is not set
++CONFIG_SERIAL_AMBA_PL011=y
++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
++# CONFIG_HW_RANDOM is not set
++CONFIG_RAW_DRIVER=y
++CONFIG_GPIO_SYSFS=y
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_BCM2708_WDT=m
++# CONFIG_MFD_SUPPORT is not set
++CONFIG_FB=y
++CONFIG_FB_BCM2708=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_SOUND=y
++CONFIG_SND=m
++CONFIG_SND_SEQUENCER=m
++CONFIG_SND_SEQ_DUMMY=m
++CONFIG_SND_MIXER_OSS=m
++CONFIG_SND_PCM_OSS=m
++CONFIG_SND_SEQUENCER_OSS=y
++CONFIG_SND_HRTIMER=m
++CONFIG_SND_DUMMY=m
++CONFIG_SND_ALOOP=m
++CONFIG_SND_VIRMIDI=m
++CONFIG_SND_MTPAV=m
++CONFIG_SND_SERIAL_U16550=m
++CONFIG_SND_MPU401=m
++CONFIG_SND_BCM2835=m
++CONFIG_SND_USB_AUDIO=m
++CONFIG_SND_USB_UA101=m
++CONFIG_SND_USB_CAIAQ=m
++CONFIG_SND_USB_6FIRE=m
++CONFIG_SOUND_PRIME=m
++CONFIG_HID_PID=y
++CONFIG_USB_HIDDEV=y
++CONFIG_HID_A4TECH=m
++CONFIG_HID_ACRUX=m
++CONFIG_HID_APPLE=m
++CONFIG_HID_BELKIN=m
++CONFIG_HID_CHERRY=m
++CONFIG_HID_CHICONY=m
++CONFIG_HID_CYPRESS=m
++CONFIG_HID_DRAGONRISE=m
++CONFIG_HID_EMS_FF=m
++CONFIG_HID_ELECOM=m
++CONFIG_HID_EZKEY=m
++CONFIG_HID_HOLTEK=m
++CONFIG_HID_KEYTOUCH=m
++CONFIG_HID_KYE=m
++CONFIG_HID_UCLOGIC=m
++CONFIG_HID_WALTOP=m
++CONFIG_HID_GYRATION=m
++CONFIG_HID_TWINHAN=m
++CONFIG_HID_KENSINGTON=m
++CONFIG_HID_LCPOWER=m
++CONFIG_HID_LOGITECH=m
++CONFIG_HID_MAGICMOUSE=m
++CONFIG_HID_MICROSOFT=m
++CONFIG_HID_MONTEREY=m
++CONFIG_HID_MULTITOUCH=m
++CONFIG_HID_NTRIG=m
++CONFIG_HID_ORTEK=m
++CONFIG_HID_PANTHERLORD=m
++CONFIG_HID_PETALYNX=m
++CONFIG_HID_PICOLCD=m
++CONFIG_HID_QUANTA=m
++CONFIG_HID_ROCCAT=m
++CONFIG_HID_SAMSUNG=m
++CONFIG_HID_SONY=m
++CONFIG_HID_SPEEDLINK=m
++CONFIG_HID_SUNPLUS=m
++CONFIG_HID_GREENASIA=m
++CONFIG_HID_SMARTJOYPLUS=m
++CONFIG_HID_TOPSEED=m
++CONFIG_HID_THRUSTMASTER=m
++CONFIG_HID_WACOM=m
++CONFIG_HID_WIIMOTE=m
++CONFIG_HID_ZEROPLUS=m
++CONFIG_HID_ZYDACRON=m
++CONFIG_USB=y
++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
++CONFIG_USB_MON=m
++CONFIG_USB_DWCOTG=y
++CONFIG_USB_STORAGE=y
++CONFIG_USB_STORAGE_REALTEK=m
++CONFIG_USB_STORAGE_DATAFAB=m
++CONFIG_USB_STORAGE_FREECOM=m
++CONFIG_USB_STORAGE_ISD200=m
++CONFIG_USB_STORAGE_USBAT=m
++CONFIG_USB_STORAGE_SDDR09=m
++CONFIG_USB_STORAGE_SDDR55=m
++CONFIG_USB_STORAGE_JUMPSHOT=m
++CONFIG_USB_STORAGE_ALAUDA=m
++CONFIG_USB_STORAGE_ONETOUCH=m
++CONFIG_USB_STORAGE_KARMA=m
++CONFIG_USB_STORAGE_CYPRESS_ATACB=m
++CONFIG_USB_STORAGE_ENE_UB6250=m
++CONFIG_USB_UAS=y
++CONFIG_USB_LIBUSUAL=y
++CONFIG_USB_MDC800=m
++CONFIG_USB_MICROTEK=m
++CONFIG_USB_SERIAL=m
++CONFIG_USB_SERIAL_GENERIC=y
++CONFIG_USB_SERIAL_AIRCABLE=m
++CONFIG_USB_SERIAL_ARK3116=m
++CONFIG_USB_SERIAL_BELKIN=m
++CONFIG_USB_SERIAL_CH341=m
++CONFIG_USB_SERIAL_WHITEHEAT=m
++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
++CONFIG_USB_SERIAL_CP210X=m
++CONFIG_USB_SERIAL_CYPRESS_M8=m
++CONFIG_USB_SERIAL_EMPEG=m
++CONFIG_USB_SERIAL_FTDI_SIO=m
++CONFIG_USB_SERIAL_FUNSOFT=m
++CONFIG_USB_SERIAL_VISOR=m
++CONFIG_USB_SERIAL_IPAQ=m
++CONFIG_USB_SERIAL_IR=m
++CONFIG_USB_SERIAL_EDGEPORT=m
++CONFIG_USB_SERIAL_EDGEPORT_TI=m
++CONFIG_USB_SERIAL_GARMIN=m
++CONFIG_USB_SERIAL_IPW=m
++CONFIG_USB_SERIAL_IUU=m
++CONFIG_USB_SERIAL_KEYSPAN_PDA=m
++CONFIG_USB_SERIAL_KEYSPAN=m
++CONFIG_USB_SERIAL_KLSI=m
++CONFIG_USB_SERIAL_KOBIL_SCT=m
++CONFIG_USB_SERIAL_MCT_U232=m
++CONFIG_USB_SERIAL_MOS7720=m
++CONFIG_USB_SERIAL_MOS7840=m
++CONFIG_USB_SERIAL_MOTOROLA=m
++CONFIG_USB_SERIAL_NAVMAN=m
++CONFIG_USB_SERIAL_PL2303=m
++CONFIG_USB_SERIAL_OTI6858=m
++CONFIG_USB_SERIAL_QCAUX=m
++CONFIG_USB_SERIAL_QUALCOMM=m
++CONFIG_USB_SERIAL_SPCP8X5=m
++CONFIG_USB_SERIAL_HP4X=m
++CONFIG_USB_SERIAL_SAFE=m
++CONFIG_USB_SERIAL_SIEMENS_MPI=m
++CONFIG_USB_SERIAL_SIERRAWIRELESS=m
++CONFIG_USB_SERIAL_SYMBOL=m
++CONFIG_USB_SERIAL_TI=m
++CONFIG_USB_SERIAL_CYBERJACK=m
++CONFIG_USB_SERIAL_XIRCOM=m
++CONFIG_USB_SERIAL_OPTION=m
++CONFIG_USB_SERIAL_OMNINET=m
++CONFIG_USB_SERIAL_OPTICON=m
++CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
++CONFIG_USB_SERIAL_ZIO=m
++CONFIG_USB_SERIAL_SSU100=m
++CONFIG_USB_SERIAL_DEBUG=m
++CONFIG_USB_EMI62=m
++CONFIG_USB_EMI26=m
++CONFIG_USB_ADUTUX=m
++CONFIG_USB_SEVSEG=m
++CONFIG_USB_RIO500=m
++CONFIG_USB_LEGOTOWER=m
++CONFIG_USB_LCD=m
++CONFIG_USB_LED=m
++CONFIG_USB_CYPRESS_CY7C63=m
++CONFIG_USB_CYTHERM=m
++CONFIG_USB_IDMOUSE=m
++CONFIG_USB_FTDI_ELAN=m
++CONFIG_USB_APPLEDISPLAY=m
++CONFIG_USB_LD=m
++CONFIG_USB_TRANCEVIBRATOR=m
++CONFIG_USB_IOWARRIOR=m
++CONFIG_USB_TEST=m
++CONFIG_USB_ISIGHTFW=m
++CONFIG_USB_YUREX=m
++CONFIG_MMC=y
++CONFIG_MMC_SDHCI=y
++CONFIG_MMC_SDHCI_PLTFM=y
++CONFIG_MMC_SDHCI_BCM2708=y
++CONFIG_MMC_SDHCI_BCM2708_DMA=y
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_TRIGGER_TIMER=m
++CONFIG_LEDS_TRIGGER_HEARTBEAT=m
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
++CONFIG_UIO=m
++CONFIG_UIO_PDRV=m
++CONFIG_UIO_PDRV_GENIRQ=m
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_POSIX_ACL=y
++CONFIG_EXT4_FS_SECURITY=y
++CONFIG_REISERFS_FS=m
++CONFIG_REISERFS_FS_XATTR=y
++CONFIG_REISERFS_FS_POSIX_ACL=y
++CONFIG_REISERFS_FS_SECURITY=y
++CONFIG_JFS_FS=m
++CONFIG_JFS_POSIX_ACL=y
++CONFIG_JFS_SECURITY=y
++CONFIG_JFS_STATISTICS=y
++CONFIG_XFS_FS=m
++CONFIG_XFS_QUOTA=y
++CONFIG_XFS_POSIX_ACL=y
++CONFIG_XFS_RT=y
++CONFIG_GFS2_FS=m
++CONFIG_OCFS2_FS=m
++CONFIG_BTRFS_FS=m
++CONFIG_BTRFS_FS_POSIX_ACL=y
++CONFIG_NILFS2_FS=m
++CONFIG_FANOTIFY=y
++CONFIG_AUTOFS4_FS=y
++CONFIG_FUSE_FS=m
++CONFIG_CUSE=m
++CONFIG_FSCACHE=y
++CONFIG_FSCACHE_STATS=y
++CONFIG_FSCACHE_HISTOGRAM=y
++CONFIG_CACHEFILES=y
++CONFIG_ISO9660_FS=m
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_UDF_FS=m
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
++CONFIG_NTFS_FS=m
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_CONFIGFS_FS=y
++CONFIG_SQUASHFS=m
++CONFIG_SQUASHFS_XATTR=y
++CONFIG_SQUASHFS_LZO=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_ROOT_NFS=y
++CONFIG_NFS_FSCACHE=y
++CONFIG_CIFS=m
++CONFIG_CIFS_WEAK_PW_HASH=y
++CONFIG_CIFS_XATTR=y
++CONFIG_CIFS_POSIX=y
++CONFIG_9P_FS=m
++CONFIG_9P_FS_POSIX_ACL=y
++CONFIG_PARTITION_ADVANCED=y
++CONFIG_MAC_PARTITION=y
++CONFIG_EFI_PARTITION=y
++CONFIG_NLS_DEFAULT="utf8"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_CODEPAGE_737=m
++CONFIG_NLS_CODEPAGE_775=m
++CONFIG_NLS_CODEPAGE_850=m
++CONFIG_NLS_CODEPAGE_852=m
++CONFIG_NLS_CODEPAGE_855=m
++CONFIG_NLS_CODEPAGE_857=m
++CONFIG_NLS_CODEPAGE_860=m
++CONFIG_NLS_CODEPAGE_861=m
++CONFIG_NLS_CODEPAGE_862=m
++CONFIG_NLS_CODEPAGE_863=m
++CONFIG_NLS_CODEPAGE_864=m
++CONFIG_NLS_CODEPAGE_865=m
++CONFIG_NLS_CODEPAGE_866=m
++CONFIG_NLS_CODEPAGE_869=m
++CONFIG_NLS_CODEPAGE_936=m
++CONFIG_NLS_CODEPAGE_950=m
++CONFIG_NLS_CODEPAGE_932=m
++CONFIG_NLS_CODEPAGE_949=m
++CONFIG_NLS_CODEPAGE_874=m
++CONFIG_NLS_ISO8859_8=m
++CONFIG_NLS_CODEPAGE_1250=m
++CONFIG_NLS_CODEPAGE_1251=m
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=m
++CONFIG_NLS_ISO8859_2=m
++CONFIG_NLS_ISO8859_3=m
++CONFIG_NLS_ISO8859_4=m
++CONFIG_NLS_ISO8859_5=m
++CONFIG_NLS_ISO8859_6=m
++CONFIG_NLS_ISO8859_7=m
++CONFIG_NLS_ISO8859_9=m
++CONFIG_NLS_ISO8859_13=m
++CONFIG_NLS_ISO8859_14=m
++CONFIG_NLS_ISO8859_15=m
++CONFIG_NLS_KOI8_R=m
++CONFIG_NLS_KOI8_U=m
++CONFIG_NLS_UTF8=m
++CONFIG_PRINTK_TIME=y
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_TIMER_STATS=y
++CONFIG_DEBUG_STACK_USAGE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_BOOT_PRINTK_DELAY=y
++CONFIG_LATENCYTOP=y
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_IRQSOFF_TRACER=y
++CONFIG_SCHED_TRACER=y
++CONFIG_STACK_TRACER=y
++CONFIG_BLK_DEV_IO_TRACE=y
++CONFIG_FUNCTION_PROFILER=y
++CONFIG_KGDB=y
++CONFIG_KGDB_KDB=y
++CONFIG_KDB_KEYBOARD=y
++CONFIG_STRICT_DEVMEM=y
++CONFIG_CRYPTO_AUTHENC=m
++CONFIG_CRYPTO_SEQIV=m
++CONFIG_CRYPTO_CBC=y
++CONFIG_CRYPTO_HMAC=y
++CONFIG_CRYPTO_XCBC=m
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=m
++CONFIG_CRYPTO_SHA512=m
++CONFIG_CRYPTO_TGR192=m
++CONFIG_CRYPTO_WP512=m
++CONFIG_CRYPTO_CAST5=m
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_DEFLATE=m
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++CONFIG_CRC_ITU_T=y
++CONFIG_LIBCRC32C=y
+--- a/arch/arm/mach-bcm2708/Kconfig
++++ b/arch/arm/mach-bcm2708/Kconfig
+@@ -22,4 +22,11 @@ config BCM2708_VCMEM
+ help
+ Helper for videocore memory access and total size allocation.
+
++config BCM2708_NOL2CACHE
++ bool "Videocore L2 cache disable"
++ depends on MACH_BCM2708
++ default n
++ help
++ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt.
++
+ endmenu
+--- a/arch/arm/mach-bcm2708/bcm2708.c
++++ b/arch/arm/mach-bcm2708/bcm2708.c
+@@ -29,6 +29,7 @@
+ #include <linux/clockchips.h>
+ #include <linux/cnt32_to_63.h>
+ #include <linux/io.h>
++#include <linux/module.h>
+
+ #include <linux/version.h>
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
+@@ -68,6 +69,9 @@
+ */
+ #define DMA_MASK_BITS_COMMON 32
+
++/* command line parameters */
++static unsigned boardrev, serial;
++
+ static void __init bcm2708_init_led(void);
+
+ void __init bcm2708_init_irq(void)
+@@ -77,58 +81,57 @@ void __init bcm2708_init_irq(void)
+
+ static struct map_desc bcm2708_io_desc[] __initdata = {
+ {
+- .virtual = IO_ADDRESS(ARMCTRL_BASE),
+- .pfn = __phys_to_pfn(ARMCTRL_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(UART0_BASE),
+- .pfn = __phys_to_pfn(UART0_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(UART1_BASE),
+- .pfn = __phys_to_pfn(UART1_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+-#ifdef CONFIG_MMC_BCM2708 /* broadcom legacy SD */
+- .virtual = IO_ADDRESS(MMCI0_BASE),
+- .pfn = __phys_to_pfn(MMCI0_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+-#endif
+- .virtual = IO_ADDRESS(DMA_BASE),
+- .pfn = __phys_to_pfn(DMA_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(MCORE_BASE),
+- .pfn = __phys_to_pfn(MCORE_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(ST_BASE),
+- .pfn = __phys_to_pfn(ST_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(USB_BASE),
+- .pfn = __phys_to_pfn(USB_BASE),
+- .length = SZ_128K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(PM_BASE),
+- .pfn = __phys_to_pfn(PM_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }, {
+- .virtual = IO_ADDRESS(GPIO_BASE),
+- .pfn = __phys_to_pfn(GPIO_BASE),
+- .length = SZ_4K,
+- .type = MT_DEVICE
+- }
++ .virtual = IO_ADDRESS(ARMCTRL_BASE),
++ .pfn = __phys_to_pfn(ARMCTRL_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(UART0_BASE),
++ .pfn = __phys_to_pfn(UART0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(UART1_BASE),
++ .pfn = __phys_to_pfn(UART1_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++#ifdef CONFIG_MMC_BCM2708 /* broadcom legacy SD */
++ {
++ .virtual = IO_ADDRESS(MMCI0_BASE),
++ .pfn = __phys_to_pfn(MMCI0_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++#endif
++ {
++ .virtual = IO_ADDRESS(DMA_BASE),
++ .pfn = __phys_to_pfn(DMA_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(MCORE_BASE),
++ .pfn = __phys_to_pfn(MCORE_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(ST_BASE),
++ .pfn = __phys_to_pfn(ST_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(USB_BASE),
++ .pfn = __phys_to_pfn(USB_BASE),
++ .length = SZ_128K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(PM_BASE),
++ .pfn = __phys_to_pfn(PM_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE},
++ {
++ .virtual = IO_ADDRESS(GPIO_BASE),
++ .pfn = __phys_to_pfn(GPIO_BASE),
++ .length = SZ_4K,
++ .type = MT_DEVICE}
+ };
+
+ void __init bcm2708_map_io(void)
+@@ -136,74 +139,91 @@ void __init bcm2708_map_io(void)
+ iotable_init(bcm2708_io_desc, ARRAY_SIZE(bcm2708_io_desc));
+ }
+
+-unsigned long frc_clock_ticks32(void)
++// The STC is a free running counter that increments at the rate of 1MHz
++#define STC_FREQ_HZ 1000000
++
++static cycle_t stc_read_cycles(struct clocksource *cs)
+ {
+ /* STC: a free running counter that increments at the rate of 1MHz */
+- return readl(__io_address(ST_BASE+0x04));
++ return (cycle_t) readl(__io_address(ST_BASE + 0x04));
+ }
+
+-unsigned long long frc_clock_ticks63(void)
++static struct clocksource clocksource_stc = {
++ .name = "stc",
++ .rating = 300,
++ .read = stc_read_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++unsigned long frc_clock_ticks32(void)
+ {
+- unsigned long t = frc_clock_ticks32();
+- /* For cnt32_to_63 to work correctly we MUST call this routine
+- * at least once every half-32-bit-wraparound period - that's once
+- * every 35minutes or so - using it in sched_clock() should ensure this
+- */
+- return cnt32_to_63(t);
++ return (unsigned long)stc_read_cycles(&clocksource_stc);
++}
++
++static void __init bcm2708_clocksource_init(void)
++{
++ // calculate .shift and .mult values and register clocksource
++ if (clocksource_register_hz(&clocksource_stc, STC_FREQ_HZ)) {
++ printk(KERN_ERR "timer: failed to initialize clock "
++ "source %s\n", clocksource_stc.name);
++ }
+ }
+
+ unsigned long long sched_clock(void)
+ {
+- return 1000ull * frc_clock_ticks63();
++ return clocksource_cyc2ns(clocksource_stc.read(&clocksource_stc),
++ clocksource_stc.mult, clocksource_stc.shift);
+ }
+
+ /*
+ * These are fixed clocks.
+ */
+ static struct clk ref24_clk = {
+- .rate = 3000000, /* The UART is clocked at 3MHz via APB_CLK */
++ .rate = 3000000, /* The UART is clocked at 3MHz via APB_CLK */
+ };
++
+ static struct clk osc_clk = {
+ #ifdef CONFIG_ARCH_BCM2708_CHIPIT
+- .rate = 27000000,
++ .rate = 27000000,
+ #else
+- .rate = 500000000, /* ARM clock is set from the VideoCore booter */
++ .rate = 500000000, /* ARM clock is set from the VideoCore booter */
+ #endif
+ };
++
+ /* warning - the USB needs a clock > 34MHz */
+
+ #ifdef CONFIG_MMC_BCM2708
+ static struct clk sdhost_clk = {
+ #ifdef CONFIG_ARCH_BCM2708_CHIPIT
+- .rate = 4000000, /* 4MHz */
++ .rate = 4000000, /* 4MHz */
+ #else
+- .rate = 250000000, /* 250MHz */
++ .rate = 250000000, /* 250MHz */
+ #endif
+ };
+ #endif
+
+ static struct clk_lookup lookups[] = {
+- { /* UART0 */
+- .dev_id = "dev:f1",
+- .clk = &ref24_clk,
+- },
+- { /* USB */
+- .dev_id = "bcm2708_usb",
+- .clk = &osc_clk,
++ { /* UART0 */
++ .dev_id = "dev:f1",
++ .clk = &ref24_clk,
++ },
++ { /* USB */
++ .dev_id = "bcm2708_usb",
++ .clk = &osc_clk,
+ #ifdef CONFIG_MMC_BCM2708
+- },
+- { /* MCI */
+- .dev_id = "bcm2708_mci.0",
+- .clk = &sdhost_clk,
++ },
++ { /* MCI */
++ .dev_id = "bcm2708_mci.0",
++ .clk = &sdhost_clk,
+ #endif
+- }
++ }
+ };
+
+-
+ #define UART0_IRQ { IRQ_UART, NO_IRQ }
+ #define UART0_DMA { 15, 14 }
+
+-AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
++AMBA_DEVICE(uart0, "dev:f1", UART0, NULL);
+
+ static struct amba_device *amba_devs[] __initdata = {
+ &uart0_device,
+@@ -211,262 +231,232 @@ static struct amba_device *amba_devs[] _
+
+ static struct resource bcm2708_dmaman_resources[] = {
+ {
+- .start = DMA_BASE,
+- .end = DMA_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- }
++ .start = DMA_BASE,
++ .end = DMA_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ }
+ };
+
+ static struct platform_device bcm2708_dmaman_device = {
+- .name = BCM_DMAMAN_DRIVER_NAME,
+- .id = 0, /* first bcm2708_dma */
+- .resource = bcm2708_dmaman_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),
++ .name = BCM_DMAMAN_DRIVER_NAME,
++ .id = 0, /* first bcm2708_dma */
++ .resource = bcm2708_dmaman_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources),
+ };
+
+ #ifdef CONFIG_MMC_BCM2708
+ static struct resource bcm2708_mci_resources[] = {
+ {
+- .start = MMCI0_BASE,
+- .end = MMCI0_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- }, {
+- .start = IRQ_SDIO,
+- .end = IRQ_SDIO,
+- .flags = IORESOURCE_IRQ,
+- }
++ .start = MMCI0_BASE,
++ .end = MMCI0_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_SDIO,
++ .end = IRQ_SDIO,
++ .flags = IORESOURCE_IRQ,
++ }
+ };
+
+-
+ static struct platform_device bcm2708_mci_device = {
+- .name = "bcm2708_mci",
+- .id = 0, /* first bcm2708_mci */
+- .resource = bcm2708_mci_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_mci_resources),
+- .dev = {
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = "bcm2708_mci",
++ .id = 0, /* first bcm2708_mci */
++ .resource = bcm2708_mci_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_mci_resources),
++ .dev = {
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+ #endif /* CONFIG_MMC_BCM2708 */
+
+-
+ static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ static struct platform_device bcm2708_fb_device = {
+- .name = "bcm2708_fb",
+- .id = -1, /* only one bcm2708_fb */
+- .resource = NULL,
+- .num_resources = 0,
+- .dev = {
+- .dma_mask = &fb_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = "bcm2708_fb",
++ .id = -1, /* only one bcm2708_fb */
++ .resource = NULL,
++ .num_resources = 0,
++ .dev = {
++ .dma_mask = &fb_dmamask,
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+
+ static struct plat_serial8250_port bcm2708_uart1_platform_data[] = {
+ {
+- .mapbase = UART1_BASE + 0x40,
+- .irq = IRQ_AUX,
+- .uartclk = 125000000,
+- .regshift = 2,
+- .iotype = UPIO_MEM,
+- .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,
+- .type = PORT_8250,
+- },
+- { },
++ .mapbase = UART1_BASE + 0x40,
++ .irq = IRQ_AUX,
++ .uartclk = 125000000,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_FIXED_TYPE | UPF_IOREMAP | UPF_SKIP_TEST,
++ .type = PORT_8250,
++ },
++ {},
+ };
+
+ static struct platform_device bcm2708_uart1_device = {
+- .name = "serial8250",
+- .id = PLAT8250_DEV_PLATFORM,
+- .dev = {
+- .platform_data = bcm2708_uart1_platform_data,
+- },
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = bcm2708_uart1_platform_data,
++ },
+ };
+
+ static struct resource bcm2708_usb_resources[] = {
+- [0] = {
+- .start = USB_BASE,
+- .end = USB_BASE + SZ_128K - 1,
+- .flags = IORESOURCE_MEM,
+- },
+- [1] = {
+- .start = IRQ_USB,
+- .end = IRQ_USB,
+- .flags = IORESOURCE_IRQ,
+- },
++ [0] = {
++ .start = USB_BASE,
++ .end = USB_BASE + SZ_128K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = IRQ_USB,
++ .end = IRQ_USB,
++ .flags = IORESOURCE_IRQ,
++ },
+ };
+
+ static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ static struct platform_device bcm2708_usb_device = {
+- .name = "bcm2708_usb",
+- .id = -1, /* only one bcm2708_usb */
+- .resource = bcm2708_usb_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_usb_resources),
+- .dev = {
+- .dma_mask = &usb_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = "bcm2708_usb",
++ .id = -1, /* only one bcm2708_usb */
++ .resource = bcm2708_usb_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_usb_resources),
++ .dev = {
++ .dma_mask = &usb_dmamask,
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+
+ static struct resource bcm2708_vcio_resources[] = {
+- [0] = { /* mailbox/semaphore/doorbell access */
+- .start = MCORE_BASE,
+- .end = MCORE_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- },
++ [0] = { /* mailbox/semaphore/doorbell access */
++ .start = MCORE_BASE,
++ .end = MCORE_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
+ };
+
+ static u64 vcio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ static struct platform_device bcm2708_vcio_device = {
+- .name = BCM_VCIO_DRIVER_NAME,
+- .id = -1, /* only one VideoCore I/O area */
+- .resource = bcm2708_vcio_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_vcio_resources),
+- .dev = {
+- .dma_mask = &vcio_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = BCM_VCIO_DRIVER_NAME,
++ .id = -1, /* only one VideoCore I/O area */
++ .resource = bcm2708_vcio_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_vcio_resources),
++ .dev = {
++ .dma_mask = &vcio_dmamask,
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+
+ #ifdef CONFIG_BCM2708_GPIO
+ #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
+
+ static struct resource bcm2708_gpio_resources[] = {
+- [0] = { /* general purpose I/O */
+- .start = GPIO_BASE,
+- .end = GPIO_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- },
++ [0] = { /* general purpose I/O */
++ .start = GPIO_BASE,
++ .end = GPIO_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
+ };
+
+ static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ static struct platform_device bcm2708_gpio_device = {
+- .name = BCM_GPIO_DRIVER_NAME,
+- .id = -1, /* only one VideoCore I/O area */
+- .resource = bcm2708_gpio_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
+- .dev = {
+- .dma_mask = &gpio_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
+-};
+-#endif
+-
+-#ifdef CONFIG_BCM2708_BUTTONS
+-static struct resource bcm2708_vcbuttons_resources[] = {
+-};
+-
+-static u64 vcbuttons_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+-
+-static struct platform_device bcm2708_vcbuttons_device = {
+- .name = "bcm2708_vcbuttons",
+- .id = -1, /* only one VideoCore I/O area */
+- .resource = bcm2708_vcbuttons_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_vcbuttons_resources),
+- .dev = {
+- .dma_mask = &vcbuttons_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
+-};
+-#endif
+-
+-#ifdef CONFIG_BCM2708_TOUCHSCREEN
+-static struct resource bcm2708_vctouch_resources[] = {
+-};
+-
+-static u64 vctouch_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+-
+-static struct platform_device bcm2708_vctouch_device = {
+- .name = "bcm2708_vctouch",
+- .id = -1, /* only one VideoCore I/O area */
+- .resource = bcm2708_vctouch_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_vctouch_resources),
+- .dev = {
+- .dma_mask = &vctouch_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = BCM_GPIO_DRIVER_NAME,
++ .id = -1, /* only one VideoCore I/O area */
++ .resource = bcm2708_gpio_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
++ .dev = {
++ .dma_mask = &gpio_dmamask,
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+ #endif
+
+ static struct resource bcm2708_systemtimer_resources[] = {
+- [0] = { /* system timer access */
+- .start = ST_BASE,
+- .end = ST_BASE + SZ_4K - 1,
+- .flags = IORESOURCE_MEM,
+- }, {
+- .start = IRQ_TIMER3,
+- .end = IRQ_TIMER3,
+- .flags = IORESOURCE_IRQ,
+- }
+-
++ [0] = { /* system timer access */
++ .start = ST_BASE,
++ .end = ST_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = IRQ_TIMER3,
++ .end = IRQ_TIMER3,
++ .flags = IORESOURCE_IRQ,
++ }
+
+ };
+
+ static u64 systemtimer_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ static struct platform_device bcm2708_systemtimer_device = {
+- .name = "bcm2708_systemtimer",
+- .id = -1, /* only one VideoCore I/O area */
+- .resource = bcm2708_systemtimer_resources,
+- .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),
+- .dev = {
+- .dma_mask = &systemtimer_dmamask,
+- .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
+- },
++ .name = "bcm2708_systemtimer",
++ .id = -1, /* only one VideoCore I/O area */
++ .resource = bcm2708_systemtimer_resources,
++ .num_resources = ARRAY_SIZE(bcm2708_systemtimer_resources),
++ .dev = {
++ .dma_mask = &systemtimer_dmamask,
++ .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
++ },
+ };
+
+-#ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */
++#ifdef CONFIG_MMC_SDHCI_BCM2708 /* Arasan emmc SD */
+ static struct resource bcm2708_emmc_resources[] = {
+ [0] = {
+- .start = EMMC_BASE,
+- .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */
+- /* the memory map actually makes SZ_4K available */
+- .flags = IORESOURCE_MEM,
+- },
++ .start = EMMC_BASE,
++ .end = EMMC_BASE + SZ_256 - 1, /* we only need this area */
++ /* the memory map actually makes SZ_4K available */
++ .flags = IORESOURCE_MEM,
++ },
+ [1] = {
+- .start = IRQ_ARASANSDIO,
+- .end = IRQ_ARASANSDIO,
+- .flags = IORESOURCE_IRQ,
+- },
++ .start = IRQ_ARASANSDIO,
++ .end = IRQ_ARASANSDIO,
++ .flags = IORESOURCE_IRQ,
++ },
+ };
+
+ static u64 bcm2708_emmc_dmamask = 0xffffffffUL;
+
+ struct platform_device bcm2708_emmc_device = {
+- .name = "bcm2708_sdhci",
+- .id = 0,
+- .num_resources = ARRAY_SIZE(bcm2708_emmc_resources),
+- .resource = bcm2708_emmc_resources,
+- .dev = {
+- .dma_mask = &bcm2708_emmc_dmamask,
+- .coherent_dma_mask = 0xffffffffUL
+- },
++ .name = "bcm2708_sdhci",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bcm2708_emmc_resources),
++ .resource = bcm2708_emmc_resources,
++ .dev = {
++ .dma_mask = &bcm2708_emmc_dmamask,
++ .coherent_dma_mask = 0xffffffffUL},
+ };
+ #endif /* CONFIG_MMC_SDHCI_BCM2708 */
+
+ static struct resource bcm2708_powerman_resources[] = {
+ [0] = {
+- .start = PM_BASE,
+- .end = PM_BASE + SZ_256 - 1,
+- .flags = IORESOURCE_MEM,
+- },
++ .start = PM_BASE,
++ .end = PM_BASE + SZ_256 - 1,
++ .flags = IORESOURCE_MEM,
++ },
+ };
+
+ static u64 powerman_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
+ struct platform_device bcm2708_powerman_device = {
+- .name = "bcm2708_powerman",
+- .id = 0,
+- .num_resources = ARRAY_SIZE(bcm2708_powerman_resources),
+- .resource = bcm2708_powerman_resources,
+- .dev = {
+- .dma_mask = &powerman_dmamask,
+- .coherent_dma_mask = 0xffffffffUL
+- },
++ .name = "bcm2708_powerman",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(bcm2708_powerman_resources),
++ .resource = bcm2708_powerman_resources,
++ .dev = {
++ .dma_mask = &powerman_dmamask,
++ .coherent_dma_mask = 0xffffffffUL},
++};
++
++static struct platform_device bcm2708_alsa_devices[] = {
++ [0] = {
++ .name = "bcm2835_AUD0",
++ .id = 0, /* first audio device */
++ .resource = 0,
++ .num_resources = 0,
++ },
+ };
+
+ int __init bcm_register_device(struct platform_device *pdev)
+@@ -500,30 +490,29 @@ void __init bcm2708_init(void)
+ bcm_register_device(&bcm2708_fb_device);
+ bcm_register_device(&bcm2708_usb_device);
+ bcm_register_device(&bcm2708_uart1_device);
+-#ifdef CONFIG_BCM2708_BUTTONS
+- bcm_register_device(&bcm2708_vcbuttons_device);
+-#endif
+-#ifdef CONFIG_BCM2708_TOUCHSCREEN
+- bcm_register_device(&bcm2708_vctouch_device);
+-#endif
+ bcm_register_device(&bcm2708_powerman_device);
+ #ifdef CONFIG_MMC_SDHCI_BCM2708
+ bcm_register_device(&bcm2708_emmc_device);
+ #endif
+- bcm2708_init_led();
++ bcm2708_init_led();
++ for (i = 0; i < ARRAY_SIZE(bcm2708_alsa_devices); i++)
++ bcm_register_device(&bcm2708_alsa_devices[i]);
++
+ #ifdef CONFIG_BCM2708_VCMEM
+-{
+- extern void vc_mem_connected_init(void);
+- vc_mem_connected_init();
+-}
++ {
++ extern void vc_mem_connected_init(void);
++ vc_mem_connected_init();
++ }
+ #endif
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
+ }
++ system_rev = boardrev;
++ system_serial_low = serial;
+ }
+
+-#define TIMER_PERIOD 10000 /* HZ in microsecs */
++#define TIMER_PERIOD 10000 /* HZ in microsecs */
+
+ static void timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+@@ -532,37 +521,36 @@ static void timer_set_mode(enum clock_ev
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+- stc = readl(__io_address(ST_BASE+0x04));
+- writel(stc + TIMER_PERIOD,
+- __io_address(ST_BASE+0x18));/* stc3 */
++ stc = readl(__io_address(ST_BASE + 0x04));
++ writel(stc + TIMER_PERIOD, __io_address(ST_BASE + 0x18)); /* stc3 */
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ printk(KERN_ERR "timer_set_mode: unhandled mode:%d\n",
+- (int)mode);
++ (int)mode);
+ break;
+ }
+
+ }
+
+-static int timer_set_next_event(unsigned long evt,
++static int timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *unused)
+ {
+ unsigned long stc;
+
+- stc = readl(__io_address(ST_BASE + 0x04));
+- writel(stc + TIMER_PERIOD, __io_address(ST_BASE+0x18)); /* stc3 */
++ stc = readl(__io_address(ST_BASE + 0x04));
++ writel(stc + cycles, __io_address(ST_BASE + 0x18)); /* stc3 */
+ return 0;
+ }
+
+-static struct clock_event_device timer0_clockevent = {
+- .name = "timer0",
+- .shift = 32,
+- .features = CLOCK_EVT_FEAT_ONESHOT,
+- .set_mode = timer_set_mode,
+- .set_next_event = timer_set_next_event,
++static struct clock_event_device timer0_clockevent = {
++ .name = "timer0",
++ .shift = 32,
++ .features = CLOCK_EVT_FEAT_ONESHOT,
++ .set_mode = timer_set_mode,
++ .set_next_event = timer_set_next_event,
+ };
+
+ /*
+@@ -572,7 +560,7 @@ static irqreturn_t bcm2708_timer_interru
+ {
+ struct clock_event_device *evt = &timer0_clockevent;
+
+- writel(1<<3, __io_address(ST_BASE+0x00)); /* stcs clear timer int */
++ writel(1 << 3, __io_address(ST_BASE + 0x00)); /* stcs clear timer int */
+
+ evt->event_handler(evt);
+
+@@ -580,9 +568,9 @@ static irqreturn_t bcm2708_timer_interru
+ }
+
+ static struct irqaction bcm2708_timer_irq = {
+- .name = "BCM2708 Timer Tick",
+- .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+- .handler = bcm2708_timer_interrupt,
++ .name = "BCM2708 Timer Tick",
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = bcm2708_timer_interrupt,
+ };
+
+ /*
+@@ -590,6 +578,9 @@ static struct irqaction bcm2708_timer_ir
+ */
+ static void __init bcm2708_timer_init(void)
+ {
++ /* init high res timer */
++ bcm2708_clocksource_init();
++
+ /*
+ * Initialise to a known state (all timers off)
+ */
+@@ -600,18 +591,18 @@ static void __init bcm2708_timer_init(vo
+ setup_irq(IRQ_TIMER3, &bcm2708_timer_irq);
+
+ timer0_clockevent.mult =
+- div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
++ div_sc(STC_FREQ_HZ, NSEC_PER_SEC, timer0_clockevent.shift);
+ timer0_clockevent.max_delta_ns =
+- clockevent_delta2ns(0xffffffff, &timer0_clockevent);
++ clockevent_delta2ns(0xffffffff, &timer0_clockevent);
+ timer0_clockevent.min_delta_ns =
+- clockevent_delta2ns(0xf, &timer0_clockevent);
++ clockevent_delta2ns(0xf, &timer0_clockevent);
+
+ timer0_clockevent.cpumask = cpumask_of(0);
+ clockevents_register_device(&timer0_clockevent);
+ }
+
+ struct sys_timer bcm2708_timer = {
+- .init = bcm2708_timer_init,
++ .init = bcm2708_timer_init,
+ };
+
+ #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+@@ -619,24 +610,24 @@ struct sys_timer bcm2708_timer = {
+
+ static struct gpio_led bcm2708_leds[] = {
+ [0] = {
+- .gpio = 16,
+- .name = "led0",
+- .default_trigger = "mmc0",
+- .active_low = 0,
+- },
++ .gpio = 16,
++ .name = "led0",
++ .default_trigger = "mmc0",
++ .active_low = 1,
++ },
+ };
+
+ static struct gpio_led_platform_data bcm2708_led_pdata = {
+- .num_leds = ARRAY_SIZE(bcm2708_leds),
+- .leds = bcm2708_leds,
++ .num_leds = ARRAY_SIZE(bcm2708_leds),
++ .leds = bcm2708_leds,
+ };
+
+ static struct platform_device bcm2708_led_device = {
+- .name = "leds-gpio",
+- .id = -1,
+- .dev = {
+- .platform_data = &bcm2708_led_pdata,
+- },
++ .name = "leds-gpio",
++ .id = -1,
++ .dev = {
++ .platform_data = &bcm2708_led_pdata,
++ },
+ };
+
+ static void __init bcm2708_init_led(void)
+@@ -644,14 +635,14 @@ static void __init bcm2708_init_led(void
+ platform_device_register(&bcm2708_led_device);
+ }
+ #else
+-static inline void bcm2708_init_led(void) {}
++static inline void bcm2708_init_led(void)
++{
++}
+ #endif
+
+-
+ MACHINE_START(BCM2708, "BCM2708")
+- /* Maintainer: Broadcom Europe Ltd. */
+- .map_io = bcm2708_map_io,
+- .init_irq = bcm2708_init_irq,
+- .timer = &bcm2708_timer,
+- .init_machine = bcm2708_init,
+-MACHINE_END
++ /* Maintainer: Broadcom Europe Ltd. */
++ .map_io = bcm2708_map_io,.init_irq = bcm2708_init_irq,.timer =
++ &bcm2708_timer,.init_machine =
++ bcm2708_init, MACHINE_END module_param(boardrev, uint, 0644);
++module_param(serial, uint, 0644);
+--- a/arch/arm/mach-bcm2708/include/mach/memory.h
++++ b/arch/arm/mach-bcm2708/include/mach/memory.h
+@@ -32,9 +32,14 @@
+ /*
+ * Physical DRAM offset.
+ */
+-#define PHYS_OFFSET UL(0x00000000)
++#define PLAT_PHYS_OFFSET UL(0x00000000)
+ #define ARMMEM_OFFSET UL(0x00000000) /* offset in VC of ARM memory */
+-#define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */
++
++#ifdef CONFIG_BCM2708_NOL2CACHE
++ #define _REAL_BUS_OFFSET UL(0xC0000000) /* don't use L1 or L2 caches */
++#else
++ #define _REAL_BUS_OFFSET UL(0x40000000) /* use L2 cache */
++#endif
+
+ /* We're using the memory at 64M in the VideoCore for Linux - this adjustment
+ * will provide the offset into this area as well as setting the bits that
+@@ -46,8 +51,8 @@
+ #define BUS_OFFSET (ARMMEM_OFFSET + _REAL_BUS_OFFSET)
+ #define __virt_to_bus(x) ((x) + (BUS_OFFSET - PAGE_OFFSET))
+ #define __bus_to_virt(x) ((x) - (BUS_OFFSET - PAGE_OFFSET))
+-#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PHYS_OFFSET))
+-#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PHYS_OFFSET))
++#define __pfn_to_bus(x) (__pfn_to_phys(x) + (BUS_OFFSET - PLAT_PHYS_OFFSET))
++#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET))
+
+ /*
+ * Consistent DMA area set to 2M. Framebuffer now allocated on host
+--- a/arch/arm/mach-bcm2708/include/mach/vc_mem.h
++++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h
+@@ -21,6 +21,7 @@
+
+ #define VC_MEM_IOC_MEM_PHYS_ADDR _IOR( VC_MEM_IOC_MAGIC, 0, unsigned long )
+ #define VC_MEM_IOC_MEM_SIZE _IOR( VC_MEM_IOC_MAGIC, 1, unsigned int )
++#define VC_MEM_IOC_MEM_BASE _IOR( VC_MEM_IOC_MAGIC, 2, unsigned int )
+
+ #if defined( __KERNEL__ )
+ #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF
+--- a/arch/arm/mach-bcm2708/power.c
++++ b/arch/arm/mach-bcm2708/power.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/semaphore.h>
+ #include <linux/bug.h>
++#include <linux/delay.h>
+ #include <mach/power.h>
+ #include <mach/vcio.h>
+ #include <mach/arm_power.h>
+@@ -96,7 +97,6 @@ int bcm_power_request(BCM_POWER_HANDLE_T
+ bcm_mailbox_write(MBOX_CHAN_POWER,
+ global_request << 4);
+
+- /* Wait for a response during power-up */
+ if (global_request & ~g_state.global_request) {
+ rc = bcm_mailbox_read(MBOX_CHAN_POWER,
+ &actual);
+@@ -111,14 +111,14 @@ int bcm_power_request(BCM_POWER_HANDLE_T
+
+ if (rc == 0) {
+ if (actual != global_request) {
+- printk(KERN_ERR
+- "%s: prev global %x, new global %x, actual %x, request %x, others_request %x\n",
++ printk(KERN_INFO
++ "%s: Fail: prev global %x, new global %x, actual %x request %x, others_request %x\n",
+ __func__,
+ g_state.global_request,
+ global_request, actual, request, others_request);
+ /* A failure */
+- BUG_ON((others_request & actual)
+- != others_request);
++ // BUG_ON((others_request & actual)
++ // != others_request);
+ request &= actual;
+ rc = -EIO;
+ }
+@@ -161,6 +161,7 @@ static int __init bcm_power_init(void)
+ int i;
+
+ printk(KERN_INFO "bcm_power: Broadcom power driver\n");
++ bcm_mailbox_write(MBOX_CHAN_POWER, 0);
+
+ for (i = 0; i < BCM_POWER_MAXCLIENTS; i++)
+ g_state.client_request[i] = BCM_POWER_NOCLIENT;
+--- a/arch/arm/mach-bcm2708/vc_mem.c
++++ b/arch/arm/mach-bcm2708/vc_mem.c
+@@ -85,9 +85,11 @@ unsigned long mm_vc_mem_phys_addr = MM_A
+ #endif
+
+ unsigned int mm_vc_mem_size = 0;
++unsigned int mm_vc_mem_base = 0;
+
+ EXPORT_SYMBOL(mm_vc_mem_phys_addr);
+ EXPORT_SYMBOL(mm_vc_mem_size);
++EXPORT_SYMBOL(mm_vc_mem_base);
+
+ /****************************************************************************
+ *
+@@ -132,36 +134,19 @@ vc_mem_release(struct inode *inode, stru
+ static void
+ vc_mem_get_size(void)
+ {
+-#ifdef CONFIG_ARCH_BCM2708
+ mm_vc_mem_size = 256 * 1024 * 1024; // Static for now
+-#else
+- CHAL_IPC_HANDLE ipc_handle;
+- uint32_t wakeup_register;
+-
+- // Get the videocore memory size from the IPC mailbox if not yet
+- // assigned.
+- if (mm_vc_mem_size == 0) {
+- ipc_handle = chal_ipc_config(NULL);
+- if (ipc_handle == NULL) {
+- LOG_ERR("%s: failed to get IPC handlle", __func__);
+- return;
+- }
++}
+
+- chal_ipc_query_wakeup_vc(ipc_handle, &wakeup_register);
+- if ((wakeup_register & ~1) == 0) {
+- LOG_DBG("%s: videocore not yet loaded, skipping...",
+- __func__);
+- } else {
+- if (chal_ipc_read_mailbox(ipc_handle,
+- IPC_MAILBOX_ID_0,
+- &mm_vc_mem_size) !=
+- BCM_SUCCESS) {
+- LOG_ERR("%s: failed to read from IPC mailbox",
+- __func__);
+- }
+- }
+- }
+-#endif
++/****************************************************************************
++*
++* vc_mem_get_base
++*
++***************************************************************************/
++
++static void
++vc_mem_get_base(void)
++{
++ mm_vc_mem_base = 128 * 1024 * 1024; // Static for now
+ }
+
+ /****************************************************************************
+@@ -220,6 +205,20 @@ vc_mem_ioctl(struct file *file, unsigned
+ rc = -EFAULT;
+ }
+ break;
++ }
++ case VC_MEM_IOC_MEM_BASE:
++ {
++ // Get the videocore memory base
++ vc_mem_get_base();
++
++ LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__,
++ mm_vc_mem_base);
++
++ if (copy_to_user((void *) arg, &mm_vc_mem_base,
++ sizeof (mm_vc_mem_base)) != 0) {
++ rc = -EFAULT;
++ }
++ break;
+ }
+ default:
+ {
+--- a/arch/arm/mach-bcm2708/vcio.c
++++ b/arch/arm/mach-bcm2708/vcio.c
+@@ -119,8 +119,7 @@ static int mbox_read(struct vc_mailbox *
+ if (mbox->magic != MBOX_MAGIC)
+ rc = -EINVAL;
+ else {
+- if (mbox->msg[chan] ||
+- (down_interruptible(&mbox->sema[chan]) == 0)) {
++ if (down_interruptible(&mbox->sema[chan]) == 0) {
+ *data28 = MBOX_DATA28(mbox->msg[chan]);
+ mbox->msg[chan] = 0;
+ rc = 0;
+--- a/drivers/misc/vc04_services/Makefile
++++ b/drivers/misc/vc04_services/Makefile
+@@ -2,6 +2,8 @@ obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o
+
+ vchiq-objs := \
+ interface/vchiq_arm/vchiq_core.o \
++ interface/vchiq_arm/vchiq_shim.o \
++ interface/vchiq_arm/vchiq_util.o \
+ interface/vchiq_arm/vchiq_arm.o \
+ interface/vchiq_arm/vchiq_kern_lib.o \
+ interface/vchiq_arm/vchiq_2835_arm.o \
+@@ -13,7 +15,7 @@ vchiq-objs := \
+ interface/vcos/generic/vcos_mem_from_malloc.o \
+ interface/vcos/generic/vcos_cmd.o
+
+-EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel
++EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel
+
+
+
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/connections/connection.h
+@@ -0,0 +1,309 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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 CONNECTION_H_
++#define CONNECTION_H_
++
++#include "interface/vchi/vchi_cfg_internal.h"
++#include "interface/vchi/vchi_common.h"
++#include "interface/vchi/message_drivers/message.h"
++
++/******************************************************************************
++ Global defs
++ *****************************************************************************/
++
++// Opaque handle for a connection / service pair
++typedef struct opaque_vchi_connection_connected_service_handle_t *VCHI_CONNECTION_SERVICE_HANDLE_T;
++
++// opaque handle to the connection state information
++typedef struct opaque_vchi_connection_info_t VCHI_CONNECTION_STATE_T;
++
++typedef struct vchi_connection_t VCHI_CONNECTION_T;
++
++
++/******************************************************************************
++ API
++ *****************************************************************************/
++
++// Routine to init a connection with a particular low level driver
++typedef VCHI_CONNECTION_STATE_T * (*VCHI_CONNECTION_INIT_T)( struct vchi_connection_t * connection,
++ const VCHI_MESSAGE_DRIVER_T * driver );
++
++// Routine to control CRC enabling at a connection level
++typedef int32_t (*VCHI_CONNECTION_CRC_CONTROL_T)( VCHI_CONNECTION_STATE_T *state_handle,
++ VCHI_CRC_CONTROL_T control );
++
++// Routine to create a service
++typedef int32_t (*VCHI_CONNECTION_SERVICE_CONNECT_T)( VCHI_CONNECTION_STATE_T *state_handle,
++ vcos_fourcc_t service_id,
++ uint32_t rx_fifo_size,
++ uint32_t tx_fifo_size,
++ int server,
++ VCHI_CALLBACK_T callback,
++ void *callback_param,
++ vcos_bool_t want_crc,
++ vcos_bool_t want_unaligned_bulk_rx,
++ vcos_bool_t want_unaligned_bulk_tx,
++ VCHI_CONNECTION_SERVICE_HANDLE_T *service_handle );
++
++// Routine to close a service
++typedef int32_t (*VCHI_CONNECTION_SERVICE_DISCONNECT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle );
++
++// Routine to queue a message
++typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ const void *data,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *msg_handle );
++
++// scatter-gather (vector) message queueing
++typedef int32_t (*VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ VCHI_MSG_VECTOR_T *vector,
++ uint32_t count,
++ VCHI_FLAGS_T flags,
++ void *msg_handle );
++
++// Routine to dequeue a message
++typedef int32_t (*VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void *data,
++ uint32_t max_data_size_to_read,
++ uint32_t *actual_msg_size,
++ VCHI_FLAGS_T flags );
++
++// Routine to peek at a message
++typedef int32_t (*VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void **data,
++ uint32_t *msg_size,
++ VCHI_FLAGS_T flags );
++
++// Routine to hold a message
++typedef int32_t (*VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void **data,
++ uint32_t *msg_size,
++ VCHI_FLAGS_T flags,
++ void **message_handle );
++
++// Routine to initialise a received message iterator
++typedef int32_t (*VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ VCHI_MSG_ITER_T *iter,
++ VCHI_FLAGS_T flags );
++
++// Routine to release a held message
++typedef int32_t (*VCHI_CONNECTION_HELD_MSG_RELEASE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void *message_handle );
++
++// Routine to get info on a held message
++typedef int32_t (*VCHI_CONNECTION_HELD_MSG_INFO_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void *message_handle,
++ void **data,
++ int32_t *msg_size,
++ uint32_t *tx_timestamp,
++ uint32_t *rx_timestamp );
++
++// Routine to check whether the iterator has a next message
++typedef vcos_bool_t (*VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
++ const VCHI_MSG_ITER_T *iter );
++
++// Routine to advance the iterator
++typedef int32_t (*VCHI_CONNECTION_MSG_ITER_NEXT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
++ VCHI_MSG_ITER_T *iter,
++ void **data,
++ uint32_t *msg_size );
++
++// Routine to remove the last message returned by the iterator
++typedef int32_t (*VCHI_CONNECTION_MSG_ITER_REMOVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
++ VCHI_MSG_ITER_T *iter );
++
++// Routine to hold the last message returned by the iterator
++typedef int32_t (*VCHI_CONNECTION_MSG_ITER_HOLD_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service,
++ VCHI_MSG_ITER_T *iter,
++ void **msg_handle );
++
++// Routine to transmit bulk data
++typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ const void *data_src,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *bulk_handle );
++
++// Routine to receive data
++typedef int32_t (*VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T)( VCHI_CONNECTION_SERVICE_HANDLE_T service_handle,
++ void *data_dst,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *bulk_handle );
++
++// Routine to report if a server is available
++typedef int32_t (*VCHI_CONNECTION_SERVER_PRESENT)( VCHI_CONNECTION_STATE_T *state, vcos_fourcc_t service_id, int32_t peer_flags );
++
++// Routine to report the number of RX slots available
++typedef int (*VCHI_CONNECTION_RX_SLOTS_AVAILABLE)( const VCHI_CONNECTION_STATE_T *state );
++
++// Routine to report the RX slot size
++typedef uint32_t (*VCHI_CONNECTION_RX_SLOT_SIZE)( const VCHI_CONNECTION_STATE_T *state );
++
++// Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
++typedef void (*VCHI_CONNECTION_RX_BULK_BUFFER_ADDED)(VCHI_CONNECTION_STATE_T *state,
++ vcos_fourcc_t service,
++ uint32_t length,
++ MESSAGE_TX_CHANNEL_T channel,
++ uint32_t channel_params,
++ uint32_t data_length,
++ uint32_t data_offset);
++
++// Callback to inform a service that a Xon or Xoff message has been received
++typedef void (*VCHI_CONNECTION_FLOW_CONTROL)(VCHI_CONNECTION_STATE_T *state, vcos_fourcc_t service_id, int32_t xoff);
++
++// Callback to inform a service that a server available reply message has been received
++typedef void (*VCHI_CONNECTION_SERVER_AVAILABLE_REPLY)(VCHI_CONNECTION_STATE_T *state, vcos_fourcc_t service_id, uint32_t flags);
++
++// Callback to indicate that bulk auxiliary messages have arrived
++typedef void (*VCHI_CONNECTION_BULK_AUX_RECEIVED)(VCHI_CONNECTION_STATE_T *state);
++
++// Callback to indicate that bulk auxiliary messages have arrived
++typedef void (*VCHI_CONNECTION_BULK_AUX_TRANSMITTED)(VCHI_CONNECTION_STATE_T *state, void *handle);
++
++// Callback with all the connection info you require
++typedef void (*VCHI_CONNECTION_INFO)(VCHI_CONNECTION_STATE_T *state, uint32_t protocol_version, uint32_t slot_size, uint32_t num_slots, uint32_t min_bulk_size);
++
++// Callback to inform of a disconnect
++typedef void (*VCHI_CONNECTION_DISCONNECT)(VCHI_CONNECTION_STATE_T *state, uint32_t flags);
++
++// Callback to inform of a power control request
++typedef void (*VCHI_CONNECTION_POWER_CONTROL)(VCHI_CONNECTION_STATE_T *state, MESSAGE_TX_CHANNEL_T channel, vcos_bool_t enable);
++
++// allocate memory suitably aligned for this connection
++typedef void * (*VCHI_BUFFER_ALLOCATE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, uint32_t * length);
++
++// free memory allocated by buffer_allocate
++typedef void (*VCHI_BUFFER_FREE)(VCHI_CONNECTION_SERVICE_HANDLE_T service_handle, void * address);
++
++
++/******************************************************************************
++ System driver struct
++ *****************************************************************************/
++
++struct opaque_vchi_connection_api_t
++{
++ // Routine to init the connection
++ VCHI_CONNECTION_INIT_T init;
++
++ // Connection-level CRC control
++ VCHI_CONNECTION_CRC_CONTROL_T crc_control;
++
++ // Routine to connect to or create service
++ VCHI_CONNECTION_SERVICE_CONNECT_T service_connect;
++
++ // Routine to disconnect from a service
++ VCHI_CONNECTION_SERVICE_DISCONNECT_T service_disconnect;
++
++ // Routine to queue a message
++ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGE_T service_queue_msg;
++
++ // scatter-gather (vector) message queue
++ VCHI_CONNECTION_SERVICE_QUEUE_MESSAGEV_T service_queue_msgv;
++
++ // Routine to dequeue a message
++ VCHI_CONNECTION_SERVICE_DEQUEUE_MESSAGE_T service_dequeue_msg;
++
++ // Routine to peek at a message
++ VCHI_CONNECTION_SERVICE_PEEK_MESSAGE_T service_peek_msg;
++
++ // Routine to hold a message
++ VCHI_CONNECTION_SERVICE_HOLD_MESSAGE_T service_hold_msg;
++
++ // Routine to initialise a received message iterator
++ VCHI_CONNECTION_SERVICE_LOOKAHEAD_MESSAGE_T service_look_ahead_msg;
++
++ // Routine to release a message
++ VCHI_CONNECTION_HELD_MSG_RELEASE_T held_msg_release;
++
++ // Routine to get information on a held message
++ VCHI_CONNECTION_HELD_MSG_INFO_T held_msg_info;
++
++ // Routine to check for next message on iterator
++ VCHI_CONNECTION_MSG_ITER_HAS_NEXT_T msg_iter_has_next;
++
++ // Routine to get next message on iterator
++ VCHI_CONNECTION_MSG_ITER_NEXT_T msg_iter_next;
++
++ // Routine to remove the last message returned by iterator
++ VCHI_CONNECTION_MSG_ITER_REMOVE_T msg_iter_remove;
++
++ // Routine to hold the last message returned by iterator
++ VCHI_CONNECTION_MSG_ITER_HOLD_T msg_iter_hold;
++
++ // Routine to transmit bulk data
++ VCHI_CONNECTION_BULK_QUEUE_TRANSMIT_T bulk_queue_transmit;
++
++ // Routine to receive data
++ VCHI_CONNECTION_BULK_QUEUE_RECEIVE_T bulk_queue_receive;
++
++ // Routine to report the available servers
++ VCHI_CONNECTION_SERVER_PRESENT server_present;
++
++ // Routine to report the number of RX slots available
++ VCHI_CONNECTION_RX_SLOTS_AVAILABLE connection_rx_slots_available;
++
++ // Routine to report the RX slot size
++ VCHI_CONNECTION_RX_SLOT_SIZE connection_rx_slot_size;
++
++ // Callback to indicate that the other side has added a buffer to the rx bulk DMA FIFO
++ VCHI_CONNECTION_RX_BULK_BUFFER_ADDED rx_bulk_buffer_added;
++
++ // Callback to inform a service that a Xon or Xoff message has been received
++ VCHI_CONNECTION_FLOW_CONTROL flow_control;
++
++ // Callback to inform a service that a server available reply message has been received
++ VCHI_CONNECTION_SERVER_AVAILABLE_REPLY server_available_reply;
++
++ // Callback to indicate that bulk auxiliary messages have arrived
++ VCHI_CONNECTION_BULK_AUX_RECEIVED bulk_aux_received;
++
++ // Callback to indicate that a bulk auxiliary message has been transmitted
++ VCHI_CONNECTION_BULK_AUX_TRANSMITTED bulk_aux_transmitted;
++
++ // Callback to provide information about the connection
++ VCHI_CONNECTION_INFO connection_info;
++
++ // Callback to notify that peer has requested disconnect
++ VCHI_CONNECTION_DISCONNECT disconnect;
++
++ // Callback to notify that peer has requested power change
++ VCHI_CONNECTION_POWER_CONTROL power_control;
++
++ // allocate memory suitably aligned for this connection
++ VCHI_BUFFER_ALLOCATE buffer_allocate;
++
++ // free memory allocated by buffer_allocate
++ VCHI_BUFFER_FREE buffer_free;
++
++};
++
++struct vchi_connection_t {
++ const VCHI_CONNECTION_API_T *api;
++ VCHI_CONNECTION_STATE_T *state;
++#ifdef VCHI_COARSE_LOCKING
++ VCOS_SEMAPHORE_T sem;
++#endif
++};
++
++
++#endif /* CONNECTION_H_ */
++
++/****************************** End of file **********************************/
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h
+@@ -0,0 +1,186 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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 _VCHI_MESSAGE_H_
++#define _VCHI_MESSAGE_H_
++
++#include "interface/vchi/vchi_cfg_internal.h"
++#include "interface/vcos/vcos.h"
++#include "interface/vchi/vchi_common.h"
++
++
++typedef enum message_event_type {
++ MESSAGE_EVENT_NONE,
++ MESSAGE_EVENT_NOP,
++ MESSAGE_EVENT_MESSAGE,
++ MESSAGE_EVENT_SLOT_COMPLETE,
++ MESSAGE_EVENT_RX_BULK_PAUSED,
++ MESSAGE_EVENT_RX_BULK_COMPLETE,
++ MESSAGE_EVENT_TX_COMPLETE,
++ MESSAGE_EVENT_MSG_DISCARDED
++} MESSAGE_EVENT_TYPE_T;
++
++typedef enum vchi_msg_flags
++{
++ VCHI_MSG_FLAGS_NONE = 0x0,
++ VCHI_MSG_FLAGS_TERMINATE_DMA = 0x1
++} VCHI_MSG_FLAGS_T;
++
++typedef enum message_tx_channel
++{
++ MESSAGE_TX_CHANNEL_MESSAGE = 0,
++ MESSAGE_TX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
++} MESSAGE_TX_CHANNEL_T;
++
++// Macros used for cycling through bulk channels
++#define MESSAGE_TX_CHANNEL_BULK_PREV(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION-1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
++#define MESSAGE_TX_CHANNEL_BULK_NEXT(c) (MESSAGE_TX_CHANNEL_BULK+((c)-MESSAGE_TX_CHANNEL_BULK+1)%VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION)
++
++typedef enum message_rx_channel
++{
++ MESSAGE_RX_CHANNEL_MESSAGE = 0,
++ MESSAGE_RX_CHANNEL_BULK = 1 // drivers may provide multiple bulk channels, from 1 upwards
++} MESSAGE_RX_CHANNEL_T;
++
++// Message receive slot information
++typedef struct rx_msg_slot_info {
++
++ struct rx_msg_slot_info *next;
++ //struct slot_info *prev;
++#if !defined VCHI_COARSE_LOCKING
++ VCOS_SEMAPHORE_T sem;
++#endif
++
++ uint8_t *addr; // base address of slot
++ uint32_t len; // length of slot in bytes
++
++ uint32_t write_ptr; // hardware causes this to advance
++ uint32_t read_ptr; // this module does the reading
++ int active; // is this slot in the hardware dma fifo?
++ uint32_t msgs_parsed; // count how many messages are in this slot
++ uint32_t msgs_released; // how many messages have been released
++ void *state; // connection state information
++ uint8_t ref_count[VCHI_MAX_SERVICES_PER_CONNECTION]; // reference count for slots held by services
++} RX_MSG_SLOTINFO_T;
++
++// The message driver no longer needs to know about the fields of RX_BULK_SLOTINFO_T - sort this out.
++// In particular, it mustn't use addr and len - they're the client buffer, but the message
++// driver will be tasked with sending the aligned core section.
++typedef struct rx_bulk_slotinfo_t {
++ struct rx_bulk_slotinfo_t *next;
++
++ VCOS_SEMAPHORE_T *blocking;
++
++ // needed by DMA
++ void *addr;
++ uint32_t len;
++
++ // needed for the callback
++ void *service;
++ void *handle;
++ VCHI_FLAGS_T flags;
++} RX_BULK_SLOTINFO_T;
++
++
++/* ----------------------------------------------------------------------
++ * each connection driver will have a pool of the following struct.
++ *
++ * the pool will be managed by vchi_qman_*
++ * this means there will be multiple queues (single linked lists)
++ * a given struct message_info will be on exactly one of these queues
++ * at any one time
++ * -------------------------------------------------------------------- */
++typedef struct rx_message_info {
++
++ struct message_info *next;
++ //struct message_info *prev;
++
++ uint8_t *addr;
++ uint32_t len;
++ RX_MSG_SLOTINFO_T *slot; // points to whichever slot contains this message
++ uint32_t tx_timestamp;
++ uint32_t rx_timestamp;
++
++} RX_MESSAGE_INFO_T;
++
++typedef struct {
++ MESSAGE_EVENT_TYPE_T type;
++
++ struct {
++ // for messages
++ void *addr; // address of message
++ uint16_t slot_delta; // whether this message indicated slot delta
++ uint32_t len; // length of message
++ RX_MSG_SLOTINFO_T *slot; // slot this message is in
++ vcos_fourcc_t service; // service id this message is destined for
++ uint32_t tx_timestamp; // timestamp from the header
++ uint32_t rx_timestamp; // timestamp when we parsed it
++ } message;
++
++ // FIXME: cleanup slot reporting...
++ RX_MSG_SLOTINFO_T *rx_msg;
++ RX_BULK_SLOTINFO_T *rx_bulk;
++ void *tx_handle;
++ MESSAGE_TX_CHANNEL_T tx_channel;
++
++} MESSAGE_EVENT_T;
++
++
++// callbacks
++typedef void VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T( void *state );
++
++typedef struct {
++ VCHI_MESSAGE_DRIVER_EVENT_CALLBACK_T *event_callback;
++} VCHI_MESSAGE_DRIVER_OPEN_T;
++
++
++// handle to this instance of message driver (as returned by ->open)
++typedef struct opaque_mhandle_t *VCHI_MDRIVER_HANDLE_T;
++
++struct opaque_vchi_message_driver_t {
++ VCHI_MDRIVER_HANDLE_T *(*open)( VCHI_MESSAGE_DRIVER_OPEN_T *params, void *state );
++ int32_t (*suspending)( VCHI_MDRIVER_HANDLE_T *handle );
++ int32_t (*resumed)( VCHI_MDRIVER_HANDLE_T *handle );
++ int32_t (*power_control)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T, vcos_bool_t enable );
++ int32_t (*add_msg_rx_slot)( VCHI_MDRIVER_HANDLE_T *handle, RX_MSG_SLOTINFO_T *slot ); // rx message
++ int32_t (*add_bulk_rx)( VCHI_MDRIVER_HANDLE_T *handle, void *data, uint32_t len, RX_BULK_SLOTINFO_T *slot ); // rx data (bulk)
++ int32_t (*send)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, VCHI_MSG_FLAGS_T flags, void *send_handle ); // tx (message & bulk)
++ void (*next_event)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_EVENT_T *event ); // get the next event from message_driver
++ int32_t (*enable)( VCHI_MDRIVER_HANDLE_T *handle );
++ int32_t (*form_message)( VCHI_MDRIVER_HANDLE_T *handle, vcos_fourcc_t service_id, VCHI_MSG_VECTOR_T *vector, uint32_t count, void
++ *address, uint32_t length_avail, uint32_t max_total_length, vcos_bool_t pad_to_fill, vcos_bool_t allow_partial );
++
++ int32_t (*update_message)( VCHI_MDRIVER_HANDLE_T *handle, void *dest, int16_t *slot_count );
++ int32_t (*buffer_aligned)( VCHI_MDRIVER_HANDLE_T *handle, int tx, int uncached, const void *address, const uint32_t length );
++ void * (*allocate_buffer)( VCHI_MDRIVER_HANDLE_T *handle, uint32_t *length );
++ void (*free_buffer)( VCHI_MDRIVER_HANDLE_T *handle, void *address );
++ int (*rx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
++ int (*tx_slot_size)( VCHI_MDRIVER_HANDLE_T *handle, int msg_size );
++
++ vcos_bool_t (*tx_supports_terminate)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
++ uint32_t (*tx_bulk_chunk_size)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
++ int (*tx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel );
++ int (*rx_alignment)( const VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_RX_CHANNEL_T channel );
++ void (*form_bulk_aux)( VCHI_MDRIVER_HANDLE_T *handle, MESSAGE_TX_CHANNEL_T channel, const void *data, uint32_t len, uint32_t chunk_size, const void **aux_data, int32_t *aux_len );
++ void (*debug)( VCHI_MDRIVER_HANDLE_T *handle );
++};
++
++
++#endif // _VCHI_MESSAGE_H_
++
++/****************************** End of file ***********************************/
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/vchi.h
+@@ -0,0 +1,347 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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
++ */
++
++/*=============================================================================
++Contains the protypes for the vchi functions.
++=============================================================================*/
++
++#ifndef VCHI_H_
++#define VCHI_H_
++
++#include "interface/vcos/vcos.h"
++#include "interface/vchi/vchi_cfg.h"
++#include "interface/vchi/vchi_common.h"
++#include "interface/vchi/connections/connection.h"
++#include "vchi_mh.h"
++
++
++/******************************************************************************
++ Global defs
++ *****************************************************************************/
++
++#define VCHI_BULK_ROUND_UP(x) ((((unsigned long)(x))+VCHI_BULK_ALIGN-1) & ~(VCHI_BULK_ALIGN-1))
++#define VCHI_BULK_ROUND_DOWN(x) (((unsigned long)(x)) & ~(VCHI_BULK_ALIGN-1))
++#define VCHI_BULK_ALIGN_NBYTES(x) (VCHI_BULK_ALIGNED(x) ? 0 : (VCHI_BULK_ALIGN - ((unsigned long)(x) & (VCHI_BULK_ALIGN-1))))
++
++#ifdef USE_VCHIQ_ARM
++#define VCHI_BULK_ALIGNED(x) 1
++#else
++#define VCHI_BULK_ALIGNED(x) (((unsigned long)(x) & (VCHI_BULK_ALIGN-1)) == 0)
++#endif
++
++
++typedef enum
++{
++ VCHI_VEC_POINTER,
++ VCHI_VEC_HANDLE,
++ VCHI_VEC_LIST
++} VCHI_MSG_VECTOR_TYPE_T;
++
++typedef struct vchi_msg_vector_ex {
++
++ VCHI_MSG_VECTOR_TYPE_T type;
++ union
++ {
++ // a memory handle
++ struct
++ {
++ VCHI_MEM_HANDLE_T handle;
++ uint32_t offset;
++ int32_t vec_len;
++ } handle;
++
++ // an ordinary data pointer
++ struct
++ {
++ const void *vec_base;
++ int32_t vec_len;
++ } ptr;
++
++ // a nested vector list
++ struct
++ {
++ struct vchi_msg_vector_ex *vec;
++ uint32_t vec_len;
++ } list;
++ } u;
++} VCHI_MSG_VECTOR_EX_T;
++
++
++// Construct an entry in a msg vector for a pointer (p) of length (l)
++#define VCHI_VEC_POINTER(p,l) VCHI_VEC_POINTER, { { (VCHI_MEM_HANDLE_T)(p), (l) } }
++
++// Construct an entry in a msg vector for a message handle (h), starting at offset (o) of length (l)
++#define VCHI_VEC_HANDLE(h,o,l) VCHI_VEC_HANDLE, { { (h), (o), (l) } }
++
++// Macros to manipulate fourcc_t values
++#define MAKE_FOURCC(x) ((fourcc_t)( (x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3] ))
++#define FOURCC_TO_CHAR(x) (x >> 24) & 0xFF,(x >> 16) & 0xFF,(x >> 8) & 0xFF, x & 0xFF
++
++
++// Opaque service information
++struct opaque_vchi_service_t;
++
++// Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold,
++// vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only.
++typedef struct
++{
++ struct opaque_vchi_service_t *service;
++ void *message;
++} VCHI_HELD_MSG_T;
++
++
++
++// structure used to provide the information needed to open a server or a client
++typedef struct {
++ vcos_fourcc_t service_id;
++ VCHI_CONNECTION_T *connection;
++ uint32_t rx_fifo_size;
++ uint32_t tx_fifo_size;
++ VCHI_CALLBACK_T callback;
++ void *callback_param;
++ vcos_bool_t want_unaligned_bulk_rx; // client intends to receive bulk transfers of odd lengths or into unaligned buffers
++ vcos_bool_t want_unaligned_bulk_tx; // client intends to transmit bulk transfers of odd lengths or out of unaligned buffers
++ vcos_bool_t want_crc; // client wants to check CRCs on (bulk) transfers. Only needs to be set at 1 end - will do both directions.
++} SERVICE_CREATION_T;
++
++// Opaque handle for a VCHI instance
++typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T;
++
++// Opaque handle for a server or client
++typedef struct opaque_vchi_service_handle_t *VCHI_SERVICE_HANDLE_T;
++
++// Service registration & startup
++typedef void (*VCHI_SERVICE_INIT)(VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections);
++
++typedef struct service_info_tag {
++ const char * const vll_filename; /* VLL to load to start this service. This is an empty string if VLL is "static" */
++ VCHI_SERVICE_INIT init; /* Service initialisation function */
++ void *vll_handle; /* VLL handle; NULL when unloaded or a "static VLL" in build */
++} SERVICE_INFO_T;
++
++/******************************************************************************
++ Global funcs - implementation is specific to which side you are on (local / remote)
++ *****************************************************************************/
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++extern /*@observer@*/ VCHI_CONNECTION_T * vchi_create_connection( const VCHI_CONNECTION_API_T * function_table,
++ const VCHI_MESSAGE_DRIVER_T * low_level);
++
++
++// Routine used to initialise the vchi on both local + remote connections
++extern int32_t vchi_initialise( VCHI_INSTANCE_T *instance_handle );
++
++extern int32_t vchi_exit( void );
++
++extern int32_t vchi_connect( VCHI_CONNECTION_T **connections,
++ const uint32_t num_connections,
++ VCHI_INSTANCE_T instance_handle );
++
++//When this is called, ensure that all services have no data pending.
++//Bulk transfers can remain 'queued'
++extern int32_t vchi_disconnect( VCHI_INSTANCE_T instance_handle );
++
++// Global control over bulk CRC checking
++extern int32_t vchi_crc_control( VCHI_CONNECTION_T *connection,
++ VCHI_CRC_CONTROL_T control );
++
++// helper functions
++extern void * vchi_allocate_buffer(VCHI_SERVICE_HANDLE_T handle, uint32_t *length);
++extern void vchi_free_buffer(VCHI_SERVICE_HANDLE_T handle, void *address);
++extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle);
++
++
++/******************************************************************************
++ Global service API
++ *****************************************************************************/
++// Routine to create a named service
++extern int32_t vchi_service_create( VCHI_INSTANCE_T instance_handle,
++ SERVICE_CREATION_T *setup,
++ VCHI_SERVICE_HANDLE_T *handle );
++
++// Routine to destory a service
++extern int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle );
++
++// Routine to open a named service
++extern int32_t vchi_service_open( VCHI_INSTANCE_T instance_handle,
++ SERVICE_CREATION_T *setup,
++ VCHI_SERVICE_HANDLE_T *handle);
++
++// Routine to close a named service
++extern int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle );
++
++// Routine to increment ref count on a named service
++extern int32_t vchi_service_use( const VCHI_SERVICE_HANDLE_T handle );
++
++// Routine to decrement ref count on a named service
++extern int32_t vchi_service_release( const VCHI_SERVICE_HANDLE_T handle );
++
++// Routine to send a message accross a service
++extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle,
++ const void *data,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *msg_handle );
++
++// scatter-gather (vector) and send message
++int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle,
++ VCHI_MSG_VECTOR_EX_T *vector,
++ uint32_t count,
++ VCHI_FLAGS_T flags,
++ void *msg_handle );
++
++// legacy scatter-gather (vector) and send message, only handles pointers
++int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle,
++ VCHI_MSG_VECTOR_T *vector,
++ uint32_t count,
++ VCHI_FLAGS_T flags,
++ void *msg_handle );
++
++// Routine to receive a msg from a service
++// Dequeue is equivalent to hold, copy into client buffer, release
++extern int32_t vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T handle,
++ void *data,
++ uint32_t max_data_size_to_read,
++ uint32_t *actual_msg_size,
++ VCHI_FLAGS_T flags );
++
++// Routine to look at a message in place.
++// The message is not dequeued, so a subsequent call to peek or dequeue
++// will return the same message.
++extern int32_t vchi_msg_peek( VCHI_SERVICE_HANDLE_T handle,
++ void **data,
++ uint32_t *msg_size,
++ VCHI_FLAGS_T flags );
++
++// Routine to remove a message after it has been read in place with peek
++// The first message on the queue is dequeued.
++extern int32_t vchi_msg_remove( VCHI_SERVICE_HANDLE_T handle );
++
++// Routine to look at a message in place.
++// The message is dequeued, so the caller is left holding it; the descriptor is
++// filled in and must be released when the user has finished with the message.
++extern int32_t vchi_msg_hold( VCHI_SERVICE_HANDLE_T handle,
++ void **data, // } may be NULL, as info can be
++ uint32_t *msg_size, // } obtained from HELD_MSG_T
++ VCHI_FLAGS_T flags,
++ VCHI_HELD_MSG_T *message_descriptor );
++
++// Initialise an iterator to look through messages in place
++extern int32_t vchi_msg_look_ahead( VCHI_SERVICE_HANDLE_T handle,
++ VCHI_MSG_ITER_T *iter,
++ VCHI_FLAGS_T flags );
++
++/******************************************************************************
++ Global service support API - operations on held messages and message iterators
++ *****************************************************************************/
++
++// Routine to get the address of a held message
++extern void *vchi_held_msg_ptr( const VCHI_HELD_MSG_T *message );
++
++// Routine to get the size of a held message
++extern int32_t vchi_held_msg_size( const VCHI_HELD_MSG_T *message );
++
++// Routine to get the transmit timestamp as written into the header by the peer
++extern uint32_t vchi_held_msg_tx_timestamp( const VCHI_HELD_MSG_T *message );
++
++// Routine to get the reception timestamp, written as we parsed the header
++extern uint32_t vchi_held_msg_rx_timestamp( const VCHI_HELD_MSG_T *message );
++
++// Routine to release a held message after it has been processed
++extern int32_t vchi_held_msg_release( VCHI_HELD_MSG_T *message );
++
++// Indicates whether the iterator has a next message.
++extern vcos_bool_t vchi_msg_iter_has_next( const VCHI_MSG_ITER_T *iter );
++
++// Return the pointer and length for the next message and advance the iterator.
++extern int32_t vchi_msg_iter_next( VCHI_MSG_ITER_T *iter,
++ void **data,
++ uint32_t *msg_size );
++
++// Remove the last message returned by vchi_msg_iter_next.
++// Can only be called once after each call to vchi_msg_iter_next.
++extern int32_t vchi_msg_iter_remove( VCHI_MSG_ITER_T *iter );
++
++// Hold the last message returned by vchi_msg_iter_next.
++// Can only be called once after each call to vchi_msg_iter_next.
++extern int32_t vchi_msg_iter_hold( VCHI_MSG_ITER_T *iter,
++ VCHI_HELD_MSG_T *message );
++
++// Return information for the next message, and hold it, advancing the iterator.
++extern int32_t vchi_msg_iter_hold_next( VCHI_MSG_ITER_T *iter,
++ void **data, // } may be NULL
++ uint32_t *msg_size, // }
++ VCHI_HELD_MSG_T *message );
++
++
++/******************************************************************************
++ Global bulk API
++ *****************************************************************************/
++
++// Routine to prepare interface for a transfer from the other side
++extern int32_t vchi_bulk_queue_receive( VCHI_SERVICE_HANDLE_T handle,
++ void *data_dst,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *transfer_handle );
++
++
++// Prepare interface for a transfer from the other side into relocatable memory.
++int32_t vchi_bulk_queue_receive_reloc( const VCHI_SERVICE_HANDLE_T handle,
++ VCHI_MEM_HANDLE_T h_dst,
++ uint32_t offset,
++ uint32_t data_size,
++ const VCHI_FLAGS_T flags,
++ void * const bulk_handle );
++
++// Routine to queue up data ready for transfer to the other (once they have signalled they are ready)
++extern int32_t vchi_bulk_queue_transmit( VCHI_SERVICE_HANDLE_T handle,
++ const void *data_src,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *transfer_handle );
++
++
++/******************************************************************************
++ Configuration plumbing
++ *****************************************************************************/
++
++// function prototypes for the different mid layers (the state info gives the different physical connections)
++extern const VCHI_CONNECTION_API_T *single_get_func_table( void );
++//extern const VCHI_CONNECTION_API_T *local_server_get_func_table( void );
++//extern const VCHI_CONNECTION_API_T *local_client_get_func_table( void );
++
++// declare all message drivers here
++const VCHI_MESSAGE_DRIVER_T *vchi_mphi_message_driver_func_table( void );
++
++#ifdef __cplusplus
++}
++#endif
++
++extern int32_t vchi_bulk_queue_transmit_reloc( VCHI_SERVICE_HANDLE_T handle,
++ VCHI_MEM_HANDLE_T h_src,
++ uint32_t offset,
++ uint32_t data_size,
++ VCHI_FLAGS_T flags,
++ void *transfer_handle );
++#endif /* VCHI_H_ */
++
++/****************************** End of file **********************************/
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h
+@@ -0,0 +1,214 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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
++ */
++
++/*=============================================================================
++Contains the #defines for the number of servers / clients etc, these can be
++over-ridden from the platform makefile if needed
++=============================================================================*/
++
++#ifndef VCHI_CFG_H_
++#define VCHI_CFG_H_
++
++/****************************************************************************************
++ * Defines in this first section are part of the VCHI API and may be examined by VCHI
++ * services.
++ ***************************************************************************************/
++
++/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */
++/* Really determined by the message driver, and should be available from a run-time call. */
++#ifndef VCHI_BULK_ALIGN
++# if __VCCOREVER__ >= 0x04000000
++# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans
++# else
++# define VCHI_BULK_ALIGN 16
++# endif
++#endif
++
++/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */
++/* May be less than or greater than VCHI_BULK_ALIGN */
++/* Really determined by the message driver, and should be available from a run-time call. */
++#ifndef VCHI_BULK_GRANULARITY
++# if __VCCOREVER__ >= 0x04000000
++# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans
++# else
++# define VCHI_BULK_GRANULARITY 16
++# endif
++#endif
++
++/* The largest possible message to be queued with vchi_msg_queue. */
++#ifndef VCHI_MAX_MSG_SIZE
++# if defined VCHI_LOCAL_HOST_PORT
++# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk?
++# else
++# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!!
++# endif
++#endif
++
++/******************************************************************************************
++ * Defines below are system configuration options, and should not be used by VCHI services.
++ *****************************************************************************************/
++
++/* How many connections can we support? A localhost implementation uses 2 connections,
++ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW
++ * driver. */
++#ifndef VCHI_MAX_NUM_CONNECTIONS
++# define VCHI_MAX_NUM_CONNECTIONS 3
++#endif
++
++/* How many services can we open per connection? Extending this doesn't cost processing time, just a small
++ * amount of static memory. */
++#ifndef VCHI_MAX_SERVICES_PER_CONNECTION
++# define VCHI_MAX_SERVICES_PER_CONNECTION 36
++#endif
++
++/* Adjust if using a message driver that supports more logical TX channels */
++#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION
++# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels
++#endif
++
++/* Adjust if using a message driver that supports more logical RX channels */
++#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION
++# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI
++#endif
++
++/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective
++ * receive queue space, less message headers. */
++#ifndef VCHI_NUM_READ_SLOTS
++# if defined(VCHI_LOCAL_HOST_PORT)
++# define VCHI_NUM_READ_SLOTS 4
++# else
++# define VCHI_NUM_READ_SLOTS 48
++# endif
++#endif
++
++/* Do we utilise overrun facility for receive message slots? Can aid peer transmit
++ * performance. Only define on VideoCore end, talking to host.
++ */
++//#define VCHI_MSG_RX_OVERRUN
++
++/* How many transmit slots do we use. Generally don't need many, as the hardware driver
++ * underneath VCHI will usually have its own buffering. */
++#ifndef VCHI_NUM_WRITE_SLOTS
++# define VCHI_NUM_WRITE_SLOTS 4
++#endif
++
++/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots,
++ * then it's taking up too much buffer space, and the peer service will be told to stop
++ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS
++ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency
++ * is too high. */
++#ifndef VCHI_XOFF_THRESHOLD
++# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2)
++#endif
++
++/* After we've sent an XOFF, the peer will be told to resume transmission once the local
++ * service has dequeued/released enough messages that it's now occupying
++ * VCHI_XON_THRESHOLD slots or fewer. */
++#ifndef VCHI_XON_THRESHOLD
++# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4)
++#endif
++
++/* A size below which a bulk transfer omits the handshake completely and always goes
++ * via the message channel, if bulk auxiliary is being sent on that service. (The user
++ * can guarantee this by enabling unaligned transmits).
++ * Not API. */
++#ifndef VCHI_MIN_BULK_SIZE
++# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 )
++#endif
++
++/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between
++ * speed and latency; the smaller the chunk size the better change of messages and other
++ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not
++ * break transmissions into chunks.
++ */
++#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI
++# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024)
++#endif
++
++/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode
++ * with multiple-line frames. Only use if the receiver can cope. */
++#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2
++# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0
++#endif
++
++/* How many TX messages can we have pending in our transmit slots. Once exhausted,
++ * vchi_msg_queue will be blocked. */
++#ifndef VCHI_TX_MSG_QUEUE_SIZE
++# define VCHI_TX_MSG_QUEUE_SIZE 256
++#endif
++
++/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing
++ * will be suspended until older messages are dequeued/released. */
++#ifndef VCHI_RX_MSG_QUEUE_SIZE
++# define VCHI_RX_MSG_QUEUE_SIZE 256
++#endif
++
++/* Really should be able to cope if we run out of received message descriptors, by
++ * suspending parsing as the comment above says, but we don't. This sweeps the issue
++ * under the carpet. */
++#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
++# undef VCHI_RX_MSG_QUEUE_SIZE
++# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS
++#endif
++
++/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit
++ * will be blocked. */
++#ifndef VCHI_TX_BULK_QUEUE_SIZE
++# define VCHI_TX_BULK_QUEUE_SIZE 64
++#endif
++
++/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive
++ * will be blocked. */
++#ifndef VCHI_RX_BULK_QUEUE_SIZE
++# define VCHI_RX_BULK_QUEUE_SIZE 64
++#endif
++
++/* A limit on how many outstanding bulk requests we expect the peer to give us. If
++ * the peer asks for more than this, VCHI will fail and assert. The number is determined
++ * by the peer's hardware - it's the number of outstanding requests that can be queued
++ * on all bulk channels. VC3's MPHI peripheral allows 16. */
++#ifndef VCHI_MAX_PEER_BULK_REQUESTS
++# define VCHI_MAX_PEER_BULK_REQUESTS 32
++#endif
++
++/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2
++ * transmitter on and off.
++ */
++/*#define VCHI_CCP2TX_MANUAL_POWER*/
++
++#ifndef VCHI_CCP2TX_MANUAL_POWER
++
++/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set
++ * negative for no IDLE.
++ */
++# ifndef VCHI_CCP2TX_IDLE_TIMEOUT
++# define VCHI_CCP2TX_IDLE_TIMEOUT 5
++# endif
++
++/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set
++ * negative for no OFF.
++ */
++# ifndef VCHI_CCP2TX_OFF_TIMEOUT
++# define VCHI_CCP2TX_OFF_TIMEOUT 1000
++# endif
++
++#endif /* VCHI_CCP2TX_MANUAL_POWER */
++
++#endif /* VCHI_CFG_H_ */
++
++/****************************** End of file **********************************/
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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 VCHI_CFG_INTERNAL_H_
++#define VCHI_CFG_INTERNAL_H_
++
++/****************************************************************************************
++ * Control optimisation attempts.
++ ***************************************************************************************/
++
++// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second
++#define VCHI_COARSE_LOCKING
++
++// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx)
++// (only relevant if VCHI_COARSE_LOCKING)
++#define VCHI_ELIDE_BLOCK_EXIT_LOCK
++
++// Avoid lock on non-blocking peek
++// (only relevant if VCHI_COARSE_LOCKING)
++#define VCHI_AVOID_PEEK_LOCK
++
++// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation.
++#define VCHI_MULTIPLE_HANDLER_THREADS
++
++// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash
++// our way through the pool of descriptors.
++#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD
++
++// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING.
++#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS
++
++// Don't use message descriptors for TX messages that don't need them
++#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS
++
++// Nano-locks for multiqueue
++//#define VCHI_MQUEUE_NANOLOCKS
++
++// Lock-free(er) dequeuing
++//#define VCHI_RX_NANOLOCKS
++
++#endif /*VCHI_CFG_INTERNAL_H_*/
+--- /dev/null
++++ b/drivers/misc/vc04_services/interface/vchi/vchi_common.h
+@@ -0,0 +1,152 @@
++/*
++ * Copyright (c) 2010-2011 Broadcom Corporation. 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
++ */
++
++/*=============================================================================
++Contains global defs used by submodules within vchi.
++=============================================================================*/
++
++#ifndef VCHI_COMMON_H_
++#define VCHI_COMMON_H_
++
++
++//flags used when sending messages (must be bitmapped)
++typedef enum
++{
++ VCHI_FLAGS_NONE = 0x0,
++ VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side)
++ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go
++ VCHI_FLAGS_ALLOW_PARTIAL = 0x8,
++ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10,
++ VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20,
++
++ VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only
++ VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only
++ VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only
++ VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only
++ VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only
++ VCHI_FLAGS_INTERNAL = 0xFF0000
++} VCHI_FLAGS_T;
++
++// constants for vchi_crc_control()
++typedef enum {
++ VCHI_CRC_NOTHING = -1,
++ VCHI_CRC_PER_SERVICE = 0,
++ VCHI_CRC_EVERYTHING = 1,
++} VCHI_CRC_CONTROL_T;
++
++//callback reasons when an event occurs on a service
++typedef enum
++{
++ VCHI_CALLBACK_REASON_MIN,
++
++ //This indicates that there is data available
++ //handle is the msg id that was transmitted with the data
++ // When a message is received and there was no FULL message available previously, send callback
++ // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails
++ VCHI_CALLBACK_MSG_AVAILABLE,
++ VCHI_CALLBACK_MSG_SENT,
++ VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented
++
++ // This indicates that a transfer from the other side has completed
++ VCHI_CALLBACK_BULK_RECEIVED,
++ //This indicates that data queued up to be sent has now gone
++ //handle is the msg id that was used when sending the data
++ VCHI_CALLBACK_BULK_SENT,
++ VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented
++ VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented
++
++ VCHI_CALLBACK_SERVICE_CLOSED,
++
++ // this side has sent XOFF to peer due to lack of data consumption by service
++ // (suggests the service may need to take some recovery action if it has
++ // been deliberately holding off consuming data)
++ VCHI_CALLBACK_SENT_XOFF,
++ VCHI_CALLBACK_SENT_XON,
++
++ // indicates that a bulk transfer has finished reading the source buffer
++ VCHI_CALLBACK_BULK_DATA_READ,
++
++ // power notification events (currently host side only)
++ VCHI_CALLBACK_PEER_OFF,
++ VCHI_CALLBACK_PEER_SUSPENDED,
++ VCHI_CALLBACK_PEER_ON,
++ VCHI_CALLBACK_PEER_RESUMED,
++ VCHI_CALLBACK_FORCED_POWER_OFF,
++
++#ifdef USE_VCHIQ_ARM
++ // some extra notifications provided by vchiq_arm
++ VCHI_CALLBACK_SERVICE_OPENED,
++ VCHI_CALLBACK_BULK_RECEIVE_ABORTED,
++ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED,
++#endif
++
++ VCHI_CALLBACK_REASON_MAX
++} VCHI_CALLBACK_REASON_T;
++
++//Calback used by all services / bulk transfers
++typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param
++ VCHI_CALLBACK_REASON_T reason,
++ void *handle ); //for transmitting msg's only
++
++
++
++/*
++ * Define vector struct for scatter-gather (vector) operations
++ * Vectors can be nested - if a vector element has negative length, then
++ * the data pointer is treated as pointing to another vector array, with
++ * '-vec_len' elements. Thus to append a header onto an existing vector,
++ * you can do this:
++ *
++ * void foo(const VCHI_MSG_VECTOR_T *v, int n)
++ * {
++ * VCHI_MSG_VECTOR_T nv[2];
++ * nv[0].vec_base = my_header;
++ * nv[0].vec_len = sizeof my_header;
++ * nv[1].vec_base = v;
++ * nv[1].vec_len = -n;
++ * ...
++ *
++ */
++typedef struct vchi_msg_vector {
++ const void *vec_base;
++ int32_t vec_len;
++} VCHI_MSG_VECTOR_T;
++
++// Opaque type for a connection API
++typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T;
++
++// Opaque type for a message driver
++typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T;
++
++
++// Iterator structure for reading ahead through received message queue. Allocated by client,
++// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only.
++// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead -
++// will not proceed to messages received since. Behaviour is undefined if an iterator
++// is used again after messages for that service are removed/dequeued by any
++// means other than vchi_msg_iter_... calls on the iterator itself.
++typedef struct {
++ struct opaque_vchi_service_t *service;
++ void *last;
++ void *next;
++ void *remove;
++} VCHI_MSG_ITER_T;
++
++
++#endif // VCHI_COMMON_H_
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+@@ -36,7 +36,7 @@
+ #define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32)
+
+ #define VCHIQ_DOORBELL_IRQ IRQ_ARM_DOORBELL_0
+-#define VCHIQ_ARM_ADDRESS(x) __virt_to_bus(x)
++#define VCHIQ_ARM_ADDRESS(x) ((void *)__virt_to_bus((unsigned)x))
+
+ #include "vchiq_arm.h"
+ #include "vchiq_2835.h"
+@@ -182,7 +182,15 @@ remote_event_signal(REMOTE_EVENT_T *even
+ int
+ vchiq_copy_from_user(void *dst, const void *src, int size)
+ {
+- return copy_from_user(dst, src, size);
++ if ( (uint32_t)src < TASK_SIZE)
++ {
++ return copy_from_user(dst, src, size);
++ }
++ else
++ {
++ memcpy( dst, src, size );
++ return 0;
++ }
+ }
+
+ VCHIQ_STATUS_T
+@@ -239,6 +247,22 @@ vchiq_dump_platform_state(void *dump_con
+ vchiq_dump(dump_context, buf, len + 1);
+ }
+
++VCHIQ_STATUS_T
++vchiq_platform_suspend(VCHIQ_STATE_T *state)
++{
++ vcos_unused(state);
++ vcos_assert_msg(0, "Suspend/resume not supported");
++ return VCHIQ_ERROR;
++}
++
++VCHIQ_STATUS_T
++vchiq_platform_resume(VCHIQ_STATE_T *state)
++{
++ vcos_unused(state);
++ vcos_assert_msg(0, "Suspend/resume not supported");
++ return VCHIQ_ERROR;
++}
++
+ void
+ vchiq_platform_paused(VCHIQ_STATE_T *state)
+ {
+@@ -253,33 +277,40 @@ vchiq_platform_resumed(VCHIQ_STATE_T *st
+ vcos_assert_msg(0, "Suspend/resume not supported");
+ }
+
+-VCHIQ_STATUS_T
+-vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)
++int
++vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state)
+ {
+- VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+- if (!service)
+- return VCHIQ_ERROR;
+- return VCHIQ_SUCCESS;
++ vcos_unused(state);
++ return 1; // autosuspend not supported - videocore always wanted
+ }
+
+-VCHIQ_STATUS_T
+-vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle)
++#if VCOS_HAVE_TIMER
++int
++vchiq_platform_use_suspend_timer(void)
+ {
+- VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+- if (!service)
+- return VCHIQ_ERROR;
+- return VCHIQ_SUCCESS;
++ return 0;
++}
++#endif
++void
++vchiq_dump_platform_use_state(VCHIQ_STATE_T *state)
++{
++ vcos_unused(state);
+ }
+
+ VCHIQ_STATUS_T
+-vchiq_check_service(VCHIQ_SERVICE_HANDLE_T handle)
++vchiq_platform_init_state(VCHIQ_STATE_T *state)
+ {
+- VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+- if (!service)
+- return VCHIQ_ERROR;
++ vcos_unused(state);
+ return VCHIQ_SUCCESS;
+ }
+
++VCHIQ_ARM_STATE_T*
++vchiq_platform_get_arm_state(VCHIQ_STATE_T *state)
++{
++ vcos_unused(state);
++ return NULL;
++}
++
+ /*
+ * Local functions
+ */
+@@ -479,9 +510,3 @@ free_pagelist(PAGELIST_T *pagelist, int
+ kfree(pagelist);
+ }
+
+-VCHIQ_STATUS_T
+-vchiq_platform_suspend(VCHIQ_STATE_T *state)
+-{
+- vcos_unused(state);
+- return VCHIQ_ERROR;
+-}
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
+@@ -23,6 +23,9 @@
+ #include <linux/cdev.h>
+ #include <linux/fs.h>
+ #include <linux/device.h>
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/pagemap.h>
+
+ #include "vchiq_core.h"
+ #include "vchiq_ioctl.h"
+@@ -44,6 +47,15 @@
+
+ #define VCOS_LOG_CATEGORY (&vchiq_arm_log_category)
+
++#define VCHIQ_ARM_VCSUSPEND_TASK_STACK 4096
++
++#if VCOS_HAVE_TIMER
++#define SUSPEND_TIMER_TIMEOUT_MS 100
++static VCOS_TIMER_T g_suspend_timer;
++static void suspend_timer_callback(void *context);
++#endif
++
++
+ typedef struct client_service_struct {
+ VCHIQ_SERVICE_T *service;
+ void *userdata;
+@@ -106,10 +118,17 @@ static const char *ioctl_names[] =
+ "GET_CONFIG",
+ "CLOSE_SERVICE",
+ "USE_SERVICE",
+- "RELEASE_SERIVCE"
++ "RELEASE_SERVICE",
++ "SET_SERVICE_OPTION",
++ "DUMP_PHYS_MEM"
+ };
+
+-VCOS_LOG_LEVEL_T vchiq_default_arm_log_level = VCOS_LOG_WARN;
++vcos_static_assert(vcos_countof(ioctl_names) == (VCHIQ_IOC_MAX + 1));
++
++VCOS_LOG_LEVEL_T vchiq_default_arm_log_level = VCOS_LOG_ERROR;
++
++static void
++dump_phys_mem( void *virt_addr, uint32_t num_bytes );
+
+ /****************************************************************************
+ *
+@@ -118,7 +137,7 @@ VCOS_LOG_LEVEL_T vchiq_default_arm_log_l
+ ***************************************************************************/
+
+ static inline USER_SERVICE_T *find_service_by_handle(
+- VCHIQ_INSTANCE_T instance, int handle )
++ VCHIQ_INSTANCE_T instance, int handle )
+ {
+ USER_SERVICE_T *user_service;
+
+@@ -524,7 +543,7 @@ vchiq_ioctl(struct file *file, unsigned
+ status = (cmd == VCHIQ_IOC_USE_SERVICE) ? vchiq_use_service(&user_service->service->base) : vchiq_release_service(&user_service->service->base);
+ if (status != VCHIQ_SUCCESS)
+ {
+- ret = -EINVAL; // ???
++ ret = -EINVAL; /* ??? */
+ }
+ }
+ }
+@@ -872,6 +891,21 @@ vchiq_ioctl(struct file *file, unsigned
+ }
+ break;
+
++ case VCHIQ_IOC_DUMP_PHYS_MEM:
++ {
++ VCHIQ_DUMP_MEM_T args;
++
++ if (copy_from_user
++ (&args, (const void __user *)arg,
++ sizeof(args)) != 0) {
++ ret = -EFAULT;
++ break;
++ }
++ dump_phys_mem( args.virt_addr, args.num_bytes );
++ }
++ break;
++
++
+ default:
+ ret = -ENOTTY;
+ break;
+@@ -1060,7 +1094,7 @@ vchiq_dump(void *dump_context, const cha
+ char cr = '\n';
+ if (copy_to_user(context->buf + context->actual - 1, &cr, 1))
+ {
+- context->actual = -EFAULT;
++ context->actual = -EFAULT;
+ }
+ }
+ }
+@@ -1153,6 +1187,88 @@ vchiq_dump_platform_service_state(void *
+
+ /****************************************************************************
+ *
++* dump_user_mem
++*
++***************************************************************************/
++
++static void
++dump_phys_mem( void *virt_addr, uint32_t num_bytes )
++{
++ int rc;
++ uint8_t *end_virt_addr = virt_addr + num_bytes;
++ int num_pages;
++ int offset;
++ int end_offset;
++ int page_idx;
++ int prev_idx;
++ struct page *page;
++ struct page **pages;
++ uint8_t *kmapped_virt_ptr;
++
++ // Align virtAddr and endVirtAddr to 16 byte boundaries.
++
++ virt_addr = (void *)((unsigned long)virt_addr & ~0x0fuL );
++ end_virt_addr = (void *)(( (unsigned long)end_virt_addr + 15uL ) & ~0x0fuL);
++
++ offset = (int)(long)virt_addr & ( PAGE_SIZE - 1 );
++ end_offset = (int)(long)end_virt_addr & ( PAGE_SIZE - 1 );
++
++ num_pages = (offset + num_bytes + PAGE_SIZE - 1) / PAGE_SIZE;
++
++ if (( pages = kmalloc( sizeof( struct page *) * num_pages, GFP_KERNEL )) == NULL )
++ {
++ printk( KERN_ERR "Unable to allocation memory for %d pages\n", num_pages );
++ return;
++ }
++
++ down_read( &current->mm->mmap_sem );
++ rc = get_user_pages( current, /* task */
++ current->mm, /* mm */
++ (unsigned long)virt_addr, /* start */
++ num_pages, /* len */
++ 0, /* write */
++ 0, /* force */
++ pages, /* pages (array of pointers to page) */
++ NULL ); /* vmas */
++ up_read( &current->mm->mmap_sem );
++
++ prev_idx = -1;
++ page = NULL;
++
++ while ( offset < end_offset ) {
++
++ int page_offset = offset % PAGE_SIZE;
++ page_idx = offset / PAGE_SIZE;
++
++ if ( page_idx != prev_idx ) {
++
++ if (page != NULL) {
++ kunmap( page );
++ }
++ page = pages[page_idx];
++ kmapped_virt_ptr = kmap( page );
++
++ prev_idx = page_idx;
++ }
++
++ vcos_log_dump_mem_impl( &vchiq_arm_log_category, "ph",
++ (uint32_t)(unsigned long)&kmapped_virt_ptr[page_offset],
++ &kmapped_virt_ptr[page_offset], 16 );
++
++ offset += 16;
++ }
++ if (page != NULL) {
++ kunmap( page );
++ }
++
++ for ( page_idx = 0; page_idx < num_pages; page_idx++ ) {
++ page_cache_release( pages[page_idx] );
++ }
++ kfree( pages );
++}
++
++/****************************************************************************
++*
+ * vchiq_read
+ *
+ ***************************************************************************/
+@@ -1204,6 +1320,505 @@ vchiq_fops = {
+ .read = vchiq_read
+ };
+
++/*
++ * Autosuspend related functionality
++ */
++
++static int vchiq_videocore_wanted(VCHIQ_STATE_T* state)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ if(!arm_state)
++ { // autosuspend not supported - always return wanted
++ return 1;
++ }
++ else if(!arm_state->videocore_use_count)
++ { // usage count zero - check for override
++ return vchiq_platform_videocore_wanted(state);
++ }
++ else
++ { // non-zero usage count - videocore still required
++ return 1;
++ }
++}
++
++
++/* Called by the lp thread */
++static void *
++lp_func(void *v)
++{
++ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++
++ while (1) {
++ vcos_event_wait(&arm_state->lp_evt);
++
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++ if (!vchiq_videocore_wanted(state))
++ {
++ arm_state->suspend_pending = 1;
++ }
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++
++ vchiq_arm_vcsuspend(state);
++ }
++ return NULL;
++}
++/* Called by the hp thread */
++static void *
++hp_func(void *v)
++{
++ VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ int send_pending;
++
++ while (1) {
++ vcos_event_wait(&arm_state->hp_evt);
++
++ send_pending = 0;
++
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++ if (vchiq_videocore_wanted(state))
++ {
++ vchiq_arm_vcresume(state);
++ }
++ if(arm_state->use_notify_pending)
++ {
++ send_pending = arm_state->use_notify_pending;
++ arm_state->use_notify_pending=0;
++ }
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++ while(send_pending--)
++ {
++ vcos_log_info( "%s sending VCHIQ_MSG_REMOTE_USE_ACTIVE", __func__);
++ if ( vchiq_send_remote_use_active(state) != VCHIQ_SUCCESS)
++ {
++ BUG(); /* vc should be resumed, so shouldn't be a problem sending message */
++ }
++ }
++ }
++ return NULL;
++}
++
++VCHIQ_STATUS_T
++vchiq_arm_init_state(VCHIQ_STATE_T* state, VCHIQ_ARM_STATE_T *arm_state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
++ VCOS_THREAD_ATTR_T attrs;
++ char threadname[10];
++
++ if(arm_state)
++ {
++ vcos_mutex_create(&arm_state->use_count_mutex, "v.use_count_mutex");
++ vcos_mutex_create(&arm_state->suspend_resume_mutex, "v.susp_res_mutex");
++
++ vcos_event_create(&arm_state->lp_evt, "LP_EVT");
++ vcos_event_create(&arm_state->hp_evt, "HP_EVT");
++
++ vcos_thread_attr_init(&attrs);
++ vcos_thread_attr_setstacksize(&attrs, VCHIQ_ARM_VCSUSPEND_TASK_STACK);
++ vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_LOWEST);
++ vcos_snprintf(threadname, sizeof(threadname), "VCHIQl-%d", state->id);
++ if(vcos_thread_create(&arm_state->lp_thread, threadname, &attrs, lp_func, state) != VCOS_SUCCESS)
++ {
++ vcos_log_error("vchiq: FATAL: couldn't create thread %s", threadname);
++ status = VCHIQ_ERROR;
++ }
++ else
++ {
++ vcos_thread_attr_init(&attrs);
++ vcos_thread_attr_setstacksize(&attrs, VCHIQ_ARM_VCSUSPEND_TASK_STACK);
++ vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_HIGHEST);
++ vcos_snprintf(threadname, sizeof(threadname), "VCHIQh-%d", state->id);
++
++ if(vcos_thread_create(&arm_state->hp_thread, threadname, &attrs, hp_func, state) != VCOS_SUCCESS)
++ {
++ vcos_log_error("vchiq: FATAL: couldn't create thread %s", threadname);
++ status = VCHIQ_ERROR;
++ }
++ }
++ }
++ return status;
++}
++
++
++VCHIQ_STATUS_T
++vchiq_arm_vcsuspend(VCHIQ_STATE_T *state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++
++ if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED)
++ return VCHIQ_ERROR;
++
++ if(arm_state->suspend_pending)
++ {
++ vcos_mutex_lock(&arm_state->suspend_resume_mutex);
++ if(arm_state->videocore_suspended)
++ {
++ vcos_log_info("%s - already suspended", __func__);
++ }
++ else
++ {
++ vcos_log_info("%s - suspending", __func__);
++
++ status = vchiq_platform_suspend(state);
++ arm_state->videocore_suspended = (status == VCHIQ_SUCCESS) ? 1 : 0;
++
++ vcos_mutex_unlock(&arm_state->suspend_resume_mutex);
++
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++ if(!arm_state->suspend_pending)
++ { /* Something has changed the suspend_pending state while we were suspending.
++ Run the HP task to check if we need to resume */
++ vcos_log_info( "%s trigger HP task to check resume", __func__);
++ vcos_event_signal(&arm_state->hp_evt);
++ }
++ arm_state->suspend_pending = 0;
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++ }
++ }
++ else
++ {
++ vchiq_check_resume(state);
++ }
++ return status;
++}
++
++
++VCHIQ_STATUS_T
++vchiq_arm_vcresume(VCHIQ_STATE_T *state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ vcos_mutex_lock(&arm_state->suspend_resume_mutex);
++
++ status = vchiq_platform_resume(state);
++ arm_state->videocore_suspended = (status == VCHIQ_RETRY) ? 1 : 0;
++
++ vcos_mutex_unlock(&arm_state->suspend_resume_mutex);
++
++ return status;
++}
++
++void
++vchiq_check_resume(VCHIQ_STATE_T* state)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++
++ if (arm_state->videocore_suspended && vchiq_videocore_wanted(state))
++ { /* signal high priority task to resume vc */
++ vcos_event_signal(&arm_state->hp_evt);
++ }
++
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++}
++
++void
++vchiq_check_suspend(VCHIQ_STATE_T* state)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++
++ if (!arm_state->videocore_suspended && !vchiq_videocore_wanted(state))
++ { /* signal low priority task to suspend vc */
++ vcos_event_signal(&arm_state->lp_evt);
++ }
++
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++}
++
++
++
++static VCHIQ_STATUS_T
++vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int block_while_resume)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;
++ char entity[10];
++ int* entity_uc;
++
++ if(arm_state)
++ {
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++
++ if (service)
++ {
++ sprintf(entity, "%c%c%c%c:%03d",VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), service->client_id);
++ entity_uc = &service->service_use_count;
++ }
++ else
++ {
++ sprintf(entity, "PEER: ");
++ entity_uc = &arm_state->peer_use_count;
++ }
++
++ if (!arm_state->videocore_suspended && !vchiq_videocore_wanted(state))
++ {
++#if VCOS_HAVE_TIMER
++ if (vchiq_platform_use_suspend_timer())
++ {
++ vcos_log_trace( "%s %s - cancel suspend timer", __func__, entity);
++ }
++ vcos_timer_cancel(&g_suspend_timer);
++#endif
++ }
++
++ arm_state->videocore_use_count++;
++ (*entity_uc)++;
++ arm_state->suspend_pending = 0;
++
++ if (arm_state->videocore_suspended && vchiq_videocore_wanted(state))
++ {
++ vcos_log_info( "%s %s count %d, state count %d", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ if(block_while_resume)
++ {
++ ret = vchiq_arm_vcresume(state);
++ }
++ else
++ {
++ vcos_log_info( "%s trigger HP task to do resume", __func__); /* triggering is done below */
++ }
++ }
++ else
++ {
++ vcos_log_trace( "%s %s count %d, state count %d", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ }
++ if(!block_while_resume)
++ {
++ arm_state->use_notify_pending++;
++ vcos_event_signal(&arm_state->hp_evt); /* hp task will check if we need to resume and also send use notify */
++ }
++
++ if (ret == VCHIQ_RETRY)
++ { /* if we're told to retry, decrement the counters. VCHIQ_ERROR probably means we're already resumed. */
++ (*entity_uc)--;
++ arm_state->videocore_use_count--;
++ }
++
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++ }
++ return ret;
++}
++
++static VCHIQ_STATUS_T
++vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ VCHIQ_STATUS_T ret = VCHIQ_SUCCESS;
++ char entity[10];
++ int* entity_uc;
++
++ if(arm_state)
++ {
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++
++ if (service)
++ {
++ sprintf(entity, "%c%c%c%c:%03d",VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), service->client_id);
++ entity_uc = &service->service_use_count;
++ }
++ else
++ {
++ sprintf(entity, "PEER: ");
++ entity_uc = &arm_state->peer_use_count;
++ }
++
++ if (*entity_uc && arm_state->videocore_use_count)
++ {
++ arm_state->videocore_use_count--;
++ (*entity_uc)--;
++
++ if (!vchiq_videocore_wanted(state))
++ {
++#if VCOS_HAVE_TIMER
++ if (vchiq_platform_use_suspend_timer())
++ {
++ vcos_log_trace( "%s %s count %d, state count %d - starting suspend timer", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ vcos_timer_cancel(&g_suspend_timer);
++ vcos_timer_set(&g_suspend_timer, SUSPEND_TIMER_TIMEOUT_MS);
++ }
++ else
++#endif
++ {
++ vcos_log_info( "%s %s count %d, state count %d - suspend pending", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ vcos_event_signal(&arm_state->lp_evt); /* kick the lp thread to do the suspend */
++ }
++ }
++ else
++ {
++ vcos_log_trace( "%s %s count %d, state count %d", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ }
++ }
++ else
++ {
++ vcos_log_error( "%s %s ERROR releasing service; count %d, state count %d", __func__, entity, *entity_uc, arm_state->videocore_use_count);
++ ret = VCHIQ_ERROR;
++ }
++
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++ }
++ return ret;
++}
++
++VCHIQ_STATUS_T
++vchiq_on_remote_use(VCHIQ_STATE_T *state)
++{
++ vcos_log_info("%s state %p", __func__, state);
++ return state ? vchiq_use_internal(state, NULL, 0) : VCHIQ_ERROR;
++}
++
++VCHIQ_STATUS_T
++vchiq_on_remote_release(VCHIQ_STATE_T *state)
++{
++ vcos_log_info("%s state %p", __func__, state);
++ return state ? vchiq_release_internal(state, NULL) : VCHIQ_ERROR;
++}
++
++VCHIQ_STATUS_T
++vchiq_use_service_internal(VCHIQ_SERVICE_T *service)
++{
++ VCHIQ_STATE_T* state = NULL;
++
++ if (service)
++ {
++ state = service->state;
++ }
++
++ if (!service || !state)
++ {
++ return VCHIQ_ERROR;
++ }
++ return vchiq_use_internal(state, service, 1);
++}
++
++VCHIQ_STATUS_T
++vchiq_release_service_internal(VCHIQ_SERVICE_T *service)
++{
++ VCHIQ_STATE_T* state = NULL;
++
++ if (service)
++ {
++ state = service->state;
++ }
++
++ if (!service || !state)
++ {
++ return VCHIQ_ERROR;
++ }
++ return vchiq_release_internal(state, service);
++}
++
++
++#if VCOS_HAVE_TIMER
++static void suspend_timer_callback(void* context)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state((VCHIQ_STATE_T*)context);
++ vcos_log_info( "%s - suspend pending", __func__);
++ vcos_event_signal(&arm_state->lp_evt);
++}
++#endif
++
++VCHIQ_STATUS_T
++vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle)
++{
++ VCHIQ_STATUS_T ret = VCHIQ_ERROR;
++ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
++ if (service)
++ {
++ ret = vchiq_use_service_internal(service);
++ }
++ return ret;
++}
++
++VCHIQ_STATUS_T
++vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle)
++{
++ VCHIQ_STATUS_T ret = VCHIQ_ERROR;
++ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
++ if (service)
++ {
++ ret = vchiq_release_service_internal(service);
++ }
++ return ret;
++}
++
++void
++vchiq_dump_service_use_state(VCHIQ_STATE_T *state)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state);
++ int i;
++ if(arm_state)
++ {
++ vcos_mutex_lock(&arm_state->suspend_resume_mutex);
++ if (arm_state->videocore_suspended)
++ {
++ vcos_log_warn("--VIDEOCORE SUSPENDED--");
++ }
++ else
++ {
++ vcos_log_warn("--VIDEOCORE AWAKE--");
++ }
++ for (i = 0; i < state->unused_service; i++) {
++ VCHIQ_SERVICE_T *service_ptr = state->services[i];
++ if (service_ptr && (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE))
++ {
++ if (service_ptr->service_use_count)
++ vcos_log_error("----- %c%c%c%c:%d service count %d <-- preventing suspend", VCHIQ_FOURCC_AS_4CHARS(service_ptr->base.fourcc), service_ptr->client_id, service_ptr->service_use_count);
++ else
++ vcos_log_warn("----- %c%c%c%c:%d service count 0", VCHIQ_FOURCC_AS_4CHARS(service_ptr->base.fourcc), service_ptr->client_id);
++ }
++ }
++ vcos_log_warn("----- PEER use count count %d", arm_state->peer_use_count);
++ vcos_log_warn("--- Overall vchiq instance use count %d", arm_state->videocore_use_count);
++
++ vchiq_dump_platform_use_state(state);
++
++ vcos_mutex_unlock(&arm_state->suspend_resume_mutex);
++ }
++}
++
++VCHIQ_STATUS_T
++vchiq_check_service(VCHIQ_SERVICE_T * service)
++{
++ VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(service->state);
++ VCHIQ_STATUS_T ret = VCHIQ_ERROR;
++ /* on 2835 vchiq does not have an arm_state */
++ if (!arm_state)
++ return VCHIQ_SUCCESS;
++ if (service && arm_state)
++ {
++ vcos_mutex_lock(&arm_state->use_count_mutex);
++ if (!service->service_use_count)
++ {
++ vcos_log_error( "%s ERROR - %c%c%c%c:%d service count %d, state count %d, videocore_suspended %d", __func__,VCHIQ_FOURCC_AS_4CHARS(service->base.fourcc), service->client_id, service->service_use_count, arm_state->videocore_use_count, arm_state->videocore_suspended);
++ vchiq_dump_service_use_state(service->state);
++ vcos_assert(0); // vcos_assert should kill the calling thread, so a user thread shouldn't be able to kill the kernel.
++ }
++ else
++ {
++ ret = VCHIQ_SUCCESS;
++ }
++ vcos_mutex_unlock(&arm_state->use_count_mutex);
++ }
++ return ret;
++}
++
++/* stub functions */
++void vchiq_on_remote_use_active(VCHIQ_STATE_T *state)
++{
++ vcos_unused(state);
++}
++
++void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate)
++{
++ vcos_unused(state);
++ vcos_unused(oldstate);
++ vcos_unused(oldstate);
++}
++
++
+ /****************************************************************************
+ *
+ * vchiq_init - called when the module is loaded.
+@@ -1250,6 +1865,10 @@ vchiq_init(void)
+ if (err != 0)
+ goto failed_platform_init;
+
++#if VCOS_HAVE_TIMER
++ vcos_timer_create( &g_suspend_timer, "suspend_timer", suspend_timer_callback, (void*)(&g_state));
++#endif
++
+ vcos_log_error("vchiq: initialised - version %d (min %d), device %d.%d",
+ VCHIQ_VERSION, VCHIQ_VERSION_MIN,
+ MAJOR(vchiq_devid), MINOR(vchiq_devid));
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
+@@ -21,6 +21,40 @@
+
+ #include "vchiq_core.h"
+
++
++typedef struct vchiq_arm_state_struct {
++
++ VCOS_THREAD_T lp_thread; /* processes low priority messages (eg suspend) */
++ VCOS_THREAD_T hp_thread; /* processes high priority messages (eg resume) */
++
++ VCOS_EVENT_T lp_evt;
++ VCOS_EVENT_T hp_evt;
++
++ VCOS_MUTEX_T use_count_mutex;
++ VCOS_MUTEX_T suspend_resume_mutex;
++
++ int suspend_pending;
++
++ /* Global use count for videocore.
++ * This is equal to the sum of the use counts for all services. When this hits
++ * zero the videocore suspend procedure will be initiated. */
++ int videocore_use_count;
++
++ /* Use count to track requests from videocore peer.
++ * This use count is not associated with a service, so needs to be tracked separately
++ * with the state.
++ */
++ int peer_use_count;
++
++ /* Flag to indicate whether videocore is currently suspended */
++ int videocore_suspended;
++
++ /* Flag to indicate whether a notification is pending back to videocore that it's
++ * "remote use request" has been actioned */
++ int use_notify_pending;
++} VCHIQ_ARM_STATE_T;
++
++
+ extern VCOS_LOG_CAT_T vchiq_arm_log_category;
+
+ extern int __init
+@@ -35,4 +69,50 @@ vchiq_platform_exit(VCHIQ_STATE_T *state
+ extern VCHIQ_STATE_T *
+ vchiq_get_state(void);
+
++extern VCHIQ_STATUS_T
++vchiq_arm_vcsuspend(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_arm_vcresume(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state);
++
++extern void
++vchiq_check_resume(VCHIQ_STATE_T* state);
++
++extern void
++vchiq_check_suspend(VCHIQ_STATE_T* state);
++
++extern VCHIQ_STATUS_T
++vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle);
++
++extern VCHIQ_STATUS_T
++vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle);
++
++extern VCHIQ_STATUS_T
++vchiq_check_service(VCHIQ_SERVICE_T * service);
++
++extern VCHIQ_STATUS_T
++vchiq_platform_suspend(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_platform_resume(VCHIQ_STATE_T *state);
++
++extern int
++vchiq_platform_videocore_wanted(VCHIQ_STATE_T* state);
++
++extern int
++vchiq_platform_use_suspend_timer(void);
++
++extern void
++vchiq_dump_platform_use_state(VCHIQ_STATE_T *state);
++
++extern void
++vchiq_dump_service_use_state(VCHIQ_STATE_T *state);
++
++extern VCHIQ_ARM_STATE_T*
++vchiq_platform_get_arm_state(VCHIQ_STATE_T *state);
++
++
+ #endif /* VCHIQ_ARM_H */
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
+@@ -30,6 +30,11 @@
+
+ #define BULK_INDEX(x) (x & (VCHIQ_NUM_SERVICE_BULKS - 1))
+
++
++/* Used to check use counts allow vchiq use. */
++extern VCHIQ_STATUS_T vchiq_check_service(VCHIQ_SERVICE_T * service);
++
++
+ typedef struct bulk_waiter_struct
+ {
+ VCOS_EVENT_T event;
+@@ -114,6 +119,13 @@ vchiq_set_service_state(VCHIQ_SERVICE_T
+ service->srvstate = newstate;
+ }
+
++static inline int
++is_valid_service(VCHIQ_SERVICE_T *service)
++{
++ return ((service != NULL) &&
++ (service->srvstate != VCHIQ_SRVSTATE_FREE));
++}
++
+ static inline VCHIQ_STATUS_T
+ make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason,
+ VCHIQ_HEADER_T *header, void *bulk_userdata)
+@@ -127,10 +139,12 @@ make_service_callback(VCHIQ_SERVICE_T *s
+ static inline void
+ vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate)
+ {
++ VCHIQ_CONNSTATE_T oldstate = state->conn_state;
+ vcos_log_info("%d: %s->%s", state->id,
+- conn_state_names[state->conn_state],
++ conn_state_names[oldstate],
+ conn_state_names[newstate]);
+ state->conn_state = newstate;
++ vchiq_platform_conn_state_changed(state, oldstate, newstate);
+ }
+
+ static inline void
+@@ -323,7 +337,7 @@ process_free_queue(VCHIQ_STATE_T *state)
+
+ while (slot_queue_available != local->slot_queue_recycle)
+ {
+- int pos;
++ unsigned int pos;
+ int slot_index = local->slot_queue[slot_queue_available++ & VCHIQ_SLOT_QUEUE_MASK];
+ char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index);
+
+@@ -343,17 +357,37 @@ process_free_queue(VCHIQ_STATE_T *state)
+ if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA)
+ {
+ int port = VCHIQ_MSG_SRCPORT(msgid);
++ VCHIQ_SERVICE_QUOTA_T *service_quota =
++ &state->service_quotas[port];
++ int count;
++ count = service_quota->message_use_count;
++ if (count > 0)
++ {
++ service_quota->message_use_count = count - 1;
++ if (count == service_quota->message_quota)
++ {
++ /* Signal the service that it has dropped below its quota */
++ vcos_event_signal(&service_quota->quota_event);
++ }
++ }
++ else
++ {
++ vcos_log_error("service %d message_use_count=%d (header %x,"
++ " msgid %x, header->msgid %x, header->size %x)",
++ port, service_quota->message_use_count,
++ (unsigned int)header, msgid, header->msgid,
++ header->size);
++ vcos_assert(0);
++ }
+ if (!BITSET_IS_SET(service_found, port))
+ {
+- VCHIQ_SERVICE_QUOTA_T *service_quota =
+- &state->service_quotas[port];
+-
+ /* Set the found bit for this service */
+ BITSET_SET(service_found, port);
+
+- if (service_quota->slot_use_count > 0)
++ count = service_quota->slot_use_count;
++ if (count > 0)
+ {
+- service_quota->slot_use_count--;
++ service_quota->slot_use_count = count - 1;
+ /* Signal the service in case it has dropped below its quota */
+ vcos_event_signal(&service_quota->quota_event);
+ vcos_log_trace("%d: pfq:%d %x@%x - slot_use->%d",
+@@ -376,7 +410,7 @@ process_free_queue(VCHIQ_STATE_T *state)
+ pos += calc_stride(header->size);
+ if (pos > VCHIQ_SLOT_SIZE)
+ {
+- vcos_log_error("pos %x: header %x, msgid %x, header->msgid %x, header->size %x",
++ vcos_log_error("pfq - pos %x: header %x, msgid %x, header->msgid %x, header->size %x",
+ pos, (unsigned int)header, msgid, header->msgid, header->size);
+ vcos_assert(0);
+ }
+@@ -431,20 +465,21 @@ queue_message(VCHIQ_STATE_T *state, VCHI
+
+ service_quota = &state->service_quotas[service->localport];
+
+- /* ...ensure it doesn't use more than its quota of slots */
+- while ((tx_end_index != service_quota->previous_tx_index) &&
+- (service_quota->slot_use_count == service_quota->slot_quota))
++ /* ...ensure it doesn't use more than its quota of messages or slots */
++ while ((service_quota->message_use_count == service_quota->message_quota) ||
++ ((tx_end_index != service_quota->previous_tx_index) &&
++ (service_quota->slot_use_count == service_quota->slot_quota)))
+ {
+- vcos_log_trace("%d: qm:%d %s,%x - quota stall",
++ vcos_log_trace("%d: qm:%d %s,%x - quota stall (msg %d, slot %d)",
+ state->id, service->localport,
+- msg_type_str(VCHIQ_MSG_TYPE(msgid)), size);
++ msg_type_str(VCHIQ_MSG_TYPE(msgid)), size,
++ service_quota->message_use_count, service_quota->slot_use_count);
+ VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
+ vcos_mutex_unlock(&state->slot_mutex);
+ if (vcos_event_wait(&service_quota->quota_event) != VCOS_SUCCESS)
+ return VCHIQ_RETRY;
+ if (vcos_mutex_lock(&state->slot_mutex) != VCOS_SUCCESS)
+ return VCHIQ_RETRY;
+- vcos_assert(service_quota->slot_use_count <= service_quota->slot_quota);
+ tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1);
+ }
+ }
+@@ -498,6 +533,7 @@ queue_message(VCHIQ_STATE_T *state, VCHI
+ }
+
+ service_quota->previous_tx_index = tx_end_index;
++ service_quota->message_use_count++;
+ VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count);
+ VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size);
+ } else {
+@@ -1232,6 +1268,17 @@ parse_rx_slots(VCHIQ_STATE_T *state)
+ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
+ vchiq_platform_resumed(state);
+ break;
++
++ case VCHIQ_MSG_REMOTE_USE:
++ vchiq_on_remote_use(state);
++ break;
++ case VCHIQ_MSG_REMOTE_RELEASE:
++ vchiq_on_remote_release(state);
++ break;
++ case VCHIQ_MSG_REMOTE_USE_ACTIVE:
++ vchiq_on_remote_use_active(state);
++ break;
++
+ default:
+ vcos_log_error("%d: prs invalid msgid %x@%x,%x",
+ state->id, msgid, (unsigned int)header, size);
+@@ -1326,8 +1373,6 @@ slot_handler_func(void *v)
+ return NULL;
+ }
+
+-extern VCHIQ_STATUS_T
+-vchiq_platform_suspend(VCHIQ_STATE_T *state);
+
+ /* Called by the recycle thread */
+ static void *
+@@ -1348,23 +1393,6 @@ recycle_func(void *v)
+ return NULL;
+ }
+
+-/* Called by the lp thread */
+-static void *
+-lp_func(void *v)
+-{
+- VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v;
+-
+- while (1) {
+- vcos_event_wait(&state->lp_evt);
+- vcos_mutex_lock(&state->use_count_mutex);
+- if (state->videocore_use_count == 0)
+- {
+- vchiq_platform_suspend(state);
+- }
+- vcos_mutex_unlock(&state->use_count_mutex);
+- }
+- return NULL;
+-}
+
+ static void
+ init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue)
+@@ -1417,6 +1445,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ VCHIQ_SHARED_STATE_T *local;
+ VCHIQ_SHARED_STATE_T *remote;
+ VCOS_THREAD_ATTR_T attrs;
++ VCHIQ_STATUS_T status;
+ char threadname[10];
+ static int id = 0;
+ int i;
+@@ -1426,7 +1455,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ vcos_log_register("vchiq_core", &vchiq_core_log_category);
+ vcos_log_register("vchiq_core_msg", &vchiq_core_msg_log_category);
+
+- vcos_log_warn( "%s: slot_zero = 0x%08lx, is_master = %d\n", __func__, (unsigned long)slot_zero, is_master );
++ vcos_log_warn( "%s: slot_zero = 0x%08lx, is_master = %d", __func__, (unsigned long)slot_zero, is_master );
+
+ /* Check the input configuration */
+
+@@ -1501,6 +1530,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ }
+
+ memset(state, 0, sizeof(VCHIQ_STATE_T));
++ vcos_log_warn( "%s: called", __func__);
+ state->id = id++;
+ state->is_master = is_master;
+
+@@ -1523,8 +1553,6 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+
+ vcos_mutex_create(&state->slot_mutex, "v.slot_mutex");
+ vcos_mutex_create(&state->recycle_mutex, "v.recycle_mutex");
+- vcos_mutex_create(&state->use_count_mutex, "v.use_count_mutex");
+- vcos_mutex_create(&state->suspend_resume_mutex, "v.susp_res_mutex");
+
+ vcos_event_create(&state->slot_available_event, "v.slot_available_event");
+ vcos_event_create(&state->slot_remove_event, "v.slot_remove_event");
+@@ -1543,6 +1571,7 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ }
+
+ state->default_slot_quota = state->slot_queue_available/2;
++ state->default_message_quota = vcos_min(state->default_slot_quota * 256, (unsigned short)~0);
+
+ local->trigger.event = &state->trigger_event;
+ remote_event_create(&local->trigger);
+@@ -1552,8 +1581,6 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ remote_event_create(&local->recycle);
+ local->slot_queue_recycle = state->slot_queue_available;
+
+- vcos_event_create(&state->lp_evt, "LP_EVT");
+-
+ local->debug[DEBUG_ENTRIES] = DEBUG_MAX;
+
+ /*
+@@ -1566,7 +1593,10 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ vcos_snprintf(threadname, sizeof(threadname), "VCHIQ-%d", state->id);
+ if (vcos_thread_create(&state->slot_handler_thread, threadname,
+ &attrs, slot_handler_func, state) != VCOS_SUCCESS)
++ {
++ vcos_log_error("vchiq: FATAL: couldn't create thread %s", threadname);
+ return VCHIQ_ERROR;
++ }
+
+ vcos_thread_attr_init(&attrs);
+ vcos_thread_attr_setstacksize(&attrs, VCHIQ_SLOT_HANDLER_STACK);
+@@ -1574,20 +1604,17 @@ vchiq_init_state(VCHIQ_STATE_T *state, V
+ vcos_snprintf(threadname, sizeof(threadname), "VCHIQr-%d", state->id);
+ if (vcos_thread_create(&state->recycle_thread, threadname,
+ &attrs, recycle_func, state) != VCOS_SUCCESS)
++ {
++ vcos_log_error("vchiq: FATAL: couldn't create thread %s", threadname);
+ return VCHIQ_ERROR;
++ }
+
+- vcos_thread_attr_init(&attrs);
+- vcos_thread_attr_setstacksize(&attrs, VCHIQ_SLOT_HANDLER_STACK);
+- vcos_thread_attr_setpriority(&attrs, VCOS_THREAD_PRI_LOWEST);
+- vcos_snprintf(threadname, sizeof(threadname), "VCHIQl-%d", state->id);
+- if (vcos_thread_create(&state->lp_thread, threadname,
+- &attrs, lp_func, state) != VCOS_SUCCESS)
+- return VCHIQ_ERROR;
++ status = vchiq_platform_init_state(state);
+
+ /* Indicate readiness to the other side */
+ local->initialised = 1;
+
+- return VCHIQ_SUCCESS;
++ return status;
+ }
+
+ /* Called from application thread when a client or server service is created. */
+@@ -1684,6 +1711,7 @@ vchiq_add_service_internal(VCHIQ_STATE_T
+ init_bulk_queue(&service->bulk_tx);
+ init_bulk_queue(&service->bulk_rx);
+ service_quota->slot_quota = state->default_slot_quota;
++ service_quota->message_quota = state->default_message_quota;
+ if (service_quota->slot_use_count == 0)
+ service_quota->previous_tx_index =
+ SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) - 1;
+@@ -1833,9 +1861,13 @@ vchiq_close_service_internal(VCHIQ_SERVI
+
+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSING)
+ {
++ int i;
++ int uc = service->service_use_count;
+ /* Complete the close process */
+- vchiq_release_service(&service->base);
+-
++ for( i=0; i<uc; i++)
++ { /* cater for cases where close is forced and the client may not close all it's handles */
++ vchiq_release_service_internal(service);
++ }
+ service->client_id = 0;
+
+ /* Now tell the client that the services is closed */
+@@ -1912,7 +1944,7 @@ vchiq_free_service_internal(VCHIQ_SERVIC
+ if (slot_info->release_count != slot_info->use_count)
+ {
+ char *data = (char *)SLOT_DATA_FROM_INDEX(state, i);
+- int pos, end;
++ unsigned int pos, end;
+
+ end = VCHIQ_SLOT_SIZE;
+ if (data == state->rx_data)
+@@ -1938,6 +1970,12 @@ vchiq_free_service_internal(VCHIQ_SERVIC
+ }
+ }
+ pos += calc_stride(header->size);
++ if (pos > VCHIQ_SLOT_SIZE)
++ {
++ vcos_log_error("fsi - pos %x: header %x, msgid %x, header->msgid %x, header->size %x",
++ pos, (unsigned int)header, msgid, header->msgid, header->size);
++ vcos_assert(0);
++ }
+ }
+ }
+ }
+@@ -2050,7 +2088,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE
+ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
+ VCHIQ_STATUS_T status = VCHIQ_ERROR;
+
+- if (service == NULL)
++ if (!is_valid_service(service))
+ return VCHIQ_ERROR;
+
+ vcos_log_info("%d: close_service:%d", service->state->id, service->localport);
+@@ -2080,7 +2118,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDL
+ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *) handle;
+ VCHIQ_STATUS_T status = VCHIQ_SUCCESS;
+
+- if (service == NULL)
++ if (!is_valid_service(service))
+ return VCHIQ_ERROR;
+
+ vcos_log_info("%d: remove_service:%d", service->state->id, service->localport);
+@@ -2137,15 +2175,14 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_T *ser
+ const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX;
+ VCHIQ_STATUS_T status = VCHIQ_ERROR;
+
+- if ((service == NULL) ||
+- ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)))
++ if (!is_valid_service(service) ||
++ (service->srvstate != VCHIQ_SRVSTATE_OPEN) ||
++ ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) ||
++ (vchiq_check_service(service) != VCHIQ_SUCCESS))
+ return VCHIQ_ERROR;
+
+ state = service->state;
+
+- if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
+- return VCHIQ_ERROR; /* Must be connected */
+-
+ if (vcos_mutex_lock(&service->bulk_mutex) != VCOS_SUCCESS)
+ return VCHIQ_RETRY;
+
+@@ -2325,8 +2362,9 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE
+ unsigned int size = 0;
+ unsigned int i;
+
+- if ((service == NULL) ||
+- (service->srvstate != VCHIQ_SRVSTATE_OPEN))
++ if (!is_valid_service(service) ||
++ (service->srvstate != VCHIQ_SRVSTATE_OPEN) ||
++ (vchiq_check_service(service) != VCHIQ_SUCCESS))
+ return VCHIQ_ERROR;
+
+ for (i = 0; i < (unsigned int)count; i++)
+@@ -2361,7 +2399,7 @@ vchiq_release_message(VCHIQ_SERVICE_HAND
+ int slot_index;
+ int msgid;
+
+- if (service == NULL)
++ if (!is_valid_service(service))
+ return;
+
+ state = service->state;
+@@ -2418,7 +2456,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_H
+ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+ VCHIQ_STATUS_T status = VCHIQ_ERROR;
+
+- if (service)
++ if (is_valid_service(service))
+ {
+ switch (option)
+ {
+@@ -2427,6 +2465,48 @@ vchiq_set_service_option(VCHIQ_SERVICE_H
+ status = VCHIQ_SUCCESS;
+ break;
+
++ case VCHIQ_SERVICE_OPTION_SLOT_QUOTA:
++ {
++ VCHIQ_SERVICE_QUOTA_T *service_quota =
++ &service->state->service_quotas[service->localport];
++ if (value == 0)
++ value = service->state->default_slot_quota;
++ if ((value >= service_quota->slot_use_count) &&
++ (value < (unsigned short)~0))
++ {
++ service_quota->slot_quota = value;
++ if ((value >= service_quota->slot_use_count) &&
++ (service_quota->message_quota >= service_quota->message_use_count))
++ {
++ /* Signal the service that it may have dropped below its quota */
++ vcos_event_signal(&service_quota->quota_event);
++ }
++ status = VCHIQ_SUCCESS;
++ }
++ }
++ break;
++
++ case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA:
++ {
++ VCHIQ_SERVICE_QUOTA_T *service_quota =
++ &service->state->service_quotas[service->localport];
++ if (value == 0)
++ value = service->state->default_message_quota;
++ if ((value >= service_quota->message_use_count) &&
++ (value < (unsigned short)~0))
++ {
++ service_quota->message_quota = value;
++ if ((value >= service_quota->message_use_count) &&
++ (service_quota->slot_quota >= service_quota->slot_use_count))
++ {
++ /* Signal the service that it may have dropped below its quota */
++ vcos_event_signal(&service_quota->quota_event);
++ }
++ status = VCHIQ_SUCCESS;
++ }
++ }
++ break;
++
+ default:
+ break;
+ }
+@@ -2568,9 +2648,11 @@ vchiq_dump_service_state(void *dump_cont
+ vcos_strcpy(remoteport, "n/a");
+
+ len += vcos_snprintf(buf + len, sizeof(buf) - len,
+- " '%c%c%c%c' remote %s (slot use %d/%d)",
++ " '%c%c%c%c' remote %s (msg use %d/%d, slot use %d/%d)",
+ VCHIQ_FOURCC_AS_4CHARS(fourcc),
+ remoteport,
++ service_quota->message_use_count,
++ service_quota->message_quota,
+ service_quota->slot_use_count,
+ service_quota->slot_quota);
+
+@@ -2602,3 +2684,34 @@ vchiq_dump_service_state(void *dump_cont
+
+ vchiq_dump_platform_service_state(dump_context, service);
+ }
++
++
++VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T * state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_RETRY;
++ if(state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)
++ {
++ status = queue_message(state, NULL, VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE, 0, 0), NULL, 0, 0, 0);
++ }
++ return status;
++}
++
++VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T * state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_RETRY;
++ if(state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)
++ {
++ status = queue_message(state, NULL, VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_RELEASE, 0, 0), NULL, 0, 0, 0);
++ }
++ return status;
++}
++
++VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T * state)
++{
++ VCHIQ_STATUS_T status = VCHIQ_RETRY;
++ if(state->conn_state != VCHIQ_CONNSTATE_DISCONNECTED)
++ {
++ status = queue_message(state, NULL, VCHIQ_MAKE_MSG(VCHIQ_MSG_REMOTE_USE_ACTIVE, 0, 0), NULL, 0, 0, 0);
++ }
++ return status;
++}
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
+@@ -47,6 +47,9 @@ vcos_static_assert(IS_POW2(VCHIQ_MAX_SLO
+ #define VCHIQ_MSG_BULK_TX_DONE 9 // + (srcport, dstport), actual
+ #define VCHIQ_MSG_PAUSE 10 // -
+ #define VCHIQ_MSG_RESUME 11 // -
++#define VCHIQ_MSG_REMOTE_USE 12 // -
++#define VCHIQ_MSG_REMOTE_RELEASE 13 // -
++#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 // -
+
+ #define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1)
+ #define VCHIQ_PORT_FREE 0x1000
+@@ -194,6 +197,8 @@ typedef struct remote_event_struct {
+ VCOS_EVENT_T * event;
+ } REMOTE_EVENT_T;
+
++typedef struct opaque_platform_state_t* VCHIQ_PLATFORM_STATE_T;
++
+ typedef struct vchiq_state_struct VCHIQ_STATE_T;
+
+ typedef struct vchiq_slot_struct {
+@@ -253,8 +258,10 @@ typedef struct vchiq_service_struct {
+ usage is carried over between users of the same port number.
+ */
+ typedef struct vchiq_service_quota_struct {
+- int slot_quota;
+- int slot_use_count;
++ unsigned short slot_quota;
++ unsigned short slot_use_count;
++ unsigned short message_quota;
++ unsigned short message_use_count;
+ VCOS_EVENT_T quota_event;
+ int previous_tx_index;
+ } VCHIQ_SERVICE_QUOTA_T;
+@@ -314,7 +321,8 @@ struct vchiq_state_struct {
+ VCHIQ_SHARED_STATE_T *remote;
+ VCHIQ_SLOT_T *slot_data;
+
+- int default_slot_quota;
++ unsigned short default_slot_quota;
++ unsigned short default_message_quota;
+
+ VCOS_EVENT_T connect; // event indicating connect message received
+ VCOS_MUTEX_T mutex; // mutex protecting services
+@@ -322,7 +330,6 @@ struct vchiq_state_struct {
+
+ VCOS_THREAD_T slot_handler_thread; // processes incoming messages
+ VCOS_THREAD_T recycle_thread; // processes recycled slots
+- VCOS_THREAD_T lp_thread; // processes low priority messages (eg suspend)
+
+ /* Local implementation of the trigger remote event */
+ VCOS_EVENT_T trigger_event;
+@@ -330,8 +337,6 @@ struct vchiq_state_struct {
+ /* Local implementation of the recycle remote event */
+ VCOS_EVENT_T recycle_event;
+
+- VCOS_EVENT_T lp_evt;
+-
+ char *tx_data;
+ char *rx_data;
+ VCHIQ_SLOT_INFO_T *rx_info;
+@@ -340,17 +345,6 @@ struct vchiq_state_struct {
+
+ VCOS_MUTEX_T recycle_mutex;
+
+- VCOS_MUTEX_T suspend_resume_mutex;
+- VCOS_MUTEX_T use_count_mutex;
+-
+- /* Global use count for videocore.
+- * This is equal to the sum of the use counts for all services. When this hits
+- * zero the videocore suspend procedure will be initiated. */
+- int videocore_use_count;
+-
+- /* Flag to indicate whether videocore is currently suspended */
+- int videocore_suspended;
+-
+ /* Indicates the byte position within the stream from where the next message
+ will be read. The least significant bits are an index into the slot.
+ The next bits are the index of the slot in remote->slot_queue. */
+@@ -388,6 +382,8 @@ struct vchiq_state_struct {
+ VCHIQ_SERVICE_T *services[VCHIQ_MAX_SERVICES];
+ VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES];
+ VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS];
++
++ VCHIQ_PLATFORM_STATE_T platform_state;
+ };
+
+ extern VCHIQ_SLOT_ZERO_T *
+@@ -477,4 +473,34 @@ extern void
+ vchiq_dump_platform_service_state(void *dump_context,
+ VCHIQ_SERVICE_T *service);
+
++extern VCHIQ_STATUS_T
++vchiq_use_service_internal(VCHIQ_SERVICE_T *service);
++
++extern VCHIQ_STATUS_T
++vchiq_release_service_internal(VCHIQ_SERVICE_T *service);
++
++extern VCHIQ_STATUS_T
++vchiq_on_remote_use(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_on_remote_release(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_platform_init_state(VCHIQ_STATE_T *state);
++
++extern void
++vchiq_on_remote_use_active(VCHIQ_STATE_T *state);
++
++extern VCHIQ_STATUS_T
++vchiq_send_remote_use(VCHIQ_STATE_T * state);
++
++extern VCHIQ_STATUS_T
++vchiq_send_remote_release(VCHIQ_STATE_T * state);
++
++extern VCHIQ_STATUS_T
++vchiq_send_remote_use_active(VCHIQ_STATE_T * state);
++
++extern void
++vchiq_platform_conn_state_changed(VCHIQ_STATE_T* state, VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate);
++
+ #endif
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
+@@ -55,7 +55,9 @@ typedef enum
+
+ typedef enum
+ {
+- VCHIQ_SERVICE_OPTION_AUTOCLOSE
++ VCHIQ_SERVICE_OPTION_AUTOCLOSE,
++ VCHIQ_SERVICE_OPTION_SLOT_QUOTA,
++ VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA
+ } VCHIQ_SERVICE_OPTION_T;
+
+ #ifdef __HIGHC__
+@@ -94,11 +96,11 @@ typedef struct vchiq_service_base_struct
+ } VCHIQ_SERVICE_BASE_T;
+
+ typedef struct vchiq_service_params_struct {
+- int fourcc;
+- VCHIQ_CALLBACK_T callback;
+- void *userdata;
+- short version; /* Increment for non-trivial changes */
+- short version_min; /* Update for incompatible changes */
++ int fourcc;
++ VCHIQ_CALLBACK_T callback;
++ void *userdata;
++ short version; /* Increment for non-trivial changes */
++ short version_min; /* Update for incompatible changes */
+ } VCHIQ_SERVICE_PARAMS_T;
+
+ typedef struct vchiq_config_struct {
+@@ -112,6 +114,8 @@ typedef struct vchiq_config_struct {
+ } VCHIQ_CONFIG_T;
+
+ typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T;
++typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void* cb_arg);
++
+
+ extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance);
+ extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance);
+@@ -143,6 +147,9 @@ extern int vchiq_get_client_i
+ extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, int config_size, VCHIQ_CONFIG_T *pconfig);
+ extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, VCHIQ_SERVICE_OPTION_T option, int value);
+
++extern VCHIQ_STATUS_T vchiq_remote_use(VCHIQ_INSTANCE_T instance, VCHIQ_REMOTE_USE_CALLBACK_T callback, void* cb_arg);
++extern VCHIQ_STATUS_T vchiq_remote_release(VCHIQ_INSTANCE_T instance);
++
+ extern VCHIQ_STATUS_T vchiq_dump_phys_mem( VCHIQ_SERVICE_HANDLE_T service, void *ptr, size_t num_bytes );
+
+ #endif /* VCHIQ_IF_H */
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+@@ -91,15 +91,15 @@ typedef struct {
+ #define VCHIQ_IOC_QUEUE_MESSAGE _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T)
+ #define VCHIQ_IOC_QUEUE_BULK_TRANSMIT _IOW(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T)
+ #define VCHIQ_IOC_QUEUE_BULK_RECEIVE _IOW(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T)
+-#define VCHIQ_IOC_AWAIT_COMPLETION _IOW(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)
+-#define VCHIQ_IOC_DEQUEUE_MESSAGE _IOW(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)
++#define VCHIQ_IOC_AWAIT_COMPLETION _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T)
++#define VCHIQ_IOC_DEQUEUE_MESSAGE _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T)
+ #define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9)
+-#define VCHIQ_IOC_GET_CONFIG _IOW(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)
+-#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11)
+-#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12)
+-#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13)
+-#define VCHIQ_IOC_SET_SERVICE_OPTION _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
+-#define VCHIQ_IOC_DUMP_PHYS_MEM _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
++#define VCHIQ_IOC_GET_CONFIG _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T)
++#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11)
++#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12)
++#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13)
++#define VCHIQ_IOC_SET_SERVICE_OPTION _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T)
++#define VCHIQ_IOC_DUMP_PHYS_MEM _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T)
+ #define VCHIQ_IOC_MAX 15
+
+ #endif
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c
+@@ -97,6 +97,12 @@ is_valid_instance(VCHIQ_INSTANCE_T insta
+ return (instance == &vchiq_instance) && (instance->initialised > 0);
+ }
+
++static __inline int
++is_valid_service(VCHIQ_SERVICE_T *service)
++{
++ return ((service != NULL) && (service->fd != VCHIQ_INVALID_HANDLE));
++}
++
+ /*
+ * VCHIQ API
+ */
+@@ -318,6 +324,9 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_CLOSE_SERVICE, service->handle));
+
+ if (ret != 0)
+@@ -335,6 +344,9 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDL
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
+
+ if (ret != 0)
+@@ -355,6 +367,9 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.elements = elements;
+ args.count = count;
+@@ -384,6 +399,9 @@ vchiq_queue_bulk_transmit(VCHIQ_SERVICE_
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.data = (void *)data;
+ args.size = size;
+@@ -406,6 +424,9 @@ vchiq_queue_bulk_receive(VCHIQ_SERVICE_H
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.data = data;
+ args.size = size;
+@@ -457,6 +478,9 @@ vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.data = (void *)data;
+ args.size = size;
+@@ -480,6 +504,9 @@ vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_
+
+ vcos_log_trace( "%s called service handle = 0x%08x", __func__, (uint32_t)handle );
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.data = data;
+ args.size = size;
+@@ -521,6 +548,9 @@ vchiq_get_client_id(VCHIQ_SERVICE_HANDLE
+ {
+ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ return ioctl(service->fd, VCHIQ_IOC_GET_CLIENT_ID, service->handle);
+ }
+
+@@ -546,10 +576,14 @@ vchiq_get_config(VCHIQ_INSTANCE_T instan
+ int32_t
+ vchiq_use_service( const VCHIQ_SERVICE_HANDLE_T handle )
+ {
+- VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+- int ret;
+- RETRY(ret,ioctl(service->fd, VCHIQ_IOC_USE_SERVICE, service->handle));
+- return ret;
++ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
++ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
++ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_USE_SERVICE, service->handle));
++ return ret;
+ }
+
+ int32_t
+@@ -569,6 +603,9 @@ vchiq_set_service_option(VCHIQ_SERVICE_H
+ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
+ int ret;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.option = option;
+ args.value = value;
+@@ -633,6 +670,9 @@ vchi_msg_peek( VCHI_SERVICE_HANDLE_T han
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ ret = fill_peek_buf(service, flags);
+
+ if (ret == 0)
+@@ -659,6 +699,9 @@ vchi_msg_remove( VCHI_SERVICE_HANDLE_T h
+ {
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ /* Why would you call vchi_msg_remove without calling vchi_msg_peek first? */
+ vcos_assert(service->peek_size >= 0);
+
+@@ -697,6 +740,9 @@ vchi_msg_queue( VCHI_SERVICE_HANDLE_T ha
+ vcos_unused(msg_handle);
+ vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.elements = &element;
+ args.count = 1;
+@@ -730,6 +776,9 @@ vchi_bulk_queue_receive( VCHI_SERVICE_HA
+ VCHIQ_QUEUE_BULK_TRANSFER_T args;
+ int ret;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ switch ((int)flags) {
+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
+ args.mode = VCHIQ_BULK_MODE_CALLBACK;
+@@ -780,6 +829,9 @@ vchi_bulk_queue_transmit( VCHI_SERVICE_H
+ VCHIQ_QUEUE_BULK_TRANSFER_T args;
+ int ret;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ switch ((int)flags) {
+ case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | VCHI_FLAGS_BLOCK_UNTIL_QUEUED:
+ args.mode = VCHIQ_BULK_MODE_CALLBACK;
+@@ -833,6 +885,9 @@ vchi_msg_dequeue( VCHI_SERVICE_HANDLE_T
+
+ vcos_assert(flags == VCHI_FLAGS_NONE || flags == VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE);
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ if (service->peek_size >= 0)
+ {
+ fprintf(stderr, "vchi_msg_dequeue -> using peek buffer\n");
+@@ -903,6 +958,9 @@ vchi_msg_queuev( VCHI_SERVICE_HANDLE_T h
+
+ vcos_assert(flags == VCHI_FLAGS_BLOCK_UNTIL_QUEUED);
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ args.handle = service->handle;
+ args.elements = (const VCHIQ_ELEMENT_T *)vector;
+ args.count = count;
+@@ -961,6 +1019,9 @@ vchi_msg_hold( VCHI_SERVICE_HANDLE_T han
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
+
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ ret = fill_peek_buf(service, flags);
+
+ if (ret == 0)
+@@ -1116,6 +1177,10 @@ vchi_service_close( const VCHI_SERVICE_H
+ {
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
+
+ if (ret == 0)
+@@ -1129,6 +1194,10 @@ vchi_service_destroy( const VCHI_SERVICE
+ {
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_REMOVE_SERVICE, service->handle));
+
+ if (ret == 0)
+@@ -1200,6 +1269,10 @@ vchi_service_use( const VCHI_SERVICE_HAN
+ {
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_USE_SERVICE, service->handle));
+ return ret;
+ }
+@@ -1218,10 +1291,47 @@ int32_t vchi_service_release( const VCHI
+ {
+ VCHI_SERVICE_T *service = (VCHI_SERVICE_T *)handle;
+ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
+ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_RELEASE_SERVICE, service->handle));
+ return ret;
+ }
+
++/***********************************************************
++ * Name: vchiq_dump_phys_mem
++ *
++ * Arguments: const VCHI_SERVICE_HANDLE_T handle
++ * void *buffer
++ * size_t num_bytes
++ *
++ * Description: Dumps the physical memory associated with
++ * a buffer.
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++VCHIQ_STATUS_T vchiq_dump_phys_mem( VCHIQ_SERVICE_HANDLE_T handle,
++ void *ptr,
++ size_t num_bytes )
++{
++ VCHIQ_SERVICE_T *service = (VCHIQ_SERVICE_T *)handle;
++ VCHIQ_DUMP_MEM_T dump_mem;
++ int ret;
++
++ if (!is_valid_service(service))
++ return VCHIQ_ERROR;
++
++ dump_mem.virt_addr = ptr;
++ dump_mem.num_bytes = num_bytes;
++
++ RETRY(ret,ioctl(service->fd, VCHIQ_IOC_DUMP_PHYS_MEM, &dump_mem));
++ return (ret >= 0) ? VCHIQ_SUCCESS : VCHIQ_ERROR;
++}
++
++
++
+ /*
+ * Support functions
+ */
+--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
+@@ -859,10 +859,38 @@ int32_t vchi_service_create( VCHI_INSTAN
+
+ int32_t vchi_service_close( const VCHI_SERVICE_HANDLE_T handle )
+ {
+- vcos_unused(handle);
++ int32_t ret = -1;
++ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
++ if(service)
++ {
++ VCHIQ_STATUS_T status = vchiq_close_service(service->handle);
++ if (status == VCHIQ_SUCCESS)
++ {
++ service_free(service);
++ service = NULL;
++ }
++
++ ret = vchiq_status_to_vchi( status );
++ }
++ return ret;
++}
+
+- // YTI??
+- return 0;
++int32_t vchi_service_destroy( const VCHI_SERVICE_HANDLE_T handle )
++{
++ int32_t ret = -1;
++ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle;
++ if(service)
++ {
++ VCHIQ_STATUS_T status = vchiq_remove_service(service->handle);
++ if (status == VCHIQ_SUCCESS)
++ {
++ service_free(service);
++ service = NULL;
++ }
++
++ ret = vchiq_status_to_vchi( status );
++ }
++ return ret;
+ }
+
+ /* ----------------------------------------------------------------------
+@@ -962,9 +990,12 @@ EXPORT_SYMBOL(vchi_bulk_queue_transmit);
+ EXPORT_SYMBOL(vchi_msg_dequeue);
+ EXPORT_SYMBOL(vchi_msg_queue);
+ EXPORT_SYMBOL(vchi_msg_queuev);
++EXPORT_SYMBOL(vchi_msg_peek);
++EXPORT_SYMBOL(vchi_msg_remove);
+ EXPORT_SYMBOL(vchi_service_close);
+ EXPORT_SYMBOL(vchi_service_open);
+ EXPORT_SYMBOL(vchi_service_create);
++EXPORT_SYMBOL(vchi_service_destroy);
+ EXPORT_SYMBOL(vchi_service_use);
+ EXPORT_SYMBOL(vchi_service_release);
+ #endif
+--- a/drivers/mmc/host/sdhci-bcm2708.c
++++ b/drivers/mmc/host/sdhci-bcm2708.c
+@@ -26,7 +26,9 @@
+ #include <linux/highmem.h>
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
++#include <linux/mmc/mmc.h>
+ #include <linux/mmc/host.h>
++#include <linux/mmc/sd.h>
+
+ #include <linux/io.h>
+ #include <linux/dma-mapping.h>
+@@ -57,6 +59,9 @@
+ //#define LOG_REGISTERS
+
+ #define USE_SCHED_TIME
++#define USE_SPACED_WRITES_2CLK 1 /* space consecutive register writes */
++#define USE_SOFTWARE_TIMEOUTS 1 /* not hardware timeouts */
++#define SOFTWARE_ERASE_TIMEOUT_SEC 30
+
+ #define SDHCI_BCM_DMA_CHAN 4 /* this default is normally overriden */
+ #define SDHCI_BCM_DMA_WAITS 0 /* delays slowing DMA transfers: 0-31 */
+@@ -68,6 +73,9 @@
+
+ #define BCM2708_SDHCI_SLEEP_TIMEOUT 1000 /* msecs */
+
++/* Mhz clock that the EMMC core is running at. Should match the platform clockman settings */
++#define BCM2708_EMMC_CLOCK_FREQ 80000000
++
+ #define POWER_OFF 0
+ #define POWER_LAZY_OFF 1
+ #define POWER_ON 2
+@@ -222,6 +230,12 @@ u8 sdhci_bcm2708_readb(struct sdhci_host
+
+ static void sdhci_bcm2708_raw_writel(struct sdhci_host *host, u32 val, int reg)
+ {
++ u32 ier;
++
++#if USE_SPACED_WRITES_2CLK
++ static bool timeout_disabled = false;
++ unsigned int ns_2clk = 0;
++
+ /* The Arasan has a bugette whereby it may lose the content of
+ * successive writes to registers that are within two SD-card clock
+ * cycles of each other (a clock domain crossing problem).
+@@ -229,12 +243,11 @@ static void sdhci_bcm2708_raw_writel(str
+ * (Which is just as well - otherwise we'd have to nobble the DMA engine
+ * too)
+ */
+-#if 1
+ if (reg != SDHCI_BUFFER && host->clock != 0) {
+ /* host->clock is the clock freq in Hz */
+ static hptime_t last_write_hpt;
+ hptime_t now = hptime();
+- unsigned int ns_2clk = 2000000000/host->clock;
++ ns_2clk = 2000000000/host->clock;
+
+ if (now == last_write_hpt || now == last_write_hpt+1) {
+ /* we can't guarantee any significant time has
+@@ -250,6 +263,27 @@ static void sdhci_bcm2708_raw_writel(str
+ }
+ last_write_hpt = now;
+ }
++#if USE_SOFTWARE_TIMEOUTS
++ /* The Arasan is clocked for timeouts using the SD clock which is too
++ * fast for ERASE commands and causes issues. So we disable timeouts
++ * for ERASE */
++ if (host->cmd != NULL && host->cmd->opcode == MMC_ERASE &&
++ reg == (SDHCI_COMMAND & ~3)) {
++ mod_timer(&host->timer,
++ jiffies + SOFTWARE_ERASE_TIMEOUT_SEC * HZ);
++ ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
++ ier &= ~SDHCI_INT_DATA_TIMEOUT;
++ writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++ timeout_disabled = true;
++ udelay((ns_2clk+1000-1)/1000);
++ } else if (timeout_disabled) {
++ ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
++ ier |= SDHCI_INT_DATA_TIMEOUT;
++ writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++ timeout_disabled = false;
++ udelay((ns_2clk+1000-1)/1000);
++ }
++#endif
+ writel(val, host->ioaddr + reg);
+ #else
+ void __iomem * regaddr = host->ioaddr + reg;
+@@ -325,14 +359,68 @@ void sdhci_bcm2708_writeb(struct sdhci_h
+
+ static unsigned int sdhci_bcm2708_get_max_clock(struct sdhci_host *host)
+ {
+- return 100000000; // this value is in Hz (100MHz/4)
++ return 20000000; // this value is in Hz (20MHz)
+ }
+
+ static unsigned int sdhci_bcm2708_get_timeout_clock(struct sdhci_host *host)
+ {
+- return 100000; // this value is in kHz (100MHz/4)
++ if(host->clock)
++ return (host->clock / 1000); // this value is in kHz (100MHz)
++ else
++ return (sdhci_bcm2708_get_max_clock(host) / 1000);
+ }
+
++static void sdhci_bcm2708_set_clock(struct sdhci_host *host, unsigned int clock)
++{
++ int div = 0;
++ u16 clk = 0;
++ unsigned long timeout;
++
++ if (clock == host->clock)
++ return;
++
++ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
++
++ if (clock == 0)
++ goto out;
++
++ if (BCM2708_EMMC_CLOCK_FREQ <= clock)
++ div = 1;
++ else {
++ for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
++ if ((BCM2708_EMMC_CLOCK_FREQ / div) <= clock)
++ break;
++ }
++ }
++
++ DBG( "desired SD clock: %d, actual: %d\n",
++ clock, BCM2708_EMMC_CLOCK_FREQ / div);
++
++ clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
++ clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
++ << SDHCI_DIVIDER_HI_SHIFT;
++ clk |= SDHCI_CLOCK_INT_EN;
++
++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++ timeout = 20;
++ while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
++ & SDHCI_CLOCK_INT_STABLE)) {
++ if (timeout == 0) {
++ printk(KERN_ERR "%s: Internal clock never "
++ "stabilised.\n", mmc_hostname(host->mmc));
++ return;
++ }
++ timeout--;
++ mdelay(1);
++ }
++
++ clk |= SDHCI_CLOCK_CARD_EN;
++ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
++out:
++ host->clock = clock;
++ }
++
+ /*****************************************************************************\
+ * *
+ * DMA Operation *
+@@ -429,7 +517,8 @@ static void schci_bcm2708_cb_read(struct
+ cb->stride = 0;
+
+ if (is_last) {
+- cb->info |= BCM2708_DMA_INT_EN;
++ cb->info |= BCM2708_DMA_INT_EN |
++ BCM2708_DMA_WAIT_RESP;
+ cb->next = 0;
+ } else
+ cb->next = host->cb_handle +
+@@ -460,7 +549,8 @@ static void schci_bcm2708_cb_write(struc
+ cb->stride = 0;
+
+ if (is_last) {
+- cb->info |= BCM2708_DMA_INT_EN;
++ cb->info |= BCM2708_DMA_INT_EN |
++ BCM2708_DMA_WAIT_RESP;
+ cb->next = 0;
+ } else
+ cb->next = host->cb_handle +
+@@ -806,8 +896,7 @@ static void sdhci_bcm2708_dma_complete_i
+ We get CRC and DEND errors unless we wait for
+ the SD controller to finish reading/writing to the card. */
+ u32 state_mask;
+- int timeout=1000000;
+- hptime_t now = hptime();
++ int timeout=1000;
+
+ DBG("PDMA over - sync card\n");
+ if (data->flags & MMC_DATA_READ)
+@@ -815,17 +904,12 @@ static void sdhci_bcm2708_dma_complete_i
+ else
+ state_mask = SDHCI_DOING_WRITE;
+
+- while (0 != (sdhci_bcm2708_raw_readl(host,
+- SDHCI_PRESENT_STATE) &
+- state_mask) && --timeout > 0)
++ while (0 != (sdhci_bcm2708_raw_readl(host, SDHCI_PRESENT_STATE)
++ & state_mask) && --timeout > 0)
++ {
++ udelay(100);
+ continue;
+-
+- if (1000000-timeout > 4000) /*ave. is about 3250*/
+- printk(KERN_INFO "%s: note - long %s sync %luns - "
+- "%d its.\n",
+- mmc_hostname(host->mmc),
+- data->flags & MMC_DATA_READ? "read": "write",
+- since_ns(now), 1000000-timeout);
++ }
+ if (timeout <= 0)
+ printk(KERN_ERR"%s: final %s to SD card still "
+ "running\n",
+@@ -1201,6 +1285,11 @@ static unsigned int sdhci_bcm2708_uhs_br
+ return 1;
+ }
+
++static unsigned int sdhci_bcm2708_missing_status(struct sdhci_host *host)
++{
++ return 1;
++}
++
+ /***************************************************************************** \
+ * *
+ * Device ops *
+@@ -1219,7 +1308,7 @@ static struct sdhci_ops sdhci_bcm2708_op
+ #error The BCM2708 SDHCI driver needs CONFIG_MMC_SDHCI_IO_ACCESSORS to be set
+ #endif
+ //.enable_dma = NULL,
+- //.set_clock = NULL,
++ .set_clock = sdhci_bcm2708_set_clock,
+ .get_max_clock = sdhci_bcm2708_get_max_clock,
+ //.get_min_clock = NULL,
+ .get_timeout_clock = sdhci_bcm2708_get_timeout_clock,
+@@ -1238,6 +1327,7 @@ static struct sdhci_ops sdhci_bcm2708_op
+ .spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc,
+ .voltage_broken = sdhci_bcm2708_quirk_voltage_broken,
+ .uhs_broken = sdhci_bcm2708_uhs_broken,
++ .missing_status = sdhci_bcm2708_missing_status,
+ };
+
+ /*****************************************************************************\
+@@ -1282,7 +1372,9 @@ static int __devinit sdhci_bcm2708_probe
+ host->irq = platform_get_irq(pdev, 0);
+
+ host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
+- SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
++ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
++ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
++ SDHCI_QUIRK_NONSTANDARD_CLOCK;
+ #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA
+ host->flags = SDHCI_USE_PLATDMA;
+ #endif
+@@ -1349,6 +1441,8 @@ static int __devinit sdhci_bcm2708_probe
+ host_priv->cb_base, (unsigned)host_priv->cb_handle,
+ host_priv->dma_chan, host_priv->dma_chan_base,
+ host_priv->dma_irq);
++
++ host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
+ #endif
+
+ ret = sdhci_add_host(host);
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -974,6 +974,12 @@ static void sdhci_send_command(struct sd
+ if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
+ mask |= SDHCI_DATA_INHIBIT;
+
++ if(host->ops->missing_status && (cmd->opcode == MMC_SEND_STATUS)) {
++ timeout = 5000; // Really obscenely large delay to send the status, due to bug in controller
++ // which might cause the STATUS command to get stuck when a data operation is in flow
++ mask |= SDHCI_DATA_INHIBIT;
++ }
++
+ /* We shouldn't wait for data inihibit for stop commands, even
+ though they might use busy signaling */
+ if (host->mrq->data && (cmd == host->mrq->data->stop))
+@@ -2098,7 +2104,7 @@ static void sdhci_timeout_timer(unsigned
+
+ if (host->mrq) {
+ pr_err("%s: Timeout waiting for hardware "
+- "interrupt.\n", mmc_hostname(host->mmc));
++ "interrupt - cmd%d.\n", mmc_hostname(host->mmc), host->last_cmdop);
+ sdhci_dumpregs(host);
+
+ if (host->data) {
+@@ -3065,8 +3071,11 @@ int sdhci_add_host(struct sdhci_host *ho
+ mmc->caps |= MMC_CAP_MAX_CURRENT_200;
+ }
+
+- if(host->ops->voltage_broken)
+- ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
++ if(host->ops->voltage_broken) {
++ ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
++ // Cannot support UHS modes is we are stuck at 3.3V;
++ mmc->caps &= ~(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50);
++ }
+
+ mmc->ocr_avail = ocr_avail;
+ mmc->ocr_avail_sdio = ocr_avail;
+--- a/drivers/mmc/host/sdhci.h
++++ b/drivers/mmc/host/sdhci.h
+@@ -291,6 +291,7 @@ struct sdhci_ops {
+ unsigned int (*spurious_crc_acmd51)(struct sdhci_host *host);
+ unsigned int (*voltage_broken)(struct sdhci_host *host);
+ unsigned int (*uhs_broken)(struct sdhci_host *host);
++ unsigned int (*missing_status)(struct sdhci_host *host);
+
+ void (*hw_reset)(struct sdhci_host *host);
+ };
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -1073,6 +1073,7 @@ static int smsc95xx_bind(struct usbnet *
+ dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
+ dev->net->flags |= IFF_MULTICAST;
+ dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
++ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+ return 0;
+ }
+
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -536,28 +536,6 @@ config USB_GADGET_SUPERSPEED
+ bool
+ depends on USB_GADGET_DUALSPEED
+
+-config USB_GADGET_SNPS_DWC_OTG
+- boolean "Synopsys Driver for DWC_otg Controller"
+- depends on USB && EXPERIMENTAL
+- select USB_OTG
+- select USB_GADGET_DUALSPEED
+- help
+- Selects the Synopsys Driver for the DWC_otg Controller.
+-
+-config USB_DWC_OTG_LPM
+- boolean "Enable LPM support"
+- depends on USB && EXPERIMENTAL
+- help
+- Enables LPM support.
+-
+-config USB_GADGET_SNPS_DWC_OTG
+- boolean "Synopsys Driver for DWC_otg Controller"
+- depends on USB && EXPERIMENTAL
+- select USB_OTG
+- select USB_GADGET_DUALSPEED
+- help
+- Selects the Synopsys Driver for the DWC_otg Controller.
+-
+ config USB_DWC_OTG_LPM
+ boolean "Enable LPM support"
+ depends on USB && EXPERIMENTAL
+--- a/drivers/usb/host/dwc_common_port/Makefile
++++ b/drivers/usb/host/dwc_common_port/Makefile
+@@ -6,7 +6,9 @@ ifneq ($(KERNELRELEASE),)
+
+ #CPPFLAGS += -DDEBUG_MEMORY
+
++ifeq ($(CONFIG_USB_DEBUG),y)
+ CPPFLAGS += -DDEBUG
++endif
+ CPPFLAGS += -DDWC_LINUX
+
+ obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o
+--- a/drivers/usb/host/dwc_common_port/dwc_os.h
++++ b/drivers/usb/host/dwc_common_port/dwc_os.h
+@@ -216,6 +216,7 @@ extern void __DWC_DEBUG(char *format, ..
+ #endif
+ #else
+ #define __DWC_DEBUG printk
++#include <linux/kernel.h>
+ #endif
+
+ /**
+--- a/drivers/usb/host/dwc_otg/Makefile
++++ b/drivers/usb/host/dwc_otg/Makefile
+@@ -9,7 +9,9 @@ ifeq ($(BUS_INTERFACE),)
+ BUS_INTERFACE = -DPLATFORM_INTERFACE=1
+ endif
+
+-CPPFLAGS += -DDEBUG
++ifeq ($(CONFIG_USB_DEBUG),y)
++CPPFLAGS += -DDEBUG
++endif
+
+ # Use one of the following flags to compile the software in host-only or
+ # device-only mode.
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+@@ -909,6 +909,10 @@ static void assign_and_init_hc(dwc_otg_h
+ return 0;
+ #endif
+
++ if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info))
++ urb->actual_length = urb->length;
++
++
+ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list);
+
+ /* Remove the host channel from the free list. */
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+@@ -628,7 +628,7 @@ static inline void dwc_otg_hcd_qh_remove
+ * @return Returns the memory allocate or NULL on error. */
+ static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void)
+ {
+- return (dwc_otg_qh_t *) dwc_alloc(sizeof(dwc_otg_qh_t));
++ return (dwc_otg_qh_t *) dwc_alloc_atomic(sizeof(dwc_otg_qh_t));
+ }
+
+ extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb);
+@@ -640,7 +640,7 @@ extern int dwc_otg_hcd_qtd_add(dwc_otg_q
+ * @return Returns the memory allocate or NULL on error. */
+ static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void)
+ {
+- return (dwc_otg_qtd_t *) dwc_alloc(sizeof(dwc_otg_qtd_t));
++ return (dwc_otg_qtd_t *) dwc_alloc_atomic(sizeof(dwc_otg_qtd_t));
+ }
+
+ /** Frees the memory for a QTD structure. QTD should already be removed from
+--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+@@ -417,6 +417,9 @@ int hcd_init(
+
+ hcd->regs = otg_dev->base;
+
++ /* Integrate TT in root hub */
++ hcd->has_tt = 1;
++
+ /* Initialize the DWC OTG HCD. */
+ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
+ if (!dwc_otg_hcd) {
+@@ -668,6 +671,9 @@ static int urb_enqueue(struct usb_hcd *h
+ urb->number_of_packets,
+ mem_flags == GFP_ATOMIC ? 1 : 0);
+
++ if(dwc_otg_urb == NULL)
++ return -ENOMEM;
++
+ urb->hcpriv = dwc_otg_urb;
+
+ dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
+@@ -755,10 +761,12 @@ static int urb_dequeue(struct usb_hcd *h
+ dump_urb_info(urb, "urb_dequeue");
+ }
+ #endif
+- dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv);
++ if(urb->hcpriv != NULL) {
++ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv);
+
+- dwc_free(urb->hcpriv);
+- urb->hcpriv = NULL;
++ urb->hcpriv = NULL;
++ dwc_free(urb->hcpriv);
++ }
+
+ /* Higher layer software sets URB status. */
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+--- a/drivers/video/bcm2708_fb.c
++++ b/drivers/video/bcm2708_fb.c
+@@ -7,14 +7,17 @@
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+- * Broadcom simple framebuffer driver
++ * Broadcom simple framebuffer driver
++ *
++ * This file is derived from cirrusfb.c
++ * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
++ *
+ */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/slab.h>
+-#include <linux/delay.h>
+ #include <linux/mm.h>
+ #include <linux/fb.h>
+ #include <linux/init.h>
+@@ -22,6 +25,8 @@
+ #include <linux/list.h>
+ #include <linux/platform_device.h>
+ #include <linux/clk.h>
++#include <linux/printk.h>
++#include <linux/console.h>
+
+ #include <mach/platform.h>
+ #include <mach/vcio.h>
+@@ -38,26 +43,24 @@ static const char *bcm2708_name = "BCM27
+ /* this data structure describes each frame buffer device we find */
+
+ struct fbinfo_s {
+- int xres, yres, xres_virtual, yres_virtual;
+- int pitch, bpp;
+- int xoffset, yoffset;
+- int base;
+- int screen_size;
++ u32 xres, yres, xres_virtual, yres_virtual;
++ u32 pitch, bpp;
++ u32 xoffset, yoffset;
++ u32 base;
++ u32 screen_size;
+ };
+
+ struct bcm2708_fb {
+- struct fb_info fb;
+- struct platform_device *dev;
+- void __iomem *regs;
+- volatile struct fbinfo_s *info;
+- dma_addr_t dma;
+- u32 cmap[16];
++ struct fb_info fb;
++ struct platform_device *dev;
++ struct fbinfo_s *info;
++ dma_addr_t dma;
++ u32 cmap[16];
+ };
+
+ #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb)
+
+-static int
+-bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
++static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var)
+ {
+ int ret = 0;
+
+@@ -72,12 +75,12 @@ bcm2708_fb_set_bitfields(struct fb_var_s
+ case 2:
+ case 4:
+ case 8:
+- var->red.length = var->bits_per_pixel;
+- var->red.offset = 0;
+- var->green.length = var->bits_per_pixel;
+- var->green.offset = 0;
+- var->blue.length = var->bits_per_pixel;
+- var->blue.offset = 0;
++ var->red.length = var->bits_per_pixel;
++ var->red.offset = 0;
++ var->green.length = var->bits_per_pixel;
++ var->green.offset = 0;
++ var->blue.length = var->bits_per_pixel;
++ var->blue.offset = 0;
+ break;
+ case 16:
+ var->red.length = 5;
+@@ -89,10 +92,16 @@ bcm2708_fb_set_bitfields(struct fb_var_s
+ if (var->green.length != 5 && var->green.length != 6)
+ var->green.length = 6;
+ break;
++ case 24:
++ var->red.length = 8;
++ var->blue.length = 8;
++ var->green.length = 8;
++ break;
+ case 32:
+- var->red.length = 8;
+- var->green.length = 8;
+- var->blue.length = 8;
++ var->red.length = 8;
++ var->green.length = 8;
++ var->blue.length = 8;
++ var->transp.length = 8;
+ break;
+ default:
+ ret = -EINVAL;
+@@ -104,134 +113,148 @@ bcm2708_fb_set_bitfields(struct fb_var_s
+ * encoded in the pixel data. Calculate their position from
+ * the bitfield length defined above.
+ */
+- if (ret == 0 && var->bits_per_pixel >= 16) {
++ if (ret == 0 && var->bits_per_pixel >= 24) {
++ var->red.offset = 0;
++ var->green.offset = var->red.offset + var->red.length;
++ var->blue.offset = var->green.offset + var->green.length;
++ var->transp.offset = var->blue.offset + var->blue.length;
++ } else if (ret == 0 && var->bits_per_pixel >= 16) {
+ var->blue.offset = 0;
+ var->green.offset = var->blue.offset + var->blue.length;
+ var->red.offset = var->green.offset + var->green.length;
++ var->transp.offset = var->red.offset + var->red.length;
+ }
+
+ return ret;
+ }
+
+-static int bcm2708_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++static int bcm2708_fb_check_var(struct fb_var_screeninfo *var,
++ struct fb_info *info)
+ {
++ /* info input, var output */
++ int yres;
++ /* memory size in pixels */
++ unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
++
++ /* info input, var output */
++ pr_info("bcm2708_fb_check_var info(%p) %dx%d (%dx%d), %d, %d\n", info,
++ info->var.xres, info->var.yres, info->var.xres_virtual,
++ info->var.yres_virtual, (int)info->screen_size,
++ info->var.bits_per_pixel);
++ pr_info("bcm2708_fb_check_var var(%p) %dx%d (%dx%d), %d, %d\n", var,
++ var->xres, var->yres, var->xres_virtual, var->yres_virtual,
++ var->bits_per_pixel, pixels);
++
++ if (!var->bits_per_pixel)
++ var->bits_per_pixel = 16;
++
++ if (bcm2708_fb_set_bitfields(var) != 0) {
++ pr_err("bcm2708_fb_check_var: invalid bits_per_pixel %d\n",
++ var->bits_per_pixel);
++ return -EINVAL;
++ }
+
+- // info input, var output
+- int yres;
+- /* memory size in pixels */
+- unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
+-
+- // info input, var output
+- printk(KERN_ERR "bcm2708_fb_check_var info(%p) %dx%d (%dx%d), %d, %d\n", info, info->var.xres, info->var.yres, info->var.xres_virtual, info->var.yres_virtual, (int)info->screen_size, info->var.bits_per_pixel );
+- printk(KERN_ERR "bcm2708_fb_check_var var(%p) %dx%d (%dx%d), %d, %d\n", var, var->xres, var->yres, var->xres_virtual, var->yres_virtual, var->bits_per_pixel, pixels);
+-
+- if (!var->bits_per_pixel) var->bits_per_pixel = 16;
+-
+- if (0 && var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
+- printk(KERN_ERR "bcm2708_fb_check_var: ERROR: bits_per_pixel=%d\n", var->bits_per_pixel);
+- return -EINVAL;
+- }
+-
+- bcm2708_fb_set_bitfields(var);
+-
+- if (var->xres_virtual < var->xres)
+- var->xres_virtual = var->xres;
+- /* use highest possible virtual resolution */
+- if (var->yres_virtual == -1) {
+- var->yres_virtual = 480; //pixels / var->xres_virtual;
+-
+- printk(KERN_ERR
+- "bcm2708_fb_check_var: virtual resolution set to maximum of %dx%d\n",
+- var->xres_virtual, var->yres_virtual);
+- }
+- if (var->yres_virtual < var->yres)
+- var->yres_virtual = var->yres;
+-
+- #if 0
+- if (var->xres_virtual * var->yres_virtual > pixels) {
+- printk(KERN_ERR "bcm2708_fb_check_var: mode %dx%dx%d rejected... "
+- "virtual resolution too high to fit into video memory!\n",
+- var->xres_virtual, var->yres_virtual,
+- var->bits_per_pixel);
+- return -EINVAL;
+- }
+- #endif
+- if (var->xoffset < 0)
+- var->xoffset = 0;
+- if (var->yoffset < 0)
+- var->yoffset = 0;
+-
+- /* truncate xoffset and yoffset to maximum if too high */
+- if (var->xoffset > var->xres_virtual - var->xres)
+- var->xoffset = var->xres_virtual - var->xres - 1;
+- if (var->yoffset > var->yres_virtual - var->yres)
+- var->yoffset = var->yres_virtual - var->yres - 1;
+-
+- var->red.msb_right =
+- var->green.msb_right =
+- var->blue.msb_right =
+- var->transp.offset =
+- var->transp.length =
+- var->transp.msb_right = 0;
+-
+- yres = var->yres;
+- if (var->vmode & FB_VMODE_DOUBLE)
+- yres *= 2;
+- else if (var->vmode & FB_VMODE_INTERLACED)
+- yres = (yres + 1) / 2;
+-
+- if (yres > 1200) {
+- printk(KERN_ERR "bcm2708_fb_check_var: ERROR: VerticalTotal >= 1200; "
+- "special treatment required! (TODO)\n");
+- return -EINVAL;
+- }
+
+- //if (cirrusfb_check_pixclock(var, info))
+- // return -EINVAL;
++ if (var->xres_virtual < var->xres)
++ var->xres_virtual = var->xres;
++ /* use highest possible virtual resolution */
++ if (var->yres_virtual == -1) {
++ var->yres_virtual = 480;
++
++ pr_err
++ ("bcm2708_fb_check_var: virtual resolution set to maximum of %dx%d\n",
++ var->xres_virtual, var->yres_virtual);
++ }
++ if (var->yres_virtual < var->yres)
++ var->yres_virtual = var->yres;
+
+- //if (!is_laguna(cinfo))
+- // var->accel_flags = FB_ACCELF_TEXT;
++ if (var->xoffset < 0)
++ var->xoffset = 0;
++ if (var->yoffset < 0)
++ var->yoffset = 0;
++
++ /* truncate xoffset and yoffset to maximum if too high */
++ if (var->xoffset > var->xres_virtual - var->xres)
++ var->xoffset = var->xres_virtual - var->xres - 1;
++ if (var->yoffset > var->yres_virtual - var->yres)
++ var->yoffset = var->yres_virtual - var->yres - 1;
++
++ yres = var->yres;
++ if (var->vmode & FB_VMODE_DOUBLE)
++ yres *= 2;
++ else if (var->vmode & FB_VMODE_INTERLACED)
++ yres = (yres + 1) / 2;
++
++ if (yres > 1200) {
++ pr_err("bcm2708_fb_check_var: ERROR: VerticalTotal >= 1200; "
++ "special treatment required! (TODO)\n");
++ return -EINVAL;
++ }
+
+- return 0;
++ return 0;
+ }
+
+ static int bcm2708_fb_set_par(struct fb_info *info)
+ {
+- unsigned val = 0;
++ uint32_t val = 0;
+ struct bcm2708_fb *fb = to_bcm2708(info);
+- volatile struct fbinfo_s *fbinfo = fb->info;
+- fbinfo->xres = info->var.xres;
+- fbinfo->yres = info->var.yres;
+- fbinfo->xres_virtual = info->var.xres_virtual;
+- fbinfo->yres_virtual = info->var.yres_virtual;
+- fbinfo->bpp = info->var.bits_per_pixel;
+- fbinfo->xoffset = info->var.xoffset;
+- fbinfo->yoffset = info->var.yoffset;
+- fbinfo->base = 0; // filled in by VC
+- fbinfo->pitch = 0; // filled in by VC
++ volatile struct fbinfo_s *fbinfo = fb->info;
++ fbinfo->xres = info->var.xres;
++ fbinfo->yres = info->var.yres;
++ fbinfo->xres_virtual = info->var.xres_virtual;
++ fbinfo->yres_virtual = info->var.yres_virtual;
++ fbinfo->bpp = info->var.bits_per_pixel;
++ fbinfo->xoffset = info->var.xoffset;
++ fbinfo->yoffset = info->var.yoffset;
++ fbinfo->base = 0; /* filled in by VC */
++ fbinfo->pitch = 0; /* filled in by VC */
++
++ pr_info("bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info,
++ info->var.xres, info->var.yres, info->var.xres_virtual,
++ info->var.yres_virtual, (int)info->screen_size,
++ info->var.bits_per_pixel);
+
+- printk(KERN_ERR "bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info, info->var.xres, info->var.yres, info->var.xres_virtual, info->var.yres_virtual, (int)info->screen_size, info->var.bits_per_pixel );
++ /* ensure last write to fbinfo is visible to GPU */
++ wmb();
+
+- // inform vc about new framebuffer
++ /* inform vc about new framebuffer */
+ bcm_mailbox_write(MBOX_CHAN_FB, fb->dma);
+
+- // wait for response
+- bcm_mailbox_read(MBOX_CHAN_FB, &val);
+-
+- fb->fb.fix.line_length = fbinfo->pitch;
++ /* TODO: replace fb driver with vchiq version */
++ /* wait for response */
++ bcm_mailbox_read(MBOX_CHAN_FB, &val);
++
++ /* ensure GPU writes are visible to us */
++ rmb();
++
++ if (val == 0) {
++ fb->fb.fix.line_length = fbinfo->pitch;
++
++ if (info->var.bits_per_pixel <= 8)
++ fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++ else
++ fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
++
++ fb->fb.fix.smem_start = fbinfo->base;
++ fb->fb.fix.smem_len = fbinfo->pitch * fbinfo->yres_virtual;
++ fb->fb.screen_size = fbinfo->screen_size;
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
++ fb->fb.screen_base =
++ (void *)ioremap_wc(fb->fb.fix.smem_start, fb->fb.screen_size);
++ if (!fb->fb.screen_base) {
++ /* the console may currently be locked */
++ console_trylock();
++ console_unlock();
+
+- if (info->var.bits_per_pixel <= 8)
+- fb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+- else
+- fb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+-
+- fb->fb.fix.smem_start = fbinfo->base;
+- fb->fb.fix.smem_len = fbinfo->pitch * fbinfo->yres_virtual;
+- fb->fb.screen_size = fbinfo->screen_size;
+- fb->fb.screen_base = (void *)ioremap_nocache(fb->fb.fix.smem_start, fb->fb.screen_size);
+-
+- printk(KERN_ERR "BCM2708FB: start = %p,%p,%p width=%d, height=%d, bpp=%d, pitch=%d\n",
+- (void *)fb->fb.screen_base, (void *)fb->fb.fix.smem_start, (void *)val, fbinfo->xres, fbinfo->yres, fbinfo->bpp, fbinfo->pitch);
++ BUG(); /* what can we do here */
++ }
++ }
++ pr_info
++ ("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d success=%d\n",
++ (void *)fb->fb.screen_base, (void *)fb->fb.fix.smem_start,
++ fbinfo->xres, fbinfo->yres, fbinfo->bpp,
++ fbinfo->pitch, (int)fb->fb.screen_size, val);
+
+ return val;
+ }
+@@ -243,58 +266,62 @@ static inline u32 convert_bitfield(int v
+ return (val >> (16 - bf->length) & mask) << bf->offset;
+ }
+
+-static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
+- unsigned int blue, unsigned int transp, struct fb_info *info)
++static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
++ unsigned int green, unsigned int blue,
++ unsigned int transp, struct fb_info *info)
+ {
+ struct bcm2708_fb *fb = to_bcm2708(info);
+
+ if (regno < 16)
+ fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
+- convert_bitfield(blue, &fb->fb.var.blue) |
+- convert_bitfield(green, &fb->fb.var.green) |
+- convert_bitfield(red, &fb->fb.var.red);
++ convert_bitfield(blue, &fb->fb.var.blue) |
++ convert_bitfield(green, &fb->fb.var.green) |
++ convert_bitfield(red, &fb->fb.var.red);
+
+ return regno > 255;
+ }
+
+ static int bcm2708_fb_blank(int blank_mode, struct fb_info *info)
+ {
+-//printk(KERN_ERR "bcm2708_fb_blank\n");
++ /*pr_info("bcm2708_fb_blank\n"); */
+ return -1;
+ }
+
+-static void bcm2708_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
++static void bcm2708_fb_fillrect(struct fb_info *info,
++ const struct fb_fillrect *rect)
+ {
+-// (is called) printk(KERN_ERR "bcm2708_fb_fillrect\n");
++ /* (is called) pr_info("bcm2708_fb_fillrect\n"); */
+ cfb_fillrect(info, rect);
+ }
+
+-static void bcm2708_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
++static void bcm2708_fb_copyarea(struct fb_info *info,
++ const struct fb_copyarea *region)
+ {
+-//printk(KERN_ERR "bcm2708_fb_copyarea\n");
++ /*pr_info("bcm2708_fb_copyarea\n"); */
+ cfb_copyarea(info, region);
+ }
+
+-static void bcm2708_fb_imageblit(struct fb_info *info, const struct fb_image *image)
++static void bcm2708_fb_imageblit(struct fb_info *info,
++ const struct fb_image *image)
+ {
+-// (is called) printk(KERN_ERR "bcm2708_fb_imageblit\n");
++ /* (is called) pr_info("bcm2708_fb_imageblit\n"); */
+ cfb_imageblit(info, image);
+ }
+
+ static struct fb_ops bcm2708_fb_ops = {
+- .owner = THIS_MODULE,
+- .fb_check_var = bcm2708_fb_check_var,
+- .fb_set_par = bcm2708_fb_set_par,
+- .fb_setcolreg = bcm2708_fb_setcolreg,
+- .fb_blank = bcm2708_fb_blank,
+- .fb_fillrect = bcm2708_fb_fillrect,
+- .fb_copyarea = bcm2708_fb_copyarea,
+- .fb_imageblit = bcm2708_fb_imageblit,
++ .owner = THIS_MODULE,
++ .fb_check_var = bcm2708_fb_check_var,
++ .fb_set_par = bcm2708_fb_set_par,
++ .fb_setcolreg = bcm2708_fb_setcolreg,
++ .fb_blank = bcm2708_fb_blank,
++ .fb_fillrect = bcm2708_fb_fillrect,
++ .fb_copyarea = bcm2708_fb_copyarea,
++ .fb_imageblit = bcm2708_fb_imageblit,
+ };
+
+-static int FBWIDTH =800; /* module parameter */
+-static int FBHEIGHT =480; /* module parameter */
+-
++static int fbwidth = 800; /* module parameter */
++static int fbheight = 480; /* module parameter */
++static int fbdepth = 16; /* module parameter */
+
+ static int bcm2708_fb_register(struct bcm2708_fb *fb)
+ {
+@@ -302,45 +329,47 @@ static int bcm2708_fb_register(struct bc
+ dma_addr_t dma;
+ void *mem;
+
+- mem = dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma, GFP_KERNEL);
++ mem =
++ dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), &dma,
++ GFP_KERNEL);
+
+ if (NULL == mem) {
+- printk(KERN_ERR ": unable to allocate fbinfo buffer\n");
++ pr_err(": unable to allocate fbinfo buffer\n");
+ ret = -ENOMEM;
+ } else {
+ fb->info = (struct fbinfo_s *)mem;
+- fb->dma = dma;
+- }
+- fb->fb.fbops = &bcm2708_fb_ops;
+- fb->fb.flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
+- fb->fb.pseudo_palette = fb->cmap;
++ fb->dma = dma;
++ }
++ fb->fb.fbops = &bcm2708_fb_ops;
++ fb->fb.flags = FBINFO_FLAG_DEFAULT;
++ fb->fb.pseudo_palette = fb->cmap;
+
+ strncpy(fb->fb.fix.id, bcm2708_name, sizeof(fb->fb.fix.id));
+- fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+- fb->fb.fix.type_aux = 0;
+- fb->fb.fix.xpanstep = 0;
+- fb->fb.fix.ypanstep = 0;
+- fb->fb.fix.ywrapstep = 0;
+- fb->fb.fix.accel = FB_ACCEL_NONE;
+-
+- fb->fb.var.xres = FBWIDTH;
+- fb->fb.var.yres = FBHEIGHT;
+- fb->fb.var.xres_virtual = FBWIDTH;
+- fb->fb.var.yres_virtual = FBHEIGHT;
+- fb->fb.var.bits_per_pixel = 16;
+- fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
+- fb->fb.var.activate = FB_ACTIVATE_NOW;
+- fb->fb.var.nonstd = 0;
+- fb->fb.var.height = FBWIDTH;
+- fb->fb.var.width = FBHEIGHT;
+- fb->fb.var.accel_flags = 0;
+-
+- fb->fb.monspecs.hfmin = 0;
+- fb->fb.monspecs.hfmax = 100000;
+- fb->fb.monspecs.vfmin = 0;
+- fb->fb.monspecs.vfmax = 400;
++ fb->fb.fix.type = FB_TYPE_PACKED_PIXELS;
++ fb->fb.fix.type_aux = 0;
++ fb->fb.fix.xpanstep = 0;
++ fb->fb.fix.ypanstep = 0;
++ fb->fb.fix.ywrapstep = 0;
++ fb->fb.fix.accel = FB_ACCEL_NONE;
++
++ fb->fb.var.xres = fbwidth;
++ fb->fb.var.yres = fbheight;
++ fb->fb.var.xres_virtual = fbwidth;
++ fb->fb.var.yres_virtual = fbheight;
++ fb->fb.var.bits_per_pixel = fbdepth;
++ fb->fb.var.vmode = FB_VMODE_NONINTERLACED;
++ fb->fb.var.activate = FB_ACTIVATE_NOW;
++ fb->fb.var.nonstd = 0;
++ fb->fb.var.height = fbwidth;
++ fb->fb.var.width = fbheight;
++ fb->fb.var.accel_flags = 0;
++
++ fb->fb.monspecs.hfmin = 0;
++ fb->fb.monspecs.hfmax = 100000;
++ fb->fb.monspecs.vfmin = 0;
++ fb->fb.monspecs.vfmax = 400;
+ fb->fb.monspecs.dclkmin = 1000000;
+- fb->fb.monspecs.dclkmax = 100000000;
++ fb->fb.monspecs.dclkmax = 100000000;
+
+ bcm2708_fb_set_bitfields(&fb->fb.var);
+
+@@ -350,17 +379,16 @@ static int bcm2708_fb_register(struct bc
+
+ fb_set_var(&fb->fb, &fb->fb.var);
+
+- printk(KERN_INFO "BCM2708FB: registering framebuffer (%d, %d)\n", FBWIDTH, FBHEIGHT);
++ pr_info("BCM2708FB: registering framebuffer (%dx%d@%d)\n", fbwidth,
++ fbheight, fbdepth);
+
+ ret = register_framebuffer(&fb->fb);
+- printk(KERN_ERR "BCM2708FB: register framebuffer (%d)\n", ret);
++ pr_info("BCM2708FB: register framebuffer (%d)\n", ret);
+ if (ret == 0)
+ goto out;
+
+- printk(KERN_ERR "BCM2708FB: cannot register framebuffer (%d)\n", ret);
+-
+- iounmap(fb->regs);
+- out:
++ pr_info("BCM2708FB: cannot register framebuffer (%d)\n", ret);
++out:
+ return ret;
+ }
+
+@@ -371,7 +399,8 @@ static int bcm2708_fb_probe(struct platf
+
+ fb = kmalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
+ if (!fb) {
+- dev_err(&dev->dev, "could not allocate new bcm2708_fb struct\n");
++ dev_err(&dev->dev,
++ "could not allocate new bcm2708_fb struct\n");
+ ret = -ENOMEM;
+ goto free_region;
+ }
+@@ -386,9 +415,9 @@ static int bcm2708_fb_probe(struct platf
+ }
+
+ kfree(fb);
+- free_region:
++free_region:
+ dev_err(&dev->dev, "probe failed, err %d\n", ret);
+- out:
++out:
+ return ret;
+ }
+
+@@ -398,22 +427,24 @@ static int bcm2708_fb_remove(struct plat
+
+ platform_set_drvdata(dev, NULL);
+
++ if (fb->fb.screen_base)
++ iounmap(fb->fb.screen_base);
+ unregister_framebuffer(&fb->fb);
+- iounmap(fb->regs);
+
+- dma_free_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), (void *)fb->info, fb->dma);
++ dma_free_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), (void *)fb->info,
++ fb->dma);
+ kfree(fb);
+
+ return 0;
+ }
+
+ static struct platform_driver bcm2708_fb_driver = {
+- .probe = bcm2708_fb_probe,
+- .remove = bcm2708_fb_remove,
+- .driver = {
+- .name = DRIVER_NAME,
+- .owner = THIS_MODULE,
+- },
++ .probe = bcm2708_fb_probe,
++ .remove = bcm2708_fb_remove,
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ },
+ };
+
+ static int __init bcm2708_fb_init(void)
+@@ -430,11 +461,13 @@ static void __exit bcm2708_fb_exit(void)
+
+ module_exit(bcm2708_fb_exit);
+
+-module_param(FBWIDTH, int, 0644);
+-module_param(FBHEIGHT, int, 0644);
++module_param(fbwidth, int, 0644);
++module_param(fbheight, int, 0644);
++module_param(fbdepth, int, 0644);
+
+ MODULE_DESCRIPTION("BCM2708 framebuffer driver");
+ MODULE_LICENSE("GPL");
+
+-MODULE_PARM_DESC(FBWIDTH, "Width of ARM Framebuffer");
+-MODULE_PARM_DESC(FBHEIGHT, "Height of ARM Framebuffer");
++MODULE_PARM_DESC(fbwidth, "Width of ARM Framebuffer");
++MODULE_PARM_DESC(fbheight, "Height of ARM Framebuffer");
++MODULE_PARM_DESC(fbdepth, "Bit depth of ARM Framebuffer");
+--- a/sound/arm/Kconfig
++++ b/sound/arm/Kconfig
+@@ -39,5 +39,12 @@ config SND_PXA2XX_AC97
+ Say Y or M if you want to support any AC97 codec attached to
+ the PXA2xx AC97 interface.
+
++config SND_BCM2835
++ tristate "BCM2835 ALSA driver"
++ depends on ARCH_BCM2708 && SND
++ select SND_PCM
++ help
++ Say Y or M if you want to support BCM2835 Alsa pcm card driver
++
+ endif # SND_ARM
+
+--- a/sound/arm/Makefile
++++ b/sound/arm/Makefile
+@@ -14,3 +14,9 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_A
+
+ obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
+ snd-pxa2xx-ac97-objs := pxa2xx-ac97.o
++
++obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o
++snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
++
++EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
++
+--- /dev/null
++++ b/sound/arm/bcm2835-ctl.c
+@@ -0,0 +1,172 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#include <linux/platform_device.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/jiffies.h>
++#include <linux/slab.h>
++#include <linux/time.h>
++#include <linux/wait.h>
++#include <linux/delay.h>
++#include <linux/moduleparam.h>
++#include <linux/sched.h>
++
++#include <sound/core.h>
++#include <sound/control.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/rawmidi.h>
++#include <sound/initval.h>
++#include <sound/tlv.h>
++
++#include "bcm2835.h"
++
++static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = -10240;
++ uinfo->value.integer.max = 2303;
++ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = 1;
++ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++ uinfo->count = 1;
++ uinfo->value.integer.min = 0;
++ uinfo->value.integer.max = AUDIO_DEST_MAX-0;
++ }
++
++ return 0;
++}
++
++static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++
++ BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK));
++
++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME)
++ ucontrol->value.integer.value[0] = chip->volume;
++ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE)
++ ucontrol->value.integer.value[0] = chip->mute;
++ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE)
++ ucontrol->value.integer.value[0] = chip->dest;
++
++ return 0;
++}
++
++static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ int changed = 0;
++
++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) {
++ if (chip->mute) {
++ chip->mute = 0;
++ changed = 1;
++ }
++ if (changed
++ || (ucontrol->value.integer.value[0] != chip->volume)) {
++ int atten;
++
++ chip->volume = ucontrol->value.integer.value[0];
++ changed = 1;
++ atten = -((chip->volume << 8) / 100);
++ chip->volume = atten;
++ }
++
++ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) {
++ /* Not implemented */
++ if (ucontrol->value.integer.value[0] != chip->mute) {
++ chip->mute = ucontrol->value.integer.value[0];
++ changed = 0;
++ }
++ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) {
++ if (ucontrol->value.integer.value[0] != chip->dest) {
++ chip->dest = ucontrol->value.integer.value[0];
++ changed = 1;
++ }
++ }
++
++ if (changed) {
++ if (bcm2835_audio_set_ctls(chip))
++ printk(KERN_ERR "Failed to set ALSA controls..\n");
++ }
++
++ return changed;
++}
++
++static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, -10240, 1, 1);
++
++static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "PCM Playback Volume",
++ .index = 0,
++ .access =
++ SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE,
++ .private_value = PCM_PLAYBACK_VOLUME,
++ .info = snd_bcm2835_ctl_info,
++ .get = snd_bcm2835_ctl_get,
++ .put = snd_bcm2835_ctl_put,
++ .count = 1,
++ .tlv = {.p = snd_bcm2835_db_scale}
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "PCM Playback Switch",
++ .index = 0,
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++ .private_value = PCM_PLAYBACK_MUTE,
++ .info = snd_bcm2835_ctl_info,
++ .get = snd_bcm2835_ctl_get,
++ .put = snd_bcm2835_ctl_put,
++ .count = 1,
++ },
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++ .name = "PCM Playback Route",
++ .index = 0,
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
++ .private_value = PCM_PLAYBACK_DEVICE,
++ .info = snd_bcm2835_ctl_info,
++ .get = snd_bcm2835_ctl_get,
++ .put = snd_bcm2835_ctl_put,
++ .count = 1,
++ },
++};
++
++int __devinit snd_bcm2835_new_ctl(bcm2835_chip_t * chip)
++{
++ int err;
++ unsigned int idx;
++
++ strcpy(chip->card->mixername, "Broadcom Mixer");
++ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) {
++ err =
++ snd_ctl_add(chip->card,
++ snd_ctl_new1(&snd_bcm2835_ctl[idx], chip));
++ if (err < 0)
++ return err;
++ }
++ return 0;
++}
+--- /dev/null
++++ b/sound/arm/bcm2835-pcm.c
+@@ -0,0 +1,424 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#include <linux/interrupt.h>
++#include <linux/slab.h>
++
++#include "bcm2835.h"
++
++/* hardware definition */
++static struct snd_pcm_hardware snd_bcm2835_playback_hw = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER),
++ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
++ .rate_min = 8000,
++ .rate_max = 48000,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = (4 * 8 - 1) * 1024, /* Needs to be less than audioplay buffer size */
++ .period_bytes_min = 1 * 1024,
++ .period_bytes_max = (4 * 8 - 1) * 1024,
++ .periods_min = 1,
++ .periods_max = 4 * 8 - 1,
++};
++
++static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
++{
++ audio_info("Freeing up alsa stream here ..\n");
++ if (runtime->private_data)
++ kfree(runtime->private_data);
++ runtime->private_data = NULL;
++}
++
++static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id)
++{
++ bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id;
++ uint32_t consumed = 0;
++ int new_period = 0;
++
++ audio_info(" .. IN\n");
++
++ audio_info("alsa_stream=%p substream=%p\n", alsa_stream,
++ alsa_stream ? alsa_stream->substream : 0);
++
++ if (alsa_stream->open)
++ consumed = bcm2835_audio_retrieve_buffers(alsa_stream);
++
++ /* We get called only if playback was triggered, So, the number of buffers we retrieve in
++ * each iteration are the buffers that have been played out already
++ */
++
++ if (alsa_stream->period_size) {
++ if ((alsa_stream->pos / alsa_stream->period_size) !=
++ ((alsa_stream->pos + consumed) / alsa_stream->period_size))
++ new_period = 1;
++ }
++ audio_debug("updating pos cur: %d + %d max:%d new_period:%d\n",
++ alsa_stream->pos,
++ (consumed /** AUDIO_IPC_BLOCK_BUFFER_SIZE*/ ),
++ alsa_stream->buffer_size, new_period);
++ if (alsa_stream->buffer_size) {
++ alsa_stream->pos += consumed;
++ alsa_stream->pos %= alsa_stream->buffer_size;
++ }
++ if (alsa_stream->substream) {
++ if (new_period)
++ snd_pcm_period_elapsed(alsa_stream->substream);
++ } else {
++ audio_warning(" unexpected NULL substream\n");
++ }
++ audio_info(" .. OUT\n");
++
++ return IRQ_HANDLED;
++}
++
++/* open callback */
++static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
++{
++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream;
++ int idx;
++ int err;
++
++ audio_info(" .. IN (%d)\n", substream->number);
++
++ audio_warning("Alsa open (%d)\n", substream->number);
++ idx = substream->number;
++
++ if (idx > MAX_SUBSTREAMS) {
++ audio_error
++ ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
++ idx, MAX_SUBSTREAMS);
++ err = -ENODEV;
++ goto out;
++ }
++
++ /* Check if we are ready */
++ if (!(chip->avail_substreams & (1 << idx))) {
++ /* We are not ready yet */
++ audio_error("substream(%d) device is not ready yet\n", idx);
++ err = -EAGAIN;
++ goto out;
++ }
++
++ alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL);
++ if (alsa_stream == NULL) {
++ return -ENOMEM;
++ }
++
++ /* Initialise alsa_stream */
++ alsa_stream->chip = chip;
++ alsa_stream->substream = substream;
++ alsa_stream->idx = idx;
++ chip->alsa_stream[idx] = alsa_stream;
++
++ sema_init(&alsa_stream->buffers_update_sem, 0);
++ sema_init(&alsa_stream->control_sem, 0);
++ spin_lock_init(&alsa_stream->lock);
++
++ /* Enabled in start trigger, called on each "fifo irq" after that */
++ alsa_stream->enable_fifo_irq = 0;
++ alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq;
++
++ runtime->private_data = alsa_stream;
++ runtime->private_free = snd_bcm2835_playback_free;
++ runtime->hw = snd_bcm2835_playback_hw;
++
++ /* minimum 16 bytes alignment (for vchiq bulk transfers) */
++ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
++ 16);
++
++ err = bcm2835_audio_open(alsa_stream);
++ if (err != 0) {
++ kfree(alsa_stream);
++ return err;
++ }
++
++ alsa_stream->open = 1;
++ alsa_stream->draining = 1;
++
++out:
++ audio_info(" .. OUT =%d\n", err);
++
++ return err;
++}
++
++/* close callback */
++static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
++{
++ /* the hardware-specific codes will be here */
++
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++
++ audio_info(" .. IN\n");
++ audio_warning("Alsa close\n");
++
++ /*
++ * Call stop if it's still running. This happens when app
++ * is force killed and we don't get a stop trigger.
++ */
++ if (alsa_stream->running) {
++ int err;
++ err = bcm2835_audio_stop(alsa_stream);
++ alsa_stream->running = 0;
++ if (err != 0)
++ audio_error(" Failed to STOP alsa device\n");
++ }
++
++ alsa_stream->period_size = 0;
++ alsa_stream->buffer_size = 0;
++
++ if (alsa_stream->open) {
++ alsa_stream->open = 0;
++ bcm2835_audio_close(alsa_stream);
++ }
++ if (alsa_stream->chip)
++ alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL;
++ /*
++ * Do not free up alsa_stream here, it will be freed up by
++ * runtime->private_free callback we registered in *_open above
++ */
++
++ audio_info(" .. OUT\n");
++
++ return 0;
++}
++
++/* hw_params callback */
++static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ int err;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream =
++ (bcm2835_alsa_stream_t *) runtime->private_data;
++
++ audio_info(" .. IN\n");
++
++ err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
++ if (err < 0) {
++ audio_error
++ (" pcm_lib_malloc failed to allocated pages for buffers\n");
++ return err;
++ }
++
++ err = bcm2835_audio_set_params(alsa_stream, params_channels(params),
++ params_rate(params),
++ snd_pcm_format_width(params_format
++ (params)));
++ if (err < 0) {
++ audio_error(" error setting hw params\n");
++ }
++
++ bcm2835_audio_setup(alsa_stream);
++ audio_info(" .. OUT\n");
++
++ return err;
++}
++
++/* hw_free callback */
++static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ audio_info(" .. IN\n");
++ return snd_pcm_lib_free_pages(substream);
++}
++
++/* prepare callback */
++static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++
++ audio_info(" .. IN\n");
++
++ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream);
++ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream);
++ alsa_stream->pos = 0;
++
++ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n",
++ alsa_stream->buffer_size, alsa_stream->period_size,
++ alsa_stream->pos, runtime->frame_bits);
++
++ audio_info(" .. OUT\n");
++ return 0;
++}
++
++/* trigger callback */
++static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++ int err = 0;
++
++ audio_info(" .. IN\n");
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n",
++ alsa_stream->running);
++ if (!alsa_stream->running) {
++ err = bcm2835_audio_start(alsa_stream);
++ if (err == 0) {
++ alsa_stream->running = 1;
++ alsa_stream->draining = 1;
++ }
++ }
++ break;
++ case SNDRV_PCM_TRIGGER_STOP:
++ audio_debug
++ ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n",
++ runtime->status->state == SNDRV_PCM_STATE_DRAINING,
++ alsa_stream->running);
++ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
++ audio_info("DRAINING\n");
++ alsa_stream->draining = 1;
++ } else {
++ audio_info("DROPPING\n");
++ alsa_stream->draining = 0;
++ }
++ if (alsa_stream->running) {
++ err = bcm2835_audio_stop(alsa_stream);
++ if (err != 0)
++ audio_error(" Failed to STOP alsa device\n");
++ alsa_stream->running = 0;
++ }
++ break;
++ default:
++ err = -EINVAL;
++ }
++
++ audio_info(" .. OUT\n");
++ return err;
++}
++
++/* pointer callback */
++static snd_pcm_uframes_t
++snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++
++ audio_info(" .. IN\n");
++
++ audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0,
++ frames_to_bytes(runtime, runtime->status->hw_ptr),
++ frames_to_bytes(runtime, runtime->control->appl_ptr),
++ alsa_stream->pos);
++
++ audio_info(" .. OUT\n");
++ return bytes_to_frames(runtime, alsa_stream->pos);
++}
++
++static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream,
++ int channel, snd_pcm_uframes_t pos, void *src,
++ snd_pcm_uframes_t count)
++{
++ int ret;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++
++ audio_info(" .. IN\n");
++ audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n",
++ frames_to_bytes(runtime, count), frames_to_bytes(runtime,
++ runtime->
++ status->
++ hw_ptr),
++ frames_to_bytes(runtime, runtime->control->appl_ptr),
++ alsa_stream->pos);
++ ret =
++ bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count),
++ src);
++ audio_info(" .. OUT\n");
++ return ret;
++}
++
++static int snd_bcm2835_pcm_silence(struct snd_pcm_substream *substream,
++ int channel, snd_pcm_uframes_t post,
++ snd_pcm_uframes_t count)
++{
++ int ret;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++
++ audio_info(" .. IN\n");
++ audio_debug("silence....... (%d) hwptr=%d appl=%d pos=%d\n",
++ frames_to_bytes(runtime, count), frames_to_bytes(runtime,
++ runtime->
++ status->
++ hw_ptr),
++ frames_to_bytes(runtime, runtime->control->appl_ptr),
++ alsa_stream->pos);
++ ret =
++ bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count),
++ NULL);
++ audio_info(" .. OUT\n");
++ return ret;
++}
++
++static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream,
++ unsigned int cmd, void *arg)
++{
++ int ret = snd_pcm_lib_ioctl(substream, cmd, arg);
++ audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream,
++ cmd, arg, arg ? *(unsigned *)arg : 0, ret);
++ return ret;
++}
++
++/* operators */
++static struct snd_pcm_ops snd_bcm2835_playback_ops = {
++ .open = snd_bcm2835_playback_open,
++ .close = snd_bcm2835_playback_close,
++ .ioctl = snd_bcm2835_pcm_lib_ioctl,
++ .hw_params = snd_bcm2835_pcm_hw_params,
++ .hw_free = snd_bcm2835_pcm_hw_free,
++ .prepare = snd_bcm2835_pcm_prepare,
++ .trigger = snd_bcm2835_pcm_trigger,
++ .pointer = snd_bcm2835_pcm_pointer,
++ .copy = snd_bcm2835_pcm_copy,
++ .silence = snd_bcm2835_pcm_silence,
++};
++
++/* create a pcm device */
++int __devinit snd_bcm2835_new_pcm(bcm2835_chip_t * chip)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ audio_info(" .. IN\n");
++ err =
++ snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm);
++ if (err < 0)
++ return err;
++ pcm->private_data = chip;
++ strcpy(pcm->name, "bcm2835 ALSA");
++ chip->pcm = pcm;
++ chip->dest = AUDIO_DEST_AUTO;
++ chip->volume = 100;
++ /* set operators */
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_bcm2835_playback_ops);
++
++ /* pre-allocation of buffers */
++ /* NOTE: this may fail */
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
++ snd_dma_continuous_data
++ (GFP_KERNEL), 64 * 1024,
++ 64 * 1024);
++
++ audio_info(" .. OUT\n");
++
++ return 0;
++}
+--- /dev/null
++++ b/sound/arm/bcm2835-vchiq.c
+@@ -0,0 +1,818 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#include <linux/device.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/mm.h>
++#include <linux/syscalls.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/atomic.h>
++
++#include "bcm2835.h"
++
++/* ---- Include Files -------------------------------------------------------- */
++
++#include "interface/vchi/vchi.h"
++#include "interface/vcos/vcos.h"
++#include "interface/vcos/vcos_logging.h"
++#include "vc_vchi_audioserv_defs.h"
++
++/* ---- Private Constants and Types ------------------------------------------ */
++
++/* VCOS logging category for this service */
++#define VCOS_LOG_CATEGORY (&audio_log_category)
++
++/* Default VCOS logging level */
++#define LOG_LEVEL VCOS_LOG_WARN
++
++/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */
++#define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg)
++#define LOG_WARN( fmt, arg... ) vcos_log_warn( "%s:%d " fmt, __func__, __LINE__, ##arg)
++#define LOG_INFO( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
++#define LOG_DBG( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg)
++
++typedef struct opaque_AUDIO_INSTANCE_T {
++ uint32_t num_connections;
++ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS];
++ VCOS_EVENT_T msg_avail_event;
++ VCOS_MUTEX_T vchi_mutex;
++ bcm2835_alsa_stream_t *alsa_stream;
++ int32_t result, got_result;
++} AUDIO_INSTANCE_T;
++
++/* ---- Private Variables ---------------------------------------------------- */
++
++/* VCOS logging category for this service */
++static VCOS_LOG_CAT_T audio_log_category;
++
++/* ---- Private Function Prototypes ------------------------------------------ */
++
++/* ---- Private Functions ---------------------------------------------------- */
++
++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream);
++static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream);
++
++typedef struct {
++ struct work_struct my_work;
++ bcm2835_alsa_stream_t *alsa_stream;
++ int x;
++} my_work_t;
++
++static void my_wq_function(struct work_struct *work)
++{
++ my_work_t *w = (my_work_t *) work;
++ int ret = -9;
++ LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->x);
++ switch (w->x) {
++ case 1:
++ ret = bcm2835_audio_start_worker(w->alsa_stream);
++ break;
++ case 2:
++ ret = bcm2835_audio_stop_worker(w->alsa_stream);
++ break;
++ default:
++ LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->x);
++ break;
++ }
++ kfree((void *)work);
++ LOG_DBG(" .. OUT %d\n", ret);
++}
++
++int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream)
++{
++ int ret = -1;
++ LOG_DBG(" .. IN\n");
++ if (alsa_stream->my_wq) {
++ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_KERNEL);
++ /* Queue some work (item 1) */
++ if (work) {
++ INIT_WORK((struct work_struct *)work, my_wq_function);
++ work->alsa_stream = alsa_stream;
++ work->x = 1;
++ if (queue_work
++ (alsa_stream->my_wq, (struct work_struct *)work))
++ ret = 0;
++ } else
++ LOG_ERR(" .. Error: NULL work kmalloc\n");
++ }
++ LOG_DBG(" .. OUT %d\n", ret);
++ return ret;
++}
++
++int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream)
++{
++ int ret = -1;
++ LOG_DBG(" .. IN\n");
++ if (alsa_stream->my_wq) {
++ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_KERNEL);
++ /* Queue some work (item 1) */
++ if (work) {
++ INIT_WORK((struct work_struct *)work, my_wq_function);
++ work->alsa_stream = alsa_stream;
++ work->x = 2;
++ if (queue_work
++ (alsa_stream->my_wq, (struct work_struct *)work))
++ ret = 0;
++ } else
++ LOG_ERR(" .. Error: NULL work kmalloc\n");
++ }
++ LOG_DBG(" .. OUT %d\n", ret);
++ return ret;
++}
++
++void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream)
++{
++ alsa_stream->my_wq = create_workqueue("my_queue");
++}
++
++void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream)
++{
++ if (alsa_stream->my_wq) {
++ flush_workqueue(alsa_stream->my_wq);
++ destroy_workqueue(alsa_stream->my_wq);
++ alsa_stream->my_wq = NULL;
++ }
++}
++
++static void audio_vchi_callback(void *param,
++ const VCHI_CALLBACK_REASON_T reason,
++ void *msg_handle)
++{
++ AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param;
++ int32_t status;
++ int32_t msg_len;
++ VC_AUDIO_MSG_T m;
++ bcm2835_alsa_stream_t *alsa_stream = 0;
++ LOG_DBG(" .. IN instance=%p, param=%p, reason=%d, handle=%p\n",
++ instance, param, reason, msg_handle);
++
++ if (!instance || reason != VCHI_CALLBACK_MSG_AVAILABLE) {
++ return;
++ }
++ alsa_stream = instance->alsa_stream;
++ status = vchi_msg_dequeue(instance->vchi_handle[0],
++ &m, sizeof m, &msg_len, VCHI_FLAGS_NONE);
++ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) {
++ LOG_DBG
++ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n",
++ instance, m.u.result.success);
++ BUG_ON(instance->got_result);
++ instance->result = m.u.result.success;
++ instance->got_result = 1;
++ vcos_event_signal(&instance->msg_avail_event);
++ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) {
++ irq_handler_t callback = (irq_handler_t) m.u.complete.callback;
++ LOG_DBG
++ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n",
++ instance, m.u.complete.count);
++ if (alsa_stream && callback) {
++ atomic_add(m.u.complete.count, &alsa_stream->retrieved);
++ callback(0, alsa_stream);
++ } else {
++ LOG_DBG(" .. unexpected alsa_stream=%p, callback=%p\n",
++ alsa_stream, callback);
++ }
++ vcos_event_signal(&instance->msg_avail_event);
++ } else {
++ LOG_DBG(" .. unexpected m.type=%d\n", m.type);
++ }
++}
++
++static AUDIO_INSTANCE_T *vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance,
++ VCHI_CONNECTION_T **
++ vchi_connections,
++ uint32_t num_connections)
++{
++ uint32_t i;
++ AUDIO_INSTANCE_T *instance;
++ VCOS_STATUS_T status;
++
++ LOG_DBG("%s: start", __func__);
++
++ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) {
++ LOG_ERR("%s: unsupported number of connections %u (max=%u)",
++ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS);
++
++ return NULL;
++ }
++ /* Allocate memory for this instance */
++ instance = vcos_malloc(sizeof(*instance), "audio_instance");
++ memset(instance, 0, sizeof(*instance));
++
++ instance->num_connections = num_connections;
++ /* Create the message available event */
++ status =
++ vcos_event_create(&instance->msg_avail_event, "audio_msg_avail");
++ if (status != VCOS_SUCCESS) {
++ LOG_ERR("%s: failed to create event (status=%d)", __func__,
++ status);
++
++ goto err_free_mem;
++ }
++ /* Create a lock for exclusive, serialized VCHI connection access */
++ status = vcos_mutex_create(&instance->vchi_mutex, "audio_vchi_mutex");
++ if (status != VCOS_SUCCESS) {
++ LOG_ERR("%s: failed to create event (status=%d)", __func__,
++ status);
++
++ goto err_delete_event;
++ }
++ /* Open the VCHI service connections */
++ for (i = 0; i < num_connections; i++) {
++ SERVICE_CREATION_T params = {
++ VC_AUDIO_SERVER_NAME, // 4cc service code
++ vchi_connections[i], // passed in fn pointers
++ 0, // rx fifo size (unused)
++ 0, // tx fifo size (unused)
++ audio_vchi_callback, // service callback
++ instance, // service callback parameter
++ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk recieves
++ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk transmits
++ VCOS_FALSE // want crc check on bulk transfers
++ };
++
++ status = vchi_service_open(vchi_instance, &params,
++ &instance->vchi_handle[i]);
++ if (status != VCOS_SUCCESS) {
++ LOG_ERR
++ ("%s: failed to open VCHI service connection (status=%d)",
++ __func__, status);
++
++ goto err_close_services;
++ }
++ /* Finished with the service for now */
++ vchi_service_release(instance->vchi_handle[i]);
++ }
++
++ return instance;
++
++err_close_services:
++ for (i = 0; i < instance->num_connections; i++) {
++ vchi_service_close(instance->vchi_handle[i]);
++ }
++
++ vcos_mutex_delete(&instance->vchi_mutex);
++
++err_delete_event:
++ vcos_event_delete(&instance->msg_avail_event);
++
++err_free_mem:
++ vcos_free(instance);
++
++ return NULL;
++}
++
++static int32_t vc_vchi_audio_deinit(AUDIO_INSTANCE_T * instance)
++{
++ uint32_t i;
++
++ LOG_DBG(" .. IN\n");
++
++ if (instance == NULL) {
++ LOG_ERR("%s: invalid handle %p", __func__, instance);
++
++ return -1;
++ }
++
++ LOG_DBG(" .. about to lock (%d)\n", instance->num_connections);
++ vcos_mutex_lock(&instance->vchi_mutex);
++
++ /* Close all VCHI service connections */
++ for (i = 0; i < instance->num_connections; i++) {
++ int32_t success;
++ LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]);
++ vchi_service_use(instance->vchi_handle[i]);
++
++ success = vchi_service_close(instance->vchi_handle[i]);
++ if (success != 0) {
++ LOG_ERR
++ ("%s: failed to close VCHI service connection (status=%d)",
++ __func__, success);
++ }
++ }
++
++ vcos_mutex_unlock(&instance->vchi_mutex);
++
++ vcos_mutex_delete(&instance->vchi_mutex);
++
++ vcos_event_delete(&instance->msg_avail_event);
++
++ vcos_free(instance);
++
++ /* Unregister the log category so we can add it back next time */
++ vcos_log_unregister(&audio_log_category);
++
++ LOG_DBG(" .. OUT\n");
++
++ return 0;
++}
++
++static int bcm2835_audio_open_connection(bcm2835_alsa_stream_t * alsa_stream)
++{
++ static VCHI_INSTANCE_T vchi_instance;
++ static VCHI_CONNECTION_T *vchi_connection;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ LOG_INFO("%s: start", __func__);
++ //BUG_ON(instance);
++ if (instance) {
++ LOG_ERR("%s: VCHI instance already open (%p)",
++ __func__, instance);
++ instance->alsa_stream = alsa_stream;
++ alsa_stream->instance = instance;
++ ret = 0; // xxx todo -1;
++ goto err_free_mem;
++ }
++
++ /* Initialize and create a VCHI connection */
++ ret = vchi_initialise(&vchi_instance);
++ if (ret != 0) {
++ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++ ret = vchi_connect(NULL, 0, vchi_instance);
++ if (ret != 0) {
++ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)",
++ __func__, ret);
++
++ ret = -EIO;
++ goto err_free_mem;
++ }
++
++ /* Set up the VCOS logging */
++ vcos_log_set_level(VCOS_LOG_CATEGORY, LOG_LEVEL);
++ vcos_log_register("audio", VCOS_LOG_CATEGORY);
++
++ /* Initialize an instance of the audio service */
++ instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1);
++
++ if (instance == NULL /*|| audio_handle != instance */ ) {
++ LOG_ERR("%s: failed to initialize audio service", __func__);
++
++ ret = -EPERM;
++ goto err_free_mem;
++ }
++
++ instance->alsa_stream = alsa_stream;
++ alsa_stream->instance = instance;
++
++ LOG_DBG(" success !\n");
++err_free_mem:
++ LOG_DBG(" .. OUT\n");
++
++ return ret;
++}
++
++int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream)
++{
++ AUDIO_INSTANCE_T *instance;
++ VC_AUDIO_MSG_T m;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ my_workqueue_init(alsa_stream);
++
++ ret = bcm2835_audio_open_connection(alsa_stream);
++ if (ret != 0) {
++ ret = -1;
++ goto exit;
++ }
++ instance = alsa_stream->instance;
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ m.type = VC_AUDIO_MSG_TYPE_OPEN;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++exit:
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream,
++ bcm2835_chip_t * chip)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ LOG_INFO
++ (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume);
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ instance->got_result = 0;
++ instance->result = -1;
++
++ m.type = VC_AUDIO_MSG_TYPE_CONTROL;
++ m.u.control.dest = chip->dest;
++ m.u.control.volume = chip->volume;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ /* We are expecting a reply from the videocore */
++ while (!instance->got_result) {
++ success = vcos_event_wait(&instance->msg_avail_event);
++ if (success != VCOS_SUCCESS) {
++ LOG_ERR("%s: failed on waiting for event (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++ }
++
++ if (instance->result != 0) {
++ LOG_ERR("%s: result=%d", __func__, instance->result);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++int bcm2835_audio_set_ctls(bcm2835_chip_t * chip)
++{
++ int i;
++ int ret = 0;
++ LOG_DBG(" .. IN\n");
++ /* change ctls for all substreams */
++ for (i = 0; i < MAX_SUBSTREAMS; i++) {
++ if (chip->avail_substreams & (1 << i)) {
++ if (!chip->alsa_stream[i])
++ ret = 0;
++ else if (bcm2835_audio_set_ctls_chan
++ (chip->alsa_stream[i], chip) != 0)
++ ret = -1;
++ }
++ }
++ LOG_DBG(" .. OUT ret=%d\n", ret);
++ return ret;
++}
++
++int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,
++ uint32_t channels, uint32_t samplerate,
++ uint32_t bps)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ LOG_INFO
++ (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n",
++ channels, samplerate, bps);
++
++ /* resend ctls - alsa_stream may not have been open when first send */
++ ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip);
++ if (ret != 0) {
++ LOG_ERR(" Alsa controls not supported\n");
++ return -EINVAL;
++ }
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ instance->got_result = 0;
++ instance->result = -1;
++
++ m.type = VC_AUDIO_MSG_TYPE_CONFIG;
++ m.u.config.channels = channels;
++ m.u.config.samplerate = samplerate;
++ m.u.config.bps = bps;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ /* We are expecting a reply from the videocore */
++ while (!instance->got_result) {
++ success = vcos_event_wait(&instance->msg_avail_event);
++ if (success != VCOS_SUCCESS) {
++ LOG_ERR("%s: failed on waiting for event (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++ }
++
++ if (instance->result != 0) {
++ LOG_ERR("%s: result=%d", __func__, instance->result);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream)
++{
++ LOG_DBG(" .. IN\n");
++
++ LOG_DBG(" .. OUT\n");
++
++ return 0;
++}
++
++static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ m.type = VC_AUDIO_MSG_TYPE_START;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ m.type = VC_AUDIO_MSG_TYPE_STOP;
++ m.u.stop.draining = alsa_stream->draining;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++ LOG_DBG(" .. IN\n");
++
++ my_workqueue_quit(alsa_stream);
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ m.type = VC_AUDIO_MSG_TYPE_CLOSE;
++ instance->got_result = 0;
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++ ret = -1;
++ goto unlock;
++ }
++ while (!instance->got_result) {
++ success = vcos_event_wait(&instance->msg_avail_event);
++ if (success != VCOS_SUCCESS) {
++ LOG_ERR("%s: failed on waiting for event (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++ }
++ if (instance->result != 0) {
++ LOG_ERR("%s: failed result (status=%d)",
++ __func__, instance->result);
++
++ ret = -1;
++ goto unlock;
++ }
++
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++
++ /* Stop the audio service */
++ if (instance) {
++ vc_vchi_audio_deinit(instance);
++ alsa_stream->instance = NULL;
++ }
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count,
++ void *src)
++{
++ VC_AUDIO_MSG_T m;
++ AUDIO_INSTANCE_T *instance = alsa_stream->instance;
++ int32_t success;
++ int ret;
++
++ LOG_DBG(" .. IN\n");
++
++ LOG_INFO(" Writing %d bytes from %p\n", count, src);
++
++ vcos_mutex_lock(&instance->vchi_mutex);
++ vchi_service_use(instance->vchi_handle[0]);
++
++ m.type = VC_AUDIO_MSG_TYPE_WRITE;
++ m.u.write.count = count;
++ m.u.write.callback = alsa_stream->fifo_irq_handler;
++ m.u.write.cookie = alsa_stream;
++ m.u.write.silence = src == NULL;
++
++ /* Send the message to the videocore */
++ success = vchi_msg_queue(instance->vchi_handle[0],
++ &m, sizeof m,
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
++
++ if (success != 0) {
++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++ LOG_DBG(" ... sent header\n");
++ if (!m.u.write.silence) {
++ /* Send the message to the videocore */
++ success = vchi_bulk_queue_transmit(instance->vchi_handle[0],
++ src, count,
++ 0 *
++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED
++ +
++ 1 *
++ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ,
++ NULL);
++ if (success != 0) {
++ LOG_ERR
++ ("%s: failed on vchi_bulk_queue_transmit (status=%d)",
++ __func__, success);
++
++ ret = -1;
++ goto unlock;
++ }
++ }
++ ret = 0;
++
++unlock:
++ vchi_service_release(instance->vchi_handle[0]);
++ vcos_mutex_unlock(&instance->vchi_mutex);
++ LOG_DBG(" .. OUT\n");
++ return ret;
++}
++
++/**
++ * Returns all buffers from arm->vc
++ */
++void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream)
++{
++ LOG_DBG(" .. IN\n");
++ LOG_DBG(" .. OUT\n");
++ return;
++}
++
++/**
++ * Forces VC to flush(drop) its filled playback buffers and
++ * return them the us. (VC->ARM)
++ */
++void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream)
++{
++ LOG_DBG(" .. IN\n");
++ LOG_DBG(" .. OUT\n");
++}
++
++uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream)
++{
++ uint32_t count = atomic_read(&alsa_stream->retrieved);
++ atomic_sub(count, &alsa_stream->retrieved);
++ return count;
++}
+--- /dev/null
++++ b/sound/arm/bcm2835.c
+@@ -0,0 +1,424 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#include <linux/platform_device.h>
++
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++
++#include "bcm2835.h"
++
++/* module parameters (see "Module Parameters") */
++/* SNDRV_CARDS: maximum number of cards supported by this module */
++static int index[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = -1 };
++static char *id[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = NULL };
++static int enable[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = 1 };
++
++/* HACKY global pointers needed for successive probes to work : ssp
++ * But compared against the changes we will have to do in VC audio_ipc code
++ * to export 8 audio_ipc devices as a single IPC device and then monitor all
++ * four devices in a thread, this gets things done quickly and should be easier
++ * to debug if we run into issues
++ */
++
++static struct snd_card *g_card = NULL;
++static bcm2835_chip_t *g_chip = NULL;
++
++static int snd_bcm2835_free(bcm2835_chip_t * chip)
++{
++ kfree(chip);
++ return 0;
++}
++
++/* component-destructor
++ * (see "Management of Cards and Components")
++ */
++static int snd_bcm2835_dev_free(struct snd_device *device)
++{
++ return snd_bcm2835_free(device->device_data);
++}
++
++/* chip-specific constructor
++ * (see "Management of Cards and Components")
++ */
++static int __devinit snd_bcm2835_create(struct snd_card *card,
++ struct platform_device *pdev,
++ bcm2835_chip_t ** rchip)
++{
++ bcm2835_chip_t *chip;
++ int err;
++ static struct snd_device_ops ops = {
++ .dev_free = snd_bcm2835_dev_free,
++ };
++
++ *rchip = NULL;
++
++ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
++ if (chip == NULL)
++ return -ENOMEM;
++
++ chip->card = card;
++
++ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
++ if (err < 0) {
++ snd_bcm2835_free(chip);
++ return err;
++ }
++
++ *rchip = chip;
++ return 0;
++}
++
++static int __devinit snd_bcm2835_alsa_probe(struct platform_device *pdev)
++{
++ static int dev;
++ bcm2835_chip_t *chip;
++ struct snd_card *card;
++ int err;
++ printk(KERN_INFO "### snd_bcm2835_alsa_probe %p ###", pdev);
++
++ printk
++ ("############ PROBING FOR bcm2835 ALSA device (%d):(%d) ###############\n",
++ dev, enable[dev]);
++
++ if (dev >= MAX_SUBSTREAMS)
++ return -ENODEV;
++
++ if (!enable[dev]) {
++ dev++;
++ return -ENOENT;
++ }
++
++ if (dev > 0)
++ goto add_register_map;
++
++ printk("Creating card...\n");
++ err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &g_card);
++ if (err < 0)
++ goto out;
++
++ snd_card_set_dev(g_card, &pdev->dev);
++ strcpy(g_card->driver, "BRCM bcm2835 ALSA Driver");
++ strcpy(g_card->shortname, "bcm2835 ALSA");
++ sprintf(g_card->longname, "%s", g_card->shortname);
++
++ printk("Creating device/chip ..\n");
++ err = snd_bcm2835_create(g_card, pdev, &chip);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to create bcm2835 chip\n");
++ goto out_bcm2835_create;
++ }
++
++ g_chip = chip;
++ err = snd_bcm2835_new_pcm(chip);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to create new BCM2835 pcm device\n");
++ goto out_bcm2835_new_pcm;
++ }
++
++ printk("Adding controls ..\n");
++ err = snd_bcm2835_new_ctl(chip);
++ if (err < 0) {
++ printk(KERN_ERR "Failed to create new BCM2835 ctl\n");
++ goto out_bcm2835_new_ctl;
++ }
++
++add_register_map:
++ card = g_card;
++ chip = g_chip;
++
++ BUG_ON(!(card && chip));
++
++ chip->avail_substreams |= (1 << dev);
++ chip->pdev[dev] = pdev;
++
++ if (dev == 0) {
++ printk("Registering card ....\n");
++ err = snd_card_register(card);
++ if (err < 0) {
++ printk(KERN_ERR
++ "Failed to register bcm2835 ALSA card \n");
++ goto out_card_register;
++ }
++ platform_set_drvdata(pdev, card);
++ printk("bcm2835 ALSA CARD CREATED!\n");
++ } else {
++ printk("bcm2835 ALSA CHIP CREATED!\n");
++ platform_set_drvdata(pdev, (void *)dev);
++ }
++
++ dev++;
++
++ return 0;
++
++out_card_register:
++out_bcm2835_new_ctl:
++out_bcm2835_new_pcm:
++out_bcm2835_create:
++ BUG_ON(!g_card);
++ if (snd_card_free(g_card))
++ printk(KERN_ERR "Failed to free Registered alsa card\n");
++ g_card = NULL;
++out:
++ dev = SNDRV_CARDS; /* stop more avail_substreams from being probed */
++ printk(KERN_ERR "BCM2835 ALSA Probe failed !!\n");
++ return err;
++}
++
++static int snd_bcm2835_alsa_remove(struct platform_device *pdev)
++{
++ uint32_t idx;
++ void *drv_data;
++
++ drv_data = platform_get_drvdata(pdev);
++
++ if (drv_data == (void *)g_card) {
++ /* This is the card device */
++ snd_card_free((struct snd_card *)drv_data);
++ g_card = NULL;
++ g_chip = NULL;
++ } else {
++ idx = (uint32_t) drv_data;
++ if (g_card != NULL) {
++ BUG_ON(!g_chip);
++ /* We pass chip device numbers in audio ipc devices
++ * other than the one we registered our card with
++ */
++ idx = (uint32_t) drv_data;
++ BUG_ON(!idx || idx > MAX_SUBSTREAMS);
++ g_chip->avail_substreams &= ~(1 << idx);
++ /* There should be atleast one substream registered
++ * after we are done here, as it wil be removed when
++ * the *remove* is called for the card device
++ */
++ BUG_ON(!g_chip->avail_substreams);
++ }
++ }
++
++ platform_set_drvdata(pdev, NULL);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int snd_bcm2835_alsa_suspend(struct platform_device *pdev,
++ pm_message_t state)
++{
++ return 0;
++}
++
++static int snd_bcm2835_alsa_resume(struct platform_device *pdev)
++{
++ return 0;
++}
++
++#endif
++
++static struct platform_driver bcm2835_alsa0_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD0",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa1_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD1",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa2_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD2",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa3_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD3",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa4_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD4",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa5_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD5",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa6_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD6",
++ .owner = THIS_MODULE,
++ },
++};
++
++static struct platform_driver bcm2835_alsa7_driver = {
++ .probe = snd_bcm2835_alsa_probe,
++ .remove = snd_bcm2835_alsa_remove,
++#ifdef CONFIG_PM
++ .suspend = snd_bcm2835_alsa_suspend,
++ .resume = snd_bcm2835_alsa_resume,
++#endif
++ .driver = {
++ .name = "bcm2835_AUD7",
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __devinit bcm2835_alsa_device_init(void)
++{
++ int err;
++ err = platform_driver_register(&bcm2835_alsa0_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa0_driver %d .\n", err);
++ goto out;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa1_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa1_driver %d .\n", err);
++ goto unregister_0;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa2_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa2_driver %d .\n", err);
++ goto unregister_1;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa3_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa3_driver %d .\n", err);
++ goto unregister_2;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa4_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa4_driver %d .\n", err);
++ goto unregister_3;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa5_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa5_driver %d .\n", err);
++ goto unregister_4;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa6_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa6_driver %d .\n", err);
++ goto unregister_5;
++ }
++
++ err = platform_driver_register(&bcm2835_alsa7_driver);
++ if (err) {
++ printk("Error registering bcm2835_alsa7_driver %d .\n", err);
++ goto unregister_6;
++ }
++ printk(KERN_INFO "### BCM2835 ALSA driver init %s ### \n",
++ err ? "FAILED" : "OK");
++
++ return 0;
++
++unregister_6:
++ platform_driver_unregister(&bcm2835_alsa6_driver);
++unregister_5:
++ platform_driver_unregister(&bcm2835_alsa5_driver);
++unregister_4:
++ platform_driver_unregister(&bcm2835_alsa4_driver);
++unregister_3:
++ platform_driver_unregister(&bcm2835_alsa3_driver);
++unregister_2:
++ platform_driver_unregister(&bcm2835_alsa2_driver);
++unregister_1:
++ platform_driver_unregister(&bcm2835_alsa1_driver);
++unregister_0:
++ platform_driver_unregister(&bcm2835_alsa0_driver);
++out:
++ return err;
++}
++
++static void __devexit bcm2835_alsa_device_exit(void)
++{
++ platform_driver_unregister(&bcm2835_alsa0_driver);
++ platform_driver_unregister(&bcm2835_alsa1_driver);
++ platform_driver_unregister(&bcm2835_alsa2_driver);
++ platform_driver_unregister(&bcm2835_alsa3_driver);
++ platform_driver_unregister(&bcm2835_alsa4_driver);
++ platform_driver_unregister(&bcm2835_alsa5_driver);
++ platform_driver_unregister(&bcm2835_alsa6_driver);
++ platform_driver_unregister(&bcm2835_alsa7_driver);
++}
++
++late_initcall(bcm2835_alsa_device_init);
++module_exit(bcm2835_alsa_device_exit);
++
++MODULE_AUTHOR("Dom Cobley");
++MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:bcm2835_alsa");
+--- /dev/null
++++ b/sound/arm/bcm2835.h
+@@ -0,0 +1,242 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#ifndef __SOUND_ARM_BCM2835_H
++#define __SOUND_ARM_BCM2835_H
++
++#define SUBSTREAM_NUM 1
++
++#include <linux/device.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <linux/workqueue.h>
++
++/* #define DUMP_RAW_DATA */
++//#define AUDIO_DEBUG_ENABLE
++//#define AUDIO_VERBOSE_DEBUG_ENABLE
++
++/* Debug macros */
++#ifdef AUDIO_DEBUG_ENABLE
++
++#ifdef AUDIO_VERBOSE_DEBUG_ENABLE
++
++#define audio_debug(fmt, arg...) \
++ printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)
++
++#define audio_info(fmt, arg...) \
++ printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg)
++
++#else
++
++#define audio_debug(fmt, arg...) do {} while (0)
++
++#define audio_info(fmt, arg...) do {} while (0)
++
++#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */
++
++#else
++
++#define audio_debug(fmt, arg...) do {} while (0)
++
++#define audio_info(fmt, arg...) do {} while (0)
++
++#endif /* AUDIO_DEBUG_ENABLE */
++
++#define audio_error(fmt, arg...) \
++ printk(KERN_ERR"%s:%d " fmt, __func__, __LINE__, ##arg)
++
++#define audio_warning(fmt, arg...) \
++ printk(KERN_WARNING"%s:%d " fmt, __func__, __LINE__, ##arg)
++
++#define audio_alert(fmt, arg...) \
++ printk(KERN_ALERT"%s:%d " fmt, __func__, __LINE__, ##arg)
++
++#define MAX_SUBSTREAMS (8)
++#define AVAIL_SUBSTREAMS_MASK (0xff)
++
++#define AUDIO_IPC_BLOCK_NUM_BUFFERS (8)
++#define AUDIO_IPC_BLOCK_BUFFER_SIZE (1024*8)
++
++#define AUDIO_CONTROL_OFFSET (0x00)
++#define CTRL_EN_SHIFT (0)
++#define CTRL_EN_MASK (0x00000001)
++#define CTRL_PLAY_SHIFT (1)
++#define CTRL_PLAY_MASK (0x00000002)
++#define CTRL_MUTE_SHIFT (2)
++#define CTRL_MUTE_MASK (0x00000004)
++#define CTRL_SETUP_SHIFT (3)
++#define CTRL_SETUP_MASK (0x00000008)
++#define CTRL_FLUSH_SHIFT (4)
++#define CTRL_FLUSH_MASK (0x00000010)
++#define CTRL_STOPMODE_SHIFT (5)
++#define CTRL_STOPMODE_MASK (0x00000020)
++
++#define AUDIO_STATUS_OFFSET (0x04)
++#define STAT_EN_SHIFT (0)
++#define STAT_EN_MASK (0x00000001)
++#define STAT_PLAY_SHIFT (1)
++#define STAT_PLAY_MASK (0x00000002)
++#define STAT_MUTE_SHIFT (2)
++#define STAT_MUTE_MASK (0x00000004)
++#define STAT_SETUP_SHIFT (3)
++#define STAT_SETUP_MASK (0x00000008)
++#define STAT_FLUSH_SHIFT (4)
++#define STAT_FLUSH_MASK (0x00000010)
++#define STAT_STOPMODE_SHIFT (5)
++#define STAT_STOPMODE_MASK (0x00000020)
++
++/* Interrupt status */
++#define AUDIO_INTSTAT_OFFSET (0x08)
++#define INTSTAT_CONTROL_SHIFT (0)
++#define INTSTAT_CONTROL_MASK (0x0000000f)
++#define INTSTAT_FIFO_SHIFT (4)
++#define INTSTAT_FIFO_MASK (0x000000f0)
++
++/* Configuration */
++#define AUDIO_DESTINATION_OFFSET (0x0C)
++#define AUDIO_SAMPLE_RATE_OFFSET (0x10)
++#define AUDIO_BIT_RATE_OFFSET (0x14)
++#define AUDIO_VOLUME_OFFSET (0x18)
++#define AUDIO_CHANNELS_OFFSET (0x1C)
++
++/* Implemention of peterson's algorithm for shared memory semaphores */
++#define AUDIO_FLAG0_OFFSET (0x20)
++#define AUDIO_FLAG1_OFFSET (0x24)
++#define AUDIO_TURN_OFFSET (0x28)
++
++/* Fifo registers */
++#define AUDIO_IN_WRITE_PTR_OFFSET (0x30)
++#define AUDIO_IN_READ_PTR_OFFSET (0x34)
++#define AUDIO_IN_FIFO_SIZE_OFFSET (0x38)
++#define AUDIO_IN_FIFO_ENTRY_OFFSET (0x3C)
++#define AUDIO_IN_FIFO_START_OFFSET (0x40)
++
++/* 8 entries here of 4 words each = 0x80 gap from 0x50 */
++#define AUDIO_IN_FIFO_OFFSET (0x50)
++
++#define AUDIO_OUT_WRITE_PTR_OFFSET (0xD0)
++#define AUDIO_OUT_READ_PTR_OFFSET (0xD4)
++#define AUDIO_OUT_FIFO_SIZE_OFFSET (0xD8)
++#define AUDIO_OUT_FIFO_ENTRY_OFFSET (0xDC)
++#define AUDIO_OUT_FIFO_START_OFFSET (0xE0)
++
++/* 8 entries here of 4 words each = 0x80 gap from 0xF0 */
++#define AUDIO_OUT_FIFO_OFFSET (0xF0)
++
++/* Some constants for values .. */
++typedef enum {
++ AUDIO_DEST_AUTO = 0,
++ AUDIO_DEST_HEADPHONES = 1,
++ AUDIO_DEST_HDMI = 2,
++ AUDIO_DEST_MAX,
++} SND_BCM2835_ROUTE_T;
++
++typedef enum {
++ PCM_PLAYBACK_VOLUME,
++ PCM_PLAYBACK_MUTE,
++ PCM_PLAYBACK_DEVICE,
++} SND_BCM2835_CTRL_T;
++
++/* this struct is tightly packed - its size is 16bytes */
++typedef struct {
++ uint32_t buffer_id;
++ uint32_t buffer_size;
++ uint32_t buffer_ptr;
++ uint32_t spare;
++
++} AUDIO_FIFO_ENTRY_T;
++
++/* definition of the chip-specific record */
++typedef struct bcm2835_chip {
++ struct snd_card *card;
++ struct snd_pcm *pcm;
++ /* Bitmat for valid reg_base and irq numbers */
++ uint32_t avail_substreams;
++ struct platform_device *pdev[MAX_SUBSTREAMS];
++ struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS];
++
++ int volume;
++ int dest;
++ int mute;
++} bcm2835_chip_t;
++
++typedef struct bcm2835_audio_buffer {
++ uint32_t buffer_id;
++ phys_addr_t bus_addr;
++ uint8_t __iomem *start;
++ uint32_t size;
++ uint32_t data_left;
++ struct list_head link;
++
++} bcm2835_audio_buffer_t;
++
++typedef struct bcm2835_alsa_stream {
++ bcm2835_chip_t *chip;
++ struct snd_pcm_substream *substream;
++
++ struct semaphore buffers_update_sem;
++ struct semaphore control_sem;
++ spinlock_t lock;
++ volatile uint32_t control;
++ volatile uint32_t status;
++
++ int open;
++ int running;
++ int draining;
++
++#ifdef DUMP_RAW_DATA
++ /* for debug */
++ int file;
++#endif
++ unsigned int pos;
++ unsigned int buffer_size;
++ unsigned int period_size;
++
++ uint32_t enable_fifo_irq;
++ irq_handler_t fifo_irq_handler;
++
++ atomic_t retrieved;
++ struct opaque_AUDIO_INSTANCE_T *instance;
++ struct workqueue_struct *my_wq;
++ int idx;
++} bcm2835_alsa_stream_t;
++
++int snd_bcm2835_new_ctl(bcm2835_chip_t * chip);
++int snd_bcm2835_new_pcm(bcm2835_chip_t * chip);
++
++void bcm2835_audio_fifo_get_lock(bcm2835_alsa_stream_t * alsa_stream);
++void bcm2835_audio_fifo_put_lock(bcm2835_alsa_stream_t * alsa_stream);
++
++int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream);
++int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream);
++int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream,
++ uint32_t channels, uint32_t samplerate,
++ uint32_t bps);
++int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream);
++int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream);
++int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream);
++int bcm2835_audio_set_ctls(bcm2835_chip_t * chip);
++int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count,
++ void *src);
++//uint32_t bcm2835_audio_buffers_consumed_bytes(bcm2835_alsa_stream_t *alsa_stream);
++uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream);
++void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream);
++void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream);
++
++#endif /* __SOUND_ARM_BCM2835_H */
+--- /dev/null
++++ b/sound/arm/vc_vchi_audioserv_defs.h
+@@ -0,0 +1,112 @@
++/*****************************************************************************
++* Copyright 2011 Broadcom Corporation. All rights reserved.
++*
++* Unless you and Broadcom execute a separate written software license
++* agreement governing use of this software, this software is licensed to you
++* under the terms of the GNU General Public License version 2, available at
++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
++*
++* Notwithstanding the above, under no circumstances may you combine this
++* software in any way with any other Broadcom software provided under a
++* license other than the GPL, without Broadcom's express prior written
++* consent.
++*****************************************************************************/
++
++#ifndef _VC_AUDIO_DEFS_H_
++#define _VC_AUDIO_DEFS_H_
++
++// FourCC code used for VCHI connection
++#define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS")
++
++// Maximum message length
++#define VC_AUDIO_MAX_MSG_LEN (sizeof( VC_AUDIO_MSG_T ))
++
++// List of screens that are currently supported
++// All message types supported for HOST->VC direction
++typedef enum {
++ VC_AUDIO_MSG_TYPE_RESULT, // Generic result
++ VC_AUDIO_MSG_TYPE_COMPLETE, // Generic result
++ VC_AUDIO_MSG_TYPE_CONFIG, // Configure audio
++ VC_AUDIO_MSG_TYPE_CONTROL, // Configure audio
++ VC_AUDIO_MSG_TYPE_OPEN, // Configure audio
++ VC_AUDIO_MSG_TYPE_CLOSE, // Configure audio
++ VC_AUDIO_MSG_TYPE_START, // Configure audio
++ VC_AUDIO_MSG_TYPE_STOP, // Configure audio
++ VC_AUDIO_MSG_TYPE_WRITE, // Configure audio
++ VC_AUDIO_MSG_TYPE_MAX
++} VC_AUDIO_MSG_TYPE;
++
++// configure the audio
++typedef struct {
++ uint32_t channels;
++ uint32_t samplerate;
++ uint32_t bps;
++
++} VC_AUDIO_CONFIG_T;
++
++typedef struct {
++ uint32_t volume;
++ uint32_t dest;
++
++} VC_AUDIO_CONTROL_T;
++
++// audio
++typedef struct {
++ uint32_t dummy;
++
++} VC_AUDIO_OPEN_T;
++
++// audio
++typedef struct {
++ uint32_t dummy;
++
++} VC_AUDIO_CLOSE_T;
++// audio
++typedef struct {
++ uint32_t dummy;
++
++} VC_AUDIO_START_T;
++// audio
++typedef struct {
++ uint32_t draining;
++
++} VC_AUDIO_STOP_T;
++
++// configure the write audio samples
++typedef struct {
++ uint32_t count; // in bytes
++ void *callback;
++ void *cookie;
++ uint32_t silence;
++} VC_AUDIO_WRITE_T;
++
++// Generic result for a request (VC->HOST)
++typedef struct {
++ int32_t success; // Success value
++
++} VC_AUDIO_RESULT_T;
++
++// Generic result for a request (VC->HOST)
++typedef struct {
++ int32_t count; // Success value
++ void *callback;
++ void *cookie;
++} VC_AUDIO_COMPLETE_T;
++
++// Message header for all messages in HOST->VC direction
++typedef struct {
++ int32_t type; // Message type (VC_AUDIO_MSG_TYPE)
++ union {
++ VC_AUDIO_CONFIG_T config;
++ VC_AUDIO_CONTROL_T control;
++ VC_AUDIO_OPEN_T open;
++ VC_AUDIO_CLOSE_T close;
++ VC_AUDIO_START_T start;
++ VC_AUDIO_STOP_T stop;
++ VC_AUDIO_WRITE_T write;
++ VC_AUDIO_RESULT_T result;
++ VC_AUDIO_COMPLETE_T complete;
++ } u;
++} VC_AUDIO_MSG_T;
++
++#endif // _VC_AUDIO_DEFS_H_