From 0ead3a801218fb9aa4f496f85a4f7bccc02bf9e4 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Thu, 23 Jan 2014 05:00:50 +0100 Subject: [PATCH] projects/RPi: update RPi patches, enable kernel 3.13 support Signed-off-by: Stephan Raue --- projects/RPi/options | 2 +- ...tch => linux-01-RPi_support-33b7b36.patch} | 5459 +++-------------- 2 files changed, 894 insertions(+), 4567 deletions(-) rename projects/RPi/patches/linux/{linux-01-RPi_support-8b2af1c.patch => linux-01-RPi_support-33b7b36.patch} (95%) diff --git a/projects/RPi/options b/projects/RPi/options index 18bba01fef..9359374144 100644 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -100,7 +100,7 @@ # Kernel to use. values can be: # default: default mainline kernel - LINUX="3.12" + LINUX="default" # use linux-next (latest rc) instead latest released version LINUX_NEXT="no" diff --git a/projects/RPi/patches/linux/linux-01-RPi_support-8b2af1c.patch b/projects/RPi/patches/linux/linux-01-RPi_support-33b7b36.patch similarity index 95% rename from projects/RPi/patches/linux/linux-01-RPi_support-8b2af1c.patch rename to projects/RPi/patches/linux/linux-01-RPi_support-33b7b36.patch index 3678402bfa..1853fa969d 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support-8b2af1c.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support-33b7b36.patch @@ -1,7 +1,7 @@ -From a7a41e08412068ce87101b1f2a69d8819177b283 Mon Sep 17 00:00:00 2001 +From 2b6791aa211b8cfc8defacc7ff3b17e548d7f6ce Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 01/91] Main bcm2708 linux port +Subject: [PATCH 01/80] Main bcm2708 linux port Signed-off-by: popcornmix --- @@ -18,7 +18,7 @@ Signed-off-by: popcornmix arch/arm/mach-bcm2708/armctrl.c | 208 ++++ arch/arm/mach-bcm2708/armctrl.h | 27 + arch/arm/mach-bcm2708/bcm2708.c | 711 +++++++++++ - arch/arm/mach-bcm2708/bcm2708.h | 51 + + arch/arm/mach-bcm2708/bcm2708.h | 49 + arch/arm/mach-bcm2708/bcm2708_gpio.c | 339 +++++ arch/arm/mach-bcm2708/clock.c | 61 + arch/arm/mach-bcm2708/clock.h | 24 + @@ -44,7 +44,7 @@ Signed-off-by: popcornmix arch/arm/mach-bcm2708/include/mach/vcio.h | 141 +++ arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + arch/arm/mach-bcm2708/power.c | 194 +++ - arch/arm/mach-bcm2708/vc_mem.c | 462 +++++++ + arch/arm/mach-bcm2708/vc_mem.c | 432 +++++++ arch/arm/mach-bcm2708/vcio.c | 474 +++++++ arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 15 +- @@ -56,7 +56,7 @@ Signed-off-by: popcornmix drivers/mmc/host/sdhci.h | 37 + drivers/tty/serial/amba-pl011.c | 2 +- include/linux/mmc/sdhci.h | 2 + - 51 files changed, 7795 insertions(+), 72 deletions(-) + 51 files changed, 7763 insertions(+), 72 deletions(-) create mode 100644 arch/arm/configs/bcmrpi_cutdown_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig create mode 100644 arch/arm/configs/bcmrpi_emergency_defconfig @@ -97,10 +97,10 @@ Signed-off-by: popcornmix create mode 100644 drivers/mmc/host/sdhci-bcm2708.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 1ad6fb6..e28d7b2 100644 +index c1f1a7e..1488f2d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -368,6 +368,22 @@ config ARCH_AT91 +@@ -373,6 +373,22 @@ config ARCH_AT91 This enables support for systems based on Atmel AT91RM9200 and AT91SAM9* processors. @@ -123,7 +123,7 @@ index 1ad6fb6..e28d7b2 100644 config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" select ARCH_REQUIRE_GPIOLIB -@@ -1043,6 +1059,7 @@ source "arch/arm/mach-virt/Kconfig" +@@ -1020,6 +1036,7 @@ source "arch/arm/mach-virt/Kconfig" source "arch/arm/mach-vt8500/Kconfig" source "arch/arm/mach-w90x900/Kconfig" @@ -132,10 +132,10 @@ index 1ad6fb6..e28d7b2 100644 source "arch/arm/mach-zynq/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 9762c84..d89dd0b 100644 +index 5765abf..313f96d 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -847,6 +847,14 @@ choice +@@ -882,6 +882,14 @@ choice options; the platform specific options are deprecated and will be soon removed. @@ -151,10 +151,10 @@ index 9762c84..d89dd0b 100644 config DEBUG_EXYNOS_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index db50b62..4470657 100644 +index c99b108..14e15c1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile -@@ -146,6 +146,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 +@@ -147,6 +147,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 # by CONFIG_* macro name. machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_BCM) += bcm @@ -2028,7 +2028,7 @@ index 0000000..0aa916e +#endif diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c new file mode 100644 -index 0000000..f3d14b0 +index 0000000..2d4b548 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -0,0 +1,711 @@ @@ -2073,7 +2073,7 @@ index 0000000..f3d14b0 +#include +#include +#include -+#include ++#include + +#include +#include @@ -2745,10 +2745,10 @@ index 0000000..f3d14b0 +module_param(reboot_part, uint, 0644); diff --git a/arch/arm/mach-bcm2708/bcm2708.h b/arch/arm/mach-bcm2708/bcm2708.h new file mode 100644 -index 0000000..dfe8700 +index 0000000..e339a93 --- /dev/null +++ b/arch/arm/mach-bcm2708/bcm2708.h -@@ -0,0 +1,51 @@ +@@ -0,0 +1,49 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h + * @@ -2794,9 +2794,7 @@ index 0000000..dfe8700 + .end = (base##_BASE) + SZ_4K - 1,\ + .flags = IORESOURCE_MEM, \ + }, \ -+ .dma_mask = ~0, \ + .irq = base##_IRQ, \ -+ /* .dma = base##_DMA,*/ \ +} + +#endif @@ -5582,10 +5580,10 @@ index 0000000..256bf1a +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c new file mode 100644 -index 0000000..aeae4d5 +index 0000000..2adac12 --- /dev/null +++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -0,0 +1,462 @@ +@@ -0,0 +1,432 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* @@ -5607,7 +5605,7 @@ index 0000000..aeae4d5 +#include +#include +#include -+#include ++#include +#include +#include + @@ -5623,24 +5621,15 @@ index 0000000..aeae4d5 + +#define DRIVER_NAME "vc-mem" + -+// Uncomment to enable debug logging -+// #define ENABLE_DBG -+ -+#if defined(ENABLE_DBG) -+#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ ) -+#else -+#define LOG_DBG( fmt, ... ) -+#endif -+#define LOG_ERR( fmt, ... ) printk( KERN_ERR fmt "\n", ##__VA_ARGS__ ) -+ +// Device (/dev) related variables +static dev_t vc_mem_devnum = 0; +static struct class *vc_mem_class = NULL; +static struct cdev vc_mem_cdev; +static int vc_mem_inited = 0; + -+// Proc entry -+static struct proc_dir_entry *vc_mem_proc_entry; ++#ifdef CONFIG_DEBUG_FS ++static struct dentry *vc_mem_debugfs_entry; ++#endif + +/* + * Videocore memory addresses and size @@ -5682,7 +5671,7 @@ index 0000000..aeae4d5 + (void) inode; + (void) file; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} @@ -5699,7 +5688,7 @@ index 0000000..aeae4d5 + (void) inode; + (void) file; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + return 0; +} @@ -5754,12 +5743,12 @@ index 0000000..aeae4d5 + (void) cmd; + (void) arg; + -+ LOG_DBG("%s: called file = 0x%p", __func__, file); ++ pr_debug("%s: called file = 0x%p\n", __func__, file); + + switch (cmd) { + case VC_MEM_IOC_MEM_PHYS_ADDR: + { -+ LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p", ++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n", + __func__, (void *) mm_vc_mem_phys_addr); + + if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr, @@ -5773,7 +5762,7 @@ index 0000000..aeae4d5 + // Get the videocore memory size first + vc_mem_get_size(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__, + mm_vc_mem_size); + + if (copy_to_user((void *) arg, &mm_vc_mem_size, @@ -5787,7 +5776,7 @@ index 0000000..aeae4d5 + // Get the videocore memory base + vc_mem_get_base(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, @@ -5801,7 +5790,7 @@ index 0000000..aeae4d5 + // Get the videocore memory base + vc_mem_get_base(); + -+ LOG_DBG("%s: VC_MEM_IOC_MEM_LOAD=%u", __func__, ++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__, + mm_vc_mem_base); + + if (copy_to_user((void *) arg, &mm_vc_mem_base, @@ -5815,7 +5804,7 @@ index 0000000..aeae4d5 + return -ENOTTY; + } + } -+ LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc); ++ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc); + + return rc; +} @@ -5833,12 +5822,12 @@ index 0000000..aeae4d5 + unsigned long length = vma->vm_end - vma->vm_start; + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + -+ LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx", ++ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n", + __func__, (long) vma->vm_start, (long) vma->vm_end, + (long) vma->vm_pgoff); + + if (offset + length > mm_vc_mem_size) { -+ LOG_ERR("%s: length %ld is too big", __func__, length); ++ pr_err("%s: length %ld is too big\n", __func__, length); + return -EINVAL; + } + // Do not cache the memory map @@ -5848,7 +5837,7 @@ index 0000000..aeae4d5 + (mm_vc_mem_phys_addr >> PAGE_SHIFT) + + vma->vm_pgoff, length, vma->vm_page_prot); + if (rc != 0) { -+ LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc); ++ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc); + } + + return rc; @@ -5868,75 +5857,60 @@ index 0000000..aeae4d5 + .mmap = vc_mem_mmap, +}; + -+/**************************************************************************** -+* -+* vc_mem_proc_read -+* -+***************************************************************************/ -+ -+static int -+vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof, -+ void *data) ++#ifdef CONFIG_DEBUG_FS ++static void vc_mem_debugfs_deinit(void) +{ -+ char *p = buf; -+ -+ (void) start; -+ (void) count; -+ (void) data; -+ -+ if (offset > 0) { -+ *eof = 1; -+ return 0; -+ } -+ // Get the videocore memory size first -+ vc_mem_get_size(); -+ -+ p += sprintf(p, "Videocore memory:\n"); -+ if (mm_vc_mem_phys_addr != 0) -+ p += sprintf(p, " Physical address: 0x%p\n", -+ (void *) mm_vc_mem_phys_addr); -+ else -+ p += sprintf(p, " Physical address: 0x00000000\n"); -+ p += sprintf(p, " Length (bytes): %u\n", mm_vc_mem_size); -+ -+ *eof = 1; -+ return p - buf; ++ debugfs_remove_recursive(vc_mem_debugfs_entry); ++ vc_mem_debugfs_entry = NULL; +} + -+/**************************************************************************** -+* -+* vc_mem_proc_write -+* -+***************************************************************************/ + -+static int -+vc_mem_proc_write(struct file *file, const char __user * buffer, -+ unsigned long count, void *data) ++static int vc_mem_debugfs_init( ++ struct device *dev) +{ -+ int rc = -EFAULT; -+ char input_str[10]; -+ -+ memset(input_str, 0, sizeof (input_str)); -+ -+ if (count > sizeof (input_str)) { -+ LOG_ERR("%s: input string length too long", __func__); -+ goto out; ++ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL); ++ if (!vc_mem_debugfs_entry) { ++ dev_warn(dev, "could not create debugfs entry\n"); ++ return -EFAULT; + } + -+ if (copy_from_user(input_str, buffer, count - 1)) { -+ LOG_ERR("%s: failed to get input string", __func__); -+ goto out; ++ if (!debugfs_create_x32("vc_mem_phys_addr", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_phys_addr)) { ++ dev_warn(dev, "%s:could not create vc_mem_phys entry\n", ++ __func__); ++ goto fail; + } + -+ if (strncmp(input_str, "connect", strlen("connect")) == 0) { -+ // Get the videocore memory size from the videocore -+ vc_mem_get_size(); ++ if (!debugfs_create_x32("vc_mem_size", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_size)) { ++ dev_warn(dev, "%s:could not create vc_mem_size entry\n", ++ __func__); ++ goto fail; + } + -+ out: -+ return rc; ++ if (!debugfs_create_x32("vc_mem_base", ++ 0444, ++ vc_mem_debugfs_entry, ++ (u32 *)&mm_vc_mem_base)) { ++ dev_warn(dev, "%s:could not create vc_mem_base entry\n", ++ __func__); ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ vc_mem_debugfs_deinit(); ++ return -EFAULT; +} + ++#endif /* CONFIG_DEBUG_FS */ ++ ++ +/**************************************************************************** +* +* vc_mem_init @@ -5949,7 +5923,7 @@ index 0000000..aeae4d5 + int rc = -EFAULT; + struct device *dev; + -+ LOG_DBG("%s: called", __func__); ++ pr_debug("%s: called\n", __func__); + + mm_vc_mem_phys_addr = phys_addr; + mm_vc_mem_size = mem_size; @@ -5957,24 +5931,25 @@ index 0000000..aeae4d5 + + vc_mem_get_size(); + -+ printk("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", ++ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n", + mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024)); + + if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { -+ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); ++ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n", ++ __func__, rc); + goto out_err; + } + + cdev_init(&vc_mem_cdev, &vc_mem_fops); + if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) { -+ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); ++ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc); + goto out_unregister; + } + + vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME); + if (IS_ERR(vc_mem_class)) { + rc = PTR_ERR(vc_mem_class); -+ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); ++ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc); + goto out_cdev_del; + } + @@ -5982,25 +5957,18 @@ index 0000000..aeae4d5 + DRIVER_NAME); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); -+ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); ++ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc); + goto out_class_destroy; + } + -+#if 0 -+ vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); -+ if (vc_mem_proc_entry == NULL) { -+ rc = -EFAULT; -+ LOG_ERR("%s: create_proc_entry failed", __func__); -+ goto out_device_destroy; -+ } -+ vc_mem_proc_entry->read_proc = vc_mem_proc_read; -+ vc_mem_proc_entry->write_proc = vc_mem_proc_write; ++#ifdef CONFIG_DEBUG_FS ++ /* don't fail if the debug entries cannot be created */ ++ vc_mem_debugfs_init(dev); +#endif + + vc_mem_inited = 1; + return 0; + -+ out_device_destroy: + device_destroy(vc_mem_class, vc_mem_devnum); + + out_class_destroy: @@ -6026,11 +5994,11 @@ index 0000000..aeae4d5 +static void __exit +vc_mem_exit(void) +{ -+ LOG_DBG("%s: called", __func__); ++ pr_debug("%s: called\n", __func__); + + if (vc_mem_inited) { -+#if 0 -+ remove_proc_entry(vc_mem_proc_entry->name, NULL); ++#if CONFIG_DEBUG_FS ++ vc_mem_debugfs_deinit(); +#endif + device_destroy(vc_mem_class, vc_mem_devnum); + class_destroy(vc_mem_class); @@ -6529,7 +6497,7 @@ index 0000000..5e43e85 +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm-mbox"); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index cd2c88e..edbc5f6 100644 +index 1f8fed9..f0ee034 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -358,7 +358,7 @@ config CPU_PJ4B @@ -6542,7 +6510,7 @@ index cd2c88e..edbc5f6 100644 select CPU_ABRT_EV6 select CPU_CACHE_V6 diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S -index 1128064..3706f80 100644 +index 45dc29f..c365a3e 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) @@ -8055,7 +8023,7 @@ index 0000000..d8ef77c +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 7a7fb4f..4b250ea 100644 +index bd8a098..d27309c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -28,6 +28,7 @@ @@ -8066,7 +8034,7 @@ index 7a7fb4f..4b250ea 100644 #include #include "sdhci.h" -@@ -327,7 +328,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) +@@ -326,7 +327,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) u32 uninitialized_var(scratch); u8 *buf; @@ -8075,7 +8043,7 @@ index 7a7fb4f..4b250ea 100644 blksize = host->data->blksz; chunk = 0; -@@ -372,7 +373,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) +@@ -371,7 +372,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) u32 scratch; u8 *buf; @@ -8084,7 +8052,7 @@ index 7a7fb4f..4b250ea 100644 blksize = host->data->blksz; chunk = 0; -@@ -411,19 +412,28 @@ static void sdhci_write_block_pio(struct sdhci_host *host) +@@ -410,19 +411,28 @@ static void sdhci_write_block_pio(struct sdhci_host *host) local_irq_restore(flags); } @@ -8116,7 +8084,7 @@ index 7a7fb4f..4b250ea 100644 /* * Some controllers (JMicron JMB38x) mess up the buffer bits -@@ -434,7 +444,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) +@@ -433,7 +443,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) (host->data->blocks == 1)) mask = ~0; @@ -8125,7 +8093,7 @@ index 7a7fb4f..4b250ea 100644 if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) udelay(100); -@@ -446,9 +456,11 @@ static void sdhci_transfer_pio(struct sdhci_host *host) +@@ -445,9 +455,11 @@ static void sdhci_transfer_pio(struct sdhci_host *host) host->blocks--; if (host->blocks == 0) break; @@ -8138,7 +8106,7 @@ index 7a7fb4f..4b250ea 100644 } static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) -@@ -721,7 +733,9 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) +@@ -720,7 +732,9 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; @@ -8149,7 +8117,7 @@ index 7a7fb4f..4b250ea 100644 sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); else sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); -@@ -753,44 +767,25 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +@@ -752,44 +766,25 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) host->data_early = 0; host->data->bytes_xfered = 0; @@ -8202,7 +8170,7 @@ index 7a7fb4f..4b250ea 100644 int broken, i; struct scatterlist *sg; -@@ -849,7 +844,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +@@ -848,7 +843,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) */ WARN_ON(1); host->flags &= ~SDHCI_REQ_USE_DMA; @@ -8212,7 +8180,7 @@ index 7a7fb4f..4b250ea 100644 WARN_ON(sg_cnt != 1); sdhci_writel(host, sg_dma_address(data->sg), SDHCI_DMA_ADDRESS); -@@ -865,11 +861,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) +@@ -864,11 +860,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) if (host->version >= SDHCI_SPEC_200) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; @@ -8226,7 +8194,7 @@ index 7a7fb4f..4b250ea 100644 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } -@@ -921,7 +919,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, +@@ -920,7 +918,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; @@ -8236,7 +8204,7 @@ index 7a7fb4f..4b250ea 100644 mode |= SDHCI_TRNS_DMA; sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); -@@ -937,13 +936,16 @@ static void sdhci_finish_data(struct sdhci_host *host) +@@ -936,13 +935,16 @@ static void sdhci_finish_data(struct sdhci_host *host) host->data = NULL; if (host->flags & SDHCI_REQ_USE_DMA) { @@ -8257,7 +8225,7 @@ index 7a7fb4f..4b250ea 100644 } /* -@@ -996,6 +998,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +@@ -995,6 +997,12 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) mask |= SDHCI_DATA_INHIBIT; @@ -8270,7 +8238,7 @@ index 7a7fb4f..4b250ea 100644 /* 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)) -@@ -1013,10 +1021,16 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +@@ -1012,10 +1020,16 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout--; mdelay(1); } @@ -8287,7 +8255,7 @@ index 7a7fb4f..4b250ea 100644 sdhci_prepare_data(host, cmd); -@@ -1487,7 +1501,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) +@@ -1488,7 +1502,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) else ctrl &= ~SDHCI_CTRL_HISPD; @@ -8296,7 +8264,7 @@ index 7a7fb4f..4b250ea 100644 u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ -@@ -2183,7 +2197,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2193,7 +2207,7 @@ static void sdhci_timeout_timer(unsigned long data) if (host->mrq) { pr_err("%s: Timeout waiting for hardware " @@ -8305,7 +8273,7 @@ index 7a7fb4f..4b250ea 100644 sdhci_dumpregs(host); if (host->data) { -@@ -2228,10 +2242,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) +@@ -2238,10 +2252,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { @@ -8319,7 +8287,7 @@ index 7a7fb4f..4b250ea 100644 return; } -@@ -2301,6 +2318,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) +@@ -2311,6 +2328,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif @@ -8339,7 +8307,7 @@ index 7a7fb4f..4b250ea 100644 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { u32 command; -@@ -2330,23 +2360,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2340,23 +2370,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } } @@ -8383,7 +8351,7 @@ index 7a7fb4f..4b250ea 100644 pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); sdhci_show_adma_error(host); host->data->error = -EIO; -@@ -2354,11 +2400,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2364,11 +2410,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->ops->adma_workaround(host, intmask); } @@ -8406,7 +8374,7 @@ index 7a7fb4f..4b250ea 100644 /* * We currently don't do anything fancy with DMA -@@ -2387,18 +2440,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2397,18 +2450,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); } @@ -8427,7 +8395,7 @@ index 7a7fb4f..4b250ea 100644 } } -@@ -2454,6 +2497,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2464,6 +2507,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) tasklet_schedule(&host->card_tasklet); } @@ -8450,7 +8418,7 @@ index 7a7fb4f..4b250ea 100644 if (intmask & SDHCI_INT_CMD_MASK) { sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); -@@ -2468,7 +2527,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2478,7 +2537,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); @@ -8465,9 +8433,9 @@ index 7a7fb4f..4b250ea 100644 if (intmask & SDHCI_INT_BUS_POWER) { pr_err("%s: Card is consuming too much power!\n", -@@ -2588,7 +2653,8 @@ int sdhci_resume_host(struct sdhci_host *host) +@@ -2591,7 +2656,8 @@ int sdhci_resume_host(struct sdhci_host *host) { - int ret; + int ret = 0; - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA | @@ -8475,7 +8443,7 @@ index 7a7fb4f..4b250ea 100644 if (host->ops->enable_dma) host->ops->enable_dma(host); } -@@ -2820,14 +2886,16 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -2822,14 +2888,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } @@ -8494,7 +8462,7 @@ index 7a7fb4f..4b250ea 100644 } } } -@@ -3252,6 +3320,7 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3254,6 +3322,7 @@ int sdhci_add_host(struct sdhci_host *host) pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), @@ -8503,12 +8471,12 @@ index 7a7fb4f..4b250ea 100644 (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h -index b037f18..8a02ec8 100644 +index 0a3ed01..6857875 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h -@@ -289,6 +289,20 @@ struct sdhci_ops { - void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); +@@ -290,6 +290,20 @@ struct sdhci_ops { void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); + int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); + + int (*pdma_able)(struct sdhci_host *host, @@ -8527,7 +8495,7 @@ index b037f18..8a02ec8 100644 void (*hw_reset)(struct sdhci_host *host); void (*platform_suspend)(struct sdhci_host *host); void (*platform_resume)(struct sdhci_host *host); -@@ -400,6 +414,29 @@ static inline void *sdhci_priv(struct sdhci_host *host) +@@ -403,6 +417,29 @@ extern void sdhci_send_command(struct sdhci_host *host, extern void sdhci_enable_irq_wakeups(struct sdhci_host *host); #endif @@ -8558,7 +8526,7 @@ index b037f18..8a02ec8 100644 extern int sdhci_runtime_suspend_host(struct sdhci_host *host); extern int sdhci_runtime_resume_host(struct sdhci_host *host); diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index aaa2286..783bfb3 100644 +index 7203864..78c4ee0 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -84,7 +84,7 @@ struct vendor_data { @@ -8594,10 +8562,10 @@ index 3e781b8..aad2393 100644 1.8.5.1 -From ffd85339c2b40d74ec1a8cbf7a957884f0a2ac25 Mon Sep 17 00:00:00 2001 +From 6e2d0f72a44822e4d53238a90728b75cfe5427fc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 7 May 2013 22:20:24 +0100 -Subject: [PATCH 02/91] Add quick config. +Subject: [PATCH 02/80] Add quick config. This is designed for quick compiling when developing. No modules are needed and it includes all Pi specific drivers @@ -8813,10 +8781,10 @@ index 0000000..e5efe75 1.8.5.1 -From ef917ffb8f230dcb50638f3109a0a59288051654 Mon Sep 17 00:00:00 2001 +From f97091bb51ae6d3cd138fb8362f26797474b5c35 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 03/91] Add dwc_otg driver +Subject: [PATCH 03/80] Add dwc_otg driver Signed-off-by: popcornmix --- @@ -8969,10 +8937,10 @@ index acbfeb0..7d675c8 100644 return i; } diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 82927e1..b1ffeff 100644 +index bb31597..5449ad7 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1885,6 +1885,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) +@@ -1889,6 +1889,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -12955,10 +12923,10 @@ index 0000000..a896d73 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index b3f20d7..92f4cc3 100644 +index a9707da..e252b95 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -650,6 +650,19 @@ config USB_HWA_HCD +@@ -689,6 +689,19 @@ config USB_HWA_HCD To compile this driver a module, choose M here: the module will be called "hwa-hc". @@ -12979,10 +12947,10 @@ index b3f20d7..92f4cc3 100644 tristate "i.MX21 HCD support" depends on ARM && ARCH_MXC diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index 50b0041..64dd651 100644 +index 01e879e..71d40d3 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile -@@ -56,6 +56,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o +@@ -65,6 +65,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o @@ -65888,10 +65856,10 @@ index 0000000..cdc9963 1.8.5.1 -From a6d142fdbb59fc245779df8c5328e21df890fd42 Mon Sep 17 00:00:00 2001 +From 1b5d1e4b7bd40b5a74e6d552410433b2c0f775f5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 04/91] bcm2708 watchdog driver +Subject: [PATCH 04/80] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -65902,7 +65870,7 @@ Signed-off-by: popcornmix create mode 100644 drivers/watchdog/bcm2708_wdog.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index d1d53f3..a1eb410 100644 +index 5be6e91..dd7fe73 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -392,6 +392,12 @@ config RETU_WATCHDOG @@ -65915,11 +65883,11 @@ index d1d53f3..a1eb410 100644 + help + Enables BCM2708 watchdog support. + - # AVR32 Architecture - - config AT32AP700X_WDT + config MOXART_WDT + tristate "MOXART watchdog" + depends on ARCH_MOXART diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile -index 6c5bb27..7b1ca3f 100644 +index 91bd95a..c22a199 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o @@ -65928,8 +65896,8 @@ index 6c5bb27..7b1ca3f 100644 obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o +obj-$(CONFIG_BCM2708_WDT) += bcm2708_wdog.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o - - # AVR32 Architecture + obj-$(CONFIG_MOXART_WDT) += moxart_wdt.o + obj-$(CONFIG_SIRFSOC_WATCHDOG) += sirfsoc_wdt.o diff --git a/drivers/watchdog/bcm2708_wdog.c b/drivers/watchdog/bcm2708_wdog.c new file mode 100644 index 0000000..2f19203 @@ -66324,10 +66292,10 @@ index 0000000..2f19203 1.8.5.1 -From 79bf8b376c62ead1b7db73419d08fb0fa80b0c53 Mon Sep 17 00:00:00 2001 +From 56f85d09f08c12b58f36b255487d02b468139335 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 05/91] bcm2708 framebuffer driver +Subject: [PATCH 05/80] bcm2708 framebuffer driver Signed-off-by: popcornmix --- @@ -66339,7 +66307,7 @@ Signed-off-by: popcornmix create mode 100644 drivers/video/bcm2708_fb.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig -index 84b685f..4c82aab 100644 +index 4f2e1b3..b41c7b8 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -310,6 +310,20 @@ config FB_PM2_FIFO_DISCONNECT @@ -69366,10 +69334,10 @@ index 3c14e43..7626beb 100644 1.8.5.1 -From f66a46728dd6561fdb01b1e56829cff8c440ad56 Mon Sep 17 00:00:00 2001 +From 0862e5d3713ac76fc632f7a7cb8c66ecce7a93a8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 06/91] bcm2708 vchiq driver +Subject: [PATCH 06/80] bcm2708 vchiq driver Signed-off-by: popcornmix --- @@ -69440,24 +69408,26 @@ Signed-off-by: popcornmix create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 8dacd4c..aa7eea4 100644 +index a3e291d..f6745bb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig -@@ -537,4 +537,5 @@ source "drivers/misc/carma/Kconfig" +@@ -524,5 +524,6 @@ source "drivers/misc/carma/Kconfig" source "drivers/misc/altera-stapl/Kconfig" source "drivers/misc/mei/Kconfig" source "drivers/misc/vmw_vmci/Kconfig" +source "drivers/misc/vc04_services/Kconfig" + source "drivers/misc/mic/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index c235d5b..d72aaf2 100644 +index f45473e..a81bc2e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile -@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ +@@ -52,4 +52,5 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o obj-$(CONFIG_SRAM) += sram.o +obj-y += vc04_services/ + obj-y += mic/ diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig new file mode 100644 index 0000000..2663933 @@ -71583,7 +71553,7 @@ index 0000000..2b5fa56 +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000..f44d4b4 +index 0000000..c1fb8c3 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -0,0 +1,2813 @@ @@ -73291,7 +73261,7 @@ index 0000000..f44d4b4 + complete_all(&arm_state->vc_resume_complete); + break; + case VC_SUSPEND_IDLE: -+ INIT_COMPLETION(arm_state->vc_suspend_complete); ++ reinit_completion(&arm_state->vc_suspend_complete); + break; + case VC_SUSPEND_REQUESTED: + break; @@ -73319,7 +73289,7 @@ index 0000000..f44d4b4 + case VC_RESUME_FAILED: + break; + case VC_RESUME_IDLE: -+ INIT_COMPLETION(arm_state->vc_resume_complete); ++ reinit_completion(&arm_state->vc_resume_complete); + break; + case VC_RESUME_REQUESTED: + break; @@ -73381,7 +73351,7 @@ index 0000000..f44d4b4 + * (which only happens when blocked_count hits 0) then those threads + * will have to wait until next time around */ + if (arm_state->blocked_count) { -+ INIT_COMPLETION(arm_state->blocked_blocker); ++ reinit_completion(&arm_state->blocked_blocker); + write_unlock_bh(&arm_state->susp_res_lock); + vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " + "blocked clients", __func__); @@ -73426,7 +73396,7 @@ index 0000000..f44d4b4 + write_lock_bh(&arm_state->susp_res_lock); + resume_count++; + } -+ INIT_COMPLETION(arm_state->resume_blocker); ++ reinit_completion(&arm_state->resume_blocker); + arm_state->resume_blocked = 1; + +out: @@ -81868,10 +81838,10 @@ index 0000000..b6bfa21 1.8.5.1 -From b32aca932b5bc99b508a1973e242e308c6174f1a Mon Sep 17 00:00:00 2001 +From a04cc2d7dfa176887532462f911eb9a1918f8a82 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 07/91] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 07/80] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix --- @@ -81891,10 +81861,10 @@ Signed-off-by: popcornmix create mode 100644 include/linux/broadcom/vc_cma.h diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 1421997..3aa66f8 100644 +index fa3243d..bb602b8 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig -@@ -574,6 +574,8 @@ config DEVPORT +@@ -580,6 +580,8 @@ config DEVPORT source "drivers/s390/char/Kconfig" @@ -83112,15 +83082,16 @@ index 0000000..a635f9f +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index d72aaf2..24b40c3 100644 +index a81bc2e..40e5af1 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile -@@ -53,4 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ +@@ -52,5 +52,5 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o obj-$(CONFIG_SRAM) += sram.o -obj-y += vc04_services/ +obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ + obj-y += mic/ diff --git a/include/linux/broadcom/vc_cma.h b/include/linux/broadcom/vc_cma.h new file mode 100644 index 0000000..5325832 @@ -83160,10 +83131,10 @@ index 0000000..5325832 1.8.5.1 -From da006e46cfdac4b58647add283488aa71dd97b43 Mon Sep 17 00:00:00 2001 +From b72d0ba95ffa6f9abe5b0df96025167226fe61e3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 08/91] bcm2708: alsa sound driver +Subject: [PATCH 08/80] bcm2708: alsa sound driver Signed-off-by: popcornmix --- @@ -83249,7 +83220,7 @@ index 339aabf..df947e5 100644 CONFIG_USB_HIDDEV=y CONFIG_HID_A4TECH=m diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index f3d14b0..e6add5f 100644 +index 2d4b548..db1b7b5 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -429,6 +429,16 @@ struct platform_device bcm2708_powerman_device = { @@ -85485,10 +85456,10 @@ index 0000000..af3e6eb 1.8.5.1 -From 8c0811cfb655295da58469c49c4bb82467398db9 Mon Sep 17 00:00:00 2001 +From f7e9116fcb9571904658b4324477591392f7997e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 09/91] Allow mac address to be set in smsc95xx +Subject: [PATCH 09/80] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -85582,10 +85553,12 @@ index 3f38ba8..60076fe 100644 1.8.5.1 -From 2f53106dec15b1d2943d5ebdfe3dc663772c0968 Mon Sep 17 00:00:00 2001 +From 8782f482f66eacf485dda6a1bbc2aa15eb345b9e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 8 May 2012 23:12:13 +0100 -Subject: [PATCH 10/91] possible fix for sdcard missing status. Thank naren +Subject: [PATCH 10/80] Fixes for sdhci-bcm2708 + +possible fix for sdcard missing status. Thank naren sdcard patch improvements from naren @@ -85670,18 +85643,20 @@ sdhci-bcm2807: Increase sync_after_dma timeout The current timeout is being hit with some cards that complete successfully with a longer timeout. The timeout is not handled well, and is believed to be a code path that causes corruption. 872a8ff suggests that crappy cards can take up to 3 seconds to respond + +remove suspend/resume --- drivers/mmc/card/block.c | 2 +- drivers/mmc/core/sd.c | 110 +++++++++++++++-- - drivers/mmc/host/sdhci-bcm2708.c | 248 ++++++++++++++++++--------------------- - drivers/mmc/host/sdhci.c | 179 +++++++++++++++++++++------- + drivers/mmc/host/sdhci-bcm2708.c | 252 ++++++++++++++++++--------------------- + drivers/mmc/host/sdhci.c | 179 ++++++++++++++++++++------- drivers/mmc/host/sdhci.h | 8 +- include/linux/mmc/host.h | 1 + include/linux/mmc/sdhci.h | 1 + - 7 files changed, 361 insertions(+), 188 deletions(-) + 7 files changed, 363 insertions(+), 190 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 1a3163f..b39f38b 100644 +index 29d5d98..6e305ac 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1361,7 +1361,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, @@ -85694,19 +85669,19 @@ index 1a3163f..b39f38b 100644 * token, not a STOP_TRANSMISSION request. */ diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c -index 5e8823d..e0e9afb 100644 +index 6f42050..bb14f63 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c -@@ -13,6 +13,8 @@ - #include +@@ -14,6 +14,8 @@ #include #include + #include +#include +#include #include #include -@@ -58,6 +60,15 @@ +@@ -59,6 +61,15 @@ __res & __mask; \ }) @@ -85722,7 +85697,7 @@ index 5e8823d..e0e9afb 100644 /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */ -@@ -210,12 +221,63 @@ static int mmc_decode_scr(struct mmc_card *card) +@@ -211,12 +222,63 @@ static int mmc_decode_scr(struct mmc_card *card) } /* @@ -85787,7 +85762,7 @@ index 5e8823d..e0e9afb 100644 u32 *ssr; if (!(card->csd.cmdclass & CCC_APP_SPEC)) { -@@ -228,14 +290,40 @@ static int mmc_read_ssr(struct mmc_card *card) +@@ -229,14 +291,40 @@ static int mmc_read_ssr(struct mmc_card *card) if (!ssr) return -ENOMEM; @@ -85833,7 +85808,7 @@ index 5e8823d..e0e9afb 100644 for (i = 0; i < 16; i++) ssr[i] = be32_to_cpu(ssr[i]); -@@ -816,14 +904,10 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, +@@ -819,14 +907,10 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, if (!reinit) { /* @@ -85852,7 +85827,7 @@ index 5e8823d..e0e9afb 100644 /* diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c -index d8ef77c..f91be88 100644 +index d8ef77c..1ebbe2d 100644 --- a/drivers/mmc/host/sdhci-bcm2708.c +++ b/drivers/mmc/host/sdhci-bcm2708.c @@ -51,7 +51,6 @@ @@ -86189,6 +86164,24 @@ index d8ef77c..f91be88 100644 printk(KERN_INFO "%s: DMA disabled\n", mmc_hostname(host->mmc)); } +@@ -1126,7 +1077,7 @@ static int sdhci_bcm2708_suspend(struct platform_device *dev, pm_message_t state + int ret = 0; + + if (host->mmc) { +- ret = mmc_suspend_host(host->mmc); ++ //ret = mmc_suspend_host(host->mmc); + } + + return ret; +@@ -1139,7 +1090,7 @@ static int sdhci_bcm2708_resume(struct platform_device *dev) + int ret = 0; + + if (host->mmc) { +- ret = mmc_resume_host(host->mmc); ++ //ret = mmc_resume_host(host->mmc); + } + + return ret; @@ -1158,19 +1109,14 @@ static unsigned int sdhci_bcm2708_quirk_extra_ints(struct sdhci_host *host) return 1; } @@ -86334,10 +86327,10 @@ index d8ef77c..f91be88 100644 + + diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 4b250ea..a33407e 100644 +index d27309c..576c526 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c -@@ -132,6 +132,99 @@ static void sdhci_dumpregs(struct sdhci_host *host) +@@ -131,6 +131,99 @@ static void sdhci_dumpregs(struct sdhci_host *host) * Low level functions * * * \*****************************************************************************/ @@ -86437,7 +86430,7 @@ index 4b250ea..a33407e 100644 static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) { -@@ -301,7 +394,7 @@ static void sdhci_led_control(struct led_classdev *led, +@@ -300,7 +393,7 @@ static void sdhci_led_control(struct led_classdev *led, struct sdhci_host *host = container_of(led, struct sdhci_host, led); unsigned long flags; @@ -86446,7 +86439,7 @@ index 4b250ea..a33407e 100644 if (host->runtime_suspended) goto out; -@@ -311,7 +404,7 @@ static void sdhci_led_control(struct led_classdev *led, +@@ -310,7 +403,7 @@ static void sdhci_led_control(struct led_classdev *led, else sdhci_activate_led(host); out: @@ -86455,7 +86448,7 @@ index 4b250ea..a33407e 100644 } #endif -@@ -1019,7 +1112,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) +@@ -1018,7 +1111,9 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) return; } timeout--; @@ -86518,7 +86511,7 @@ index 4b250ea..a33407e 100644 if (host->vmmc && ios->power_mode == MMC_POWER_OFF) mmc_regulator_set_ocr(host->mmc, host->vmmc, 0); return; -@@ -1460,9 +1557,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) +@@ -1461,9 +1558,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) vdd_bit = sdhci_set_power(host, ios->vdd); if (host->vmmc && vdd_bit != -1) { @@ -86530,7 +86523,7 @@ index 4b250ea..a33407e 100644 } if (host->ops->platform_send_init_74_clocks) -@@ -1501,7 +1598,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) +@@ -1502,7 +1599,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) else ctrl &= ~SDHCI_CTRL_HISPD; @@ -86539,7 +86532,7 @@ index 4b250ea..a33407e 100644 u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ -@@ -1599,7 +1696,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) +@@ -1600,7 +1697,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); mmiowb(); @@ -86548,7 +86541,7 @@ index 4b250ea..a33407e 100644 } static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -1647,7 +1744,7 @@ static int sdhci_check_ro(struct sdhci_host *host) +@@ -1648,7 +1745,7 @@ static int sdhci_check_ro(struct sdhci_host *host) unsigned long flags; int is_readonly; @@ -86557,7 +86550,7 @@ index 4b250ea..a33407e 100644 if (host->flags & SDHCI_DEVICE_DEAD) is_readonly = 0; -@@ -1657,7 +1754,7 @@ static int sdhci_check_ro(struct sdhci_host *host) +@@ -1658,7 +1755,7 @@ static int sdhci_check_ro(struct sdhci_host *host) is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); @@ -86566,7 +86559,7 @@ index 4b250ea..a33407e 100644 /* This quirk needs to be replaced by a callback-function later */ return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? -@@ -1730,9 +1827,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) +@@ -1731,9 +1828,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) struct sdhci_host *host = mmc_priv(mmc); unsigned long flags; @@ -86578,7 +86571,7 @@ index 4b250ea..a33407e 100644 } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, -@@ -2080,7 +2177,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2090,7 +2187,7 @@ static void sdhci_card_event(struct mmc_host *mmc) if (host->ops->card_event) host->ops->card_event(host); @@ -86587,7 +86580,7 @@ index 4b250ea..a33407e 100644 /* Check host->mrq first in case we are runtime suspended */ if (host->mrq && !sdhci_do_get_cd(host)) { -@@ -2096,7 +2193,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2106,7 +2203,7 @@ static void sdhci_card_event(struct mmc_host *mmc) tasklet_schedule(&host->finish_tasklet); } @@ -86596,7 +86589,7 @@ index 4b250ea..a33407e 100644 } static const struct mmc_host_ops sdhci_ops = { -@@ -2135,14 +2232,14 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2145,14 +2242,14 @@ static void sdhci_tasklet_finish(unsigned long param) host = (struct sdhci_host*)param; @@ -86613,7 +86606,7 @@ index 4b250ea..a33407e 100644 return; } -@@ -2180,7 +2277,7 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2190,7 +2287,7 @@ static void sdhci_tasklet_finish(unsigned long param) #endif mmiowb(); @@ -86622,7 +86615,7 @@ index 4b250ea..a33407e 100644 mmc_request_done(host->mmc, mrq); sdhci_runtime_pm_put(host); -@@ -2193,7 +2290,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2203,7 +2300,7 @@ static void sdhci_timeout_timer(unsigned long data) host = (struct sdhci_host*)data; @@ -86631,7 +86624,7 @@ index 4b250ea..a33407e 100644 if (host->mrq) { pr_err("%s: Timeout waiting for hardware " -@@ -2214,7 +2311,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2224,7 +2321,7 @@ static void sdhci_timeout_timer(unsigned long data) } mmiowb(); @@ -86640,7 +86633,7 @@ index 4b250ea..a33407e 100644 } static void sdhci_tuning_timer(unsigned long data) -@@ -2224,11 +2321,11 @@ static void sdhci_tuning_timer(unsigned long data) +@@ -2234,11 +2331,11 @@ static void sdhci_tuning_timer(unsigned long data) host = (struct sdhci_host *)data; @@ -86654,7 +86647,7 @@ index 4b250ea..a33407e 100644 } /*****************************************************************************\ -@@ -2452,10 +2549,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2462,10 +2559,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) u32 intmask, unexpected = 0; int cardint = 0, max_loops = 16; @@ -86667,7 +86660,7 @@ index 4b250ea..a33407e 100644 pr_warning("%s: got irq while runtime suspended\n", mmc_hostname(host->mmc)); return IRQ_HANDLED; -@@ -2559,7 +2656,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2577,7 +2674,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask && --max_loops) goto again; out: @@ -86676,7 +86669,7 @@ index 4b250ea..a33407e 100644 if (unexpected) { pr_err("%s: Unexpected interrupt 0x%08x.\n", -@@ -2660,7 +2757,7 @@ int sdhci_resume_host(struct sdhci_host *host) +@@ -2663,7 +2760,7 @@ int sdhci_resume_host(struct sdhci_host *host) } if (!device_may_wakeup(mmc_dev(host->mmc))) { @@ -86685,7 +86678,7 @@ index 4b250ea..a33407e 100644 mmc_hostname(host->mmc), host); if (ret) return ret; -@@ -2737,15 +2834,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) +@@ -2739,15 +2836,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) host->flags &= ~SDHCI_NEEDS_RETUNING; } @@ -86705,7 +86698,7 @@ index 4b250ea..a33407e 100644 return ret; } -@@ -2771,16 +2868,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2773,16 +2870,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); if ((host_flags & SDHCI_PV_ENABLED) && !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { @@ -86725,7 +86718,7 @@ index 4b250ea..a33407e 100644 host->runtime_suspended = false; -@@ -2791,7 +2888,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2793,7 +2890,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) /* Enable Card Detection */ sdhci_enable_card_detection(host); @@ -86734,7 +86727,7 @@ index 4b250ea..a33407e 100644 return ret; } -@@ -3286,8 +3383,8 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3288,8 +3385,8 @@ int sdhci_add_host(struct sdhci_host *host) sdhci_init(host, 0); @@ -86745,7 +86738,7 @@ index 4b250ea..a33407e 100644 if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); -@@ -3348,7 +3445,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3350,7 +3447,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) unsigned long flags; if (dead) { @@ -86754,7 +86747,7 @@ index 4b250ea..a33407e 100644 host->flags |= SDHCI_DEVICE_DEAD; -@@ -3360,7 +3457,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3362,7 +3459,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) tasklet_schedule(&host->finish_tasklet); } @@ -86764,10 +86757,10 @@ index 4b250ea..a33407e 100644 sdhci_disable_card_detection(host); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h -index 8a02ec8..e434073 100644 +index 6857875..649f3cf 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h -@@ -299,8 +299,6 @@ struct sdhci_ops { +@@ -300,8 +300,6 @@ struct sdhci_ops { struct mmc_data *data); unsigned int (*extra_ints)(struct sdhci_host *host); unsigned int (*spurious_crc_acmd51)(struct sdhci_host *host); @@ -86776,7 +86769,7 @@ index 8a02ec8..e434073 100644 unsigned int (*missing_status)(struct sdhci_host *host); void (*hw_reset)(struct sdhci_host *host); -@@ -442,4 +440,10 @@ static inline void *sdhci_priv(struct sdhci_host *host) +@@ -445,4 +443,10 @@ extern void sdhci_send_command(struct sdhci_host *host, extern int sdhci_runtime_resume_host(struct sdhci_host *host); #endif @@ -86788,10 +86781,10 @@ index 8a02ec8..e434073 100644 + #endif /* __SDHCI_HW_H */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 3b0c33a..e9ae33c 100644 +index 99f5709..cd6f996 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -281,6 +281,7 @@ struct mmc_host { +@@ -282,6 +282,7 @@ struct mmc_host { MMC_CAP2_PACKED_WR) #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ #define MMC_CAP2_SANITIZE (1 << 15) /* Support Sanitize */ @@ -86815,10 +86808,10 @@ index aad2393..0aeeef8 100644 1.8.5.1 -From 638b30f422c07afab22c59eff1e4af387100d18a Mon Sep 17 00:00:00 2001 +From cc29018f0fcb797fa0b61aa70dab0b50f2bd5119 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 4 Nov 2013 18:56:10 +0000 -Subject: [PATCH 11/91] Add Chris Boot's i2c and spi drivers. +Subject: [PATCH 11/80] Add Chris Boot's i2c and spi drivers. --- arch/arm/configs/bcmrpi_cutdown_defconfig | 9 + @@ -86887,7 +86880,7 @@ index 9355841..e151ed4 100644 + Binds spidev driver to the SPI0 master endmenu diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index e6add5f..dfcc605 100644 +index db1b7b5..63b8273 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -31,6 +31,7 @@ @@ -87060,10 +87053,10 @@ index 110ce07..4d3c15d 100644 #define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index cdcbd83..5a4144c 100644 +index 3b26129..15070da 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig -@@ -345,6 +345,25 @@ config I2C_BCM2835 +@@ -346,6 +346,25 @@ config I2C_BCM2835 This support is also available as a module. If so, the module will be called i2c-bcm2835. @@ -87076,21 +87069,21 @@ index cdcbd83..5a4144c 100644 + with I2C/TWI/SMBus. + +config I2C_BCM2708_BAUDRATE -+ prompt "BCM2708 I2C baudrate" ++ prompt "BCM2708 I2C baudrate" + depends on I2C_BCM2708 -+ int -+ default 100000 -+ help -+ Set the I2C baudrate. This will alter the default value. A -+ different baudrate can be set by using a module parameter as well. If -+ no parameter is provided when loading, this is the value that will be -+ used. ++ int ++ default 100000 ++ help ++ Set the I2C baudrate. This will alter the default value. A ++ different baudrate can be set by using a module parameter as well. If ++ no parameter is provided when loading, this is the value that will be ++ used. + - config I2C_BLACKFIN_TWI - tristate "Blackfin TWI I2C support" - depends on BLACKFIN + config I2C_BCM_KONA + tristate "BCM Kona I2C adapter" + depends on ARCH_BCM_MOBILE diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index d00997f..15622cd 100644 +index c73eb0e..9c46931 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o @@ -87103,7 +87096,7 @@ index d00997f..15622cd 100644 obj-$(CONFIG_I2C_CPM) += i2c-cpm.o diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c new file mode 100644 -index 0000000..72750c7 +index 0000000..98bc4e7 --- /dev/null +++ b/drivers/i2c/busses/i2c-bcm2708.c @@ -0,0 +1,408 @@ @@ -87337,7 +87330,7 @@ index 0000000..72750c7 + + spin_lock_irqsave(&bi->lock, flags); + -+ INIT_COMPLETION(bi->done); ++ reinit_completion(&bi->done); + bi->msg = msgs; + bi->pos = 0; + bi->nmsgs = num; @@ -87516,7 +87509,7 @@ index 0000000..72750c7 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index b9c53cc..41ad35a 100644 +index eb1f1ef..e8b4f04 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -85,6 +85,14 @@ config SPI_BCM2835 @@ -87548,7 +87541,7 @@ index ab8d864..a011073 100644 obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c new file mode 100644 -index 0000000..abaa5a6 +index 0000000..180264a --- /dev/null +++ b/drivers/spi/spi-bcm2708.c @@ -0,0 +1,626 @@ @@ -87872,7 +87865,7 @@ index 0000000..abaa5a6 + stp = spi->controller_state; + } + -+ INIT_COMPLETION(bs->done); ++ reinit_completion(&bs->done); + bs->tx_buf = xfer->tx_buf; + bs->rx_buf = xfer->rx_buf; + bs->len = xfer->len; @@ -88182,10 +88175,10 @@ index 0000000..abaa5a6 1.8.5.1 -From 7d803bf765a77c95eae0874a9fe62d82775d0343 Mon Sep 17 00:00:00 2001 +From 79bf0fde9313eca745eca8aabd01a41598c107ca Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 12/91] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 12/80] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) --- @@ -88193,7 +88186,7 @@ Subject: [PATCH 12/91] enabling the realtime clock 1-wire chip DS1307 and 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index dfcc605..5f869e8 100644 +index 63b8273..2a36411 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -32,6 +32,7 @@ @@ -88248,10 +88241,10 @@ index dfcc605..5f869e8 100644 1.8.5.1 -From 025cab40ed0bdccfc6d544e9cb894116cf8ef658 Mon Sep 17 00:00:00 2001 +From 545b2d0b0ca0c4a6268f45e7784a059cc9c95f58 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:46:42 +0100 -Subject: [PATCH 13/91] Add FIQ patch to dwc_otg driver. Enable with +Subject: [PATCH 13/80] Add FIQ patch to dwc_otg driver. Enable with dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks to Gordon and Costas @@ -88282,10 +88275,10 @@ Subject: [PATCH 13/91] Add FIQ patch to dwc_otg driver. Enable with create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index e28d7b2..981adf0 100644 +index 1488f2d..d667223 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -381,6 +381,7 @@ config ARCH_BCM2708 +@@ -386,6 +386,7 @@ config ARCH_BCM2708 select ARM_ERRATA_411920 select MACH_BCM2708 select VC4 @@ -88383,7 +88376,7 @@ index da18725..274aa30 100644 return 0; } diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 5f869e8..dd73b81 100644 +index 2a36411..0836685 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -314,12 +314,32 @@ static void __init bcm2708_clocksource_init(void) @@ -89411,10 +89404,10 @@ index e46d9bb..6b2c7d0 100644 1.8.5.1 -From 9daf0bea7d05908d068aeece8be7e450cac51d55 Mon Sep 17 00:00:00 2001 +From 32ada6047eef7cbb544a0d8c1c79393397bff100 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Sep 2012 15:17:53 +0100 -Subject: [PATCH 16/91] Avoid dynamic memory allocation for channel lock in USB +Subject: [PATCH 16/80] Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005. --- @@ -89521,10 +89514,10 @@ index b7b6b0c..76b5085 100644 1.8.5.1 -From 734186aa128c8c97ccfe6cb116bf87efc1f3a1ca Mon Sep 17 00:00:00 2001 +From b44a91a00163f5991019e72372d9223a5e2632af Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 17/91] Add cpufreq driver +Subject: [PATCH 17/80] Add cpufreq driver --- arch/arm/Kconfig | 1 + @@ -89535,10 +89528,10 @@ Subject: [PATCH 17/91] Add cpufreq driver create mode 100755 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 981adf0..0e9efaf 100644 +index d667223..a97dd15 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -377,6 +377,7 @@ config ARCH_BCM2708 +@@ -382,6 +382,7 @@ config ARCH_BCM2708 select NEED_MACH_GPIO_H select NEED_MACH_MEMORY_H select CLKDEV_LOOKUP @@ -89547,10 +89540,10 @@ index 981adf0..0e9efaf 100644 select ARM_ERRATA_411920 select MACH_BCM2708 diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 0fa204b..b30b345 100644 +index ce52ed9..ee72801 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -228,6 +228,14 @@ config ARM_SPEAR_CPUFREQ +@@ -218,6 +218,14 @@ config ARM_SPEAR_CPUFREQ help This adds the CPUFreq driver support for SPEAr SOCs. @@ -89566,17 +89559,17 @@ index 0fa204b..b30b345 100644 bool "TEGRA CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index ad5866c..a47a44c 100644 +index 7494565..228317f 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o +@@ -73,6 +73,7 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o +obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o + obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o - ################################################################################## diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c new file mode 100755 index 0000000..7bc55bd @@ -89826,17 +89819,17 @@ index 0000000..7bc55bd 1.8.5.1 -From e1863ec8de63cba2532880e189c4cbd14a7bbd2d Mon Sep 17 00:00:00 2001 +From 1ffc89f77d5ee344d5186f7e2e4b4ab6706eb369 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:58:47 +0100 -Subject: [PATCH 18/91] config: add missing options from 3.6.y kernel +Subject: [PATCH 18/80] config: add missing options from 3.6.y kernel --- - arch/arm/configs/bcmrpi_defconfig | 733 +++++++++++++++++++++++++++++++++----- - 1 file changed, 636 insertions(+), 97 deletions(-) + arch/arm/configs/bcmrpi_defconfig | 741 ++++++++++++++++++++++++++++++++------ + 1 file changed, 636 insertions(+), 105 deletions(-) diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 31f5afaa..f4fba45 100644 +index 31f5afaa..31adf3c 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig @@ -1,11 +1,17 @@ @@ -89860,7 +89853,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_CGROUP_FREEZER=y -@@ -15,29 +21,42 @@ CONFIG_RESOURCE_COUNTERS=y +@@ -15,29 +21,43 @@ CONFIG_RESOURCE_COUNTERS=y CONFIG_BLK_CGROUP=y CONFIG_NAMESPACES=y CONFIG_SCHED_AUTOGROUP=y @@ -89889,6 +89882,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_AEABI=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y ++CONFIG_CMA=y +CONFIG_UACCESS_WITH_MEMCPY=y CONFIG_SECCOMP=y CONFIG_CC_STACKPROTECTOR=y @@ -89908,7 +89902,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_BINFMT_MISC=m -@@ -48,19 +67,276 @@ CONFIG_XFRM_USER=y +@@ -48,19 +68,275 @@ CONFIG_XFRM_USER=y CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -89941,10 +89935,10 @@ index 31f5afaa..f4fba45 100644 +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m -+CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y @@ -89967,7 +89961,6 @@ index 31f5afaa..f4fba45 100644 +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m -+CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m @@ -90200,7 +90193,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_BT_RFCOMM=m CONFIG_BT_RFCOMM_TTY=y CONFIG_BT_BNEP=m -@@ -89,35 +363,99 @@ CONFIG_BT_HCIVHCI=m +@@ -89,35 +363,100 @@ CONFIG_BT_HCIVHCI=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m CONFIG_BT_ATH3K=m @@ -90219,7 +90212,6 @@ index 31f5afaa..f4fba45 100644 -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_CMA=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_DRBD=m @@ -90246,13 +90238,14 @@ index 31f5afaa..f4fba45 100644 +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m -+CONFIG_DM_RAID=m +CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_RAID=m +CONFIG_DM_ZERO=m +CONFIG_DM_DELAY=m CONFIG_NETDEVICES=y +CONFIG_BONDING=m +CONFIG_DUMMY=m ++CONFIG_IFB=m +CONFIG_MACVLAN=m +CONFIG_NETCONSOLE=m CONFIG_TUN=m @@ -90281,6 +90274,7 @@ index 31f5afaa..f4fba45 100644 +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_NCM=m @@ -90308,7 +90302,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_LIBERTAS_THINFIRM=m CONFIG_LIBERTAS_THINFIRM_USB=m CONFIG_AT76C50X_USB=m -@@ -125,14 +463,17 @@ CONFIG_USB_ZD1201=m +@@ -125,14 +464,17 @@ CONFIG_USB_ZD1201=m CONFIG_USB_NET_RNDIS_WLAN=m CONFIG_RTL8187=m CONFIG_MAC80211_HWSIM=m @@ -90328,7 +90322,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_LIBERTAS=m CONFIG_LIBERTAS_USB=m CONFIG_LIBERTAS_SDIO=m -@@ -143,56 +484,25 @@ CONFIG_RT2500USB=m +@@ -143,56 +485,25 @@ CONFIG_RT2500USB=m CONFIG_RT73USB=m CONFIG_RT2800USB=m CONFIG_RT2800USB_RT53XX=y @@ -90383,7 +90377,7 @@ index 31f5afaa..f4fba45 100644 +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_XPAD=y ++CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y CONFIG_INPUT_MISC=y CONFIG_INPUT_AD714X=m @@ -90391,7 +90385,12 @@ index 31f5afaa..f4fba45 100644 CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_KEYSPAN_REMOTE=m CONFIG_INPUT_POWERMATE=m -@@ -212,21 +522,189 @@ CONFIG_VT_HW_CONSOLE_BINDING=y +@@ -207,26 +518,191 @@ 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 @@ -90510,8 +90509,6 @@ index 31f5afaa..f4fba45 100644 +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160=m -+CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m @@ -90584,7 +90581,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set -@@ -249,10 +727,10 @@ CONFIG_SND_BCM2835=m +@@ -249,10 +725,10 @@ CONFIG_SND_BCM2835=m CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_UA101=m CONFIG_SND_USB_CAIAQ=m @@ -90597,7 +90594,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_HID_A4TECH=m CONFIG_HID_ACRUX=m CONFIG_HID_APPLE=m -@@ -283,7 +761,6 @@ CONFIG_HID_ORTEK=m +@@ -283,7 +759,6 @@ CONFIG_HID_ORTEK=m CONFIG_HID_PANTHERLORD=m CONFIG_HID_PETALYNX=m CONFIG_HID_PICOLCD=m @@ -90605,7 +90602,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_HID_ROCCAT=m CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m -@@ -292,15 +769,18 @@ CONFIG_HID_SUNPLUS=m +@@ -292,15 +767,19 @@ CONFIG_HID_SUNPLUS=m CONFIG_HID_GREENASIA=m CONFIG_HID_SMARTJOYPLUS=m CONFIG_HID_TOPSEED=m @@ -90615,9 +90612,9 @@ index 31f5afaa..f4fba45 100644 CONFIG_HID_WIIMOTE=m CONFIG_HID_ZEROPLUS=m CONFIG_HID_ZYDACRON=m --CONFIG_USB=y +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_MON=m CONFIG_USB_DWCOTG=y @@ -90625,7 +90622,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_REALTEK=m CONFIG_USB_STORAGE_DATAFAB=m -@@ -315,8 +795,6 @@ CONFIG_USB_STORAGE_ONETOUCH=m +@@ -315,8 +794,6 @@ CONFIG_USB_STORAGE_ONETOUCH=m CONFIG_USB_STORAGE_KARMA=m CONFIG_USB_STORAGE_CYPRESS_ATACB=m CONFIG_USB_STORAGE_ENE_UB6250=m @@ -90634,7 +90631,13 @@ index 31f5afaa..f4fba45 100644 CONFIG_USB_MDC800=m CONFIG_USB_MICROTEK=m CONFIG_USB_SERIAL=m -@@ -337,6 +815,7 @@ CONFIG_USB_SERIAL_IPAQ=m +@@ -331,12 +808,12 @@ 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 @@ -90642,20 +90645,33 @@ index 31f5afaa..f4fba45 100644 CONFIG_USB_SERIAL_GARMIN=m CONFIG_USB_SERIAL_IPW=m CONFIG_USB_SERIAL_IUU=m -@@ -345,6 +824,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m +@@ -345,18 +822,16 @@ 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_METRO=m CONFIG_USB_SERIAL_MOS7720=m CONFIG_USB_SERIAL_MOS7840=m - CONFIG_USB_SERIAL_MOTOROLA=m -@@ -366,8 +846,12 @@ CONFIG_USB_SERIAL_OPTION=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 +@@ -365,9 +840,11 @@ 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_VIVOPAY_SERIAL=m +-CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_XSENS_MT=m - CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SERIAL_WISHBONE=m +CONFIG_USB_SERIAL_ZTE=m CONFIG_USB_SERIAL_SSU100=m @@ -90663,7 +90679,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_USB_SERIAL_DEBUG=m CONFIG_USB_EMI62=m CONFIG_USB_EMI26=m -@@ -389,17 +873,71 @@ CONFIG_USB_TEST=m +@@ -389,17 +866,71 @@ CONFIG_USB_TEST=m CONFIG_USB_ISIGHTFW=m CONFIG_USB_YUREX=m CONFIG_MMC=y @@ -90688,6 +90704,7 @@ index 31f5afaa..f4fba45 100644 +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1672=m @@ -90719,7 +90736,7 @@ index 31f5afaa..f4fba45 100644 +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_RX4581=m CONFIG_UIO=m - CONFIG_UIO_PDRV=m +-CONFIG_UIO_PDRV=m CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_STAGING=y +CONFIG_W35UND=m @@ -90739,7 +90756,7 @@ index 31f5afaa..f4fba45 100644 # CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y -@@ -422,6 +960,8 @@ CONFIG_BTRFS_FS=m +@@ -422,6 +953,8 @@ CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y CONFIG_NILFS2_FS=m CONFIG_FANOTIFY=y @@ -90748,7 +90765,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_AUTOFS4_FS=y CONFIG_FUSE_FS=m CONFIG_CUSE=m -@@ -437,28 +977,32 @@ CONFIG_MSDOS_FS=y +@@ -437,28 +970,32 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_IOCHARSET="ascii" CONFIG_NTFS_FS=m @@ -90785,7 +90802,7 @@ index 31f5afaa..f4fba45 100644 CONFIG_NLS_DEFAULT="utf8" CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m -@@ -497,39 +1041,34 @@ CONFIG_NLS_ISO8859_14=m +@@ -497,39 +1034,33 @@ CONFIG_NLS_ISO8859_14=m CONFIG_NLS_ISO8859_15=m CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m @@ -90815,10 +90832,10 @@ index 31f5afaa..f4fba45 100644 CONFIG_KDB_KEYBOARD=y CONFIG_STRICT_DEVMEM=y -CONFIG_CRYPTO_AUTHENC=m +-CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_CRYPTD=m - CONFIG_CRYPTO_SEQIV=m CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XTS=m @@ -90841,10 +90858,10 @@ index 31f5afaa..f4fba45 100644 1.8.5.1 -From d232364c5eed6e266015d146cbbcab9d0bec325f Mon Sep 17 00:00:00 2001 +From eebaab06209987c79af89b2c917fc000ed25bc34 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 8 Apr 2013 21:12:48 +0100 -Subject: [PATCH 19/91] Add NAK holdoff scheme. Enabled by default, disable +Subject: [PATCH 19/80] Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh --- @@ -91054,10 +91071,10 @@ index a9dea55..ebee73a 100644 1.8.5.1 -From 334fc0c90c021a5713c884de618ca3393613d924 Mon Sep 17 00:00:00 2001 +From 9f46c3d5353e36c987b038405ac89445a7f199b8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 20/91] Added hwmon/thermal driver for reporting core +Subject: [PATCH 20/80] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian --- @@ -91073,7 +91090,7 @@ Subject: [PATCH 20/91] Added hwmon/thermal driver for reporting core create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index dd73b81..a82d5bd 100644 +index 0836685..8b6ff52 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -567,6 +567,14 @@ struct platform_device bcm2708_powerman_device = { @@ -91102,10 +91119,10 @@ index dd73b81..a82d5bd 100644 struct amba_device *d = amba_devs[i]; amba_device_register(d, &iomem_resource); diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index b3ab9d4..d60bc7f 100644 +index 52d548f..c0d94f9 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig -@@ -1553,6 +1553,16 @@ config SENSORS_MC13783_ADC +@@ -1554,6 +1554,16 @@ config SENSORS_MC13783_ADC help Support for the A/D converter on MC13783 and MC13892 PMIC. @@ -91360,7 +91377,7 @@ index 0000000..5bbed45 + +module_platform_driver(bcm2835_hwmon_driver); diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index dbfc390..8d3c280 100644 +index f35a1f7..0839a16 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -181,6 +181,12 @@ config INTEL_POWERCLAMP @@ -91605,17 +91622,17 @@ index 0000000..3f9a733 1.8.5.1 -From d73dcb39470b7a79bff68ec7427a0e54037e748a Mon Sep 17 00:00:00 2001 +From b3c9ca84a938dce992581248daa1c46b9c804384 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 12:16:36 +0100 -Subject: [PATCH 21/91] Enable multiple ALSA channels +Subject: [PATCH 21/80] Enable multiple ALSA channels --- arch/arm/mach-bcm2708/bcm2708.c | 54 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a82d5bd..a388dd8 100644 +index 8b6ff52..b4d94bf 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -476,12 +476,54 @@ struct platform_device bcm2708_powerman_device = { @@ -91683,10 +91700,10 @@ index a82d5bd..a388dd8 100644 1.8.5.1 -From 2e8ef414d4012bac928010d3bb6f3991f34a76ba Mon Sep 17 00:00:00 2001 +From 4fc053e815994155bb42c649423b6d02b005f694 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Sun, 4 Nov 2012 15:55:01 +0000 -Subject: [PATCH 22/91] Make sure we wait for the reset to finish +Subject: [PATCH 22/80] Make sure we wait for the reset to finish --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 ++ @@ -91709,1350 +91726,10 @@ index aff59df..1a23d4b 100644 1.8.5.1 -From f40c81b08a1f7fc444af027a96c3918fe2471f72 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 19 Nov 2012 18:27:05 +0000 -Subject: [PATCH 23/91] Add Simon Hall's dma helper module, useful in future - for X acceleration - ---- - arch/arm/mach-bcm2708/Kconfig | 8 + - arch/arm/mach-bcm2708/Makefile | 3 + - arch/arm/mach-bcm2708/dmaer.c | 886 ++++++++++++++++++++++++ - arch/arm/mach-bcm2708/include/mach/vc_support.h | 69 ++ - arch/arm/mach-bcm2708/vc_support.c | 318 +++++++++ - 5 files changed, 1284 insertions(+) - create mode 100755 arch/arm/mach-bcm2708/dmaer.c - create mode 100755 arch/arm/mach-bcm2708/include/mach/vc_support.h - create mode 100755 arch/arm/mach-bcm2708/vc_support.c - -diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig -index e151ed4..2dcd6fa 100644 ---- a/arch/arm/mach-bcm2708/Kconfig -+++ b/arch/arm/mach-bcm2708/Kconfig -@@ -38,4 +38,12 @@ config BCM2708_SPIDEV - default y - help - Binds spidev driver to the SPI0 master -+ -+config BCM2708_DMAER -+ tristate "BCM2708 DMA helper" -+ depends on MACH_BCM2708 -+ default n -+ help -+ Enable DMA helper for accelerating X composition -+ - endmenu -diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile -index a722f3f..03b504b 100644 ---- a/arch/arm/mach-bcm2708/Makefile -+++ b/arch/arm/mach-bcm2708/Makefile -@@ -5,3 +5,6 @@ - obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o - obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o - obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -+ -+obj-$(CONFIG_BCM2708_DMAER) += dmaer_master.o -+dmaer_master-objs := dmaer.o vc_support.o -diff --git a/arch/arm/mach-bcm2708/dmaer.c b/arch/arm/mach-bcm2708/dmaer.c -new file mode 100755 -index 0000000..5b0f0ff ---- /dev/null -+++ b/arch/arm/mach-bcm2708/dmaer.c -@@ -0,0 +1,886 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#ifdef ECLIPSE_IGNORE -+ -+#define __user -+#define __init -+#define __exit -+#define __iomem -+#define KERN_DEBUG -+#define KERN_ERR -+#define KERN_WARNING -+#define KERN_INFO -+#define _IOWR(a, b, c) b -+#define _IOW(a, b, c) b -+#define _IO(a, b) b -+ -+#endif -+ -+//#define inline -+ -+#define PRINTK(args...) printk(args) -+//#define PRINTK_VERBOSE(args...) printk(args) -+//#define PRINTK(args...) -+#define PRINTK_VERBOSE(args...) -+ -+/***** TYPES ****/ -+#define PAGES_PER_LIST 500 -+struct PageList -+{ -+ struct page *m_pPages[PAGES_PER_LIST]; -+ unsigned int m_used; -+ struct PageList *m_pNext; -+}; -+ -+struct VmaPageList -+{ -+ //each vma has a linked list of pages associated with it -+ struct PageList *m_pPageHead; -+ struct PageList *m_pPageTail; -+ unsigned int m_refCount; -+}; -+ -+struct DmaControlBlock -+{ -+ unsigned int m_transferInfo; -+ void __user *m_pSourceAddr; -+ void __user *m_pDestAddr; -+ unsigned int m_xferLen; -+ unsigned int m_tdStride; -+ struct DmaControlBlock *m_pNext; -+ unsigned int m_blank1, m_blank2; -+}; -+ -+/***** DEFINES ******/ -+//magic number defining the module -+#define DMA_MAGIC 0xdd -+ -+//do user virtual to physical translation of the CB chain -+#define DMA_PREPARE _IOWR(DMA_MAGIC, 0, struct DmaControlBlock *) -+ -+//kick the pre-prepared CB chain -+#define DMA_KICK _IOW(DMA_MAGIC, 1, struct DmaControlBlock *) -+ -+//prepare it, kick it, wait for it -+#define DMA_PREPARE_KICK_WAIT _IOWR(DMA_MAGIC, 2, struct DmaControlBlock *) -+ -+//prepare it, kick it, don't wait for it -+#define DMA_PREPARE_KICK _IOWR(DMA_MAGIC, 3, struct DmaControlBlock *) -+ -+//not currently implemented -+#define DMA_WAIT_ONE _IO(DMA_MAGIC, 4, struct DmaControlBlock *) -+ -+//wait on all kicked CB chains -+#define DMA_WAIT_ALL _IO(DMA_MAGIC, 5) -+ -+//in order to discover the largest AXI burst that should be programmed into the transfer params -+#define DMA_MAX_BURST _IO(DMA_MAGIC, 6) -+ -+//set the address range through which the user address is assumed to already by a physical address -+#define DMA_SET_MIN_PHYS _IOW(DMA_MAGIC, 7, unsigned long) -+#define DMA_SET_MAX_PHYS _IOW(DMA_MAGIC, 8, unsigned long) -+#define DMA_SET_PHYS_OFFSET _IOW(DMA_MAGIC, 9, unsigned long) -+ -+//used to define the size for the CMA-based allocation *in pages*, can only be done once once the file is opened -+#define DMA_CMA_SET_SIZE _IOW(DMA_MAGIC, 10, unsigned long) -+ -+//used to get the version of the module, to test for a capability -+#define DMA_GET_VERSION _IO(DMA_MAGIC, 99) -+ -+#define VERSION_NUMBER 1 -+ -+#define VIRT_TO_BUS_CACHE_SIZE 8 -+ -+/***** FILE OPS *****/ -+static int Open(struct inode *pInode, struct file *pFile); -+static int Release(struct inode *pInode, struct file *pFile); -+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg); -+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp); -+static int Mmap(struct file *pFile, struct vm_area_struct *pVma); -+ -+/***** VMA OPS ****/ -+static void VmaOpen4k(struct vm_area_struct *pVma); -+static void VmaClose4k(struct vm_area_struct *pVma); -+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf); -+ -+/**** DMA PROTOTYPES */ -+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError); -+static int DmaKick(struct DmaControlBlock __user *pUserCB); -+static void DmaWaitAll(void); -+ -+/**** GENERIC ****/ -+static int __init dmaer_init(void); -+static void __exit dmaer_exit(void); -+ -+/*** OPS ***/ -+static struct vm_operations_struct g_vmOps4k = { -+ .open = VmaOpen4k, -+ .close = VmaClose4k, -+ .fault = VmaFault4k, -+}; -+ -+static struct file_operations g_fOps = { -+ .owner = THIS_MODULE, -+ .llseek = 0, -+ .read = Read, -+ .write = 0, -+ .unlocked_ioctl = Ioctl, -+ .open = Open, -+ .release = Release, -+ .mmap = Mmap, -+}; -+ -+/***** GLOBALS ******/ -+static dev_t g_majorMinor; -+ -+//tracking usage of the two files -+static atomic_t g_oneLock4k = ATOMIC_INIT(1); -+ -+//device operations -+static struct cdev g_cDev; -+static int g_trackedPages = 0; -+ -+//dma control -+static unsigned int *g_pDmaChanBase; -+static int g_dmaIrq; -+static int g_dmaChan; -+ -+//cma allocation -+static int g_cmaHandle; -+ -+//user virtual to bus address translation acceleration -+static unsigned long g_virtAddr[VIRT_TO_BUS_CACHE_SIZE]; -+static unsigned long g_busAddr[VIRT_TO_BUS_CACHE_SIZE]; -+static unsigned long g_cbVirtAddr; -+static unsigned long g_cbBusAddr; -+static int g_cacheInsertAt; -+static int g_cacheHit, g_cacheMiss; -+ -+//off by default -+static void __user *g_pMinPhys; -+static void __user *g_pMaxPhys; -+static unsigned long g_physOffset; -+ -+/****** CACHE OPERATIONS ********/ -+static inline void FlushAddrCache(void) -+{ -+ int count = 0; -+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++) -+ g_virtAddr[count] = 0xffffffff; //never going to match as we always chop the bottom bits anyway -+ -+ g_cbVirtAddr = 0xffffffff; -+ -+ g_cacheInsertAt = 0; -+} -+ -+//translate from a user virtual address to a bus address by mapping the page -+//NB this won't lock a page in memory, so to avoid potential paging issues using kernel logical addresses -+static inline void __iomem *UserVirtualToBus(void __user *pUser) -+{ -+ int mapped; -+ struct page *pPage; -+ void *phys; -+ -+ //map it (requiring that the pointer points to something that does not hang off the page boundary) -+ mapped = get_user_pages(current, current->mm, -+ (unsigned long)pUser, 1, -+ 1, 0, -+ &pPage, -+ 0); -+ -+ if (mapped <= 0) //error -+ return 0; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "user virtual %p arm phys %p bus %p\n", -+ pUser, page_address(pPage), (void __iomem *)__virt_to_bus(page_address(pPage))); -+ -+ //get the arm physical address -+ phys = page_address(pPage) + offset_in_page(pUser); -+ page_cache_release(pPage); -+ -+ //and now the bus address -+ return (void __iomem *)__virt_to_bus(phys); -+} -+ -+static inline void __iomem *UserVirtualToBusViaCbCache(void __user *pUser) -+{ -+ unsigned long virtual_page = (unsigned long)pUser & ~4095; -+ unsigned long page_offset = (unsigned long)pUser & 4095; -+ unsigned long bus_addr; -+ -+ if (g_cbVirtAddr == virtual_page) -+ { -+ bus_addr = g_cbBusAddr + page_offset; -+ g_cacheHit++; -+ return (void __iomem *)bus_addr; -+ } -+ else -+ { -+ bus_addr = (unsigned long)UserVirtualToBus(pUser); -+ -+ if (!bus_addr) -+ return 0; -+ -+ g_cbVirtAddr = virtual_page; -+ g_cbBusAddr = bus_addr & ~4095; -+ g_cacheMiss++; -+ -+ return (void __iomem *)bus_addr; -+ } -+} -+ -+//do the same as above, by query our virt->bus cache -+static inline void __iomem *UserVirtualToBusViaCache(void __user *pUser) -+{ -+ int count; -+ //get the page and its offset -+ unsigned long virtual_page = (unsigned long)pUser & ~4095; -+ unsigned long page_offset = (unsigned long)pUser & 4095; -+ unsigned long bus_addr; -+ -+ if (pUser >= g_pMinPhys && pUser < g_pMaxPhys) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "user->phys passthrough on %p\n", pUser); -+ return (void __iomem *)((unsigned long)pUser + g_physOffset); -+ } -+ -+ //check the cache for our entry -+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++) -+ if (g_virtAddr[count] == virtual_page) -+ { -+ bus_addr = g_busAddr[count] + page_offset; -+ g_cacheHit++; -+ return (void __iomem *)bus_addr; -+ } -+ -+ //not found, look up manually and then insert its page address -+ bus_addr = (unsigned long)UserVirtualToBus(pUser); -+ -+ if (!bus_addr) -+ return 0; -+ -+ g_virtAddr[g_cacheInsertAt] = virtual_page; -+ g_busAddr[g_cacheInsertAt] = bus_addr & ~4095; -+ -+ //round robin -+ g_cacheInsertAt++; -+ if (g_cacheInsertAt == VIRT_TO_BUS_CACHE_SIZE) -+ g_cacheInsertAt = 0; -+ -+ g_cacheMiss++; -+ -+ return (void __iomem *)bus_addr; -+} -+ -+/***** FILE OPERATIONS ****/ -+static int Open(struct inode *pInode, struct file *pFile) -+{ -+ PRINTK(KERN_DEBUG "file opening: %d/%d\n", imajor(pInode), iminor(pInode)); -+ -+ //check which device we are -+ if (iminor(pInode) == 0) //4k -+ { -+ //only one at a time -+ if (!atomic_dec_and_test(&g_oneLock4k)) -+ { -+ atomic_inc(&g_oneLock4k); -+ return -EBUSY; -+ } -+ } -+ else -+ return -EINVAL; -+ -+ //todo there will be trouble if two different processes open the files -+ -+ //reset after any file is opened -+ g_pMinPhys = (void __user *)-1; -+ g_pMaxPhys = (void __user *)0; -+ g_physOffset = 0; -+ g_cmaHandle = 0; -+ -+ return 0; -+} -+ -+static int Release(struct inode *pInode, struct file *pFile) -+{ -+ PRINTK(KERN_DEBUG "file closing, %d pages tracked\n", g_trackedPages); -+ if (g_trackedPages) -+ PRINTK(KERN_ERR "we\'re leaking memory!\n"); -+ -+ //wait for any dmas to finish -+ DmaWaitAll(); -+ -+ //free this memory on the application closing the file or it crashing (implicitly closing the file) -+ if (g_cmaHandle) -+ { -+ PRINTK(KERN_DEBUG "unlocking vc memory\n"); -+ if (UnlockVcMemory(g_cmaHandle)) -+ PRINTK(KERN_ERR "uh-oh, unable to unlock vc memory!\n"); -+ PRINTK(KERN_DEBUG "releasing vc memory\n"); -+ if (ReleaseVcMemory(g_cmaHandle)) -+ PRINTK(KERN_ERR "uh-oh, unable to release vc memory!\n"); -+ } -+ -+ if (iminor(pInode) == 0) -+ atomic_inc(&g_oneLock4k); -+ else -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError) -+{ -+ struct DmaControlBlock kernCB; -+ struct DmaControlBlock __user *pUNext; -+ void __iomem *pSourceBus, __iomem *pDestBus; -+ -+ //get the control block into kernel memory so we can work on it -+ if (copy_from_user(&kernCB, pUserCB, sizeof(struct DmaControlBlock)) != 0) -+ { -+ PRINTK(KERN_ERR "copy_from_user failed for user cb %p\n", pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ if (kernCB.m_pSourceAddr == 0 || kernCB.m_pDestAddr == 0) -+ { -+ PRINTK(KERN_ERR "faulty source (%p) dest (%p) addresses for user cb %p\n", -+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr, pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ pSourceBus = UserVirtualToBusViaCache(kernCB.m_pSourceAddr); -+ pDestBus = UserVirtualToBusViaCache(kernCB.m_pDestAddr); -+ -+ if (!pSourceBus || !pDestBus) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for source/dest %p/%p->%p/%p\n", -+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr, -+ pSourceBus, pDestBus); -+ *pError = 1; -+ return 0; -+ } -+ -+ //update the user structure with the new bus addresses -+ kernCB.m_pSourceAddr = pSourceBus; -+ kernCB.m_pDestAddr = pDestBus; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "final source %p dest %p\n", kernCB.m_pSourceAddr, kernCB.m_pDestAddr); -+ -+ //sort out the bus address for the next block -+ pUNext = kernCB.m_pNext; -+ -+ if (kernCB.m_pNext) -+ { -+ void __iomem *pNextBus; -+ pNextBus = UserVirtualToBusViaCbCache(kernCB.m_pNext); -+ -+ if (!pNextBus) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for m_pNext\n"); -+ *pError = 1; -+ return 0; -+ } -+ -+ //update the pointer with the bus address -+ kernCB.m_pNext = pNextBus; -+ } -+ -+ //write it back to user space -+ if (copy_to_user(pUserCB, &kernCB, sizeof(struct DmaControlBlock)) != 0) -+ { -+ PRINTK(KERN_ERR "copy_to_user failed for cb %p\n", pUserCB); -+ *pError = 1; -+ return 0; -+ } -+ -+ __cpuc_flush_dcache_area(pUserCB, 32); -+ -+ *pError = 0; -+ return pUNext; -+} -+ -+static int DmaKick(struct DmaControlBlock __user *pUserCB) -+{ -+ void __iomem *pBusCB; -+ -+ pBusCB = UserVirtualToBusViaCbCache(pUserCB); -+ if (!pBusCB) -+ { -+ PRINTK(KERN_ERR "virtual to bus translation failure for cb\n"); -+ return 1; -+ } -+ -+ //flush_cache_all(); -+ -+ bcm_dma_start(g_pDmaChanBase, (dma_addr_t)pBusCB); -+ -+ return 0; -+} -+ -+static void DmaWaitAll(void) -+{ -+ int counter = 0; -+ volatile int inner_count; -+ volatile unsigned int cs; -+ unsigned long time_before, time_after; -+ -+ time_before = jiffies; -+ //bcm_dma_wait_idle(g_pDmaChanBase); -+ dsb(); -+ -+ cs = readl(g_pDmaChanBase); -+ -+ while ((cs & 1) == 1) -+ { -+ cs = readl(g_pDmaChanBase); -+ counter++; -+ -+ for (inner_count = 0; inner_count < 32; inner_count++); -+ -+ asm volatile ("MCR p15,0,r0,c7,c0,4 \n"); -+ //cpu_do_idle(); -+ if (counter >= 1000000) -+ { -+ PRINTK(KERN_WARNING "DMA failed to finish in a timely fashion\n"); -+ break; -+ } -+ } -+ time_after = jiffies; -+ PRINTK_VERBOSE(KERN_DEBUG "done, counter %d, cs %08x", counter, cs); -+ PRINTK_VERBOSE(KERN_DEBUG "took %ld jiffies, %d HZ\n", time_after - time_before, HZ); -+} -+ -+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg) -+{ -+ int error = 0; -+ PRINTK_VERBOSE(KERN_DEBUG "ioctl cmd %x arg %lx\n", cmd, arg); -+ -+ switch (cmd) -+ { -+ case DMA_PREPARE: -+ case DMA_PREPARE_KICK: -+ case DMA_PREPARE_KICK_WAIT: -+ { -+ struct DmaControlBlock __user *pUCB = (struct DmaControlBlock *)arg; -+ int steps = 0; -+ unsigned long start_time = jiffies; -+ (void)start_time; -+ -+ //flush our address cache -+ FlushAddrCache(); -+ -+ PRINTK_VERBOSE(KERN_DEBUG "dma prepare\n"); -+ -+ //do virtual to bus translation for each entry -+ do -+ { -+ pUCB = DmaPrepare(pUCB, &error); -+ } while (error == 0 && ++steps && pUCB); -+ PRINTK_VERBOSE(KERN_DEBUG "prepare done in %d steps, %ld\n", steps, jiffies - start_time); -+ -+ //carry straight on if we want to kick too -+ if (cmd == DMA_PREPARE || error) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "falling out\n"); -+ return error ? -EINVAL : 0; -+ } -+ } -+ case DMA_KICK: -+ PRINTK_VERBOSE(KERN_DEBUG "dma begin\n"); -+ -+ if (cmd == DMA_KICK) -+ FlushAddrCache(); -+ -+ DmaKick((struct DmaControlBlock __user *)arg); -+ -+ if (cmd != DMA_PREPARE_KICK_WAIT) -+ break; -+/* case DMA_WAIT_ONE: -+ //PRINTK(KERN_DEBUG "dma wait one\n"); -+ break;*/ -+ case DMA_WAIT_ALL: -+ //PRINTK(KERN_DEBUG "dma wait all\n"); -+ DmaWaitAll(); -+ break; -+ case DMA_MAX_BURST: -+ if (g_dmaChan == 0) -+ return 10; -+ else -+ return 5; -+ case DMA_SET_MIN_PHYS: -+ g_pMinPhys = (void __user *)arg; -+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys); -+ break; -+ case DMA_SET_MAX_PHYS: -+ g_pMaxPhys = (void __user *)arg; -+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys); -+ break; -+ case DMA_SET_PHYS_OFFSET: -+ g_physOffset = arg; -+ PRINTK(KERN_DEBUG "user/phys bypass offset set to %ld\n", g_physOffset); -+ break; -+ case DMA_CMA_SET_SIZE: -+ { -+ unsigned int pBusAddr; -+ -+ if (g_cmaHandle) -+ { -+ PRINTK(KERN_ERR "memory has already been allocated (handle %d)\n", g_cmaHandle); -+ return -EINVAL; -+ } -+ -+ PRINTK(KERN_INFO "allocating %ld bytes of VC memory\n", arg * 4096); -+ -+ //get the memory -+ if (AllocateVcMemory(&g_cmaHandle, arg * 4096, 4096, MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_NO_INIT | MEM_FLAG_HINT_PERMALOCK)) -+ { -+ PRINTK(KERN_ERR "failed to allocate %ld bytes of VC memory\n", arg * 4096); -+ g_cmaHandle = 0; -+ return -EINVAL; -+ } -+ -+ //get an address for it -+ PRINTK(KERN_INFO "trying to map VC memory\n"); -+ -+ if (LockVcMemory(&pBusAddr, g_cmaHandle)) -+ { -+ PRINTK(KERN_ERR "failed to map CMA handle %d, releasing memory\n", g_cmaHandle); -+ ReleaseVcMemory(g_cmaHandle); -+ g_cmaHandle = 0; -+ } -+ -+ PRINTK(KERN_INFO "bus address for CMA memory is %x\n", pBusAddr); -+ return pBusAddr; -+ } -+ case DMA_GET_VERSION: -+ PRINTK(KERN_DEBUG "returning version number, %d\n", VERSION_NUMBER); -+ return VERSION_NUMBER; -+ default: -+ PRINTK(KERN_DEBUG "unknown ioctl: %d\n", cmd); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp) -+{ -+ return -EIO; -+} -+ -+static int Mmap(struct file *pFile, struct vm_area_struct *pVma) -+{ -+ struct PageList *pPages; -+ struct VmaPageList *pVmaList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "MMAP vma %p, length %ld (%s %d)\n", -+ pVma, pVma->vm_end - pVma->vm_start, -+ current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_DEBUG "MMAP %p %d (tracked %d)\n", pVma, current->pid, g_trackedPages); -+ -+ //make a new page list -+ pPages = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL); -+ if (!pPages) -+ { -+ PRINTK(KERN_ERR "couldn\'t allocate a new page list (%s %d)\n", -+ current->comm, current->pid); -+ return -ENOMEM; -+ } -+ -+ //clear the page list -+ pPages->m_used = 0; -+ pPages->m_pNext = 0; -+ -+ //insert our vma and new page list somewhere -+ if (!pVma->vm_private_data) -+ { -+ struct VmaPageList *pList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "new vma list, making new one (%s %d)\n", -+ current->comm, current->pid); -+ -+ //make a new vma list -+ pList = (struct VmaPageList *)kmalloc(sizeof(struct VmaPageList), GFP_KERNEL); -+ if (!pList) -+ { -+ PRINTK(KERN_ERR "couldn\'t allocate vma page list (%s %d)\n", -+ current->comm, current->pid); -+ kfree(pPages); -+ return -ENOMEM; -+ } -+ -+ //clear this list -+ pVma->vm_private_data = (void *)pList; -+ pList->m_refCount = 0; -+ } -+ -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ //add it to the vma list -+ pVmaList->m_pPageHead = pPages; -+ pVmaList->m_pPageTail = pPages; -+ -+ pVma->vm_ops = &g_vmOps4k; -+ pVma->vm_flags |= VM_IO; -+ -+ VmaOpen4k(pVma); -+ -+ return 0; -+} -+ -+/****** VMA OPERATIONS ******/ -+ -+static void VmaOpen4k(struct vm_area_struct *pVma) -+{ -+ struct VmaPageList *pVmaList; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "vma open %p private %p (%s %d), %d live pages\n", pVma, pVma->vm_private_data, current->comm, current->pid, g_trackedPages); -+ PRINTK_VERBOSE(KERN_DEBUG "OPEN %p %d %ld pages (tracked pages %d)\n", -+ pVma, current->pid, (pVma->vm_end - pVma->vm_start) >> 12, -+ g_trackedPages); -+ -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ if (pVmaList) -+ { -+ pVmaList->m_refCount++; -+ PRINTK_VERBOSE(KERN_DEBUG "ref count is now %d\n", pVmaList->m_refCount); -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "err, open but no vma page list\n"); -+ } -+} -+ -+static void VmaClose4k(struct vm_area_struct *pVma) -+{ -+ struct VmaPageList *pVmaList; -+ int freed = 0; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "vma close %p private %p (%s %d)\n", pVma, pVma->vm_private_data, current->comm, current->pid); -+ -+ //wait for any dmas to finish -+ DmaWaitAll(); -+ -+ //find our vma in the list -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ //may be a fork -+ if (pVmaList) -+ { -+ struct PageList *pPages; -+ -+ pVmaList->m_refCount--; -+ -+ if (pVmaList->m_refCount == 0) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "found vma, freeing pages (%s %d)\n", -+ current->comm, current->pid); -+ -+ pPages = pVmaList->m_pPageHead; -+ -+ if (!pPages) -+ { -+ PRINTK(KERN_ERR "no page list (%s %d)!\n", -+ current->comm, current->pid); -+ return; -+ } -+ -+ while (pPages) -+ { -+ struct PageList *next; -+ int count; -+ -+ PRINTK_VERBOSE(KERN_DEBUG "page list (%s %d)\n", -+ current->comm, current->pid); -+ -+ next = pPages->m_pNext; -+ for (count = 0; count < pPages->m_used; count++) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "freeing page %p (%s %d)\n", -+ pPages->m_pPages[count], -+ current->comm, current->pid); -+ __free_pages(pPages->m_pPages[count], 0); -+ g_trackedPages--; -+ freed++; -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "freeing page list (%s %d)\n", -+ current->comm, current->pid); -+ kfree(pPages); -+ pPages = next; -+ } -+ -+ //remove our vma from the list -+ kfree(pVmaList); -+ pVma->vm_private_data = 0; -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "ref count is %d, not closing\n", pVmaList->m_refCount); -+ } -+ } -+ else -+ { -+ PRINTK_VERBOSE(KERN_ERR "uh-oh, vma %p not found (%s %d)!\n", pVma, current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_ERR "CLOSE ERR\n"); -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "CLOSE %p %d %d pages (tracked pages %d)", -+ pVma, current->pid, freed, g_trackedPages); -+ -+ PRINTK_VERBOSE(KERN_DEBUG "%d pages open\n", g_trackedPages); -+} -+ -+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf) -+{ -+ PRINTK_VERBOSE(KERN_DEBUG "vma fault for vma %p private %p at offset %ld (%s %d)\n", pVma, pVma->vm_private_data, pVmf->pgoff, -+ current->comm, current->pid); -+ PRINTK_VERBOSE(KERN_DEBUG "FAULT\n"); -+ pVmf->page = alloc_page(GFP_KERNEL); -+ -+ if (pVmf->page) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "alloc page virtual %p\n", page_address(pVmf->page)); -+ } -+ -+ if (!pVmf->page) -+ { -+ PRINTK(KERN_ERR "vma fault oom (%s %d)\n", current->comm, current->pid); -+ return VM_FAULT_OOM; -+ } -+ else -+ { -+ struct VmaPageList *pVmaList; -+ -+ get_page(pVmf->page); -+ g_trackedPages++; -+ -+ //find our vma in the list -+ pVmaList = (struct VmaPageList *)pVma->vm_private_data; -+ -+ if (pVmaList) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "vma found (%s %d)\n", current->comm, current->pid); -+ -+ if (pVmaList->m_pPageTail->m_used == PAGES_PER_LIST) -+ { -+ PRINTK_VERBOSE(KERN_DEBUG "making new page list (%s %d)\n", current->comm, current->pid); -+ //making a new page list -+ pVmaList->m_pPageTail->m_pNext = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL); -+ if (!pVmaList->m_pPageTail->m_pNext) -+ return -ENOMEM; -+ -+ //update the tail pointer -+ pVmaList->m_pPageTail = pVmaList->m_pPageTail->m_pNext; -+ pVmaList->m_pPageTail->m_used = 0; -+ pVmaList->m_pPageTail->m_pNext = 0; -+ } -+ -+ PRINTK_VERBOSE(KERN_DEBUG "adding page to list (%s %d)\n", current->comm, current->pid); -+ -+ pVmaList->m_pPageTail->m_pPages[pVmaList->m_pPageTail->m_used] = pVmf->page; -+ pVmaList->m_pPageTail->m_used++; -+ } -+ else -+ PRINTK(KERN_ERR "returned page for vma we don\'t know %p (%s %d)\n", pVma, current->comm, current->pid); -+ -+ return 0; -+ } -+} -+ -+/****** GENERIC FUNCTIONS ******/ -+static int __init dmaer_init(void) -+{ -+ int result = alloc_chrdev_region(&g_majorMinor, 0, 1, "dmaer"); -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "unable to get major device number\n"); -+ return result; -+ } -+ else -+ PRINTK(KERN_DEBUG "major device number %d\n", MAJOR(g_majorMinor)); -+ -+ PRINTK(KERN_DEBUG "vma list size %d, page list size %d, page size %ld\n", -+ sizeof(struct VmaPageList), sizeof(struct PageList), PAGE_SIZE); -+ -+ //get a dma channel to work with -+ result = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, (void **)&g_pDmaChanBase, &g_dmaIrq); -+ -+ //uncomment to force to channel 0 -+ //result = 0; -+ //g_pDmaChanBase = 0xce808000; -+ -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "failed to allocate dma channel\n"); -+ cdev_del(&g_cDev); -+ unregister_chrdev_region(g_majorMinor, 1); -+ } -+ -+ //reset the channel -+ PRINTK(KERN_DEBUG "allocated dma channel %d (%p), initial state %08x\n", result, g_pDmaChanBase, *g_pDmaChanBase); -+ *g_pDmaChanBase = 1 << 31; -+ PRINTK(KERN_DEBUG "post-reset %08x\n", *g_pDmaChanBase); -+ -+ g_dmaChan = result; -+ -+ //clear the cache stats -+ g_cacheHit = 0; -+ g_cacheMiss = 0; -+ -+ //register our device - after this we are go go go -+ cdev_init(&g_cDev, &g_fOps); -+ g_cDev.owner = THIS_MODULE; -+ g_cDev.ops = &g_fOps; -+ -+ result = cdev_add(&g_cDev, g_majorMinor, 1); -+ if (result < 0) -+ { -+ PRINTK(KERN_ERR "failed to add character device\n"); -+ unregister_chrdev_region(g_majorMinor, 1); -+ bcm_dma_chan_free(g_dmaChan); -+ return result; -+ } -+ -+ return 0; -+} -+ -+static void __exit dmaer_exit(void) -+{ -+ PRINTK(KERN_INFO "closing dmaer device, cache stats: %d hits %d misses\n", g_cacheHit, g_cacheMiss); -+ //unregister the device -+ cdev_del(&g_cDev); -+ unregister_chrdev_region(g_majorMinor, 1); -+ //free the dma channel -+ bcm_dma_chan_free(g_dmaChan); -+} -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_AUTHOR("Simon Hall"); -+module_init(dmaer_init); -+module_exit(dmaer_exit); -diff --git a/arch/arm/mach-bcm2708/include/mach/vc_support.h b/arch/arm/mach-bcm2708/include/mach/vc_support.h -new file mode 100755 -index 0000000..70e809f ---- /dev/null -+++ b/arch/arm/mach-bcm2708/include/mach/vc_support.h -@@ -0,0 +1,69 @@ -+#ifndef _VC_SUPPORT_H_ -+#define _VC_SUPPORT_H_ -+ -+/* -+ * vc_support.h -+ * -+ * Created on: 25 Nov 2012 -+ * Author: Simon -+ */ -+ -+enum { -+/* -+ If a MEM_HANDLE_T is discardable, the memory manager may resize it to size -+ 0 at any time when it is not locked or retained. -+ */ -+ MEM_FLAG_DISCARDABLE = 1 << 0, -+ -+ /* -+ If a MEM_HANDLE_T is allocating (or normal), its block of memory will be -+ accessed in an allocating fashion through the cache. -+ */ -+ MEM_FLAG_NORMAL = 0 << 2, -+ MEM_FLAG_ALLOCATING = MEM_FLAG_NORMAL, -+ -+ /* -+ If a MEM_HANDLE_T is direct, its block of memory will be accessed -+ directly, bypassing the cache. -+ */ -+ MEM_FLAG_DIRECT = 1 << 2, -+ -+ /* -+ If a MEM_HANDLE_T is coherent, its block of memory will be accessed in a -+ non-allocating fashion through the cache. -+ */ -+ MEM_FLAG_COHERENT = 2 << 2, -+ -+ /* -+ If a MEM_HANDLE_T is L1-nonallocating, its block of memory will be accessed by -+ the VPU in a fashion which is allocating in L2, but only coherent in L1. -+ */ -+ MEM_FLAG_L1_NONALLOCATING = (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT), -+ -+ /* -+ If a MEM_HANDLE_T is zero'd, its contents are set to 0 rather than -+ MEM_HANDLE_INVALID on allocation and resize up. -+ */ -+ MEM_FLAG_ZERO = 1 << 4, -+ -+ /* -+ If a MEM_HANDLE_T is uninitialised, it will not be reset to a defined value -+ (either zero, or all 1's) on allocation. -+ */ -+ MEM_FLAG_NO_INIT = 1 << 5, -+ -+ /* -+ Hints. -+ */ -+ MEM_FLAG_HINT_PERMALOCK = 1 << 6, /* Likely to be locked for long periods of time. */ -+}; -+ -+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags); -+unsigned int ReleaseVcMemory(unsigned int handle); -+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle); -+unsigned int UnlockVcMemory(unsigned int handle); -+ -+unsigned int ExecuteVcCode(unsigned int code, -+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5); -+ -+#endif -diff --git a/arch/arm/mach-bcm2708/vc_support.c b/arch/arm/mach-bcm2708/vc_support.c -new file mode 100755 -index 0000000..0bc41c4 ---- /dev/null -+++ b/arch/arm/mach-bcm2708/vc_support.c -@@ -0,0 +1,318 @@ -+/* -+ * vc_support.c -+ * -+ * Created on: 25 Nov 2012 -+ * Author: Simon -+ */ -+ -+#include -+#include -+ -+#ifdef ECLIPSE_IGNORE -+ -+#define __user -+#define __init -+#define __exit -+#define __iomem -+#define KERN_DEBUG -+#define KERN_ERR -+#define KERN_WARNING -+#define KERN_INFO -+#define _IOWR(a, b, c) b -+#define _IOW(a, b, c) b -+#define _IO(a, b) b -+ -+#endif -+ -+/****** VC MAILBOX FUNCTIONALITY ******/ -+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_size; -+ unsigned int m_handle; -+ }; -+ unsigned int m_alignment; -+ unsigned int m_flags; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the allocation command -+ msg.m_tag.m_tagId = 0x3000c; -+ msg.m_tag.m_sendBufferSize = 12; -+ msg.m_tag.m_sendDataSize = 12; -+ -+ //fill in our args -+ msg.m_tag.m_args.m_size = size; -+ msg.m_tag.m_args.m_alignment = alignment; -+ msg.m_tag.m_args.m_flags = flags; -+ -+ //run the command -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ { -+ *pHandle = msg.m_tag.m_args.m_handle; -+ return 0; -+ } -+ else -+ { -+ printk(KERN_ERR "failed to allocate vc memory: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} -+ -+unsigned int ReleaseVcMemory(unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_error; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the release command -+ msg.m_tag.m_tagId = 0x3000f; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0) -+ return 0; -+ else -+ { -+ printk(KERN_ERR "failed to release vc memory: s=%d response=%08x recv data size=%08x error=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error); -+ return 1; -+ } -+} -+ -+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_busAddress; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the lock command -+ msg.m_tag.m_tagId = 0x3000d; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ { -+ //pick out the bus address -+ *pBusAddress = msg.m_tag.m_args.m_busAddress; -+ return 0; -+ } -+ else -+ { -+ printk(KERN_ERR "failed to lock vc memory: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} -+ -+unsigned int UnlockVcMemory(unsigned int handle) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_handle; -+ unsigned int m_error; -+ }; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the unlock command -+ msg.m_tag.m_tagId = 0x3000e; -+ msg.m_tag.m_sendBufferSize = 4; -+ msg.m_tag.m_sendDataSize = 4; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_handle = handle; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ //check the error code too -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0) -+ return 0; -+ else -+ { -+ printk(KERN_ERR "failed to unlock vc memory: s=%d response=%08x recv data size=%08x error%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error); -+ return 1; -+ } -+} -+ -+unsigned int ExecuteVcCode(unsigned int code, -+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5) -+{ -+ struct vc_msg -+ { -+ unsigned int m_msgSize; -+ unsigned int m_response; -+ -+ struct vc_tag -+ { -+ unsigned int m_tagId; -+ unsigned int m_sendBufferSize; -+ union { -+ unsigned int m_sendDataSize; -+ unsigned int m_recvDataSize; -+ }; -+ -+ struct args -+ { -+ union { -+ unsigned int m_pCode; -+ unsigned int m_return; -+ }; -+ unsigned int m_r0; -+ unsigned int m_r1; -+ unsigned int m_r2; -+ unsigned int m_r3; -+ unsigned int m_r4; -+ unsigned int m_r5; -+ } m_args; -+ } m_tag; -+ -+ unsigned int m_endTag; -+ } msg; -+ int s; -+ -+ msg.m_msgSize = sizeof(msg); -+ msg.m_response = 0; -+ msg.m_endTag = 0; -+ -+ //fill in the tag for the unlock command -+ msg.m_tag.m_tagId = 0x30010; -+ msg.m_tag.m_sendBufferSize = 28; -+ msg.m_tag.m_sendDataSize = 28; -+ -+ //pass across the handle -+ msg.m_tag.m_args.m_pCode = code; -+ msg.m_tag.m_args.m_r0 = r0; -+ msg.m_tag.m_args.m_r1 = r1; -+ msg.m_tag.m_args.m_r2 = r2; -+ msg.m_tag.m_args.m_r3 = r3; -+ msg.m_tag.m_args.m_r4 = r4; -+ msg.m_tag.m_args.m_r5 = r5; -+ -+ s = bcm_mailbox_property(&msg, sizeof(msg)); -+ -+ //check the error code too -+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004) -+ return msg.m_tag.m_args.m_return; -+ else -+ { -+ printk(KERN_ERR "failed to execute: s=%d response=%08x recv data size=%08x\n", -+ s, msg.m_response, msg.m_tag.m_recvDataSize); -+ return 1; -+ } -+} --- -1.8.5.1 - - -From 64c06aa897194fa4bfc9f522c0dc80399bdbbcc3 Mon Sep 17 00:00:00 2001 +From 739c73607532849cc8790a380965b424f4080332 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 24/91] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 23/80] lirc: added support for RaspberryPi GPIO --- drivers/staging/media/lirc/Kconfig | 6 + @@ -93793,10 +92470,10 @@ index 0000000..c76f696 1.8.5.1 -From 436b2b7ef6e95540a308b3c128b4df447c5452e4 Mon Sep 17 00:00:00 2001 +From 67e468b6fdb16ff33ee7eef666c5029aa8170fe2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 18:23:03 +0000 -Subject: [PATCH 25/91] Default to dwc_otp.lpm_enable=0 +Subject: [PATCH 24/80] Default to dwc_otp.lpm_enable=0 --- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +- @@ -93819,10 +92496,10 @@ index d58ebd7..c2bb596 100644 1.8.5.1 -From c449c30b7a79cf96c7a35390085824a4d928834f Mon Sep 17 00:00:00 2001 +From d9fa2a90a96904158e200d95f1c240ae292b80c5 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 9 Jan 2013 16:12:04 +0000 -Subject: [PATCH 26/91] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent +Subject: [PATCH 25/80] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel memory corruption, escalating to OOPS under high USB load. --- @@ -93859,10 +92536,10 @@ index ebee73a..b3efaf4 100644 1.8.5.1 -From 6e862463cba8ff71e8b6611903757416251284ca Mon Sep 17 00:00:00 2001 +From 3152c87baca1be3b9f11dfa502d77ac66fc357f3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 27/91] Add hwrng (hardware random number generator) driver +Subject: [PATCH 26/80] Add hwrng (hardware random number generator) driver --- arch/arm/mach-bcm2708/include/mach/platform.h | 1 + @@ -93885,14 +92562,13 @@ index 89e72d1..992a630 100644 #define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ #define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 0aa9d91..1d575d0 100644 +index 2f2b084..cfca8e9 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig -@@ -314,3 +314,14 @@ config HW_RANDOM_TPM - module will be called tpm-rng. +@@ -341,6 +341,17 @@ config HW_RANDOM_TPM If unsure, say Y. -+ + +config HW_RANDOM_BCM2708 + tristate "BCM2708 generic true random number generator support" + depends on HW_RANDOM && ARCH_BCM2708 @@ -93903,15 +92579,20 @@ index 0aa9d91..1d575d0 100644 + module will be called bcm2708-rng. + + If unsure, say N. ++ + config HW_RANDOM_MSM + tristate "Qualcomm MSM Random Number Generator support" + depends on HW_RANDOM && ARCH_MSM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile -index bed467c..18fc4d4 100644 +index 3ae7755..a7bfb80 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile -@@ -27,3 +27,4 @@ obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o +@@ -29,4 +29,5 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o + obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o diff --git a/drivers/char/hw_random/bcm2708-rng.c b/drivers/char/hw_random/bcm2708-rng.c new file mode 100755 index 0000000..1ffa7d7 @@ -94039,10 +92720,10 @@ index 0000000..1ffa7d7 1.8.5.1 -From def9b296a0bb5f462575fe348b5bc4b8db0997b2 Mon Sep 17 00:00:00 2001 +From 215a43131731789b30552aea22f613cdca278490 Mon Sep 17 00:00:00 2001 From: Technion Date: Mon, 11 Feb 2013 22:08:53 +1100 -Subject: [PATCH 28/91] Changed wording on logging. Previously, we received +Subject: [PATCH 27/80] Changed wording on logging. Previously, we received errors like this: mmc0: could read SD Status register (SSR) at the 3th attempt A more sensible response is now returned. A typo also fixed in comments. @@ -94052,10 +92733,10 @@ Subject: [PATCH 28/91] Changed wording on logging. Previously, we received 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c -index e0e9afb..25b98a9 100644 +index bb14f63..b66bd4c 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c -@@ -238,7 +238,7 @@ static int mmc_read_scr(struct mmc_card *card) +@@ -239,7 +239,7 @@ static int mmc_read_scr(struct mmc_card *card) err = mmc_app_send_scr(card, card->raw_scr); if( !err ) @@ -94064,7 +92745,7 @@ index e0e9afb..25b98a9 100644 touch_nmi_watchdog(); // we are still alive! -@@ -321,7 +321,7 @@ static int mmc_read_ssr(struct mmc_card *card) +@@ -322,7 +322,7 @@ static int mmc_read_ssr(struct mmc_card *card) if( tries > 1 ) { @@ -94077,10 +92758,10 @@ index e0e9afb..25b98a9 100644 1.8.5.1 -From c612839a8f31fb9e27406f4b13e175ca2d1fb525 Mon Sep 17 00:00:00 2001 +From f3ddd3fa0e49e8ca201edd13a31a13fcfba7a951 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:36:47 +0000 -Subject: [PATCH 29/91] dwc_otg: Fix unsafe access of QTD during URB enqueue +Subject: [PATCH 28/80] dwc_otg: Fix unsafe access of QTD during URB enqueue In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the transaction could complete almost immediately after the qtd was assigned @@ -94167,10 +92848,10 @@ index b3efaf4..1554be5 100644 1.8.5.1 -From 1595868ecabc0aff6ae2ccb4f3f9bb3a0708e616 Mon Sep 17 00:00:00 2001 +From ba081c67dd445b86711d9c239d22b93a883f9439 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:38:40 +0000 -Subject: [PATCH 30/91] dwc_otg: Fix incorrect URB allocation error handling +Subject: [PATCH 29/80] dwc_otg: Fix incorrect URB allocation error handling If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS because for some reason a member of the *unallocated* struct was set to @@ -94211,10 +92892,10 @@ index 35d03d1..6fe30e3 100644 1.8.5.1 -From 832c4dab3dd32fc1b488868e29854c59bf73c765 Mon Sep 17 00:00:00 2001 +From ed324adaf8d7f3885825ed78664c0156e5aed9d7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 24 Feb 2013 16:30:57 +0000 -Subject: [PATCH 31/91] Add retry on error and tidy of temperature driver +Subject: [PATCH 30/80] Add retry on error and tidy of temperature driver --- drivers/thermal/bcm2835-thermal.c | 78 ++++++++++++++------------------------- @@ -94341,10 +93022,10 @@ index 3f9a733..85fceb5 100644 1.8.5.1 -From 94f9a64587265ad6099afffa7bc6b53089864bad Mon Sep 17 00:00:00 2001 +From 202d283b15a2c971279721ea8caa4d1c61f93bc2 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 28 Feb 2013 16:52:51 +0000 -Subject: [PATCH 32/91] dwc_otg: fix potential use-after-free case in interrupt +Subject: [PATCH 31/80] dwc_otg: fix potential use-after-free case in interrupt handler If a transaction had previously aborted, certain interrupts are @@ -94376,10 +93057,10 @@ index 1a23d4b..7af455d 100644 1.8.5.1 -From 6b0e7139c1ab867a8d0f42f679d9dcb46c8bbce7 Mon Sep 17 00:00:00 2001 +From 1e7997507854bd48e541a06038708d9635214b32 Mon Sep 17 00:00:00 2001 From: P33M Date: Sun, 3 Mar 2013 14:45:53 +0000 -Subject: [PATCH 33/91] dwc_otg: add handling of SPLIT transaction data toggle +Subject: [PATCH 32/80] dwc_otg: add handling of SPLIT transaction data toggle errors Previously a data toggle error on packets from a USB1.1 device behind @@ -94434,10 +93115,10 @@ index 7af455d..a27dacd 100644 1.8.5.1 -From bcc116e749d59eb5dbcc0f53e3b8ee6096c75892 Mon Sep 17 00:00:00 2001 +From 29c3ab1289ebc4d0092bbf9347c4b74c1da9d008 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 21:14:28 +0100 -Subject: [PATCH 34/91] Add bitbanging pullups, use them for w1-gpio +Subject: [PATCH 33/80] Add bitbanging pullups, use them for w1-gpio Allows parasite power to work, uses module option pullup=1 --- @@ -94448,7 +93129,7 @@ Allows parasite power to work, uses module option pullup=1 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c -index f54ece2..217bddb 100644 +index e36b18b..3406a5a 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -22,6 +22,9 @@ @@ -94478,7 +93159,7 @@ index f54ece2..217bddb 100644 #if defined(CONFIG_OF) static struct of_device_id w1_gpio_dt_ids[] = { { .compatible = "w1-gpio" }, -@@ -127,6 +140,13 @@ static int w1_gpio_probe(struct platform_device *pdev) +@@ -134,6 +147,13 @@ static int w1_gpio_probe(struct platform_device *pdev) master->write_bit = w1_gpio_write_bit_dir; } @@ -94493,7 +93174,7 @@ index f54ece2..217bddb 100644 if (err) { dev_err(&pdev->dev, "w1_add_master device failed\n"); diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 45908e5..0ba75f6 100644 +index ca8081a..3392959 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -148,6 +148,12 @@ struct w1_bus_master @@ -94576,10 +93257,10 @@ index e10acc2..667fdd5 100644 1.8.5.1 -From 08827d2ca4ba757ab2404d82661425ba6fa7e107 Mon Sep 17 00:00:00 2001 +From 09c2a53a555f5b381f753310abe67309a0d8badb Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 21 Mar 2013 19:36:17 +0000 -Subject: [PATCH 35/91] dwc_otg: implement tasklet for returning URBs to +Subject: [PATCH 34/80] dwc_otg: implement tasklet for returning URBs to usbcore hcd layer The dwc_otg driver interrupt handler for transfer completion will spend @@ -94821,10 +93502,10 @@ index 2b4a14e..39787e3 100644 1.8.5.1 -From aa0f6f833474c39ff74e8cf4a86697282dd351ed Mon Sep 17 00:00:00 2001 +From 6e83df0ebabba07d80ae5265acc62c3ba2b1b78b Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Apr 2013 00:08:36 +0100 -Subject: [PATCH 37/91] dwc_otg: fix NAK holdoff and allow on split +Subject: [PATCH 36/80] dwc_otg: fix NAK holdoff and allow on split transactions only This corrects a bug where if a single active non-periodic endpoint @@ -94894,10 +93575,10 @@ index 533b17d..73f7643 100644 1.8.5.1 -From 80068caf5e52e9ceff4b779443900ed29d218626 Mon Sep 17 00:00:00 2001 +From d0096527c551fcdf2dd450988b0e737c6ad5febb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 26 Apr 2013 10:08:31 -0700 -Subject: [PATCH 38/91] Merge pull request #286 from +Subject: [PATCH 37/80] Merge pull request #286 from martinezjavier/rpi-3.6.y-dev add mmap support and some cleanups to bcm2835 ALSA driver @@ -95378,10 +94059,10 @@ index 080bd5c..36afee3 100755 1.8.5.1 -From 7afbc63a193e40edb5efebb8103139c14d87d25d Mon Sep 17 00:00:00 2001 +From 44b2085f0d99304b0e09195f5d2b1d10e3db4e24 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 39/91] Speed up console framebuffer imageblit function +Subject: [PATCH 38/80] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -95413,7 +94094,7 @@ Signed-off-by: Harm Hanemaaijer 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c -index baed57d..ce91bf2 100644 +index a2bb276..436494f 100644 --- a/drivers/video/cfbimgblt.c +++ b/drivers/video/cfbimgblt.c @@ -28,6 +28,11 @@ @@ -95593,10 +94274,10 @@ index baed57d..ce91bf2 100644 1.8.5.1 -From 82a53113b982c9b42ab512d56edcb9e438dc5df0 Mon Sep 17 00:00:00 2001 +From f4ed95a6942e8592d9d30e7cf99cecf08423126c Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 40/91] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 39/80] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -95611,7 +94292,7 @@ Signed-off-by: Siarhei Siamashka 2 files changed, 35 insertions(+) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c -index dacaf74..5985bfa 100644 +index 010d191..6545ce5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1083,6 +1083,25 @@ static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, @@ -95648,9 +94329,9 @@ index dacaf74..5985bfa 100644 void __user *argp = (void __user *)arg; long ret = 0; -@@ -1202,6 +1222,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, - console_unlock(); +@@ -1210,6 +1230,15 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unlock_fb_info(info); + console_unlock(); break; + case FBIOCOPYAREA: + if (info->flags & FBINFO_HWACCEL_COPYAREA) { @@ -95664,7 +94345,7 @@ index dacaf74..5985bfa 100644 default: if (!lock_fb_info(info)) return -ENODEV; -@@ -1356,6 +1385,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, +@@ -1364,6 +1393,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, case FBIOPAN_DISPLAY: case FBIOGET_CON2FBMAP: case FBIOPUT_CON2FBMAP: @@ -95692,10 +94373,10 @@ index fb795c3..fa72af0 100644 1.8.5.1 -From fa03803af5f3cc084e16042c9376807589bf369d Mon Sep 17 00:00:00 2001 +From e344b00b1af0d6239e569af42e474e78f126733f Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 16:00:25 +0300 -Subject: [PATCH 41/91] bcm2708_fb: DMA acceleration for fb_copyarea +Subject: [PATCH 40/80] bcm2708_fb: DMA acceleration for fb_copyarea Based on http://www.raspberrypi.org/phpBB3/viewtopic.php?p=62425#p62425 Also used Simon's dmaer_master module as a reference for tweaking DMA @@ -95713,23 +94394,113 @@ For comparison, VFP optimized CPU copy can only do ~114 MB/s in the same conditions (hindered by reading uncached source buffer). Signed-off-by: Siarhei Siamashka ---- - drivers/video/bcm2708_fb.c | 162 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 159 insertions(+), 3 deletions(-) +bcm2708_fb: report number of dma copies + +Add a counter (exported via debugfs) reporting the +number of dma copies that the framebuffer driver +has done, in order to help evaluate different +optimization strategies. + +Signed-off-by: Luke Diamand + +bcm2708_fb: use IRQ for DMA copies + +The copyarea ioctl() uses DMA to speed things along. This +was busy-waiting for completion. This change supports using +an interrupt instead for larger transfers. For small +transfers, busy-waiting is still likely to be faster. + +Signed-off-by: Luke Diamand +--- + arch/arm/mach-bcm2708/dma.c | 8 + + arch/arm/mach-bcm2708/include/mach/dma.h | 2 + + drivers/video/bcm2708_fb.c | 277 ++++++++++++++++++++++++++++++- + 3 files changed, 282 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c +index 51d147a..1da2413 100644 +--- a/arch/arm/mach-bcm2708/dma.c ++++ b/arch/arm/mach-bcm2708/dma.c +@@ -83,6 +83,14 @@ extern void bcm_dma_wait_idle(void __iomem *dma_chan_base) + + EXPORT_SYMBOL_GPL(bcm_dma_start); + ++extern bool bcm_dma_is_busy(void __iomem *dma_chan_base) ++{ ++ dsb(); ++ ++ return readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_ACTIVE; ++} ++EXPORT_SYMBOL_GPL(bcm_dma_is_busy); ++ + /* Complete an ongoing DMA (assuming its results are to be ignored) + Does nothing if there is no DMA in progress. + This routine waits for the current AXI transfer to complete before +diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h +index ac7a4a0..6d2f9a0 100644 +--- a/arch/arm/mach-bcm2708/include/mach/dma.h ++++ b/arch/arm/mach-bcm2708/include/mach/dma.h +@@ -62,11 +62,13 @@ struct bcm2708_dma_cb { + unsigned long next; + unsigned long pad[2]; + }; ++struct scatterlist; + + extern int bcm_sg_suitable_for_dma(struct scatterlist *sg_ptr, int sg_len); + extern void bcm_dma_start(void __iomem *dma_chan_base, + dma_addr_t control_block); + extern void bcm_dma_wait_idle(void __iomem *dma_chan_base); ++extern bool bcm_dma_is_busy(void __iomem *dma_chan_base); + extern int /*rc*/ bcm_dma_abort(void __iomem *dma_chan_base); + + /* When listing features we can ask for when allocating DMA channels give diff --git a/drivers/video/bcm2708_fb.c b/drivers/video/bcm2708_fb.c -index 08d9238..c10c5ee 100644 +index 08d9238..5758146 100644 --- a/drivers/video/bcm2708_fb.c +++ b/drivers/video/bcm2708_fb.c -@@ -28,6 +28,7 @@ +@@ -21,13 +21,16 @@ + #include + #include + #include ++#include + #include + #include + #include + #include #include #include ++#include +#include #include #include -@@ -63,6 +64,11 @@ struct bcm2708_fb { +@@ -46,6 +49,11 @@ + + #define DRIVER_NAME "bcm2708_fb" + ++static u32 dma_busy_wait_threshold = 1<<15; ++module_param(dma_busy_wait_threshold, int, 0644); ++MODULE_PARM_DESC(dma_busy_wait_threshold, "Busy-wait for DMA completion below this area"); ++ ++ + /* this data structure describes each frame buffer device we find */ + + struct fbinfo_s { +@@ -57,16 +65,73 @@ struct fbinfo_s { + u16 cmap[256]; + }; + ++struct bcm2708_fb_stats { ++ struct debugfs_regset32 regset; ++ u32 dma_copies; ++ u32 dma_irqs; ++}; ++ + struct bcm2708_fb { + struct fb_info fb; + struct platform_device *dev; struct fbinfo_s *info; dma_addr_t dma; u32 cmap[16]; @@ -95738,10 +94509,60 @@ index 08d9238..c10c5ee 100644 + void __iomem *dma_chan_base; + void *cb_base; /* DMA control blocks */ + dma_addr_t cb_handle; ++ struct dentry *debugfs_dir; ++ wait_queue_head_t dma_waitq; ++ struct bcm2708_fb_stats stats; }; #define to_bcm2708(info) container_of(info, struct bcm2708_fb, fb) -@@ -312,11 +318,133 @@ static void bcm2708_fb_fillrect(struct fb_info *info, + ++static void bcm2708_fb_debugfs_deinit(struct bcm2708_fb *fb) ++{ ++ debugfs_remove_recursive(fb->debugfs_dir); ++ fb->debugfs_dir = NULL; ++} ++ ++static int bcm2708_fb_debugfs_init(struct bcm2708_fb *fb) ++{ ++ static struct debugfs_reg32 stats_registers[] = { ++ { ++ "dma_copies", ++ offsetof(struct bcm2708_fb_stats, dma_copies) ++ }, ++ { ++ "dma_irqs", ++ offsetof(struct bcm2708_fb_stats, dma_irqs) ++ }, ++ }; ++ ++ fb->debugfs_dir = debugfs_create_dir(DRIVER_NAME, NULL); ++ if (!fb->debugfs_dir) { ++ pr_warn("%s: could not create debugfs entry\n", ++ __func__); ++ return -EFAULT; ++ } ++ ++ fb->stats.regset.regs = stats_registers; ++ fb->stats.regset.nregs = ARRAY_SIZE(stats_registers); ++ fb->stats.regset.base = &fb->stats; ++ ++ if (!debugfs_create_regset32( ++ "stats", 0444, fb->debugfs_dir, &fb->stats.regset)) { ++ pr_warn("%s: could not create statistics registers\n", ++ __func__); ++ goto fail; ++ } ++ return 0; ++ ++fail: ++ bcm2708_fb_debugfs_deinit(fb); ++ return -EFAULT; ++} ++ + static int bcm2708_fb_set_bitfields(struct fb_var_screeninfo *var) + { + int ret = 0; +@@ -312,11 +377,148 @@ static void bcm2708_fb_fillrect(struct fb_info *info, cfb_fillrect(info, rect); } @@ -95781,6 +94602,7 @@ index 08d9238..c10c5ee 100644 + int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3; + /* Channel 0 supports larger bursts and is a bit faster */ + int burst_size = (fb->dma_chan == 0) ? 8 : 2; ++ int pixels = region->width * region->height; + + /* Fallback to cfb_copyarea() if we don't like something */ + if (bytes_per_pixel > 4 || @@ -95872,12 +94694,51 @@ index 08d9238..c10c5ee 100644 + /* end of dma control blocks chain */ + cb->next = 0; + -+ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); -+ bcm_dma_wait_idle(fb->dma_chan_base); ++ ++ if (pixels < dma_busy_wait_threshold) { ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ bcm_dma_wait_idle(fb->dma_chan_base); ++ } else { ++ void __iomem *dma_chan = fb->dma_chan_base; ++ cb->info |= BCM2708_DMA_INT_EN; ++ bcm_dma_start(fb->dma_chan_base, fb->cb_handle); ++ while (bcm_dma_is_busy(dma_chan)) { ++ wait_event_interruptible( ++ fb->dma_waitq, ++ !bcm_dma_is_busy(dma_chan)); ++ } ++ fb->stats.dma_irqs++; ++ } ++ fb->stats.dma_copies++; } static void bcm2708_fb_imageblit(struct fb_info *info, -@@ -359,7 +487,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) +@@ -326,6 +528,24 @@ static void bcm2708_fb_imageblit(struct fb_info *info, + cfb_imageblit(info, image); + } + ++static irqreturn_t bcm2708_fb_dma_irq(int irq, void *cxt) ++{ ++ struct bcm2708_fb *fb = cxt; ++ ++ /* FIXME: should read status register to check if this is ++ * actually interrupting us or not, in case this interrupt ++ * ever becomes shared amongst several DMA channels ++ * ++ * readl(dma_chan_base + BCM2708_DMA_CS) & BCM2708_DMA_IRQ; ++ */ ++ ++ /* acknowledge the interrupt */ ++ writel(BCM2708_DMA_INT, fb->dma_chan_base + BCM2708_DMA_CS); ++ ++ wake_up(&fb->dma_waitq); ++ return IRQ_HANDLED; ++} ++ + static struct fb_ops bcm2708_fb_ops = { + .owner = THIS_MODULE, + .fb_check_var = bcm2708_fb_check_var, +@@ -359,7 +579,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) fb->dma = dma; } fb->fb.fbops = &bcm2708_fb_ops; @@ -95886,10 +94747,33 @@ index 08d9238..c10c5ee 100644 fb->fb.pseudo_palette = fb->cmap; strncpy(fb->fb.fix.id, bcm2708_name, sizeof(fb->fb.fix.id)); -@@ -424,6 +552,28 @@ static int bcm2708_fb_probe(struct platform_device *dev) - } - memset(fb, 0, sizeof(struct bcm2708_fb)); +@@ -390,6 +610,7 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb) + fb->fb.monspecs.dclkmax = 100000000; + bcm2708_fb_set_bitfields(&fb->fb.var); ++ init_waitqueue_head(&fb->dma_waitq); + + /* + * Allocate colourmap. +@@ -415,14 +636,48 @@ static int bcm2708_fb_probe(struct platform_device *dev) + struct bcm2708_fb *fb; + int ret; + +- fb = kmalloc(sizeof(struct bcm2708_fb), GFP_KERNEL); ++ fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL); + if (!fb) { + dev_err(&dev->dev, + "could not allocate new bcm2708_fb struct\n"); + ret = -ENOMEM; + goto free_region; + } +- memset(fb, 0, sizeof(struct bcm2708_fb)); ++ ++ bcm2708_fb_debugfs_init(fb); ++ ++ ++ bcm2708_fb_debugfs_init(fb); ++ + fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K, + &fb->cb_handle, GFP_KERNEL); + if (!fb->cb_base) { @@ -95909,23 +94793,32 @@ index 08d9238..c10c5ee 100644 + } + fb->dma_chan = ret; + ++ ret = request_irq(fb->dma_irq, bcm2708_fb_dma_irq, ++ 0, "bcm2708_fb dma", fb); ++ if (ret) { ++ pr_err("%s: failed to request DMA irq\n", __func__); ++ goto free_dma_chan; ++ } ++ ++ + pr_info("BCM2708FB: allocated DMA channel %d @ %p\n", + fb->dma_chan, fb->dma_chan_base); -+ + fb->dev = dev; - ret = bcm2708_fb_register(fb); -@@ -432,6 +582,9 @@ static int bcm2708_fb_probe(struct platform_device *dev) +@@ -432,6 +687,11 @@ static int bcm2708_fb_probe(struct platform_device *dev) goto out; } ++free_dma_chan: ++ bcm_dma_chan_free(fb->dma_chan); +free_cb: + dma_free_writecombine(&dev->dev, SZ_64K, fb->cb_base, fb->cb_handle); +free_fb: kfree(fb); free_region: dev_err(&dev->dev, "probe failed, err %d\n", ret); -@@ -449,6 +602,9 @@ static int bcm2708_fb_remove(struct platform_device *dev) +@@ -449,8 +709,15 @@ static int bcm2708_fb_remove(struct platform_device *dev) iounmap(fb->fb.screen_base); unregister_framebuffer(&fb->fb); @@ -95934,15 +94827,21 @@ index 08d9238..c10c5ee 100644 + dma_free_coherent(NULL, PAGE_ALIGN(sizeof(*fb->info)), (void *)fb->info, fb->dma); ++ bcm2708_fb_debugfs_deinit(fb); ++ ++ free_irq(fb->dma_irq, fb); ++ kfree(fb); + + return 0; -- 1.8.5.1 -From 74b5846025af0222106b1c132de9caf51bbecf1e Mon Sep 17 00:00:00 2001 +From 841328c044611e7c00be0bcd1149f19fecde61ee Mon Sep 17 00:00:00 2001 From: Mike Bradley Date: Mon, 17 Jun 2013 11:31:42 -0700 -Subject: [PATCH 42/91] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held +Subject: [PATCH 41/80] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it @@ -96029,10 +94928,10 @@ index 39787e3..5e6a26a 100644 1.8.5.1 -From de32ba2a349e4115b7a2cd397b5c0502b75d5eed Mon Sep 17 00:00:00 2001 +From cc2bedf7320d89a4137fcb19301d26a59689169d Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Thu, 4 Apr 2013 11:05:21 +0100 -Subject: [PATCH 43/91] USB fix using a FIQ to implement split transactions +Subject: [PATCH 42/80] USB fix using a FIQ to implement split transactions This commit adds a FIQ implementaion that schedules the split transactions using a FIQ so we don't get @@ -97435,10 +96334,10 @@ index 1b1f83c..c8590b5 100644 1.8.5.1 -From 6190c8c08d0027844d5316623ff6a6878f4b002d Mon Sep 17 00:00:00 2001 +From 609d1454cdc430bc143d1688944a5b2cfd8bce61 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 11:39:46 +0100 -Subject: [PATCH 44/91] dwc_otg: fix device attributes and avoid kernel +Subject: [PATCH 43/80] dwc_otg: fix device attributes and avoid kernel warnings on boot --- @@ -97507,10 +96406,10 @@ index fab2961..af1cd4d 100644 1.8.5.1 -From 179b0e9716d0885cfb6e1ac418eba852b7725926 Mon Sep 17 00:00:00 2001 +From 3666252300f1027e2f80d219055882517be0d95a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 15 Jul 2013 23:55:52 +0100 -Subject: [PATCH 45/91] dcw_otg: avoid logging function that can cause panics +Subject: [PATCH 44/80] dcw_otg: avoid logging function that can cause panics See: https://github.com/raspberrypi/firmware/issues/21 Thanks to cleverca22 for fix @@ -97535,10 +96434,10 @@ index af1cd4d..9da0c92 100644 1.8.5.1 -From 7c1335c8ba9800532aeb6fdd532bcffcc8ba5052 Mon Sep 17 00:00:00 2001 +From 97b4252a24598828f7f3178f8fd035766ea4cefb Mon Sep 17 00:00:00 2001 From: P33M Date: Sat, 13 Jul 2013 20:41:26 +0100 -Subject: [PATCH 46/91] dwc_otg: mask correct interrupts after transaction +Subject: [PATCH 45/80] dwc_otg: mask correct interrupts after transaction error recovery The dwc_otg driver will unmask certain interrupts on a transaction @@ -97605,10 +96504,10 @@ index 8e5789f..fd73e41 100644 1.8.5.1 -From f55e5ce82797d3052654aedaeec618914d82c28e Mon Sep 17 00:00:00 2001 +From 682ddc58e6a5ab950c48e1cecc9b00e629d51703 Mon Sep 17 00:00:00 2001 From: P33M Date: Sat, 13 Jul 2013 21:48:41 +0100 -Subject: [PATCH 47/91] dwc_otg: fiq: prevent FIQ thrash and incorrect state +Subject: [PATCH 46/80] dwc_otg: fiq: prevent FIQ thrash and incorrect state passing to IRQ In the case of a transaction to a device that had previously aborted @@ -97665,10 +96564,10 @@ index fd73e41..2ec0565 100644 1.8.5.1 -From 40aebae6b8d0c15c90c9cd3a62259ebf2aa5fae8 Mon Sep 17 00:00:00 2001 +From 645afb4d8c05f5df708c6dd1e259a6388b00b043 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Mon, 8 Jul 2013 04:12:19 +0100 -Subject: [PATCH 48/91] Fix function tracing +Subject: [PATCH 47/80] Fix function tracing --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++++------ @@ -97733,10 +96632,10 @@ index 2ec0565..083b1c3 100644 1.8.5.1 -From 09f3f40c3be23ec522078e17df02100d55496267 Mon Sep 17 00:00:00 2001 +From c0d1a955e9388fdde231a424d976a5aa927b3ca0 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 18 Jul 2013 16:32:41 +0100 -Subject: [PATCH 49/91] dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue +Subject: [PATCH 48/80] dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue --- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 53 ++++++++++++++-------------- @@ -97823,10 +96722,10 @@ index d1c5c2b..315c803 100644 1.8.5.1 -From e77b98b91ce833a0b3281ed00e4597b4e77b79d8 Mon Sep 17 00:00:00 2001 +From 258b48554f85e4c69587e1cd317a54dd68957552 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 18 Jul 2013 17:07:26 +0100 -Subject: [PATCH 50/91] dwc_otg: prevent OOPSes during device disconnects +Subject: [PATCH 49/80] dwc_otg: prevent OOPSes during device disconnects The dwc_otg_urb_enqueue function is thread-unsafe. In particular the access of urb->hcpriv, usb_hcd_link_urb_to_ep, dwc_otg_urb->qtd and @@ -97967,10 +96866,10 @@ index 7b92025..db95851 100644 1.8.5.1 -From 9fd11e7750d06fbbe32016939e0f4fc5fd2601df Mon Sep 17 00:00:00 2001 +From c7af0f787acac024a873cc02f1e221e0669d1f38 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Jul 2013 14:08:26 +0100 -Subject: [PATCH 51/91] dwc_otg: prevent BUG() in TT allocation if hub address +Subject: [PATCH 50/80] dwc_otg: prevent BUG() in TT allocation if hub address is > 16 A fixed-size array is used to track TT allocation. This was @@ -98060,10 +96959,10 @@ index 083b1c3..c76910d 100644 1.8.5.1 -From b69bdd06946893871ed9ee49d93e0f46546c17f0 Mon Sep 17 00:00:00 2001 +From 7ac7876592c57f97ebebd11da77a1f47dcf4b3ee Mon Sep 17 00:00:00 2001 From: P33M Date: Tue, 23 Jul 2013 14:15:32 +0100 -Subject: [PATCH 52/91] dwc_otg: make channel halts with unknown state less +Subject: [PATCH 51/80] dwc_otg: make channel halts with unknown state less damaging If the IRQ received a channel halt interrupt through the FIQ @@ -98108,10 +97007,10 @@ index c76910d..5fd8613 100644 1.8.5.1 -From ac8bb33449cf856f0e1d12355dfa6d3674d74454 Mon Sep 17 00:00:00 2001 +From 987108a30277a95dff6552706f1ecf2cbcc71355 Mon Sep 17 00:00:00 2001 From: P33M Date: Tue, 30 Jul 2013 09:58:48 +0100 -Subject: [PATCH 53/91] dwc_otg: fiq_split: use TTs with more granularity +Subject: [PATCH 52/80] dwc_otg: fiq_split: use TTs with more granularity This fixes certain issues with split transaction scheduling. @@ -98231,10 +97130,10 @@ index 5fd8613..a959a49 100644 1.8.5.1 -From 8a027a640d6e2b56e346f6b28abf1b0cf668cc72 Mon Sep 17 00:00:00 2001 +From 3ece5cf3bc9df061db76b844bf139469dbd7469c Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 2 Aug 2013 10:04:18 +0100 -Subject: [PATCH 54/91] dwc_otg: fix potential sleep while atomic during urb +Subject: [PATCH 53/80] dwc_otg: fix potential sleep while atomic during urb enqueue Fixes a regression introduced with eb1b482a. Kmalloc called from @@ -98263,10 +97162,10 @@ index 87e517d..88c0544 100644 1.8.5.1 -From cc678194e329219ddb3f71a86604d45c222e1471 Mon Sep 17 00:00:00 2001 +From 858407ff74686532ff95965e3ef97ee3cf15c476 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 11:42:12 +0100 -Subject: [PATCH 55/91] dwc_otg: make fiq_split_enable imply fiq_fix_enable +Subject: [PATCH 54/80] dwc_otg: make fiq_split_enable imply fiq_fix_enable Failing to set up the FIQ correctly would result in "IRQ 32: nobody cared" errors in dmesg. @@ -98295,10 +97194,10 @@ index 176dc14..f06c3d22 100644 1.8.5.1 -From 110c93cedd588269083f8f2bcc66132896573d7f Mon Sep 17 00:00:00 2001 +From b05092228e0d96250601a1ecf54cc3e17c8ebb55 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 11:47:12 +0100 -Subject: [PATCH 56/91] dwc_otg: prevent crashes on host port disconnects +Subject: [PATCH 55/80] dwc_otg: prevent crashes on host port disconnects Fix several issues resulting in crashes or inconsistent state if a Model A root port was disconnected. @@ -98456,10 +97355,10 @@ index 88c0544..ae4271a 100644 1.8.5.1 -From fb4384fd5a2c89da24b5641dc43b8ed1f016e099 Mon Sep 17 00:00:00 2001 +From 0c86d4ebd9f66106bd395e8b8af0cd05c5ed2f34 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 13:17:58 +0100 -Subject: [PATCH 57/91] dwc_otg: prevent leaking URBs during enqueue +Subject: [PATCH 56/80] dwc_otg: prevent leaking URBs during enqueue A dwc_otg_urb would get leaked if the HCD enqueue function failed for any reason. Free the URB at the appropriate points. @@ -98495,10 +97394,10 @@ index ae4271a..ee8eec9 100644 1.8.5.1 -From 96b81cca71307dcc2351311c5a2edc166a6f3445 Mon Sep 17 00:00:00 2001 +From c87bc0d69c80f2ac6b3c5f417f395c9e42cb2675 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 20 Sep 2013 16:08:27 +0100 -Subject: [PATCH 58/91] dwc_otg: Enable NAK holdoff for control split +Subject: [PATCH 57/80] dwc_otg: Enable NAK holdoff for control split transactions Certain low-speed devices take a very long time to complete a @@ -98531,10 +97430,10 @@ index 3a549a1..f8dc4be 100644 1.8.5.1 -From 2f727e3366339a3f86f865f9f7eb008b45f7a806 Mon Sep 17 00:00:00 2001 +From 5d4e0fca410bd7474da80d9a33c2a0e40c091ea2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Sep 2013 19:07:56 +0100 -Subject: [PATCH 59/91] dwc_otg: Fix for occasional lockup on boot when doing a +Subject: [PATCH 58/80] dwc_otg: Fix for occasional lockup on boot when doing a USB reset --- @@ -98560,10 +97459,10 @@ index f8dc4be..64d33a5 100644 1.8.5.1 -From 50a082721331f9d9edf6f0fa0e16f031f06dea46 Mon Sep 17 00:00:00 2001 +From bfc50c9dc58c50a84215a4c161541459a812ff16 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 27 Sep 2013 14:42:24 +0100 -Subject: [PATCH 60/91] dwc_otg: Don't issue traffic to LS devices in FS mode +Subject: [PATCH 59/80] dwc_otg: Don't issue traffic to LS devices in FS mode Issuing low-speed packets when the root port is in full-speed mode causes the root port to stop responding. Explicitly fail when @@ -98605,10 +97504,10 @@ index 1904f6a..22300f0 100644 1.8.5.1 -From 5c01a5307f6ce5f030450430fed730fb680142d3 Mon Sep 17 00:00:00 2001 +From b0c0507dd243b3200f63e9ee1a9a0729ce58c0df Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 6 Nov 2013 13:25:20 +0400 -Subject: [PATCH 61/91] ARM: bcm2708: PL01X debug include was moved into +Subject: [PATCH 60/80] ARM: bcm2708: PL01X debug include was moved into arch/arm/include/debug/ --- @@ -98629,162 +97528,20 @@ index 2d0dc1c..b24304a 100644 1.8.5.1 -From ce1424b7ead68cdebae2a8000f9af2d0e832e271 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 23 Nov 2013 11:47:00 +0000 -Subject: [PATCH 62/91] config: Add CONFIG_IFB - ---- - arch/arm/configs/bcmrpi_defconfig | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index f4fba45..408c328 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -408,6 +408,7 @@ CONFIG_DM_DELAY=m - CONFIG_NETDEVICES=y - CONFIG_BONDING=m - CONFIG_DUMMY=m -+CONFIG_IFB=m - CONFIG_MACVLAN=m - CONFIG_NETCONSOLE=m - CONFIG_TUN=m --- -1.8.5.1 - - -From 0dc92ec6083156e921a20cdfd57bbfba5a1ed2cb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Nov 2013 22:52:53 +0000 -Subject: [PATCH 63/91] dvb: Add support for CableStar Device - ---- - drivers/media/dvb-core/dvb-usb-ids.h | 1 + - drivers/media/usb/dvb-usb-v2/az6007.c | 59 +++++++++++++++++++++++++++++++++++ - 2 files changed, 60 insertions(+) - -diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h -index 419a2d6..4a53454 100644 ---- a/drivers/media/dvb-core/dvb-usb-ids.h -+++ b/drivers/media/dvb-core/dvb-usb-ids.h -@@ -365,6 +365,7 @@ - #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac - #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001 - #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002 -+#define USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI 0x0003 - #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004 - #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500 - #define USB_PID_CPYTO_REDI_PC50A 0xa803 -diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c -index 44c64ef3..c1051c3 100644 ---- a/drivers/media/usb/dvb-usb-v2/az6007.c -+++ b/drivers/media/usb/dvb-usb-v2/az6007.c -@@ -68,6 +68,19 @@ struct az6007_device_state { - .microcode_name = "dvb-usb-terratec-h7-drxk.fw", - }; - -+static struct drxk_config cablestar_hdci_drxk = { -+ .adr = 0x29, -+ .parallel_ts = true, -+ .dynamic_clk = true, -+ .single_master = true, -+ .enable_merr_cfg = true, -+ .no_i2c_bridge = false, -+ .chunk_size = 64, -+ .mpeg_out_clk_strength = 0x02, -+ .qam_demod_parameter_count = 2, -+ .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw", -+}; -+ - static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct az6007_device_state *st = fe_to_priv(fe); -@@ -630,6 +643,27 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap) - return 0; - } - -+static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap) -+{ -+ struct az6007_device_state *st = adap_to_priv(adap); -+ struct dvb_usb_device *d = adap_to_d(adap); -+ -+ pr_debug("attaching demod drxk\n"); -+ -+ adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk, -+ &d->i2c_adap); -+ if (!adap->fe[0]) -+ return -EINVAL; -+ -+ adap->fe[0]->sec_priv = adap; -+ st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl; -+ adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ -+ az6007_ci_init(adap); -+ -+ return 0; -+} -+ - static int az6007_tuner_attach(struct dvb_usb_adapter *adap) - { - struct dvb_usb_device *d = adap_to_d(adap); -@@ -868,6 +902,29 @@ static int az6007_download_firmware(struct dvb_usb_device *d, - } - }; - -+static struct dvb_usb_device_properties az6007_cablestar_hdci_props = { -+ .driver_name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, -+ .firmware = AZ6007_FIRMWARE, -+ -+ .adapter_nr = adapter_nr, -+ .size_of_priv = sizeof(struct az6007_device_state), -+ .i2c_algo = &az6007_i2c_algo, -+ .tuner_attach = az6007_tuner_attach, -+ .frontend_attach = az6007_cablestar_hdci_frontend_attach, -+ .streaming_ctrl = az6007_streaming_ctrl, -+/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */ -+ .get_rc_config = NULL, -+ .read_mac_address = az6007_read_mac_addr, -+ .download_firmware = az6007_download_firmware, -+ .identify_state = az6007_identify_state, -+ .power_ctrl = az6007_power_ctrl, -+ .num_adapters = 1, -+ .adapter = { -+ { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), } -+ } -+}; -+ - static struct usb_device_id az6007_usb_table[] = { - {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007, - &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)}, -@@ -875,6 +932,8 @@ static int az6007_download_firmware(struct dvb_usb_device *d, - &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, - {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2, - &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)}, -+ {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI, -+ &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)}, - {0}, - }; - --- -1.8.5.1 - - -From 01f442ea1097f5b166699225e63b20d736412e95 Mon Sep 17 00:00:00 2001 +From 14fa12e05929db43c5b5a8aa94db1da0af1abd26 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 20 Nov 2013 11:22:05 +0000 -Subject: [PATCH 64/91] sdhci: Only do one iteration of PIO reading loop +Subject: [PATCH 62/80] sdhci: Only do one iteration of PIO reading loop --- drivers/mmc/host/sdhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index a33407e..3c50449 100644 +index 576c526..46264b7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c -@@ -551,6 +551,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) +@@ -550,6 +550,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) break; state = sdhci_readl(host, SDHCI_PRESENT_STATE); available = state & mask; @@ -98796,10 +97553,10 @@ index a33407e..3c50449 100644 1.8.5.1 -From 44d55a4664c1cd5e6bf19cc4ac61e97bdeeb0bc1 Mon Sep 17 00:00:00 2001 +From 8b56d90ef3ae4ec480a4131c68104ca8cb597868 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 2 Sep 2013 16:44:57 +0100 -Subject: [PATCH 65/91] vchiq: create_pagelist copes with vmalloc memory +Subject: [PATCH 63/80] vchiq: create_pagelist copes with vmalloc memory Signed-off-by: Daniel Stone --- @@ -98940,10 +97697,10 @@ index 2b5fa56..b3bdaa2 100644 1.8.5.1 -From eee31b397622d0647e721581639248598081b88a Mon Sep 17 00:00:00 2001 +From ba3c5399e50cd39442cc0786736a6b59e3ff0d87 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 30 Sep 2013 17:04:55 +0100 -Subject: [PATCH 66/91] vchiq: fix the shim message release +Subject: [PATCH 64/80] vchiq: fix the shim message release Signed-off-by: Daniel Stone --- @@ -99035,10 +97792,10 @@ index f752f8d..fe9bd80 100644 1.8.5.1 -From b5326e571bda2df776335cd880f15f646ee52733 Mon Sep 17 00:00:00 2001 +From 6a8f61008377d2fb43d2ac50708bfc8a15ea7ccf Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 9 Nov 2013 22:37:21 +0000 -Subject: [PATCH 67/91] vchiq: export additional symbols +Subject: [PATCH 65/80] vchiq: export additional symbols Signed-off-by: Daniel Stone --- @@ -99069,10 +97826,10 @@ index fe9bd80..a0b069d 100644 1.8.5.1 -From fe35af6dea3097d7589e0afed41fdb9ca23bcc0d Mon Sep 17 00:00:00 2001 +From 459e94a06f401bf2d89e1592a72eb7c34eaa4adf Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 68/91] bcm2835: add v4l2 camera device +Subject: [PATCH 66/80] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -99184,7 +97941,7 @@ index 0000000..c585a8f + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index c7caf94..64ff97e 100644 +index d7f0249..1b5beaa 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -124,6 +124,7 @@ config VIDEO_S3C_CAMIF @@ -99196,10 +97953,10 @@ index c7caf94..64ff97e 100644 endif # V4L_PLATFORM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 4e4da48..4b7b42f 100644 +index 1348ba1..32cc20c 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile -@@ -52,4 +52,6 @@ obj-y += davinci/ +@@ -54,4 +54,6 @@ obj-y += davinci/ obj-$(CONFIG_ARCH_OMAP) += omap/ @@ -105060,10 +103817,10 @@ index 0000000..9d1d11e 1.8.5.1 -From a179a6fd38ef256bad3b372c14b272d63eb07203 Mon Sep 17 00:00:00 2001 +From 42162ae53fc5945dab8e5a5ad6ff8fb1d5136d13 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 10:58:01 +0000 -Subject: [PATCH 69/91] V4L2: Fix EV values. Add manual shutter speed control +Subject: [PATCH 67/80] V4L2: Fix EV values. Add manual shutter speed control V4L2 EV values should be in units of 1/1000. Corrected. Add support for V4L2_CID_EXPOSURE_ABSOLUTE which should @@ -105256,10 +104013,10 @@ index c611b58..d8aace5 100644 1.8.5.1 -From c1924621838eefe313c98f58df1659a9b5548afa Mon Sep 17 00:00:00 2001 +From b47ca82104176b2d10e67469cd2ed40760553df8 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:01:53 +0000 -Subject: [PATCH 70/91] V4L2: Correct JPEG Q-factor range +Subject: [PATCH 68/80] V4L2: Correct JPEG Q-factor range Should be 1-100, not 0-100 @@ -105297,10 +104054,10 @@ index 481d1f6..c2e4c64 100644 1.8.5.1 -From 3784a0fe579d50598135f9b219fce838ac3e5817 Mon Sep 17 00:00:00 2001 +From d4dc1d36e4d3efc545eb79dd9d6eef73ba60ae25 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:05:24 +0000 -Subject: [PATCH 71/91] V4L2: Fix issue of driver jamming if STREAMON failed. +Subject: [PATCH 69/80] V4L2: Fix issue of driver jamming if STREAMON failed. Fix issue where the driver was left in a partially enabled state if STREAMON failed, and would then reject many IOCTLs @@ -105336,10 +104093,10 @@ index 47fe45d..2743074 100644 1.8.5.1 -From e97e7f975bf19987152e18dc68c8ffc203f1d1e3 Mon Sep 17 00:00:00 2001 +From 8869381f436898a8c2c414f263a8d8ba1d8c918c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 15:30:48 +0000 -Subject: [PATCH 72/91] V4L2: Fix ISO controls. +Subject: [PATCH 70/80] V4L2: Fix ISO controls. Driver was passing the index to the GPU, and not the desired ISO value. @@ -105392,10 +104149,10 @@ index c2e4c64..92863f7 100644 1.8.5.1 -From 0ecbed516b524f49213d089aada558d92b2e28db Mon Sep 17 00:00:00 2001 +From 9e1e975385d581cb91d96fd786ecdf46e98cb710 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 16:40:24 +0000 -Subject: [PATCH 73/91] V4L2: Add flicker avoidance controls +Subject: [PATCH 71/80] V4L2: Add flicker avoidance controls Add support for V4L2_CID_POWER_LINE_FREQUENCY to set flicker avoidance frequencies. @@ -105510,10 +104267,10 @@ index d8aace5..b3d2c39 100644 1.8.5.1 -From c3718a2d49ea53c0e03599aa5e15c1ebc1c50326 Mon Sep 17 00:00:00 2001 +From 630e9356cfcae5ad0a07193d7b017281f2a8276b Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 13 Dec 2013 15:54:13 +0000 -Subject: [PATCH 74/91] V4L2: Add support for frame rate control. +Subject: [PATCH 72/80] V4L2: Add support for frame rate control. Add support for frame rate (or time per frame as V4L2 inverts it) control via s_parm. @@ -105752,10 +104509,10 @@ index b3d2c39..0f2bd50 100644 1.8.5.1 -From 7c1e1f7b2f1a3990955b16888b6d571a6a117b0d Mon Sep 17 00:00:00 2001 +From 70804b72bdc7cfa527122e00057a176796842f79 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 17:30:09 +0000 -Subject: [PATCH 75/91] V4L2: Improve G_FBUF handling so we pass conformance +Subject: [PATCH 73/80] V4L2: Improve G_FBUF handling so we pass conformance Return some sane numbers for get framebuffer so that we pass conformance. @@ -105795,10 +104552,10 @@ index 8c38d03..c8d8742 100644 1.8.5.1 -From 1a6a4ed1d0064a1012fec01813ee1ed88f827489 Mon Sep 17 00:00:00 2001 +From d731fa598afc81e124140b66da609d18fc900917 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 17:29:39 +0000 -Subject: [PATCH 76/91] V4L2: Fix information advertised through g_vidfmt +Subject: [PATCH 74/80] V4L2: Fix information advertised through g_vidfmt Width and height were being stored based on incorrect values. @@ -105838,10 +104595,10 @@ index c8d8742..4766a9c 100644 1.8.5.1 -From 3069a8f246ac819fd188920f4e512e47b1f612e0 Mon Sep 17 00:00:00 2001 +From 9bed8602aa1ff9c469acc187c3a574644225fa52 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:03:54 +0000 -Subject: [PATCH 77/91] V4L2: Add support for inline H264 headers +Subject: [PATCH 75/80] V4L2: Add support for inline H264 headers Add support for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER to control H264 inline headers. @@ -106146,10 +104903,10 @@ index 0f2bd50..b08a4b0 100644 1.8.5.1 -From 1113263a44cf1985ab786805fb728e796d5e17fd Mon Sep 17 00:00:00 2001 +From 5571d2cf9bd8a5d63cda96bf1db472cdb508d668 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 19 Dec 2013 17:33:02 +0000 -Subject: [PATCH 78/91] V4L2: Fix JPEG timestamp issue +Subject: [PATCH 76/80] V4L2: Fix JPEG timestamp issue JPEG images were coming through from the GPU with timestamp of 0. Detect this and give current system time instead @@ -106187,10 +104944,10 @@ index 4766a9c..9fc90a2 100644 1.8.5.1 -From ed18624b29ff137afcfce1fb485ad1af671f6875 Mon Sep 17 00:00:00 2001 +From 29d12cce03075b4fb7af8719ef29124d12c1cd57 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:24:55 +0000 -Subject: [PATCH 79/91] V4L2: Fix issue when switching down JPEG resolution. +Subject: [PATCH 77/80] V4L2: Fix issue when switching down JPEG resolution. JPEG buffer size calculation is based on input resolution. Input resolution was being configured after output port @@ -106352,20 +105109,20 @@ index 9fc90a2..4780107 100644 1.8.5.1 -From 1d6db295e852282024f17378f582d5dd9c42743f Mon Sep 17 00:00:00 2001 +From a6628f665943d95c1e4b96a9b7c38a4beca9136b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 2 Dec 2013 16:57:44 +0000 -Subject: [PATCH 80/91] config: Enable V4L / MMAL driver +Subject: [PATCH 78/80] config: Enable V4L / MMAL driver --- arch/arm/configs/bcmrpi_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 408c328..4032d53 100644 +index 31adf3c..c850de6 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -688,6 +688,9 @@ CONFIG_DVB_B2C2_FLEXCOP_USB=m +@@ -685,6 +685,9 @@ CONFIG_DVB_B2C2_FLEXCOP_USB=m CONFIG_VIDEO_EM28XX=m CONFIG_VIDEO_EM28XX_ALSA=m CONFIG_VIDEO_EM28XX_DVB=m @@ -106379,2631 +105136,201 @@ index 408c328..4032d53 100644 1.8.5.1 -From e30d2a13103489f3d1fd563215c5a4bffe3889c7 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 81/91] dmaengine: Add support for BCM2708 +From 4952870107b21b9cc4e3e824be5b5e17a0430ed9 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Thu, 9 Jan 2014 16:05:20 +0000 +Subject: [PATCH 79/80] gpio: support low and high level interrupts -Add support for DMA controller of BCM2708 as used in the Raspberry Pi. -Currently it only supports cyclic DMA. - -Signed-off-by: Florian Meier --- - drivers/dma/Kconfig | 6 + - drivers/dma/Makefile | 1 + - drivers/dma/bcm2708-dmaengine.c | 588 ++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 595 insertions(+) - create mode 100644 drivers/dma/bcm2708-dmaengine.c + arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++----------- + 1 file changed, 37 insertions(+), 15 deletions(-) -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index f238cfd..66201d9 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -288,6 +288,12 @@ config DMA_OMAP - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -+config DMA_BCM2708 -+ tristate "BCM2708 DMA engine support" -+ depends on MACH_BCM2708 -+ select DMA_ENGINE -+ select DMA_VIRTUAL_CHANNELS -+ - config TI_CPPI41 - tristate "AM33xx CPPI41 DMA support" - depends on ARCH_OMAP -diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile -index db89035..74432a4 100644 ---- a/drivers/dma/Makefile -+++ b/drivers/dma/Makefile -@@ -37,6 +37,7 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o - obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o - obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o - obj-$(CONFIG_DMA_OMAP) += omap-dma.o -+obj-$(CONFIG_DMA_BCM2708) += bcm2708-dmaengine.o - obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o - obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o - obj-$(CONFIG_TI_CPPI41) += cppi41.o -diff --git a/drivers/dma/bcm2708-dmaengine.c b/drivers/dma/bcm2708-dmaengine.c -new file mode 100644 -index 0000000..7d5ed19 ---- /dev/null -+++ b/drivers/dma/bcm2708-dmaengine.c -@@ -0,0 +1,588 @@ -+/* -+ * BCM2708 DMA engine support -+ * -+ * This driver only supports cyclic DMA transfers -+ * as needed for the I2S module. -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * Based on -+ * OMAP DMAengine support by Russell King -+ * -+ * BCM2708 DMA Driver -+ * Copyright (C) 2010 Broadcom -+ * -+ * Raspberry Pi PCM I2S ALSA Driver -+ * Copyright (c) by Phil Poole 2013 -+ * -+ * MARVELL MMP Peripheral DMA Driver -+ * Copyright 2012 Marvell International Ltd. -+ * -+ * 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "virt-dma.h" -+ -+#include -+#include -+ -+struct bcm2708_dmadev { -+ struct dma_device ddev; -+ spinlock_t lock; -+ void __iomem *base; -+ struct device_dma_parameters dma_parms; -+}; -+ -+struct bcm2708_chan { -+ struct virt_dma_chan vc; -+ struct list_head node; -+ -+ struct dma_slave_config cfg; -+ bool cyclic; -+ -+ int ch; -+ struct bcm2708_desc *desc; -+ -+ void __iomem *chan_base; -+ int irq_number; -+}; -+ -+struct bcm2708_desc { -+ struct virt_dma_desc vd; -+ enum dma_transfer_direction dir; -+ -+ unsigned int control_block_size; -+ struct bcm2708_dma_cb *control_block_base; -+ dma_addr_t control_block_base_phys; -+ -+ unsigned frames; -+ size_t size; -+}; -+ -+#define BCM2708_DMA_DATA_TYPE_S8 1 -+#define BCM2708_DMA_DATA_TYPE_S16 2 -+#define BCM2708_DMA_DATA_TYPE_S32 4 -+#define BCM2708_DMA_DATA_TYPE_S128 16 -+ -+static inline struct bcm2708_dmadev *to_bcm2708_dma_dev(struct dma_device *d) -+{ -+ return container_of(d, struct bcm2708_dmadev, ddev); -+} -+ -+static inline struct bcm2708_chan *to_bcm2708_dma_chan(struct dma_chan *c) -+{ -+ return container_of(c, struct bcm2708_chan, vc.chan); -+} -+ -+static inline struct bcm2708_desc *to_bcm2708_dma_desc( -+ struct dma_async_tx_descriptor *t) -+{ -+ return container_of(t, struct bcm2708_desc, vd.tx); -+} -+ -+static void bcm2708_dma_desc_free(struct virt_dma_desc *vd) -+{ -+ struct bcm2708_desc *desc = container_of(vd, struct bcm2708_desc, vd); -+ dma_free_coherent(desc->vd.tx.chan->device->dev, -+ desc->control_block_size, -+ desc->control_block_base, -+ desc->control_block_base_phys); -+ kfree(desc); -+} -+ -+static void bcm2708_dma_start_desc(struct bcm2708_chan *c) -+{ -+ struct virt_dma_desc *vd = vchan_next_desc(&c->vc); -+ struct bcm2708_desc *d; -+ -+ if (!vd) { -+ c->desc = NULL; -+ return; -+ } -+ -+ list_del(&vd->node); -+ -+ c->desc = d = to_bcm2708_dma_desc(&vd->tx); -+ -+ bcm_dma_start(c->chan_base, d->control_block_base_phys); -+} -+ -+static irqreturn_t bcm2708_dma_callback(int irq, void *data) -+{ -+ struct bcm2708_chan *c = data; -+ struct bcm2708_desc *d; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&c->vc.lock, flags); -+ -+ /* Acknowledge interrupt */ -+ writel(BCM2708_DMA_INT, c->chan_base + BCM2708_DMA_CS); -+ -+ d = c->desc; -+ -+ if (d) { -+ /* TODO Only works for cyclic DMA */ -+ vchan_cyclic_callback(&d->vd); -+ } -+ -+ /* Keep the DMA engine running */ -+ dsb(); /* ARM synchronization barrier */ -+ writel(BCM2708_DMA_ACTIVE, c->chan_base + BCM2708_DMA_CS); -+ -+ spin_unlock_irqrestore(&c->vc.lock, flags); -+ -+ return IRQ_HANDLED; -+} -+ -+static int bcm2708_dma_alloc_chan_resources(struct dma_chan *chan) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ -+ return request_irq(c->irq_number, -+ bcm2708_dma_callback, 0, "DMA IRQ", c); -+} -+ -+static void bcm2708_dma_free_chan_resources(struct dma_chan *chan) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ -+ vchan_free_chan_resources(&c->vc); -+ free_irq(c->irq_number, c); -+ -+ dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch); -+} -+ -+static size_t bcm2708_dma_desc_size(struct bcm2708_desc *d) -+{ -+ return d->size; -+} -+ -+static size_t bcm2708_dma_desc_size_pos(struct bcm2708_desc *d, dma_addr_t addr) -+{ -+ unsigned i; -+ size_t size; -+ -+ for (size = i = 0; i < d->frames; i++) { -+ struct bcm2708_dma_cb *control_block = -+ &d->control_block_base[i]; -+ size_t this_size = control_block->length; -+ dma_addr_t dma; -+ -+ if (d->dir == DMA_DEV_TO_MEM) -+ dma = control_block->dst; -+ else -+ dma = control_block->src; -+ -+ if (size) -+ size += this_size; -+ else if (addr >= dma && addr < dma + this_size) -+ size += dma + this_size - addr; -+ } -+ -+ return size; -+} -+ -+static enum dma_status bcm2708_dma_tx_status(struct dma_chan *chan, -+ dma_cookie_t cookie, struct dma_tx_state *txstate) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ struct virt_dma_desc *vd; -+ enum dma_status ret; -+ unsigned long flags; -+ -+ ret = dma_cookie_status(chan, cookie, txstate); -+ if (ret == DMA_SUCCESS || !txstate) -+ return ret; -+ -+ spin_lock_irqsave(&c->vc.lock, flags); -+ vd = vchan_find_desc(&c->vc, cookie); -+ if (vd) { -+ txstate->residue = -+ bcm2708_dma_desc_size(to_bcm2708_dma_desc(&vd->tx)); -+ } else if (c->desc && c->desc->vd.tx.cookie == cookie) { -+ struct bcm2708_desc *d = c->desc; -+ dma_addr_t pos; -+ -+ if (d->dir == DMA_MEM_TO_DEV) -+ pos = readl(c->chan_base + BCM2708_DMA_SOURCE_AD); -+ else if (d->dir == DMA_DEV_TO_MEM) -+ pos = readl(c->chan_base + BCM2708_DMA_DEST_AD); -+ else -+ pos = 0; -+ -+ txstate->residue = bcm2708_dma_desc_size_pos(d, pos); -+ } else { -+ txstate->residue = 0; -+ } -+ -+ spin_unlock_irqrestore(&c->vc.lock, flags); -+ -+ return ret; -+} -+ -+static void bcm2708_dma_issue_pending(struct dma_chan *chan) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ unsigned long flags; -+ -+ c->cyclic = true; /* Nothing else is implemented */ -+ -+ spin_lock_irqsave(&c->vc.lock, flags); -+ if (vchan_issue_pending(&c->vc) && !c->desc) -+ bcm2708_dma_start_desc(c); -+ -+ spin_unlock_irqrestore(&c->vc.lock, flags); -+} -+ -+static struct dma_async_tx_descriptor *bcm2708_dma_prep_dma_cyclic( -+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, -+ size_t period_len, enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ enum dma_slave_buswidth dev_width; -+ struct bcm2708_desc *d; -+ dma_addr_t dev_addr; -+ unsigned es, sync_type; -+ unsigned frame; -+ -+ /* Grab configuration */ -+ if (direction == DMA_DEV_TO_MEM) { -+ dev_addr = c->cfg.src_addr; -+ dev_width = c->cfg.src_addr_width; -+ sync_type = BCM2708_DMA_S_DREQ; -+ } else if (direction == DMA_MEM_TO_DEV) { -+ dev_addr = c->cfg.dst_addr; -+ dev_width = c->cfg.dst_addr_width; -+ sync_type = BCM2708_DMA_D_DREQ; -+ } else { -+ dev_err(chan->device->dev, "%s: bad direction?\n", __func__); -+ return NULL; -+ } -+ -+ /* Bus width translates to the element size (ES) */ -+ switch (dev_width) { -+ case DMA_SLAVE_BUSWIDTH_4_BYTES: -+ es = BCM2708_DMA_DATA_TYPE_S32; -+ break; -+ default: -+ return NULL; -+ } -+ -+ /* Now allocate and setup the descriptor. */ -+ d = kzalloc(sizeof(*d), GFP_NOWAIT); -+ if (!d) -+ return NULL; -+ -+ d->dir = direction; -+ d->frames = buf_len / period_len; -+ -+ /* Allocate memory for control blocks */ -+ d->control_block_size = d->frames * sizeof(struct bcm2708_dma_cb); -+ d->control_block_base = dma_zalloc_coherent(chan->device->dev, -+ d->control_block_size, &d->control_block_base_phys, -+ GFP_NOWAIT); -+ -+ if (!d->control_block_base) { -+ kfree(d); -+ return NULL; -+ } -+ -+ /* -+ * Iterate over all frames, create a control block -+ * for each frame and link them together. -+ */ -+ for (frame = 0; frame < d->frames; frame++) { -+ struct bcm2708_dma_cb *control_block = -+ &d->control_block_base[frame]; -+ -+ /* Setup adresses */ -+ if (d->dir == DMA_DEV_TO_MEM) { -+ control_block->info = BCM2708_DMA_D_INC; -+ control_block->src = dev_addr; -+ control_block->dst = buf_addr + frame * period_len; -+ } else { -+ control_block->info = BCM2708_DMA_S_INC; -+ control_block->src = buf_addr + frame * period_len; -+ control_block->dst = dev_addr; -+ } -+ -+ /* Enable interrupt */ -+ control_block->info |= BCM2708_DMA_INT_EN; -+ -+ /* Setup synchronization */ -+ if (sync_type != 0) -+ control_block->info |= sync_type; -+ -+ /* Setup DREQ channel */ -+ if (c->cfg.slave_id != 0) -+ control_block->info |= -+ BCM2708_DMA_PER_MAP(c->cfg.slave_id); -+ -+ /* Length of a frame */ -+ control_block->length = period_len; -+ d->size += control_block->length; -+ -+ /* -+ * Next block is the next frame. -+ * This DMA engine driver currently only supports cyclic DMA. -+ * Therefore, wrap around at number of frames. -+ */ -+ control_block->next = d->control_block_base_phys + -+ sizeof(struct bcm2708_dma_cb) -+ * ((frame + 1) % d->frames); -+ } -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ -+static int bcm2708_dma_slave_config(struct bcm2708_chan *c, -+ struct dma_slave_config *cfg) -+{ -+ if ((cfg->direction == DMA_DEV_TO_MEM && -+ cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || -+ (cfg->direction == DMA_MEM_TO_DEV && -+ cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) || -+ !is_slave_direction(cfg->direction)) { -+ return -EINVAL; -+ } -+ -+ c->cfg = *cfg; -+ -+ return 0; -+} -+ -+static int bcm2708_dma_terminate_all(struct bcm2708_chan *c) -+{ -+ struct bcm2708_dmadev *d = to_bcm2708_dma_dev(c->vc.chan.device); -+ unsigned long flags; -+ int timeout = 10000; -+ LIST_HEAD(head); -+ -+ spin_lock_irqsave(&c->vc.lock, flags); -+ -+ /* Prevent this channel being scheduled */ -+ spin_lock(&d->lock); -+ list_del_init(&c->node); -+ spin_unlock(&d->lock); -+ -+ /* -+ * Stop DMA activity: we assume the callback will not be called -+ * after bcm_dma_abort() returns (even if it does, it will see -+ * c->desc is NULL and exit.) -+ */ -+ if (c->desc) { -+ c->desc = NULL; -+ bcm_dma_abort(c->chan_base); -+ -+ /* Wait for stopping */ -+ while (timeout > 0) { -+ timeout--; -+ if (!(readl(c->chan_base + BCM2708_DMA_CS) & -+ BCM2708_DMA_ACTIVE)) -+ break; -+ -+ cpu_relax(); -+ } -+ -+ if (timeout <= 0) -+ dev_err(d->ddev.dev, "DMA transfer could not be terminated\n"); -+ } -+ -+ vchan_get_all_descriptors(&c->vc, &head); -+ spin_unlock_irqrestore(&c->vc.lock, flags); -+ vchan_dma_desc_free_list(&c->vc, &head); -+ -+ return 0; -+} -+ -+static int bcm2708_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, -+ unsigned long arg) -+{ -+ struct bcm2708_chan *c = to_bcm2708_dma_chan(chan); -+ -+ switch (cmd) { -+ case DMA_SLAVE_CONFIG: -+ return bcm2708_dma_slave_config(c, -+ (struct dma_slave_config *)arg); -+ -+ case DMA_TERMINATE_ALL: -+ return bcm2708_dma_terminate_all(c); -+ -+ default: -+ return -ENXIO; -+ } -+} -+ -+static int bcm2708_dma_chan_init(struct bcm2708_dmadev *d, void __iomem* chan_base, -+ int chan_id, int irq) -+{ -+ struct bcm2708_chan *c; -+ -+ c = devm_kzalloc(d->ddev.dev, sizeof(*c), GFP_KERNEL); -+ if (!c) -+ return -ENOMEM; -+ -+ c->vc.desc_free = bcm2708_dma_desc_free; -+ vchan_init(&c->vc, &d->ddev); -+ INIT_LIST_HEAD(&c->node); -+ -+ d->ddev.chancnt++; -+ -+ c->chan_base = chan_base; -+ c->ch = chan_id; -+ c->irq_number = irq; -+ -+ return 0; -+} -+ -+static void bcm2708_dma_free(struct bcm2708_dmadev *od) -+{ -+ while (!list_empty(&od->ddev.channels)) { -+ struct bcm2708_chan *c = list_first_entry(&od->ddev.channels, -+ struct bcm2708_chan, vc.chan.device_node); -+ -+ list_del(&c->vc.chan.device_node); -+ tasklet_kill(&c->vc.task); -+ } -+} -+ -+static int bcm2708_dma_probe(struct platform_device *pdev) -+{ -+ struct bcm2708_dmadev *od; -+ int rc, i; -+ -+ if (!pdev->dev.dma_mask) -+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; -+ -+ rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); -+ if (rc) -+ return rc; -+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); -+ -+ od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL); -+ if (!od) -+ return -ENOMEM; -+ -+ pdev->dev.dma_parms = &od->dma_parms; -+ dma_set_max_seg_size(&pdev->dev, 0x3FFFFFFF); -+ -+ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -+ dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); -+ od->ddev.device_alloc_chan_resources = bcm2708_dma_alloc_chan_resources; -+ od->ddev.device_free_chan_resources = bcm2708_dma_free_chan_resources; -+ od->ddev.device_tx_status = bcm2708_dma_tx_status; -+ od->ddev.device_issue_pending = bcm2708_dma_issue_pending; -+ od->ddev.device_prep_dma_cyclic = bcm2708_dma_prep_dma_cyclic; -+ od->ddev.device_control = bcm2708_dma_control; -+ od->ddev.dev = &pdev->dev; -+ INIT_LIST_HEAD(&od->ddev.channels); -+ spin_lock_init(&od->lock); -+ -+ platform_set_drvdata(pdev, od); -+ -+ for (i = 0; i < 16; i++) { -+ void __iomem* chan_base; -+ int chan_id, irq; -+ -+ chan_id = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, -+ &chan_base, -+ &irq); -+ -+ if (chan_id < 0) -+ break; -+ -+ rc = bcm2708_dma_chan_init(od, chan_base, chan_id, irq); -+ if (rc) { -+ bcm2708_dma_free(od); -+ return rc; -+ } -+ } -+ -+ rc = dma_async_device_register(&od->ddev); -+ if (rc) { -+ dev_err(&pdev->dev, -+ "Failed to register slave DMA engine device: %d\n", rc); -+ bcm2708_dma_free(od); -+ return rc; -+ } -+ -+ dev_dbg(&pdev->dev, "Load BCM2708 DMA engine driver\n"); -+ -+ return rc; -+} -+ -+static int bcm2708_dma_remove(struct platform_device *pdev) -+{ -+ struct bcm2708_dmadev *od = platform_get_drvdata(pdev); -+ -+ dma_async_device_unregister(&od->ddev); -+ bcm2708_dma_free(od); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm2708_dma_driver = { -+ .probe = bcm2708_dma_probe, -+ .remove = bcm2708_dma_remove, -+ .driver = { -+ .name = "bcm2708-dmaengine", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_device *pdev; -+ -+static const struct platform_device_info bcm2708_dma_dev_info = { -+ .name = "bcm2708-dmaengine", -+ .id = -1, -+}; -+ -+static int bcm2708_dma_init(void) -+{ -+ int rc = platform_driver_register(&bcm2708_dma_driver); -+ -+ if (rc == 0) { -+ pdev = platform_device_register_full(&bcm2708_dma_dev_info); -+ if (IS_ERR(pdev)) { -+ platform_driver_unregister(&bcm2708_dma_driver); -+ rc = PTR_ERR(pdev); -+ } -+ } -+ -+ return rc; -+} -+subsys_initcall(bcm2708_dma_init); -+ -+static void __exit bcm2708_dma_exit(void) -+{ -+ platform_device_unregister(pdev); -+ platform_driver_unregister(&bcm2708_dma_driver); -+} -+module_exit(bcm2708_dma_exit); -+ -+MODULE_ALIAS("platform:bcm2708-dma"); -+MODULE_DESCRIPTION("BCM2708 DMA engine driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); --- -1.8.5.1 - - -From 34f35bc2a8ea0856f25679a197b91462ec5df1ba Mon Sep 17 00:00:00 2001 -From: Liam Girdwood -Date: Mon, 16 Sep 2013 13:01:46 +0100 -Subject: [PATCH 82/91] ASoC: core: Add API for configuration of DAI BCLK ratio - -Some codec drivers when running in slave mode require that BCLK to sample rate ratio -is explicitly set by the machine driver as it may not be exactly rate * frame size. - -Extend the DAI API by adding :- - -int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); - -Signed-off-by: Liam Girdwood -Signed-off-by: Mark Brown ---- - include/sound/soc-dai.h | 3 +++ - sound/soc/soc-core.c | 16 ++++++++++++++++ - 2 files changed, 19 insertions(+) - -diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h -index ae9a227..d8acf0c 100644 ---- a/include/sound/soc-dai.h -+++ b/include/sound/soc-dai.h -@@ -105,6 +105,8 @@ int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, - int snd_soc_dai_set_pll(struct snd_soc_dai *dai, - int pll_id, int source, unsigned int freq_in, unsigned int freq_out); - -+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); -+ - /* Digital Audio interface formatting */ - int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); - -@@ -131,6 +133,7 @@ struct snd_soc_dai_ops { - int (*set_pll)(struct snd_soc_dai *dai, int pll_id, int source, - unsigned int freq_in, unsigned int freq_out); - int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div); -+ int (*set_bclk_ratio)(struct snd_soc_dai *dai, unsigned int ratio); - - /* - * DAI format configuration -diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c -index 1a38be0..09e47c1 100644 ---- a/sound/soc/soc-core.c -+++ b/sound/soc/soc-core.c -@@ -3576,6 +3576,22 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, - EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); - - /** -+ * snd_soc_dai_set_bclk_ratio - configure BCLK to sample rate ratio. -+ * @dai: DAI -+ * @ratio Ratio of BCLK to Sample rate. -+ * -+ * Configures the DAI for a preset BCLK to sample rate ratio. -+ */ -+int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio) -+{ -+ if (dai->driver && dai->driver->ops->set_bclk_ratio) -+ return dai->driver->ops->set_bclk_ratio(dai, ratio); -+ else -+ return -EINVAL; -+} -+EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio); -+ -+/** - * snd_soc_dai_set_fmt - configure DAI hardware audio format. - * @dai: DAI - * @fmt: SND_SOC_DAIFMT_ format value. --- -1.8.5.1 - - -From 851732349365674e6557a87c935bad26c624236a Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:33:38 +0100 -Subject: [PATCH 83/91] ASoC: Add support for BCM2708 - -This driver adds support for digital audio (I2S) -for the BCM2708 SoC that is used by the -Raspberry Pi. External audio codecs can be -connected to the Raspberry Pi via P5 header. - -It relies on cyclic DMA engine support for BCM2708. - -Signed-off-by: Florian Meier ---- - sound/soc/Kconfig | 1 + - sound/soc/Makefile | 1 + - sound/soc/bcm/Kconfig | 10 + - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/bcm2708-i2s.c | 940 ++++++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 956 insertions(+) - create mode 100644 sound/soc/bcm/Kconfig - create mode 100644 sound/soc/bcm/Makefile - create mode 100644 sound/soc/bcm/bcm2708-i2s.c - -diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig -index 5138b84..a5e3a70 100644 ---- a/sound/soc/Kconfig -+++ b/sound/soc/Kconfig -@@ -33,6 +33,7 @@ config SND_SOC_GENERIC_DMAENGINE_PCM - # All the supported SoCs - source "sound/soc/atmel/Kconfig" - source "sound/soc/au1x/Kconfig" -+source "sound/soc/bcm/Kconfig" - source "sound/soc/blackfin/Kconfig" - source "sound/soc/cirrus/Kconfig" - source "sound/soc/davinci/Kconfig" -diff --git a/sound/soc/Makefile b/sound/soc/Makefile -index 61a64d2..fe6f122 100644 ---- a/sound/soc/Makefile -+++ b/sound/soc/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC) += codecs/ - obj-$(CONFIG_SND_SOC) += generic/ - obj-$(CONFIG_SND_SOC) += atmel/ - obj-$(CONFIG_SND_SOC) += au1x/ -+obj-$(CONFIG_SND_SOC) += bcm/ - obj-$(CONFIG_SND_SOC) += blackfin/ - obj-$(CONFIG_SND_SOC) += cirrus/ - obj-$(CONFIG_SND_SOC) += davinci/ -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -new file mode 100644 -index 0000000..37c8f8c ---- /dev/null -+++ b/sound/soc/bcm/Kconfig -@@ -0,0 +1,10 @@ -+config SND_BCM2708_SOC_I2S -+ tristate "SoC Audio support for the Broadcom BCM2708 I2S module" -+ depends on MACH_BCM2708 -+ select REGMAP_MMIO -+ select SND_SOC_DMAENGINE_PCM -+ select SND_SOC_GENERIC_DMAENGINE_PCM -+ help -+ Say Y or M if you want to add support for codecs attached to -+ the BCM2708 I2S interface. You will also need -+ to select the audio interfaces to support below. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -new file mode 100644 -index 0000000..486ea09 ---- /dev/null -+++ b/sound/soc/bcm/Makefile -@@ -0,0 +1,4 @@ -+# BCM2708 Platform Support -+snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c -new file mode 100644 -index 0000000..ebaf3d6 ---- /dev/null -+++ b/sound/soc/bcm/bcm2708-i2s.c -@@ -0,0 +1,940 @@ -+/* -+ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * Based on -+ * Raspberry Pi PCM I2S ALSA Driver -+ * Copyright (c) by Phil Poole 2013 -+ * -+ * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor -+ * Vladimir Barinov, -+ * Copyright (C) 2007 MontaVista Software, Inc., -+ * -+ * OMAP ALSA SoC DAI driver using McBSP port -+ * Copyright (C) 2008 Nokia Corporation -+ * Contact: Jarkko Nikula -+ * Peter Ujfalusi -+ * -+ * Freescale SSI ALSA SoC Digital Audio Interface (DAI) driver -+ * Author: Timur Tabi -+ * Copyright 2007-2010 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Clock registers */ -+#define BCM2708_CLK_PCMCTL_REG 0x00 -+#define BCM2708_CLK_PCMDIV_REG 0x04 -+ -+/* Clock register settings */ -+#define BCM2708_CLK_PASSWD (0x5a000000) -+#define BCM2708_CLK_PASSWD_MASK (0xff000000) -+#define BCM2708_CLK_MASH(v) ((v) << 9) -+#define BCM2708_CLK_FLIP BIT(8) -+#define BCM2708_CLK_BUSY BIT(7) -+#define BCM2708_CLK_KILL BIT(5) -+#define BCM2708_CLK_ENAB BIT(4) -+#define BCM2708_CLK_SRC(v) (v) -+ -+#define BCM2708_CLK_SHIFT (12) -+#define BCM2708_CLK_DIVI(v) ((v) << BCM2708_CLK_SHIFT) -+#define BCM2708_CLK_DIVF(v) (v) -+#define BCM2708_CLK_DIVF_MASK (0xFFF) -+ -+enum { -+ BCM2708_CLK_MASH_0 = 0, -+ BCM2708_CLK_MASH_1, -+ BCM2708_CLK_MASH_2, -+ BCM2708_CLK_MASH_3, -+}; -+ -+enum { -+ BCM2708_CLK_SRC_GND = 0, -+ BCM2708_CLK_SRC_OSC, -+ BCM2708_CLK_SRC_DBG0, -+ BCM2708_CLK_SRC_DBG1, -+ BCM2708_CLK_SRC_PLLA, -+ BCM2708_CLK_SRC_PLLC, -+ BCM2708_CLK_SRC_PLLD, -+ BCM2708_CLK_SRC_HDMI, -+}; -+ -+/* Most clocks are not useable (freq = 0) */ -+static const unsigned int bcm2708_clk_freq[BCM2708_CLK_SRC_HDMI+1] = { -+ [BCM2708_CLK_SRC_GND] = 0, -+ [BCM2708_CLK_SRC_OSC] = 19200000, -+ [BCM2708_CLK_SRC_DBG0] = 0, -+ [BCM2708_CLK_SRC_DBG1] = 0, -+ [BCM2708_CLK_SRC_PLLA] = 0, -+ [BCM2708_CLK_SRC_PLLC] = 0, -+ [BCM2708_CLK_SRC_PLLD] = 500000000, -+ [BCM2708_CLK_SRC_HDMI] = 0, -+}; -+ -+/* I2S registers */ -+#define BCM2708_I2S_CS_A_REG 0x00 -+#define BCM2708_I2S_FIFO_A_REG 0x04 -+#define BCM2708_I2S_MODE_A_REG 0x08 -+#define BCM2708_I2S_RXC_A_REG 0x0c -+#define BCM2708_I2S_TXC_A_REG 0x10 -+#define BCM2708_I2S_DREQ_A_REG 0x14 -+#define BCM2708_I2S_INTEN_A_REG 0x18 -+#define BCM2708_I2S_INTSTC_A_REG 0x1c -+#define BCM2708_I2S_GRAY_REG 0x20 -+ -+/* I2S register settings */ -+#define BCM2708_I2S_STBY BIT(25) -+#define BCM2708_I2S_SYNC BIT(24) -+#define BCM2708_I2S_RXSEX BIT(23) -+#define BCM2708_I2S_RXF BIT(22) -+#define BCM2708_I2S_TXE BIT(21) -+#define BCM2708_I2S_RXD BIT(20) -+#define BCM2708_I2S_TXD BIT(19) -+#define BCM2708_I2S_RXR BIT(18) -+#define BCM2708_I2S_TXW BIT(17) -+#define BCM2708_I2S_CS_RXERR BIT(16) -+#define BCM2708_I2S_CS_TXERR BIT(15) -+#define BCM2708_I2S_RXSYNC BIT(14) -+#define BCM2708_I2S_TXSYNC BIT(13) -+#define BCM2708_I2S_DMAEN BIT(9) -+#define BCM2708_I2S_RXTHR(v) ((v) << 7) -+#define BCM2708_I2S_TXTHR(v) ((v) << 5) -+#define BCM2708_I2S_RXCLR BIT(4) -+#define BCM2708_I2S_TXCLR BIT(3) -+#define BCM2708_I2S_TXON BIT(2) -+#define BCM2708_I2S_RXON BIT(1) -+#define BCM2708_I2S_EN (1) -+ -+#define BCM2708_I2S_CLKDIS BIT(28) -+#define BCM2708_I2S_PDMN BIT(27) -+#define BCM2708_I2S_PDME BIT(26) -+#define BCM2708_I2S_FRXP BIT(25) -+#define BCM2708_I2S_FTXP BIT(24) -+#define BCM2708_I2S_CLKM BIT(23) -+#define BCM2708_I2S_CLKI BIT(22) -+#define BCM2708_I2S_FSM BIT(21) -+#define BCM2708_I2S_FSI BIT(20) -+#define BCM2708_I2S_FLEN(v) ((v) << 10) -+#define BCM2708_I2S_FSLEN(v) (v) -+ -+#define BCM2708_I2S_CHWEX BIT(15) -+#define BCM2708_I2S_CHEN BIT(14) -+#define BCM2708_I2S_CHPOS(v) ((v) << 4) -+#define BCM2708_I2S_CHWID(v) (v) -+#define BCM2708_I2S_CH1(v) ((v) << 16) -+#define BCM2708_I2S_CH2(v) (v) -+ -+#define BCM2708_I2S_TX_PANIC(v) ((v) << 24) -+#define BCM2708_I2S_RX_PANIC(v) ((v) << 16) -+#define BCM2708_I2S_TX(v) ((v) << 8) -+#define BCM2708_I2S_RX(v) (v) -+ -+#define BCM2708_I2S_INT_RXERR BIT(3) -+#define BCM2708_I2S_INT_TXERR BIT(2) -+#define BCM2708_I2S_INT_RXR BIT(1) -+#define BCM2708_I2S_INT_TXW BIT(0) -+ -+/* I2S DMA interface */ -+#define BCM2708_I2S_FIFO_PHYSICAL_ADDR 0x7E203004 -+#define BCM2708_DMA_DREQ_PCM_TX 2 -+#define BCM2708_DMA_DREQ_PCM_RX 3 -+ -+/* General device struct */ -+struct bcm2708_i2s_dev { -+ struct device *dev; -+ struct snd_dmaengine_dai_dma_data dma_data[2]; -+ unsigned int fmt; -+ unsigned int bclk_ratio; -+ -+ struct regmap *i2s_regmap; -+ struct regmap *clk_regmap; -+}; -+ -+static void bcm2708_i2s_start_clock(struct bcm2708_i2s_dev *dev) -+{ -+ /* Start the clock if in master mode */ -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ -+ switch (master) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ case SND_SOC_DAIFMT_CBS_CFM: -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ break; -+ default: -+ break; -+ } -+} -+ -+static void bcm2708_i2s_stop_clock(struct bcm2708_i2s_dev *dev) -+{ -+ uint32_t clkreg; -+ int timeout = 1000; -+ -+ /* Stop clock */ -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD); -+ -+ /* Wait for the BUSY flag going down */ -+ while (--timeout) { -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ if (!(clkreg & BCM2708_CLK_BUSY)) -+ break; -+ } -+ -+ if (!timeout) { -+ /* KILL the clock */ -+ dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD_MASK, -+ BCM2708_CLK_KILL | BCM2708_CLK_PASSWD); -+ } -+} -+ -+static void bcm2708_i2s_clear_fifos(struct bcm2708_i2s_dev *dev, -+ bool tx, bool rx) -+{ -+ int timeout = 1000; -+ uint32_t syncval; -+ uint32_t csreg; -+ uint32_t i2s_active_state; -+ uint32_t clkreg; -+ uint32_t clk_active_state; -+ uint32_t off; -+ uint32_t clr; -+ -+ off = tx ? BCM2708_I2S_TXON : 0; -+ off |= rx ? BCM2708_I2S_RXON : 0; -+ -+ clr = tx ? BCM2708_I2S_TXCLR : 0; -+ clr |= rx ? BCM2708_I2S_RXCLR : 0; -+ -+ /* Backup the current state */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ i2s_active_state = csreg & (BCM2708_I2S_RXON | BCM2708_I2S_TXON); -+ -+ regmap_read(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, &clkreg); -+ clk_active_state = clkreg & BCM2708_CLK_ENAB; -+ -+ /* Start clock if not running */ -+ if (!clk_active_state) { -+ regmap_update_bits(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, -+ BCM2708_CLK_PASSWD_MASK | BCM2708_CLK_ENAB, -+ BCM2708_CLK_PASSWD | BCM2708_CLK_ENAB); -+ } -+ -+ /* Stop I2S module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, off, 0); -+ -+ /* -+ * Clear the FIFOs -+ * Requires at least 2 PCM clock cycles to take effect -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, clr, clr); -+ -+ /* Wait for 2 PCM clock cycles */ -+ -+ /* -+ * Toggle the SYNC flag. After 2 PCM clock cycles it can be read back -+ * FIXME: This does not seem to work for slave mode! -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &syncval); -+ syncval &= BCM2708_I2S_SYNC; -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_SYNC, ~syncval); -+ -+ /* Wait for the SYNC flag changing it's state */ -+ while (--timeout) { -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ if ((csreg & BCM2708_I2S_SYNC) != syncval) -+ break; -+ } -+ -+ if (!timeout) -+ dev_err(dev->dev, "I2S SYNC error!\n"); -+ -+ /* Stop clock if it was not running before */ -+ if (!clk_active_state) -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Restore I2S state */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXON | BCM2708_I2S_TXON, i2s_active_state); -+} -+ -+static int bcm2708_i2s_set_dai_fmt(struct snd_soc_dai *dai, -+ unsigned int fmt) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->fmt = fmt; -+ return 0; -+} -+ -+static int bcm2708_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, -+ unsigned int ratio) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ dev->bclk_ratio = ratio; -+ return 0; -+} -+ -+static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ unsigned int sampling_rate = params_rate(params); -+ unsigned int data_length, data_delay, bclk_ratio; -+ unsigned int ch1pos, ch2pos, mode, format; -+ unsigned int mash = BCM2708_CLK_MASH_1; -+ unsigned int divi, divf, target_frequency; -+ int clk_src = -1; -+ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; -+ bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBS_CFM); -+ -+ bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS -+ || master == SND_SOC_DAIFMT_CBM_CFS); -+ uint32_t csreg; -+ -+ /* -+ * If a stream is already enabled, -+ * the registers are already set properly. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &csreg); -+ -+ if (csreg & (BCM2708_I2S_TXON | BCM2708_I2S_RXON)) -+ return 0; -+ -+ /* -+ * Adjust the data length according to the format. -+ * We prefill the half frame length with an integer -+ * divider of 2400 as explained at the clock settings. -+ * Maybe it is overwritten there, if the Integer mode -+ * does not apply. -+ */ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ data_length = 16; -+ bclk_ratio = 40; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ data_length = 32; -+ bclk_ratio = 80; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* If bclk_ratio already set, use that one. */ -+ if (dev->bclk_ratio) -+ bclk_ratio = dev->bclk_ratio; -+ -+ /* -+ * Clock Settings -+ * -+ * The target frequency of the bit clock is -+ * sampling rate * frame length -+ * -+ * Integer mode: -+ * Sampling rates that are multiples of 8000 kHz -+ * can be driven by the oscillator of 19.2 MHz -+ * with an integer divider as long as the frame length -+ * is an integer divider of 19200000/8000=2400 as set up above. -+ * This is no longer possible if the sampling rate -+ * is too high (e.g. 192 kHz), because the oscillator is too slow. -+ * -+ * MASH mode: -+ * For all other sampling rates, it is not possible to -+ * have an integer divider. Approximate the clock -+ * with the MASH module that induces a slight frequency -+ * variance. To minimize that it is best to have the fastest -+ * clock here. That is PLLD with 500 MHz. -+ */ -+ target_frequency = sampling_rate * bclk_ratio; -+ clk_src = BCM2708_CLK_SRC_OSC; -+ mash = BCM2708_CLK_MASH_0; -+ -+ if (bcm2708_clk_freq[clk_src] % target_frequency == 0 -+ && bit_master && frame_master) { -+ divi = bcm2708_clk_freq[clk_src] / target_frequency; -+ divf = 0; -+ } else { -+ uint64_t dividend; -+ -+ if (!dev->bclk_ratio) { -+ /* -+ * Overwrite bclk_ratio, because the -+ * above trick is not needed or can -+ * not be used. -+ */ -+ bclk_ratio = 2 * data_length; -+ } -+ -+ target_frequency = sampling_rate * bclk_ratio; -+ -+ clk_src = BCM2708_CLK_SRC_PLLD; -+ mash = BCM2708_CLK_MASH_1; -+ -+ dividend = bcm2708_clk_freq[clk_src]; -+ dividend <<= BCM2708_CLK_SHIFT; -+ do_div(dividend, target_frequency); -+ divi = dividend >> BCM2708_CLK_SHIFT; -+ divf = dividend & BCM2708_CLK_DIVF_MASK; -+ } -+ -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMDIV_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_DIVI(divi) -+ | BCM2708_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2708_CLK_PCMCTL_REG, BCM2708_CLK_PASSWD -+ | BCM2708_CLK_MASH(mash) -+ | BCM2708_CLK_SRC(clk_src)); -+ -+ /* Setup the frame format */ -+ format = BCM2708_I2S_CHEN; -+ -+ if (data_length > 24) -+ format |= BCM2708_I2S_CHWEX; -+ -+ format |= BCM2708_I2S_CHWID((data_length-8)&0xf); -+ -+ switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { -+ case SND_SOC_DAIFMT_I2S: -+ data_delay = 1; -+ break; -+ default: -+ /* -+ * TODO -+ * Others are possible but are not implemented at the moment. -+ */ -+ dev_err(dev->dev, "%s:bad format\n", __func__); -+ return -EINVAL; -+ } -+ -+ ch1pos = data_delay; -+ ch2pos = bclk_ratio / 2 + data_delay; -+ -+ switch (params_channels(params)) { -+ case 2: -+ format = BCM2708_I2S_CH1(format) | BCM2708_I2S_CH2(format); -+ format |= BCM2708_I2S_CH1(BCM2708_I2S_CHPOS(ch1pos)); -+ format |= BCM2708_I2S_CH2(BCM2708_I2S_CHPOS(ch2pos)); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * Set format for both streams. -+ * We cannot set another frame length -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_RXC_A_REG, format); -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_TXC_A_REG, format); -+ -+ /* Setup the I2S mode */ -+ mode = 0; -+ -+ if (data_length <= 16) { -+ /* -+ * Use frame packed mode (2 channels per 32 bit word) -+ * We cannot set another frame length in the second stream -+ * (and therefore word length) anyway, -+ * so the format will be the same. -+ */ -+ mode |= BCM2708_I2S_FTXP | BCM2708_I2S_FRXP; -+ } -+ -+ mode |= BCM2708_I2S_FLEN(bclk_ratio - 1); -+ mode |= BCM2708_I2S_FSLEN(bclk_ratio / 2); -+ -+ /* Master or slave? */ -+ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ /* CPU is master */ -+ break; -+ case SND_SOC_DAIFMT_CBM_CFS: -+ /* -+ * CODEC is bit clock master -+ * CPU is frame master -+ */ -+ mode |= BCM2708_I2S_CLKM; -+ break; -+ case SND_SOC_DAIFMT_CBS_CFM: -+ /* -+ * CODEC is frame master -+ * CPU is bit clock master -+ */ -+ mode |= BCM2708_I2S_FSM; -+ break; -+ case SND_SOC_DAIFMT_CBM_CFM: -+ /* CODEC is master */ -+ mode |= BCM2708_I2S_CLKM; -+ mode |= BCM2708_I2S_FSM; -+ break; -+ default: -+ dev_err(dev->dev, "%s:bad master\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* -+ * Invert clocks? -+ * -+ * The BCM approach seems to be inverted to the classical I2S approach. -+ */ -+ switch (dev->fmt & SND_SOC_DAIFMT_INV_MASK) { -+ case SND_SOC_DAIFMT_NB_NF: -+ /* None. Therefore, both for BCM */ -+ mode |= BCM2708_I2S_CLKI; -+ mode |= BCM2708_I2S_FSI; -+ break; -+ case SND_SOC_DAIFMT_IB_IF: -+ /* Both. Therefore, none for BCM */ -+ break; -+ case SND_SOC_DAIFMT_NB_IF: -+ /* -+ * Invert only frame sync. Therefore, -+ * invert only bit clock for BCM -+ */ -+ mode |= BCM2708_I2S_CLKI; -+ break; -+ case SND_SOC_DAIFMT_IB_NF: -+ /* -+ * Invert only bit clock. Therefore, -+ * invert only frame sync for BCM -+ */ -+ mode |= BCM2708_I2S_FSI; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ regmap_write(dev->i2s_regmap, BCM2708_I2S_MODE_A_REG, mode); -+ -+ /* Setup the DMA parameters */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_RXTHR(1) -+ | BCM2708_I2S_TXTHR(1) -+ | BCM2708_I2S_DMAEN, 0xffffffff); -+ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_DREQ_A_REG, -+ BCM2708_I2S_TX_PANIC(0x10) -+ | BCM2708_I2S_RX_PANIC(0x30) -+ | BCM2708_I2S_TX(0x30) -+ | BCM2708_I2S_RX(0x20), 0xffffffff); -+ -+ /* Clear FIFOs */ -+ bcm2708_i2s_clear_fifos(dev, true, true); -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_prepare(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t cs_reg; -+ -+ bcm2708_i2s_start_clock(dev); -+ -+ /* -+ * Clear both FIFOs if the one that should be started -+ * is not empty at the moment. This should only happen -+ * after overrun. Otherwise, hw_params would have cleared -+ * the FIFO. -+ */ -+ regmap_read(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, &cs_reg); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK -+ && !(cs_reg & BCM2708_I2S_TXE)) -+ bcm2708_i2s_clear_fifos(dev, true, false); -+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE -+ && (cs_reg & BCM2708_I2S_RXD)) -+ bcm2708_i2s_clear_fifos(dev, false, true); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_stop(struct bcm2708_i2s_dev *dev, -+ struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ uint32_t mask; -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, 0); -+ -+ /* Stop also the clock when not SND_SOC_DAIFMT_CONT */ -+ if (!dai->active && !(dev->fmt & SND_SOC_DAIFMT_CONT)) -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static int bcm2708_i2s_trigger(struct snd_pcm_substream *substream, int cmd, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ uint32_t mask; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ bcm2708_i2s_start_clock(dev); -+ -+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) -+ mask = BCM2708_I2S_RXON; -+ else -+ mask = BCM2708_I2S_TXON; -+ -+ regmap_update_bits(dev->i2s_regmap, -+ BCM2708_I2S_CS_A_REG, mask, mask); -+ break; -+ -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ bcm2708_i2s_stop(dev, substream, dai); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_startup(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ if (dai->active) -+ return 0; -+ -+ /* Should this still be running stop it */ -+ bcm2708_i2s_stop_clock(dev); -+ -+ /* Enable PCM block */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, BCM2708_I2S_EN); -+ -+ /* -+ * Disable STBY. -+ * Requires at least 4 PCM clock cycles to take effect. -+ */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_STBY, BCM2708_I2S_STBY); -+ -+ return 0; -+} -+ -+static void bcm2708_i2s_shutdown(struct snd_pcm_substream *substream, -+ struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ bcm2708_i2s_stop(dev, substream, dai); -+ -+ /* If both streams are stopped, disable module and clock */ -+ if (dai->active) -+ return; -+ -+ /* Disable the module */ -+ regmap_update_bits(dev->i2s_regmap, BCM2708_I2S_CS_A_REG, -+ BCM2708_I2S_EN, 0); -+ -+ /* -+ * Stopping clock is necessary, because stop does -+ * not stop the clock when SND_SOC_DAIFMT_CONT -+ */ -+ bcm2708_i2s_stop_clock(dev); -+} -+ -+static const struct snd_soc_dai_ops bcm2708_i2s_dai_ops = { -+ .startup = bcm2708_i2s_startup, -+ .shutdown = bcm2708_i2s_shutdown, -+ .prepare = bcm2708_i2s_prepare, -+ .trigger = bcm2708_i2s_trigger, -+ .hw_params = bcm2708_i2s_hw_params, -+ .set_fmt = bcm2708_i2s_set_dai_fmt, -+ .set_bclk_ratio = bcm2708_i2s_set_dai_bclk_ratio -+}; -+ -+static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) -+{ -+ struct bcm2708_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); -+ -+ dai->playback_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; -+ dai->capture_dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE]; -+ -+ return 0; -+} -+ -+static struct snd_soc_dai_driver bcm2708_i2s_dai = { -+ .name = "bcm2708-i2s", -+ .probe = bcm2708_i2s_dai_probe, -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .capture = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S32_LE -+ }, -+ .ops = &bcm2708_i2s_dai_ops, -+ .symmetric_rates = 1 -+}; -+ -+static bool bcm2708_i2s_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_CS_A_REG: -+ case BCM2708_I2S_FIFO_A_REG: -+ case BCM2708_I2S_INTSTC_A_REG: -+ case BCM2708_I2S_GRAY_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_i2s_precious_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_I2S_FIFO_A_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static bool bcm2708_clk_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2708_CLK_PCMCTL_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config bcm2708_regmap_config[] = { -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_I2S_GRAY_REG, -+ .precious_reg = bcm2708_i2s_precious_reg, -+ .volatile_reg = bcm2708_i2s_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2708_CLK_PCMDIV_REG, -+ .volatile_reg = bcm2708_clk_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, -+}; -+ -+static const struct snd_soc_component_driver bcm2708_i2s_component = { -+ .name = "bcm2708-i2s-comp", -+}; -+ -+ -+static void bcm2708_i2s_setup_gpio(void) -+{ -+ /* -+ * This is the common way to handle the GPIO pins for -+ * the Raspberry Pi. -+ * TODO Better way would be to handle -+ * this in the device tree! -+ */ -+#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) -+#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) -+ -+ unsigned int *gpio; -+ int pin; -+ gpio = ioremap(GPIO_BASE, SZ_16K); -+ -+ /* SPI is on GPIO 7..11 */ -+ for (pin = 28; pin <= 31; pin++) { -+ INP_GPIO(pin); /* set mode to GPIO input first */ -+ SET_GPIO_ALT(pin, 2); /* set mode to ALT 0 */ -+ } -+#undef INP_GPIO -+#undef SET_GPIO_ALT -+} -+ -+static const struct snd_pcm_hardware bcm2708_pcm_hardware = { -+ .info = SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID | -+ SNDRV_PCM_INFO_INTERLEAVED | -+ SNDRV_PCM_INFO_JOINT_DUPLEX, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S32_LE, -+ .period_bytes_min = 32, -+ .period_bytes_max = 64 * PAGE_SIZE, -+ .periods_min = 2, -+ .periods_max = 255, -+ .buffer_bytes_max = 128 * PAGE_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config bcm2708_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &bcm2708_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ -+ -+static int bcm2708_i2s_probe(struct platform_device *pdev) -+{ -+ struct bcm2708_i2s_dev *dev; -+ int i; -+ int ret; -+ struct regmap *regmap[2]; -+ struct resource *mem[2]; -+ -+ /* Request both ioareas */ -+ for (i = 0; i <= 1; i++) { -+ void __iomem *base; -+ -+ mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); -+ base = devm_ioremap_resource(&pdev->dev, mem[i]); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, -+ &bcm2708_regmap_config[i]); -+ if (IS_ERR(regmap[i])) { -+ dev_err(&pdev->dev, "I2S probe: regmap init failed\n"); -+ return PTR_ERR(regmap[i]); -+ } -+ } -+ -+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), -+ GFP_KERNEL); -+ if (IS_ERR(dev)) -+ return PTR_ERR(dev); -+ -+ bcm2708_i2s_setup_gpio(); -+ -+ dev->i2s_regmap = regmap[0]; -+ dev->clk_regmap = regmap[1]; -+ -+ /* Set the DMA address */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -+ (dma_addr_t)BCM2708_I2S_FIFO_PHYSICAL_ADDR; -+ -+ /* Set the DREQ */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].slave_id = -+ BCM2708_DMA_DREQ_PCM_TX; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].slave_id = -+ BCM2708_DMA_DREQ_PCM_RX; -+ -+ /* Set the bus width */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr_width = -+ DMA_SLAVE_BUSWIDTH_4_BYTES; -+ -+ /* Set burst */ -+ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; -+ dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; -+ -+ /* BCLK ratio - use default */ -+ dev->bclk_ratio = 0; -+ -+ /* Store the pdev */ -+ dev->dev = &pdev->dev; -+ dev_set_drvdata(&pdev->dev, dev); -+ -+ ret = snd_soc_register_component(&pdev->dev, -+ &bcm2708_i2s_component, &bcm2708_i2s_dai, 1); -+ -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); -+ ret = -ENOMEM; -+ return ret; -+ } -+ -+ ret = snd_dmaengine_pcm_register(&pdev->dev, -+ &bcm2708_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); -+ if (ret) { -+ dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); -+ snd_soc_unregister_component(&pdev->dev); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int bcm2708_i2s_remove(struct platform_device *pdev) -+{ -+ snd_dmaengine_pcm_unregister(&pdev->dev); -+ snd_soc_unregister_component(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver bcm2708_i2s_driver = { -+ .probe = bcm2708_i2s_probe, -+ .remove = bcm2708_i2s_remove, -+ .driver = { -+ .name = "bcm2708-i2s", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(bcm2708_i2s_driver); -+ -+MODULE_ALIAS("platform:bcm2708-i2s"); -+MODULE_DESCRIPTION("BCM2708 I2S interface"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); --- -1.8.5.1 - - -From d702b3d54869d8d0f2b76647840fec336e4ed00b Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:37:51 +0100 -Subject: [PATCH 84/91] BCM2708: Extend mach header - -Extend the headers of the mach-bcm2708 -in order to support I2S and DMA engine. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/include/mach/dma.h | 2 ++ - arch/arm/mach-bcm2708/include/mach/platform.h | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h -index ac7a4a0..f2568d4 100644 ---- a/arch/arm/mach-bcm2708/include/mach/dma.h -+++ b/arch/arm/mach-bcm2708/include/mach/dma.h -@@ -45,6 +45,8 @@ - #define BCM2708_DMA_ADDR 0x04 - /* the current control block appears in the following registers - read only */ - #define BCM2708_DMA_INFO 0x08 -+#define BCM2708_DMA_SOURCE_AD 0x0c -+#define BCM2708_DMA_DEST_AD 0x10 - #define BCM2708_DMA_NEXTCB 0x1C - #define BCM2708_DMA_DEBUG 0x20 - -diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h -index 992a630..2e7e1bb 100644 ---- a/arch/arm/mach-bcm2708/include/mach/platform.h -+++ b/arch/arm/mach-bcm2708/include/mach/platform.h -@@ -62,10 +62,12 @@ - #define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ - #define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ - #define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ -+#define PCM_CLOCK_BASE (BCM2708_PERI_BASE + 0x101098) /* PCM Clock */ - #define RNG_BASE (BCM2708_PERI_BASE + 0x104000) /* Hardware RNG */ - #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */ - #define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ - #define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ -+#define I2S_BASE (BCM2708_PERI_BASE + 0x203000) /* I2S */ - #define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 */ - #define BSC0_BASE (BCM2708_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */ - #define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */ --- -1.8.5.1 - - -From bad2eb3fb3e365ab242754ba2842700b37bf4343 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 85/91] ASoC: Add support for PCM5102A codec - -Some definitions to support the PCM5102A codec -by Texas Instruments. - -Signed-off-by: Florian Meier ---- - sound/soc/codecs/Kconfig | 4 +++ - sound/soc/codecs/Makefile | 2 ++ - sound/soc/codecs/pcm5102a.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 69 insertions(+) - create mode 100644 sound/soc/codecs/pcm5102a.c - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index b33b45d..34d4d55 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM1681 if I2C - select SND_SOC_PCM1792A if SPI_MASTER - select SND_SOC_PCM3008 -+ select SND_SOC_PCM5102A - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_SGTL5000 if I2C -@@ -311,6 +312,9 @@ config SND_SOC_PCM1792A - config SND_SOC_PCM3008 - tristate - -+config SND_SOC_PCM5102A -+ tristate -+ - config SND_SOC_RT5631 - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index bc12676..612f414 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o - snd-soc-pcm1681-objs := pcm1681.o - snd-soc-pcm1792a-codec-objs := pcm1792a.o - snd-soc-pcm3008-objs := pcm3008.o -+snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-sgtl5000-objs := sgtl5000.o -@@ -179,6 +180,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o - obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o - obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o - obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o -+obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o - obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -new file mode 100644 -index 0000000..126f1e9 ---- /dev/null -+++ b/sound/soc/codecs/pcm5102a.c -@@ -0,0 +1,63 @@ -+/* -+ * Driver for the PCM5102A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm5102a_dai = { -+ .name = "pcm5102a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm5102a; -+ -+static int pcm5102a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm5102a, -+ &pcm5102a_dai, 1); -+} -+ -+static int pcm5102a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm5102a_codec_driver = { -+ .probe = pcm5102a_probe, -+ .remove = pcm5102a_remove, -+ .driver = { -+ .name = "pcm5102a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm5102a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); --- -1.8.5.1 - - -From 990742b03a3a107ff9239b677014f6cd3f0b72d8 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:04:54 +0100 -Subject: [PATCH 86/91] BCM2708: Add I2S support to board file - -Adds the required initializations for I2S -to the board file of mach-bcm2708. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index a388dd8..c3e36fe 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -617,6 +617,28 @@ struct platform_device bcm2708_powerman_device = { - .name = "bcm2835_thermal", +diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c +index d0339eb..bab8a49 100644 +--- a/arch/arm/mach-bcm2708/bcm2708_gpio.c ++++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c +@@ -58,6 +58,8 @@ struct bcm2708_gpio { + struct gpio_chip gc; + unsigned long rising; + unsigned long falling; ++ unsigned long high; ++ unsigned long low; }; -+#ifdef CONFIG_SND_BCM2708_SOC_I2S_MODULE -+static struct resource bcm2708_i2s_resources[] = { -+ { -+ .start = I2S_BASE, -+ .end = I2S_BASE + 0x20, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = PCM_CLOCK_BASE, -+ .end = PCM_CLOCK_BASE + 0x02, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct platform_device bcm2708_i2s_device = { -+ .name = "bcm2708-i2s", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(bcm2708_i2s_resources), -+ .resource = bcm2708_i2s_resources, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -743,6 +765,10 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2835_hwmon_device); - bcm_register_device(&bcm2835_thermal_device); + static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, +@@ -145,20 +147,22 @@ static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) + unsigned irq = d->irq; + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); -+#ifdef CONFIG_SND_BCM2708_SOC_I2S_MODULE -+ bcm_register_device(&bcm2708_i2s_device); -+#endif +- if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) ++ gpio->rising &= ~(1 << irq_to_gpio(irq)); ++ gpio->falling &= ~(1 << irq_to_gpio(irq)); ++ gpio->high &= ~(1 << irq_to_gpio(irq)); ++ gpio->low &= ~(1 << irq_to_gpio(irq)); + - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); --- -1.8.5.1 - - -From 0ac91e6dda915e220af648c746dae7be7619bd18 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 87/91] ASoC: Add support for HifiBerry DAC - -This adds a machine driver for the HifiBerry DAC. -It is a sound card that can -be stacked onto the Raspberry Pi. - -Signed-off-by: Florian Meier ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 5 +++ - sound/soc/bcm/hifiberry_dac.c | 100 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 112 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 37c8f8c..8b14e37 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -8,3 +8,10 @@ config SND_BCM2708_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2708 I2S interface. You will also need - to select the audio interfaces to support below. -+ -+config SND_BCM2708_SOC_HIFIBERRY_DAC -+ tristate "Support for HifiBerry DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM5102A -+ help -+ Say Y or M if you want to add support for HifiBerry DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 486ea09..6834b4d 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -2,3 +2,8 @@ - snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o ++ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) + return -EINVAL; - obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o -+ -+# BCM2708 Machine Support -+snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+ -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -new file mode 100644 -index 0000000..4b70b45 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,100 @@ -+/* -+ * ASoC Driver for HifiBerry DAC -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_hifiberry_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ unsigned int sample_bits = -+ snd_pcm_format_physical_width(params_format(params)); -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dac_ops = { -+ .hw_params = snd_rpi_hifiberry_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dac_dai[] = { -+{ -+ .name = "HifiBerry DAC", -+ .stream_name = "HifiBerry DAC HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm5102a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm5102a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dac_ops, -+ .init = snd_rpi_hifiberry_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dac = { -+ .name = "snd_rpi_hifiberry_dac", -+ .dai_link = snd_rpi_hifiberry_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dac_dai), -+}; -+ -+static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dac); -+} -+ -+static struct platform_driver snd_rpi_hifiberry_dac_driver = { -+ .driver = { -+ .name = "snd-hifiberry-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_hifiberry_dac_probe, -+ .remove = snd_rpi_hifiberry_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); -+MODULE_LICENSE("GPL v2"); --- -1.8.5.1 - - -From db129e91b4bc3a2c9ee496637c06158618e94b70 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:21:34 +0100 -Subject: [PATCH 88/91] BCM2708: Add HifiBerry DAC to board file - -This adds the initalization of the HifiBerry DAC -to the mach-bcm2708 board file. - -Signed-off-by: Florian Meier ---- - arch/arm/mach-bcm2708/bcm2708.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index c3e36fe..ce4acad 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -639,6 +639,20 @@ struct platform_device bcm2708_powerman_device = { - }; - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+static struct platform_device snd_hifiberry_dac_device = { -+ .name = "snd-hifiberry-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm5102a_codec_device = { -+ .name = "pcm5102a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -769,6 +783,11 @@ void __init bcm2708_init(void) - bcm_register_device(&bcm2708_i2s_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC_MODULE) -+ bcm_register_device(&snd_hifiberry_dac_device); -+ bcm_register_device(&snd_pcm5102a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); --- -1.8.5.1 - - -From 8945296d2a662728b1b114bcb0fc37771da47cad Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 6 Dec 2013 18:55:53 +0100 -Subject: [PATCH 89/91] ASoC: BCM2708: Add 24 bit support - -This adds 24 bit support to the I2S driver of the BCM2708. -Besides enabling the 24 bit flags, it includes two bug fixes: - -MMAP is not supported. Claiming this leads to strange issues -when the format of driver and file do not match. - -The datasheet states that the width extension bit should be set -for widths greater than 24, but greater or equal would be correct. -This follows from the definition of the width field. - -Signed-off-by: Florian Meier ---- - sound/soc/bcm/bcm2708-i2s.c | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/sound/soc/bcm/bcm2708-i2s.c b/sound/soc/bcm/bcm2708-i2s.c -index ebaf3d6..a179216 100644 ---- a/sound/soc/bcm/bcm2708-i2s.c -+++ b/sound/soc/bcm/bcm2708-i2s.c -@@ -346,6 +346,10 @@ static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, - data_length = 16; - bclk_ratio = 40; - break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ data_length = 24; -+ bclk_ratio = 40; -+ break; - case SNDRV_PCM_FORMAT_S32_LE: - data_length = 32; - bclk_ratio = 80; -@@ -424,7 +428,7 @@ static int bcm2708_i2s_hw_params(struct snd_pcm_substream *substream, - /* Setup the frame format */ - format = BCM2708_I2S_CHEN; - -- if (data_length > 24) -+ if (data_length >= 24) - format |= BCM2708_I2S_CHWEX; - - format |= BCM2708_I2S_CHWID((data_length-8)&0xf); -@@ -714,6 +718,7 @@ static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE - | SNDRV_PCM_FMTBIT_S32_LE - }, - .capture = { -@@ -721,6 +726,7 @@ static int bcm2708_i2s_dai_probe(struct snd_soc_dai *dai) - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE -+ | SNDRV_PCM_FMTBIT_S24_LE - | SNDRV_PCM_FMTBIT_S32_LE - }, - .ops = &bcm2708_i2s_dai_ops, -@@ -810,11 +816,10 @@ static void bcm2708_i2s_setup_gpio(void) +- if (type & IRQ_TYPE_EDGE_RISING) { ++ if (type & IRQ_TYPE_EDGE_RISING) + gpio->rising |= (1 << irq_to_gpio(irq)); +- } else { +- gpio->rising &= ~(1 << irq_to_gpio(irq)); +- } +- +- if (type & IRQ_TYPE_EDGE_FALLING) { ++ if (type & IRQ_TYPE_EDGE_FALLING) + gpio->falling |= (1 << irq_to_gpio(irq)); +- } else { +- gpio->falling &= ~(1 << irq_to_gpio(irq)); +- } ++ if (type & IRQ_TYPE_LEVEL_HIGH) ++ gpio->high |= (1 << irq_to_gpio(irq)); ++ if (type & IRQ_TYPE_LEVEL_LOW) ++ gpio->low |= (1 << irq_to_gpio(irq)); + return 0; } - static const struct snd_pcm_hardware bcm2708_pcm_hardware = { -- .info = SNDRV_PCM_INFO_MMAP | -- SNDRV_PCM_INFO_MMAP_VALID | -- SNDRV_PCM_INFO_INTERLEAVED | -+ .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX, - .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .period_bytes_min = 32, - .period_bytes_max = 64 * PAGE_SIZE, +@@ -168,13 +172,17 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d) + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; +- unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ unsigned long high = readl(gpio->base + GPIOHEN(gb)); ++ unsigned long low = readl(gpio->base + GPIOLEN(gb)); + + gn = gn % 32; + +- writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); ++ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); ++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb)); ++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb)); + } + + static void bcm2708_gpio_irq_unmask(struct irq_data *d) +@@ -183,24 +191,38 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d) + struct bcm2708_gpio *gpio = irq_get_chip_data(irq); + unsigned gn = irq_to_gpio(irq); + unsigned gb = gn / 32; +- unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); + unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ unsigned long high = readl(gpio->base + GPIOHEN(gb)); ++ unsigned long low = readl(gpio->base + GPIOLEN(gb)); + + gn = gn % 32; + + writel(1 << gn, gpio->base + GPIOEDS(gb)); + + if (gpio->rising & (1 << gn)) { +- writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); ++ writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); + } else { + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); + } + + if (gpio->falling & (1 << gn)) { +- writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); ++ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); + } else { + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); + } ++ ++ if (gpio->high & (1 << gn)) { ++ writel(high | (1 << gn), gpio->base + GPIOHEN(gb)); ++ } else { ++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb)); ++ } ++ ++ if (gpio->low & (1 << gn)) { ++ writel(low | (1 << gn), gpio->base + GPIOLEN(gb)); ++ } else { ++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb)); ++ } + } + + static struct irq_chip bcm2708_irqchip = { -- 1.8.5.1 -From 07132c6890d9f6eefe217177962f9ba09b038666 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Mon, 2 Dec 2013 20:28:22 +0100 -Subject: [PATCH 90/91] BCM2708: Add I2S and DMA support to default config +From 33b7b360def6a599ae53beac047678087d341d4a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 18 Dec 2013 22:16:19 +0000 +Subject: [PATCH 80/80] config: Enable CONFIG_MEMCG, but leave it disabled (due + to memory cost). Enable with cgroup_enable=memory. -This commit adds several modules that are needed for -I2S support for the Raspberry Pi to the defconfig. - -Signed-off-by: Florian Meier --- - arch/arm/configs/bcmrpi_defconfig | 11 +++++++++++ - 1 file changed, 11 insertions(+) + arch/arm/configs/bcmrpi_defconfig | 1 + + kernel/cgroup.c | 27 +++++++++++++++++++++++++++ + mm/memcontrol.c | 1 + + 3 files changed, 29 insertions(+) diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 4032d53..d60ba43 100644 +index c850de6..2d79fac 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -733,6 +733,13 @@ CONFIG_SND_USB_UA101=m - CONFIG_SND_USB_CAIAQ=m - CONFIG_SND_USB_CAIAQ_INPUT=y - CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_SOC=m -+CONFIG_SND_SOC_DMAENGINE_PCM=y -+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y -+CONFIG_SND_BCM2708_SOC_I2S=m -+CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_SOC_I2C_AND_SPI=m -+CONFIG_SND_SOC_PCM5102A=m - CONFIG_SOUND_PRIME=m - CONFIG_HIDRAW=y - CONFIG_HID_A4TECH=m -@@ -924,6 +931,10 @@ CONFIG_RTC_DRV_RS5C348=m - CONFIG_RTC_DRV_DS3234=m - CONFIG_RTC_DRV_PCF2123=m - CONFIG_RTC_DRV_RX4581=m -+CONFIG_DMADEVICES=y -+CONFIG_DMA_BCM2708=m -+CONFIG_DMA_ENGINE=y -+CONFIG_DMA_VIRTUAL_CHANNELS=m - CONFIG_UIO=m - CONFIG_UIO_PDRV=m - CONFIG_UIO_PDRV_GENIRQ=m --- -1.8.5.1 - - -From 8b2af1c65260f579a54b2826d5a364fa22dfac90 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 6 Dec 2013 20:50:28 +0100 -Subject: [PATCH 91/91] ASoC: BCM2708: Add support for RPi-DAC - -This adds a machine driver for the RPi-DAC. - -Signed-off-by: Florian Meier ---- - arch/arm/configs/bcmrpi_defconfig | 2 + - arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++++ - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-dac.c | 97 +++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/Kconfig | 4 ++ - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm1794a.c | 62 +++++++++++++++++++++++++ - 8 files changed, 195 insertions(+) - create mode 100644 sound/soc/bcm/rpi-dac.c - create mode 100644 sound/soc/codecs/pcm1794a.c - -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index d60ba43..74628c9 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -738,8 +738,10 @@ CONFIG_SND_SOC_DMAENGINE_PCM=y - CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y - CONFIG_SND_BCM2708_SOC_I2S=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_SOC_I2C_AND_SPI=m - CONFIG_SND_SOC_PCM5102A=m -+CONFIG_SND_SOC_PCM1794A=m - CONFIG_SOUND_PRIME=m - CONFIG_HIDRAW=y - CONFIG_HID_A4TECH=m -diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index ce4acad..4ab2609 100644 ---- a/arch/arm/mach-bcm2708/bcm2708.c -+++ b/arch/arm/mach-bcm2708/bcm2708.c -@@ -653,6 +653,20 @@ struct platform_device bcm2708_powerman_device = { +@@ -18,6 +18,7 @@ CONFIG_CGROUP_FREEZER=y + CONFIG_CGROUP_DEVICE=y + CONFIG_CGROUP_CPUACCT=y + CONFIG_RESOURCE_COUNTERS=y ++CONFIG_MEMCG=y + CONFIG_BLK_CGROUP=y + CONFIG_NAMESPACES=y + CONFIG_SCHED_AUTOGROUP=y +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index bc1dcab..10de35a 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -5483,6 +5483,33 @@ static int __init cgroup_disable(char *str) + } + __setup("cgroup_disable=", cgroup_disable); + ++static int __init cgroup_enable(char *str) ++{ ++ struct cgroup_subsys *ss; ++ char *token; ++ int i; ++ ++ while ((token = strsep(&str, ",")) != NULL) { ++ if (!*token) ++ continue; ++ ++ /* ++ * cgroup_disable, being at boot time, can't know about ++ * module subsystems, so we don't worry about them. ++ */ ++ for_each_builtin_subsys(ss, i) { ++ if (!strcmp(token, ss->name)) { ++ ss->disabled = 0; ++ printk(KERN_INFO "Disabling %s control group" ++ " subsystem\n", ss->name); ++ break; ++ } ++ } ++ } ++ return 1; ++} ++__setup("cgroup_enable=", cgroup_enable); ++ + /** + * css_from_dir - get corresponding css from the dentry of a cgroup dir + * @dentry: directory dentry of interest +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 7f1a356..71d74e3 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -7013,6 +7013,7 @@ struct cgroup_subsys mem_cgroup_subsys = { + .bind = mem_cgroup_bind, + .base_cftypes = mem_cgroup_files, + .early_init = 0, ++ .disabled = 1, }; - #endif -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+static struct platform_device snd_rpi_dac_device = { -+ .name = "snd-rpi-dac", -+ .id = 0, -+ .num_resources = 0, -+}; -+ -+static struct platform_device snd_pcm1794a_codec_device = { -+ .name = "pcm1794a-codec", -+ .id = -1, -+ .num_resources = 0, -+}; -+#endif -+ - int __init bcm_register_device(struct platform_device *pdev) - { - int ret; -@@ -788,6 +802,11 @@ void __init bcm2708_init(void) - bcm_register_device(&snd_pcm5102a_codec_device); - #endif - -+#if defined(CONFIG_SND_BCM2708_SOC_RPI_DAC) || defined(CONFIG_SND_BCM2708_SOC_RPI_DAC_MODULE) -+ bcm_register_device(&snd_rpi_dac_device); -+ bcm_register_device(&snd_pcm1794a_codec_device); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8b14e37..1c1f5cf 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -15,3 +15,10 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC - select SND_SOC_PCM5102A - help - Say Y or M if you want to add support for HifiBerry DAC. -+ -+config SND_BCM2708_SOC_RPI_DAC -+ tristate "Support for RPi-DAC" -+ depends on SND_BCM2708_SOC_I2S -+ select SND_SOC_PCM1794A -+ help -+ Say Y or M if you want to add support for RPi-DAC. -\ No newline at end of file -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 6834b4d..95a9d44 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,5 +5,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_I2S) += snd-soc-bcm2708-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-rpi-dac-objs := rpi-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c -new file mode 100644 -index 0000000..ef3cd93 ---- /dev/null -+++ b/sound/soc/bcm/rpi-dac.c -@@ -0,0 +1,97 @@ -+/* -+ * ASoC Driver for RPi-DAC. -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static int snd_rpi_rpi_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return 0; -+} -+ -+static int snd_rpi_rpi_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_rpi_dac_ops = { -+ .hw_params = snd_rpi_rpi_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_rpi_dac_dai[] = { -+{ -+ .name = "HifiBerry Mini", -+ .stream_name = "HifiBerry Mini HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm1794a-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm1794a-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_rpi_dac_ops, -+ .init = snd_rpi_rpi_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_rpi_dac = { -+ .name = "snd_rpi_rpi_dac", -+ .dai_link = snd_rpi_rpi_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_rpi_dac_dai), -+}; -+ -+static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_rpi_dac.dev = &pdev->dev; -+ ret = snd_soc_register_card(&snd_rpi_rpi_dac); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_rpi_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_rpi_dac); -+} -+ -+static struct platform_driver snd_rpi_rpi_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-dac", -+ .owner = THIS_MODULE, -+ }, -+ .probe = snd_rpi_rpi_dac_probe, -+ .remove = snd_rpi_rpi_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_rpi_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 34d4d55..4a1dd7e 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -59,6 +59,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_PCM1681 if I2C - select SND_SOC_PCM1792A if SPI_MASTER - select SND_SOC_PCM3008 -+ select SND_SOC_PCM1794A - select SND_SOC_PCM5102A - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C -@@ -312,6 +313,9 @@ config SND_SOC_PCM1792A - config SND_SOC_PCM3008 - tristate - -+config SND_SOC_PCM1794A -+ tristate -+ - config SND_SOC_PCM5102A - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 612f414..9b806a2 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -46,6 +46,7 @@ snd-soc-hdmi-codec-objs := hdmi.o - snd-soc-pcm1681-objs := pcm1681.o - snd-soc-pcm1792a-codec-objs := pcm1792a.o - snd-soc-pcm3008-objs := pcm3008.o -+snd-soc-pcm1794a-objs := pcm1794a.o - snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o -@@ -180,6 +181,7 @@ obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o - obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o - obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o - obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o -+obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o - obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o - obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o - obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o -diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c -new file mode 100644 -index 0000000..b4eaa44 ---- /dev/null -+++ b/sound/soc/codecs/pcm1794a.c -@@ -0,0 +1,62 @@ -+/* -+ * Driver for the PCM1794A codec -+ * -+ * Author: Florian Meier -+ * Copyright 2013 -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ */ -+ -+ -+#include -+#include -+#include -+ -+#include -+ -+static struct snd_soc_dai_driver pcm1794a_dai = { -+ .name = "pcm1794a-hifi", -+ .playback = { -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_192000, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE -+ }, -+}; -+ -+static struct snd_soc_codec_driver soc_codec_dev_pcm1794a; -+ -+static int pcm1794a_probe(struct platform_device *pdev) -+{ -+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pcm1794a, -+ &pcm1794a_dai, 1); -+} -+ -+static int pcm1794a_remove(struct platform_device *pdev) -+{ -+ snd_soc_unregister_codec(&pdev->dev); -+ return 0; -+} -+ -+static struct platform_driver pcm1794a_codec_driver = { -+ .probe = pcm1794a_probe, -+ .remove = pcm1794a_remove, -+ .driver = { -+ .name = "pcm1794a-codec", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+module_platform_driver(pcm1794a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); + #ifdef CONFIG_MEMCG_SWAP -- 1.8.5.1