From 6a12b31d47e8ddcecabc398de08abdf0072ec876 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Mon, 10 Feb 2014 16:21:48 +0100 Subject: [PATCH] projects/RPi/patches: update RPi patches Signed-off-by: Stephan Raue --- ...tch => linux-01-RPi_support-0bb9f12.patch} | 4469 ++++++++++++++++- 1 file changed, 4268 insertions(+), 201 deletions(-) rename projects/RPi/patches/linux/{linux-01-RPi_support-bc287c8.patch => linux-01-RPi_support-0bb9f12.patch} (96%) diff --git a/projects/RPi/patches/linux/linux-01-RPi_support-bc287c8.patch b/projects/RPi/patches/linux/linux-01-RPi_support-0bb9f12.patch similarity index 96% rename from projects/RPi/patches/linux/linux-01-RPi_support-bc287c8.patch rename to projects/RPi/patches/linux/linux-01-RPi_support-0bb9f12.patch index 103e23de48..16709f3fd3 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support-bc287c8.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support-0bb9f12.patch @@ -1,7 +1,7 @@ -From bcdaa271b021257f572856386896b3fe74eaf00b Mon Sep 17 00:00:00 2001 +From 5220fae6e19400096331585696e74b55672bcc97 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 01/82] Main bcm2708 linux port +Subject: [PATCH 001/101] Main bcm2708 linux port Signed-off-by: popcornmix --- @@ -8023,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 bd8a098..d27309c 100644 +index 3c71920..3cd62f2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -28,6 +28,7 @@ @@ -8264,7 +8264,7 @@ index bd8a098..d27309c 100644 u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ -@@ -2193,7 +2207,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2187,7 +2201,7 @@ static void sdhci_timeout_timer(unsigned long data) if (host->mrq) { pr_err("%s: Timeout waiting for hardware " @@ -8273,7 +8273,7 @@ index bd8a098..d27309c 100644 sdhci_dumpregs(host); if (host->data) { -@@ -2238,10 +2252,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) +@@ -2232,10 +2246,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { @@ -8287,7 +8287,7 @@ index bd8a098..d27309c 100644 return; } -@@ -2311,6 +2328,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) +@@ -2305,6 +2322,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif @@ -8307,7 +8307,7 @@ index bd8a098..d27309c 100644 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { u32 command; -@@ -2340,23 +2370,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2334,23 +2364,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } } @@ -8351,7 +8351,7 @@ index bd8a098..d27309c 100644 pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); sdhci_show_adma_error(host); host->data->error = -EIO; -@@ -2364,11 +2410,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2358,11 +2404,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->ops->adma_workaround(host, intmask); } @@ -8374,7 +8374,7 @@ index bd8a098..d27309c 100644 /* * We currently don't do anything fancy with DMA -@@ -2397,18 +2450,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2391,18 +2444,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); } @@ -8395,7 +8395,7 @@ index bd8a098..d27309c 100644 } } -@@ -2464,6 +2507,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2458,6 +2501,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) tasklet_schedule(&host->card_tasklet); } @@ -8418,7 +8418,7 @@ index bd8a098..d27309c 100644 if (intmask & SDHCI_INT_CMD_MASK) { sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); -@@ -2478,7 +2537,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2472,7 +2531,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); @@ -8433,7 +8433,7 @@ index bd8a098..d27309c 100644 if (intmask & SDHCI_INT_BUS_POWER) { pr_err("%s: Card is consuming too much power!\n", -@@ -2591,7 +2656,8 @@ int sdhci_resume_host(struct sdhci_host *host) +@@ -2585,7 +2650,8 @@ int sdhci_resume_host(struct sdhci_host *host) { int ret = 0; @@ -8443,7 +8443,7 @@ index bd8a098..d27309c 100644 if (host->ops->enable_dma) host->ops->enable_dma(host); } -@@ -2822,14 +2888,16 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -2816,14 +2882,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } @@ -8462,7 +8462,7 @@ index bd8a098..d27309c 100644 } } } -@@ -3254,6 +3322,7 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3249,6 +3317,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)), @@ -8539,10 +8539,10 @@ index a0dfb86..b93df06 100644 static struct vendor_data vendor_arm = { diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h -index 3e781b8..aad2393 100644 +index 362927c4..e23fffb 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h -@@ -131,6 +131,7 @@ struct sdhci_host { +@@ -133,6 +133,7 @@ struct sdhci_host { #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ #define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ #define SDHCI_USING_RETUNING_TIMER (1<<11) /* Host is using a retuning timer for the card */ @@ -8550,7 +8550,7 @@ index 3e781b8..aad2393 100644 unsigned int version; /* SDHCI spec. version */ -@@ -146,6 +147,7 @@ struct sdhci_host { +@@ -148,6 +149,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ @@ -8562,10 +8562,10 @@ index 3e781b8..aad2393 100644 1.8.5.1 -From c8719e0445513cb4a4008f0dacac69b9f20dba40 Mon Sep 17 00:00:00 2001 +From fe933bed7bd0991a49b95c905ff5b0d52b93da0c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 7 May 2013 22:20:24 +0100 -Subject: [PATCH 02/82] Add quick config. +Subject: [PATCH 002/101] Add quick config. This is designed for quick compiling when developing. No modules are needed and it includes all Pi specific drivers @@ -8781,10 +8781,10 @@ index 0000000..e5efe75 1.8.5.1 -From 245dc77b4002fec0ca704d6e4c4e644e07024388 Mon Sep 17 00:00:00 2001 +From 247dbdc83579ab49ed03de34d69808bc93285d1b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 03/82] Add dwc_otg driver +Subject: [PATCH 003/101] Add dwc_otg driver Signed-off-by: popcornmix --- @@ -65856,10 +65856,10 @@ index 0000000..cdc9963 1.8.5.1 -From 61cb79abf0da04a6cb38f1bfd32de0ea18b1c6ae Mon Sep 17 00:00:00 2001 +From 739fd0b4ff49722674dfe8fd00c5bf22db80fc64 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 04/82] bcm2708 watchdog driver +Subject: [PATCH 004/101] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -66292,10 +66292,10 @@ index 0000000..2f19203 1.8.5.1 -From ca1d3fdf7af3ef9f3cbf3f1f75d1e266af4a9d3b Mon Sep 17 00:00:00 2001 +From bd5a02f9a5591c3104f8911f08cb1dbb66e21838 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 05/82] bcm2708 framebuffer driver +Subject: [PATCH 005/101] bcm2708 framebuffer driver Signed-off-by: popcornmix --- @@ -69334,10 +69334,10 @@ index 3c14e43..7626beb 100644 1.8.5.1 -From 5bdd6864ddf72fff9d06261bc5fc919b367da4c3 Mon Sep 17 00:00:00 2001 +From b6b336a3959926265990d2e8767c769e7f86625a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 06/82] bcm2708 vchiq driver +Subject: [PATCH 006/101] bcm2708 vchiq driver Signed-off-by: popcornmix --- @@ -81838,10 +81838,10 @@ index 0000000..b6bfa21 1.8.5.1 -From 4724880e2477417b1fe2e4faad116fd906d5c7d2 Mon Sep 17 00:00:00 2001 +From 7fe168a7f36649594d164f23489c8ce10cf4027e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 07/82] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 007/101] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix --- @@ -83131,10 +83131,10 @@ index 0000000..5325832 1.8.5.1 -From df3983c58d34c4c930de3a7eff79e1ef4f04bc6e Mon Sep 17 00:00:00 2001 +From 3a937f0cb34a6179ee5415d345bcaa6597d1d7b7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 08/82] bcm2708: alsa sound driver +Subject: [PATCH 008/101] bcm2708: alsa sound driver Signed-off-by: popcornmix --- @@ -85456,10 +85456,10 @@ index 0000000..af3e6eb 1.8.5.1 -From 9986d943e0c36b6b6ebd311e7c732ddc9865e4dd Mon Sep 17 00:00:00 2001 +From 22d2b2c8ab6e0d41dd0bd094f4649e498bc49a5e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 09/82] Allow mac address to be set in smsc95xx +Subject: [PATCH 009/101] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -85553,10 +85553,10 @@ index 3f38ba8..60076fe 100644 1.8.5.1 -From 6387104db401ddf1a92e9581ba46bd99e058b090 Mon Sep 17 00:00:00 2001 +From 62690517481edab4b066d2d1c9553d583eb725e0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 8 May 2012 23:12:13 +0100 -Subject: [PATCH 10/82] Fixes for sdhci-bcm2708 +Subject: [PATCH 010/101] Fixes for sdhci-bcm2708 possible fix for sdcard missing status. Thank naren @@ -86327,7 +86327,7 @@ index d8ef77c..1ebbe2d 100644 + + diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index d27309c..576c526 100644 +index 3cd62f2..0b44ccf 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -131,6 +131,99 @@ static void sdhci_dumpregs(struct sdhci_host *host) @@ -86571,7 +86571,7 @@ index d27309c..576c526 100644 } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, -@@ -2090,7 +2187,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2084,7 +2181,7 @@ static void sdhci_card_event(struct mmc_host *mmc) if (host->ops->card_event) host->ops->card_event(host); @@ -86580,7 +86580,7 @@ index d27309c..576c526 100644 /* Check host->mrq first in case we are runtime suspended */ if (host->mrq && !sdhci_do_get_cd(host)) { -@@ -2106,7 +2203,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2100,7 +2197,7 @@ static void sdhci_card_event(struct mmc_host *mmc) tasklet_schedule(&host->finish_tasklet); } @@ -86589,7 +86589,7 @@ index d27309c..576c526 100644 } static const struct mmc_host_ops sdhci_ops = { -@@ -2145,14 +2242,14 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2139,14 +2236,14 @@ static void sdhci_tasklet_finish(unsigned long param) host = (struct sdhci_host*)param; @@ -86606,7 +86606,7 @@ index d27309c..576c526 100644 return; } -@@ -2190,7 +2287,7 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2184,7 +2281,7 @@ static void sdhci_tasklet_finish(unsigned long param) #endif mmiowb(); @@ -86615,7 +86615,7 @@ index d27309c..576c526 100644 mmc_request_done(host->mmc, mrq); sdhci_runtime_pm_put(host); -@@ -2203,7 +2300,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2197,7 +2294,7 @@ static void sdhci_timeout_timer(unsigned long data) host = (struct sdhci_host*)data; @@ -86624,7 +86624,7 @@ index d27309c..576c526 100644 if (host->mrq) { pr_err("%s: Timeout waiting for hardware " -@@ -2224,7 +2321,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2218,7 +2315,7 @@ static void sdhci_timeout_timer(unsigned long data) } mmiowb(); @@ -86633,7 +86633,7 @@ index d27309c..576c526 100644 } static void sdhci_tuning_timer(unsigned long data) -@@ -2234,11 +2331,11 @@ static void sdhci_tuning_timer(unsigned long data) +@@ -2228,11 +2325,11 @@ static void sdhci_tuning_timer(unsigned long data) host = (struct sdhci_host *)data; @@ -86647,7 +86647,7 @@ index d27309c..576c526 100644 } /*****************************************************************************\ -@@ -2462,10 +2559,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2456,10 +2553,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) u32 intmask, unexpected = 0; int cardint = 0, max_loops = 16; @@ -86660,7 +86660,7 @@ index d27309c..576c526 100644 pr_warning("%s: got irq while runtime suspended\n", mmc_hostname(host->mmc)); return IRQ_HANDLED; -@@ -2577,7 +2674,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2571,7 +2668,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask && --max_loops) goto again; out: @@ -86669,7 +86669,7 @@ index d27309c..576c526 100644 if (unexpected) { pr_err("%s: Unexpected interrupt 0x%08x.\n", -@@ -2663,7 +2760,7 @@ int sdhci_resume_host(struct sdhci_host *host) +@@ -2657,7 +2754,7 @@ int sdhci_resume_host(struct sdhci_host *host) } if (!device_may_wakeup(mmc_dev(host->mmc))) { @@ -86678,7 +86678,7 @@ index d27309c..576c526 100644 mmc_hostname(host->mmc), host); if (ret) return ret; -@@ -2739,15 +2836,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) +@@ -2733,15 +2830,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) host->flags &= ~SDHCI_NEEDS_RETUNING; } @@ -86698,7 +86698,7 @@ index d27309c..576c526 100644 return ret; } -@@ -2773,16 +2870,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2767,16 +2864,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)) { @@ -86718,7 +86718,7 @@ index d27309c..576c526 100644 host->runtime_suspended = false; -@@ -2793,7 +2890,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2787,7 +2884,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) /* Enable Card Detection */ sdhci_enable_card_detection(host); @@ -86727,7 +86727,7 @@ index d27309c..576c526 100644 return ret; } -@@ -3288,8 +3385,8 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3283,8 +3380,8 @@ int sdhci_add_host(struct sdhci_host *host) sdhci_init(host, 0); @@ -86738,7 +86738,7 @@ index d27309c..576c526 100644 if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); -@@ -3350,7 +3447,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3345,7 +3442,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) unsigned long flags; if (dead) { @@ -86747,7 +86747,7 @@ index d27309c..576c526 100644 host->flags |= SDHCI_DEVICE_DEAD; -@@ -3362,7 +3459,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3357,7 +3454,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) tasklet_schedule(&host->finish_tasklet); } @@ -86793,11 +86793,11 @@ index 99f5709..cd6f996 100644 mmc_pm_flag_t pm_caps; /* supported pm features */ diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h -index aad2393..0aeeef8 100644 +index e23fffb..b1b6537 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h -@@ -100,6 +100,7 @@ struct sdhci_host { - #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5) +@@ -102,6 +102,7 @@ struct sdhci_host { + #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6) int irq; /* Device IRQ */ + int second_irq; /* Additional IRQ to disable/enable in low-latency mode */ @@ -86808,10 +86808,10 @@ index aad2393..0aeeef8 100644 1.8.5.1 -From 08d8888b9e603434e397952b85c3db865f041783 Mon Sep 17 00:00:00 2001 +From 7bd97decf3e2c112e16bf2afc73a33984dbd11fd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 4 Nov 2013 18:56:10 +0000 -Subject: [PATCH 11/82] Add Chris Boot's i2c and spi drivers. +Subject: [PATCH 011/101] Add Chris Boot's i2c and spi drivers. --- arch/arm/configs/bcmrpi_cutdown_defconfig | 9 + @@ -87053,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 3b26129..15070da 100644 +index faa3e8e..808a674 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig -@@ -346,6 +346,25 @@ config I2C_BCM2835 +@@ -347,6 +347,25 @@ config I2C_BCM2835 This support is also available as a module. If so, the module will be called i2c-bcm2835. @@ -88175,10 +88175,10 @@ index 0000000..180264a 1.8.5.1 -From 81c156f6adaf96efb9fe73100a07abdfb36dfa87 Mon Sep 17 00:00:00 2001 +From 98a1475d42e627b14ca940a3fff051b7a96379b9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 12/82] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 012/101] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) --- @@ -88241,10 +88241,10 @@ index 63b8273..2a36411 100644 1.8.5.1 -From 79fcae5f47de49dd681adedc51e7fbe054b58d45 Mon Sep 17 00:00:00 2001 +From 21318d111cd40e233f9f3773d125c8100118dd6b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:46:42 +0100 -Subject: [PATCH 13/82] Add FIQ patch to dwc_otg driver. Enable with +Subject: [PATCH 013/101] 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 @@ -89404,11 +89404,11 @@ index e46d9bb..6b2c7d0 100644 1.8.5.1 -From 6e179452e81484ae9651b3c8cc82a9aa42297738 Mon Sep 17 00:00:00 2001 +From c365885cb7dd112098dd3e392ee450853a087ede Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Sep 2012 15:17:53 +0100 -Subject: [PATCH 16/82] Avoid dynamic memory allocation for channel lock in USB - driver. Thanks ddv2005. +Subject: [PATCH 016/101] Avoid dynamic memory allocation for channel lock in + USB driver. Thanks ddv2005. --- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 6 +++--- @@ -89514,10 +89514,10 @@ index b7b6b0c..76b5085 100644 1.8.5.1 -From 642b610078794899fd383139d2db5838ed152f05 Mon Sep 17 00:00:00 2001 +From 0f7ac77e4b426acdc8b362563ba281323bc11f47 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 17/82] Add cpufreq driver +Subject: [PATCH 017/101] Add cpufreq driver --- arch/arm/Kconfig | 1 + @@ -89819,10 +89819,10 @@ index 0000000..7bc55bd 1.8.5.1 -From 795d722705e88258deb5ef1d32bdbe16e3b201ed Mon Sep 17 00:00:00 2001 +From 3cfb1548d1bfea92647973988e1306124b02b540 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:58:47 +0100 -Subject: [PATCH 18/82] config: add missing options from 3.6.y kernel +Subject: [PATCH 018/101] config: add missing options from 3.6.y kernel --- arch/arm/configs/bcmrpi_defconfig | 741 ++++++++++++++++++++++++++++++++------ @@ -90858,10 +90858,10 @@ index 31f5afaa..31adf3c 100644 1.8.5.1 -From d72c832ef34e9fe4ee7476a37c3a372d03c99251 Mon Sep 17 00:00:00 2001 +From c79d6e1f2d29446131d0dc5f4926caacde6534fe Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 8 Apr 2013 21:12:48 +0100 -Subject: [PATCH 19/82] Add NAK holdoff scheme. Enabled by default, disable +Subject: [PATCH 019/101] Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh --- @@ -91071,10 +91071,10 @@ index a9dea55..ebee73a 100644 1.8.5.1 -From 9e529937ec1d84d13198b50dcd1db463998bacfb Mon Sep 17 00:00:00 2001 +From e8b133b94c691d3d97b28de11bbd9c687a7b2533 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 20/82] Added hwmon/thermal driver for reporting core +Subject: [PATCH 020/101] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian --- @@ -91622,10 +91622,10 @@ index 0000000..3f9a733 1.8.5.1 -From 831ca760c5c8504098655f749d6223989e740d99 Mon Sep 17 00:00:00 2001 +From a148027d77a60ebdc99dfeb0e2996260708a06e9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 12:16:36 +0100 -Subject: [PATCH 21/82] Enable multiple ALSA channels +Subject: [PATCH 021/101] Enable multiple ALSA channels --- arch/arm/mach-bcm2708/bcm2708.c | 54 ++++++++++++++++++++++++++++++++++++----- @@ -91700,10 +91700,10 @@ index 8b6ff52..b4d94bf 100644 1.8.5.1 -From 4bae59871e446fdc27d01d7dd5fd1dc45bd9c6d8 Mon Sep 17 00:00:00 2001 +From f6fd495ae375b91675a54d1b657fde76a2f1298b Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Sun, 4 Nov 2012 15:55:01 +0000 -Subject: [PATCH 22/82] Make sure we wait for the reset to finish +Subject: [PATCH 022/101] Make sure we wait for the reset to finish --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 ++ @@ -91726,10 +91726,10 @@ index aff59df..1a23d4b 100644 1.8.5.1 -From 6e6b3f2067fa842c04d842289d95c0736b05ca1e Mon Sep 17 00:00:00 2001 +From bb3b6d02ea3bd8625c51aadec4b4c1bd0801fdb7 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 23/82] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 023/101] lirc: added support for RaspberryPi GPIO --- drivers/staging/media/lirc/Kconfig | 6 + @@ -92470,10 +92470,10 @@ index 0000000..c76f696 1.8.5.1 -From 3243d70b03fe5eaaf101d0c03d769fac2efd50e9 Mon Sep 17 00:00:00 2001 +From 07da2aaf38f9f0737c3dc9cd3d30a4cbf8fdaefc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 18:23:03 +0000 -Subject: [PATCH 24/82] Default to dwc_otp.lpm_enable=0 +Subject: [PATCH 024/101] Default to dwc_otp.lpm_enable=0 --- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +- @@ -92496,10 +92496,10 @@ index d58ebd7..c2bb596 100644 1.8.5.1 -From a5663244ff1f4c2ce2bbc9a0ca19d2b960b13a24 Mon Sep 17 00:00:00 2001 +From 1a34b1acd1d092cf1e13e5bac481ee419f976ea4 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 9 Jan 2013 16:12:04 +0000 -Subject: [PATCH 25/82] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent +Subject: [PATCH 025/101] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel memory corruption, escalating to OOPS under high USB load. --- @@ -92536,10 +92536,10 @@ index ebee73a..b3efaf4 100644 1.8.5.1 -From ebdddaf816e530c4d37d61abca0fd5074fee7a6a Mon Sep 17 00:00:00 2001 +From 96597171ccbe1c5e0e31d3bfa070acf3841e6ba7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 26/82] Add hwrng (hardware random number generator) driver +Subject: [PATCH 026/101] Add hwrng (hardware random number generator) driver --- arch/arm/mach-bcm2708/include/mach/platform.h | 1 + @@ -92720,10 +92720,10 @@ index 0000000..1ffa7d7 1.8.5.1 -From a321028653a7911528462855da3b2c53237e69aa Mon Sep 17 00:00:00 2001 +From eb9ad63adba4fc458d11b2b4e4a8c8ec210349f9 Mon Sep 17 00:00:00 2001 From: Technion Date: Mon, 11 Feb 2013 22:08:53 +1100 -Subject: [PATCH 27/82] Changed wording on logging. Previously, we received +Subject: [PATCH 027/101] 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. @@ -92758,10 +92758,10 @@ index bb14f63..b66bd4c 100644 1.8.5.1 -From c885a188b6b482e847d05f6190a72bec04fc7c48 Mon Sep 17 00:00:00 2001 +From 879e1263b2fa9659fc34b015074f2cd2461f68aa Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:36:47 +0000 -Subject: [PATCH 28/82] dwc_otg: Fix unsafe access of QTD during URB enqueue +Subject: [PATCH 028/101] 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 @@ -92848,10 +92848,10 @@ index b3efaf4..1554be5 100644 1.8.5.1 -From cb9044d0b5601a4082494d667ee4bc1936d70590 Mon Sep 17 00:00:00 2001 +From 80fd4a0817d1c866c1ae8b58024e7e3270009640 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:38:40 +0000 -Subject: [PATCH 29/82] dwc_otg: Fix incorrect URB allocation error handling +Subject: [PATCH 029/101] 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 @@ -92892,10 +92892,10 @@ index 35d03d1..6fe30e3 100644 1.8.5.1 -From afdc6482ea9a13fb20f8fb8a26cec57114bfadec Mon Sep 17 00:00:00 2001 +From b2cb5f27ddd3f3f6f79632d44a46faebccac609d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 24 Feb 2013 16:30:57 +0000 -Subject: [PATCH 30/82] Add retry on error and tidy of temperature driver +Subject: [PATCH 030/101] Add retry on error and tidy of temperature driver --- drivers/thermal/bcm2835-thermal.c | 78 ++++++++++++++------------------------- @@ -93022,11 +93022,11 @@ index 3f9a733..85fceb5 100644 1.8.5.1 -From e9859c3756174ece8b9acef95766df91954afd51 Mon Sep 17 00:00:00 2001 +From f4e72c23df1d1f3bdaeac3428db5b61a246b5a6d Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 28 Feb 2013 16:52:51 +0000 -Subject: [PATCH 31/82] dwc_otg: fix potential use-after-free case in interrupt - handler +Subject: [PATCH 031/101] dwc_otg: fix potential use-after-free case in + interrupt handler If a transaction had previously aborted, certain interrupts are enabled to track error counts and reset where necessary. On IN @@ -93057,11 +93057,11 @@ index 1a23d4b..7af455d 100644 1.8.5.1 -From fa00a06ee1178933982ecdfd12d15a6734ebc255 Mon Sep 17 00:00:00 2001 +From 900c920e23f2aee93580dd6ff7c9eecc4647f26e Mon Sep 17 00:00:00 2001 From: P33M Date: Sun, 3 Mar 2013 14:45:53 +0000 -Subject: [PATCH 32/82] dwc_otg: add handling of SPLIT transaction data toggle - errors +Subject: [PATCH 032/101] dwc_otg: add handling of SPLIT transaction data + toggle errors Previously a data toggle error on packets from a USB1.1 device behind a TT would result in the Pi locking up as the driver never handled @@ -93115,10 +93115,10 @@ index 7af455d..a27dacd 100644 1.8.5.1 -From 2980103d30e9b42215ae9966b39186896f684c69 Mon Sep 17 00:00:00 2001 +From b917febef9d7c85fa193417284e8f9449fabd56d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 21:14:28 +0100 -Subject: [PATCH 33/82] Add bitbanging pullups, use them for w1-gpio +Subject: [PATCH 033/101] Add bitbanging pullups, use them for w1-gpio Allows parasite power to work, uses module option pullup=1 --- @@ -93257,10 +93257,10 @@ index e10acc2..667fdd5 100644 1.8.5.1 -From f096911840fc80062884b2a760272f1ebdd39f31 Mon Sep 17 00:00:00 2001 +From 311c545291b356a22336b28bc1be8ed3dcb99b0b Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 21 Mar 2013 19:36:17 +0000 -Subject: [PATCH 34/82] dwc_otg: implement tasklet for returning URBs to +Subject: [PATCH 034/101] dwc_otg: implement tasklet for returning URBs to usbcore hcd layer The dwc_otg driver interrupt handler for transfer completion will spend @@ -93502,10 +93502,10 @@ index 2b4a14e..39787e3 100644 1.8.5.1 -From 555c92566f4dd563cc5611e57c32ecf056d76427 Mon Sep 17 00:00:00 2001 +From f9ce3c37fd9a888f0e0efe58d4fb248a3e9e08b8 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Apr 2013 00:08:36 +0100 -Subject: [PATCH 36/82] dwc_otg: fix NAK holdoff and allow on split +Subject: [PATCH 036/101] dwc_otg: fix NAK holdoff and allow on split transactions only This corrects a bug where if a single active non-periodic endpoint @@ -93575,10 +93575,10 @@ index 533b17d..73f7643 100644 1.8.5.1 -From 2efd920b61a61852b71a135e31fd1b41c73c1b46 Mon Sep 17 00:00:00 2001 +From 401b3ad19d5cad865496d64a2239f895ffee812d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 26 Apr 2013 10:08:31 -0700 -Subject: [PATCH 37/82] Merge pull request #286 from +Subject: [PATCH 037/101] Merge pull request #286 from martinezjavier/rpi-3.6.y-dev add mmap support and some cleanups to bcm2835 ALSA driver @@ -94059,10 +94059,10 @@ index 080bd5c..36afee3 100755 1.8.5.1 -From 0d14a35a19c326e2be2141beb2259cae3874eb3a Mon Sep 17 00:00:00 2001 +From fc7a99d3206c798fd29521fb1affc5df4147f1c7 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 38/82] Speed up console framebuffer imageblit function +Subject: [PATCH 038/101] 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 @@ -94274,10 +94274,10 @@ index a2bb276..436494f 100644 1.8.5.1 -From 1f0b8760d535cc0ec2a1c4afb64f5cf25025e079 Mon Sep 17 00:00:00 2001 +From 30505ca38f13a41c1778306ff1c429f1e8e80b7c Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 39/82] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 039/101] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -94373,10 +94373,10 @@ index fb795c3..fa72af0 100644 1.8.5.1 -From 3541f71c7a7650979ac5296be4c53b7f9a4c6e72 Mon Sep 17 00:00:00 2001 +From d12ff9cab9bb64cfad4dc081ab2f8d5e101391f5 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 16:00:25 +0300 -Subject: [PATCH 40/82] bcm2708_fb: DMA acceleration for fb_copyarea +Subject: [PATCH 040/101] 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 @@ -94838,11 +94838,11 @@ index 08d9238..5758146 100644 1.8.5.1 -From d07b2abd3cf34ac38fd1026b65d5ca27da49896e Mon Sep 17 00:00:00 2001 +From a001e87fa233c1e863c1c0d838520dddddc3f590 Mon Sep 17 00:00:00 2001 From: Mike Bradley Date: Mon, 17 Jun 2013 11:31:42 -0700 -Subject: [PATCH 41/82] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held - in completion handler +Subject: [PATCH 041/101] 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 asynchronously in the tasklet was not safe (regression in @@ -94928,10 +94928,10 @@ index 39787e3..5e6a26a 100644 1.8.5.1 -From c7f4a325df272add5d8ccda4d6d5b0e3019c381c Mon Sep 17 00:00:00 2001 +From 71e1d8bd68d55504473838eefe956e6fe5d25b8b Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Thu, 4 Apr 2013 11:05:21 +0100 -Subject: [PATCH 42/82] USB fix using a FIQ to implement split transactions +Subject: [PATCH 042/101] 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 @@ -96334,10 +96334,10 @@ index 1b1f83c..c8590b5 100644 1.8.5.1 -From 2be49b1627f409ccf460ab084073e9d622763ef3 Mon Sep 17 00:00:00 2001 +From 5edd3cdb36328b183e2c3b1bf33561b65d011bf8 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 11:39:46 +0100 -Subject: [PATCH 43/82] dwc_otg: fix device attributes and avoid kernel +Subject: [PATCH 043/101] dwc_otg: fix device attributes and avoid kernel warnings on boot --- @@ -96406,10 +96406,10 @@ index fab2961..af1cd4d 100644 1.8.5.1 -From 723116f4f0cf98864f488207035c4dc2b1620523 Mon Sep 17 00:00:00 2001 +From ffabf65b56a63527bb1fa5ce689486a28626aced Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 15 Jul 2013 23:55:52 +0100 -Subject: [PATCH 44/82] dcw_otg: avoid logging function that can cause panics +Subject: [PATCH 044/101] dcw_otg: avoid logging function that can cause panics See: https://github.com/raspberrypi/firmware/issues/21 Thanks to cleverca22 for fix @@ -96434,10 +96434,10 @@ index af1cd4d..9da0c92 100644 1.8.5.1 -From 01fa64f4d5550bf3374434fc1b9dab6cec07eb7e Mon Sep 17 00:00:00 2001 +From 4b299b3122756aec0f576ca590d478c8880dc231 Mon Sep 17 00:00:00 2001 From: P33M Date: Sat, 13 Jul 2013 20:41:26 +0100 -Subject: [PATCH 45/82] dwc_otg: mask correct interrupts after transaction +Subject: [PATCH 045/101] dwc_otg: mask correct interrupts after transaction error recovery The dwc_otg driver will unmask certain interrupts on a transaction @@ -96504,10 +96504,10 @@ index 8e5789f..fd73e41 100644 1.8.5.1 -From 4a21a502da05973ccc05361afb59896072667047 Mon Sep 17 00:00:00 2001 +From eb9ca8d11ee629310b164fbfe3fa04225822c7e8 Mon Sep 17 00:00:00 2001 From: P33M Date: Sat, 13 Jul 2013 21:48:41 +0100 -Subject: [PATCH 46/82] dwc_otg: fiq: prevent FIQ thrash and incorrect state +Subject: [PATCH 046/101] 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 @@ -96564,10 +96564,10 @@ index fd73e41..2ec0565 100644 1.8.5.1 -From 6fc4b6c7c315d0f423aef29b8ebe911bb0d371c9 Mon Sep 17 00:00:00 2001 +From 52848de36efe2e753467543410ac52c912fee304 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Mon, 8 Jul 2013 04:12:19 +0100 -Subject: [PATCH 47/82] Fix function tracing +Subject: [PATCH 047/101] Fix function tracing --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++++------ @@ -96632,10 +96632,10 @@ index 2ec0565..083b1c3 100644 1.8.5.1 -From 2cb0f507f192c30631e9bb2c9ddb4a065d1c6878 Mon Sep 17 00:00:00 2001 +From 52145d792e8109545cecefc004d5ac884029e64f Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 18 Jul 2013 16:32:41 +0100 -Subject: [PATCH 48/82] dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue +Subject: [PATCH 048/101] dwc_otg: whitespace cleanup in dwc_otg_urb_enqueue --- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 53 ++++++++++++++-------------- @@ -96722,10 +96722,10 @@ index d1c5c2b..315c803 100644 1.8.5.1 -From 3146df3884637516d10cf03cd565f0493a7c8e1c Mon Sep 17 00:00:00 2001 +From de52da135c036bce44fc5d31a8e6a357822ea49a Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 18 Jul 2013 17:07:26 +0100 -Subject: [PATCH 49/82] dwc_otg: prevent OOPSes during device disconnects +Subject: [PATCH 049/101] 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 @@ -96866,11 +96866,11 @@ index 7b92025..db95851 100644 1.8.5.1 -From 56da8bc4f88b2c1a7678ad329e91ace8c6d9cc42 Mon Sep 17 00:00:00 2001 +From ca514684576e516651a41c2b5496cce2dc61dc79 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Jul 2013 14:08:26 +0100 -Subject: [PATCH 50/82] dwc_otg: prevent BUG() in TT allocation if hub address - is > 16 +Subject: [PATCH 050/101] dwc_otg: prevent BUG() in TT allocation if hub + address is > 16 A fixed-size array is used to track TT allocation. This was previously set to 16 which caused a crash because @@ -96959,10 +96959,10 @@ index 083b1c3..c76910d 100644 1.8.5.1 -From e619b8c02c1dfe32d40c8a4b7ee1fc488652cd25 Mon Sep 17 00:00:00 2001 +From da6d374ffb134a541f198b72f0d7c79abee5de27 Mon Sep 17 00:00:00 2001 From: P33M Date: Tue, 23 Jul 2013 14:15:32 +0100 -Subject: [PATCH 51/82] dwc_otg: make channel halts with unknown state less +Subject: [PATCH 051/101] dwc_otg: make channel halts with unknown state less damaging If the IRQ received a channel halt interrupt through the FIQ @@ -97007,10 +97007,10 @@ index c76910d..5fd8613 100644 1.8.5.1 -From 2020fb8e72ec4d36a0420213bb604b78f14e661f Mon Sep 17 00:00:00 2001 +From d836be7a2b8a644245f816d1dc93236823f6b85f Mon Sep 17 00:00:00 2001 From: P33M Date: Tue, 30 Jul 2013 09:58:48 +0100 -Subject: [PATCH 52/82] dwc_otg: fiq_split: use TTs with more granularity +Subject: [PATCH 052/101] dwc_otg: fiq_split: use TTs with more granularity This fixes certain issues with split transaction scheduling. @@ -97130,10 +97130,10 @@ index 5fd8613..a959a49 100644 1.8.5.1 -From 018e6248fa586dbf5bef896ce338bf038f0d0d9f Mon Sep 17 00:00:00 2001 +From abd08090a214f8b434b02f262614324af9f714de Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 2 Aug 2013 10:04:18 +0100 -Subject: [PATCH 53/82] dwc_otg: fix potential sleep while atomic during urb +Subject: [PATCH 053/101] dwc_otg: fix potential sleep while atomic during urb enqueue Fixes a regression introduced with eb1b482a. Kmalloc called from @@ -97162,10 +97162,10 @@ index 87e517d..88c0544 100644 1.8.5.1 -From a697397929694a2d3c83f8d0e48d8b499da72c6f Mon Sep 17 00:00:00 2001 +From 77c5e2ba11f0282505d5cb26c68bc68fc55833c6 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 11:42:12 +0100 -Subject: [PATCH 54/82] dwc_otg: make fiq_split_enable imply fiq_fix_enable +Subject: [PATCH 054/101] 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. @@ -97194,10 +97194,10 @@ index 176dc14..f06c3d22 100644 1.8.5.1 -From f522db9a8d8f8e01d93a85c990381684b5be2153 Mon Sep 17 00:00:00 2001 +From 1d12008e0c6642db4a5d507eb8878dbb7d486bc4 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 11:47:12 +0100 -Subject: [PATCH 55/82] dwc_otg: prevent crashes on host port disconnects +Subject: [PATCH 055/101] 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. @@ -97355,10 +97355,10 @@ index 88c0544..ae4271a 100644 1.8.5.1 -From e5addf52a2c672e80f5c6dfe81f2e26c7b4794a6 Mon Sep 17 00:00:00 2001 +From 332ae971177794914c3e7c5e591836b924b5e8b9 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 5 Aug 2013 13:17:58 +0100 -Subject: [PATCH 56/82] dwc_otg: prevent leaking URBs during enqueue +Subject: [PATCH 056/101] 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. @@ -97394,10 +97394,10 @@ index ae4271a..ee8eec9 100644 1.8.5.1 -From 09a139bedb35d98819dba31ae32f1fd84ba1b9f8 Mon Sep 17 00:00:00 2001 +From c20c0063a90400ac4422341cf080917649f8078c Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 20 Sep 2013 16:08:27 +0100 -Subject: [PATCH 57/82] dwc_otg: Enable NAK holdoff for control split +Subject: [PATCH 057/101] dwc_otg: Enable NAK holdoff for control split transactions Certain low-speed devices take a very long time to complete a @@ -97430,11 +97430,11 @@ index 3a549a1..f8dc4be 100644 1.8.5.1 -From 2f53b3bd4134e484e384272bc2dcff0b1359695d Mon Sep 17 00:00:00 2001 +From 0f8fd6dc6706b2dba2bc04cc8522d9c6cb71ac66 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 20 Sep 2013 19:07:56 +0100 -Subject: [PATCH 58/82] dwc_otg: Fix for occasional lockup on boot when doing a - USB reset +Subject: [PATCH 058/101] dwc_otg: Fix for occasional lockup on boot when doing + a USB reset --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 4 ++-- @@ -97459,10 +97459,10 @@ index f8dc4be..64d33a5 100644 1.8.5.1 -From e529bb4a8c088eea24f914fb64837ec82097ce02 Mon Sep 17 00:00:00 2001 +From e0969f24f1900ddd1383c04f807e723bf8c52e8f Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 27 Sep 2013 14:42:24 +0100 -Subject: [PATCH 59/82] dwc_otg: Don't issue traffic to LS devices in FS mode +Subject: [PATCH 059/101] 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 @@ -97504,10 +97504,10 @@ index 1904f6a..22300f0 100644 1.8.5.1 -From 550664c07e2ccded7972e4e6de9d14571879d779 Mon Sep 17 00:00:00 2001 +From 930d19bf5e5affaf068b1747ac50a888e7a192f4 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 6 Nov 2013 13:25:20 +0400 -Subject: [PATCH 60/82] ARM: bcm2708: PL01X debug include was moved into +Subject: [PATCH 060/101] ARM: bcm2708: PL01X debug include was moved into arch/arm/include/debug/ --- @@ -97528,17 +97528,17 @@ index 2d0dc1c..b24304a 100644 1.8.5.1 -From 1dc4857bbf18f77716f17a2c1d429c0729fdbc29 Mon Sep 17 00:00:00 2001 +From 79c9a4e69fea3e820b5f8c9ff8faf516d89e4f89 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 20 Nov 2013 11:22:05 +0000 -Subject: [PATCH 62/82] sdhci: Only do one iteration of PIO reading loop +Subject: [PATCH 062/101] 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 576c526..46264b7 100644 +index 0b44ccf..51bb441 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -550,6 +550,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, u32 intstate) @@ -97553,10 +97553,10 @@ index 576c526..46264b7 100644 1.8.5.1 -From 3870392536b1cbf0fe29228bc412e48420626ec2 Mon Sep 17 00:00:00 2001 +From 37c7faaf757d4a934fdd0f8dc9807d41ce884313 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 2 Sep 2013 16:44:57 +0100 -Subject: [PATCH 63/82] vchiq: create_pagelist copes with vmalloc memory +Subject: [PATCH 063/101] vchiq: create_pagelist copes with vmalloc memory Signed-off-by: Daniel Stone --- @@ -97697,10 +97697,10 @@ index 2b5fa56..b3bdaa2 100644 1.8.5.1 -From ba4bc36b07386f0b4915f215ad643dd21b17a9be Mon Sep 17 00:00:00 2001 +From 48aa4a58d9e89cf0a7329227ef86591e72ed464c Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 30 Sep 2013 17:04:55 +0100 -Subject: [PATCH 64/82] vchiq: fix the shim message release +Subject: [PATCH 064/101] vchiq: fix the shim message release Signed-off-by: Daniel Stone --- @@ -97792,10 +97792,10 @@ index f752f8d..fe9bd80 100644 1.8.5.1 -From 57bb2f1b3d8daf6326d97142ed19fb39c4fbc915 Mon Sep 17 00:00:00 2001 +From 9f796c5d2061b4f9c6d5dceee3760ed3e8f3755b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 9 Nov 2013 22:37:21 +0000 -Subject: [PATCH 65/82] vchiq: export additional symbols +Subject: [PATCH 065/101] vchiq: export additional symbols Signed-off-by: Daniel Stone --- @@ -97826,10 +97826,10 @@ index fe9bd80..a0b069d 100644 1.8.5.1 -From a56bd14597a22db43a1a6b684b42e173e1c7d748 Mon Sep 17 00:00:00 2001 +From 6a041fa703308b4fe4b7881f318ea36a57130d19 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 66/82] bcm2835: add v4l2 camera device +Subject: [PATCH 066/101] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -103817,10 +103817,10 @@ index 0000000..9d1d11e 1.8.5.1 -From f4456764e795a65f0f81cef6faf7db8929fed307 Mon Sep 17 00:00:00 2001 +From 587dbb7b66267966e870f40e20bdedfa401dd7ce Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 10:58:01 +0000 -Subject: [PATCH 67/82] V4L2: Fix EV values. Add manual shutter speed control +Subject: [PATCH 067/101] 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 @@ -104013,10 +104013,10 @@ index c611b58..d8aace5 100644 1.8.5.1 -From 44a0f1007e1d0d90c54bc5221180adce4fc53624 Mon Sep 17 00:00:00 2001 +From cee3ee4f62d50154befa88656711859a60474f09 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:01:53 +0000 -Subject: [PATCH 68/82] V4L2: Correct JPEG Q-factor range +Subject: [PATCH 068/101] V4L2: Correct JPEG Q-factor range Should be 1-100, not 0-100 @@ -104054,10 +104054,10 @@ index 481d1f6..c2e4c64 100644 1.8.5.1 -From 733c5b6bcac19073ad9bc2c8bfdcdc6e2d29d2a1 Mon Sep 17 00:00:00 2001 +From 4a751887a26e4bbbb7275e627d2082d376ccbaf4 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:05:24 +0000 -Subject: [PATCH 69/82] V4L2: Fix issue of driver jamming if STREAMON failed. +Subject: [PATCH 069/101] 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 @@ -104093,10 +104093,10 @@ index 47fe45d..2743074 100644 1.8.5.1 -From 1f6a2ca0b969e2b79d2b3899e32e61ecf2c8d3f2 Mon Sep 17 00:00:00 2001 +From c2c61325e5ded34b45f14fb0e6e644b97bbb6a36 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 15:30:48 +0000 -Subject: [PATCH 70/82] V4L2: Fix ISO controls. +Subject: [PATCH 070/101] V4L2: Fix ISO controls. Driver was passing the index to the GPU, and not the desired ISO value. @@ -104149,10 +104149,10 @@ index c2e4c64..92863f7 100644 1.8.5.1 -From 35b70319a2b7ab5a8eb46a7dfdfefe708dcc3e50 Mon Sep 17 00:00:00 2001 +From 0b1c008b8c3d79ef55e85650ae34774aeb4f65fc Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 16:40:24 +0000 -Subject: [PATCH 71/82] V4L2: Add flicker avoidance controls +Subject: [PATCH 071/101] V4L2: Add flicker avoidance controls Add support for V4L2_CID_POWER_LINE_FREQUENCY to set flicker avoidance frequencies. @@ -104267,10 +104267,10 @@ index d8aace5..b3d2c39 100644 1.8.5.1 -From 001e371a7261ce639da491827a20dfaf377d145b Mon Sep 17 00:00:00 2001 +From 1ce9b03c2521eae261dd5c1dd6e31d1214b276a7 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Fri, 13 Dec 2013 15:54:13 +0000 -Subject: [PATCH 72/82] V4L2: Add support for frame rate control. +Subject: [PATCH 072/101] V4L2: Add support for frame rate control. Add support for frame rate (or time per frame as V4L2 inverts it) control via s_parm. @@ -104509,10 +104509,10 @@ index b3d2c39..0f2bd50 100644 1.8.5.1 -From c0c2f824b012b697f0adefb724404ef6f6646663 Mon Sep 17 00:00:00 2001 +From 05cd1dea69197da468008189fd154f460160f6d4 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 17:30:09 +0000 -Subject: [PATCH 73/82] V4L2: Improve G_FBUF handling so we pass conformance +Subject: [PATCH 073/101] V4L2: Improve G_FBUF handling so we pass conformance Return some sane numbers for get framebuffer so that we pass conformance. @@ -104552,10 +104552,10 @@ index 8c38d03..c8d8742 100644 1.8.5.1 -From 82814b4d572b7849afc8cc8cb77a4f9a9ca697ac Mon Sep 17 00:00:00 2001 +From d7884bd8712aab3cab6a91a05e564840926b712d Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 17:29:39 +0000 -Subject: [PATCH 74/82] V4L2: Fix information advertised through g_vidfmt +Subject: [PATCH 074/101] V4L2: Fix information advertised through g_vidfmt Width and height were being stored based on incorrect values. @@ -104595,10 +104595,10 @@ index c8d8742..4766a9c 100644 1.8.5.1 -From 204b43b7801977f77683d2e03243348136cd2179 Mon Sep 17 00:00:00 2001 +From 690f2de64f3ec69cecbfc745f8f0e2cb69e7ee6a Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:03:54 +0000 -Subject: [PATCH 75/82] V4L2: Add support for inline H264 headers +Subject: [PATCH 075/101] V4L2: Add support for inline H264 headers Add support for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER to control H264 inline headers. @@ -104903,10 +104903,10 @@ index 0f2bd50..b08a4b0 100644 1.8.5.1 -From 170ba8985f14ef64fe34b1b285d04cf04202a593 Mon Sep 17 00:00:00 2001 +From d5bc2b1c261c0bae7ccc79a16f1bb8ecf46df092 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 19 Dec 2013 17:33:02 +0000 -Subject: [PATCH 76/82] V4L2: Fix JPEG timestamp issue +Subject: [PATCH 076/101] 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 @@ -104944,10 +104944,10 @@ index 4766a9c..9fc90a2 100644 1.8.5.1 -From adf8591fe966866d93004ebc73fbedb5c1cfc9eb Mon Sep 17 00:00:00 2001 +From 68c4d942ae0436b072060e4f0b18b72ddfbf469b Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 9 Dec 2013 11:24:55 +0000 -Subject: [PATCH 77/82] V4L2: Fix issue when switching down JPEG resolution. +Subject: [PATCH 077/101] 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 @@ -105109,10 +105109,10 @@ index 9fc90a2..4780107 100644 1.8.5.1 -From 9db6e2ec602815858318ca18514527e2cebab5f8 Mon Sep 17 00:00:00 2001 +From 4ebd645f24a7acf5329dcbb3d07152cc33b9f8d0 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 2 Dec 2013 16:57:44 +0000 -Subject: [PATCH 78/82] config: Enable V4L / MMAL driver +Subject: [PATCH 078/101] config: Enable V4L / MMAL driver --- arch/arm/configs/bcmrpi_defconfig | 3 +++ @@ -105136,10 +105136,10 @@ index 31adf3c..c850de6 100644 1.8.5.1 -From 6b70e32aaa6fa066de613f8bfe0a02f4ba9c6b74 Mon Sep 17 00:00:00 2001 +From fcaa4bc4d0fe6a0e2fc29d5d6817b866324db753 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 9 Jan 2014 16:05:20 +0000 -Subject: [PATCH 79/82] gpio: support low and high level interrupts +Subject: [PATCH 079/101] gpio: support low and high level interrupts --- arch/arm/mach-bcm2708/bcm2708_gpio.c | 52 +++++++++++++++++++++++++----------- @@ -105257,11 +105257,11 @@ index d0339eb..bab8a49 100644 1.8.5.1 -From cd5e5d0738af9791794a69287a747a465aa81bfd Mon Sep 17 00:00:00 2001 +From db97b0606d0d38a3479da7c755d8eba975645200 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 80/82] config: Enable CONFIG_MEMCG, but leave it disabled (due - to memory cost). Enable with cgroup_enable=memory. +Subject: [PATCH 080/101] config: Enable CONFIG_MEMCG, but leave it disabled + (due to memory cost). Enable with cgroup_enable=memory. --- arch/arm/configs/bcmrpi_defconfig | 1 + @@ -105335,10 +105335,10 @@ index 7f1a356..71d74e3 100644 1.8.5.1 -From 0923f8669e44e7c8c3337177d560f0db304d2ab4 Mon Sep 17 00:00:00 2001 +From e3f75b8856b744b18ad2a884ffd96edac6e36790 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 27 Jan 2014 21:00:56 +0000 -Subject: [PATCH 81/82] config: enable RT2800USB_RT3573 and RT2800USB_RT55XX +Subject: [PATCH 081/101] config: enable RT2800USB_RT3573 and RT2800USB_RT55XX wifi drivers --- @@ -105363,10 +105363,11 @@ index 2d79fac..271679d 100644 1.8.5.1 -From bc287c8df1782dd4112079df72f2dd953cec7259 Mon Sep 17 00:00:00 2001 +From 9a222bd0451161f1abc6e91a64f002358efc24e6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 29 Jan 2014 21:37:00 +0000 -Subject: [PATCH 82/82] video: relax the dimensions check for rotated displays +Subject: [PATCH 082/101] video: relax the dimensions check for rotated + displays --- drivers/video/bcm2708_fb.c | 6 +++--- @@ -105399,3 +105400,4069 @@ index 5758146..935288d 100644 -- 1.8.5.1 + +From aa287e10e6301be19d9de6d7251f19c6de9160b0 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:22:53 +0100 +Subject: [PATCH 083/101] dmaengine: Add support for BCM2708 + +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 + +diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig +index c823daa..69e12b7 100644 +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -312,6 +312,12 @@ config TI_CPPI41 + The Communications Port Programming Interface (CPPI) 4.1 DMA engine + is currently used by the USB driver on AM335x platforms. + ++config DMA_BCM2708 ++ tristate "BCM2708 DMA engine support" ++ depends on MACH_BCM2708 ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ + config MMP_PDMA + bool "MMP PDMA support" + depends on (ARCH_MMP || ARCH_PXA) +diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile +index 0ce2da9..7045649 100644 +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -38,6 +38,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 c9937f97ae7d7c757f320291ce7a8dbef1277342 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:33:38 +0100 +Subject: [PATCH 084/101] 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 8b9e701..b52d4aa 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 00bc6486602130bb47f26d57ab5b1fbf573c808f Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:37:51 +0100 +Subject: [PATCH 085/101] 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 6d2f9a0..a4aac4c 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 5b64954c90aee6fd7012ec0ec8c7bac5bdc31bb7 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 14:59:51 +0100 +Subject: [PATCH 086/101] 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 98dcc079d071dd70a8723725bdabbf7bb78314d0 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:04:54 +0100 +Subject: [PATCH 087/101] 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 b4d94bf..d44d70e 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", + }; + ++#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); + ++#ifdef CONFIG_SND_BCM2708_SOC_I2S_MODULE ++ bcm_register_device(&bcm2708_i2s_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 ea5d0c8ae344c5a860ada84c13c0238472979f6f Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:19:08 +0100 +Subject: [PATCH 088/101] 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 + + 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 a264dc10d691b832ff54db77a245d7fd2300dc31 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:21:34 +0100 +Subject: [PATCH 089/101] 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 d44d70e..cfb1634 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 5e3c93dbd7756d5780ceece1fec7c7bcbbc5ae80 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 6 Dec 2013 18:55:53 +0100 +Subject: [PATCH 090/101] 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) + } + + 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, +-- +1.8.5.1 + + +From f213a76cae99c3a61fb070a3fe2f6416f8da3b44 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Mon, 2 Dec 2013 20:28:22 +0100 +Subject: [PATCH 091/101] BCM2708: Add I2S and DMA support to default config + +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(+) + +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 271679d..9f5bbe0 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 +@@ -920,6 +927,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_GENIRQ=m + CONFIG_STAGING=y +-- +1.8.5.1 + + +From 19ad7cb292bbe5b91c2d22203d061aa79f33e4b4 Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 6 Dec 2013 20:50:28 +0100 +Subject: [PATCH 092/101] 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 9f5bbe0..61395f4 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 cfb1634..0847c54 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 = { + }; + #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"); +-- +1.8.5.1 + + +From d2b3cf853104f6ec4c7c36848415e5cfb1b1f0ab Mon Sep 17 00:00:00 2001 +From: Peter Budd +Date: Thu, 2 Jan 2014 23:34:21 +0000 +Subject: [PATCH 093/101] Added support for Proto i2s DAC + +--- + arch/arm/mach-bcm2708/bcm2708.c | 19 ++++++ + sound/soc/bcm/rpi-proto.c | 130 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 149 insertions(+) + create mode 100644 sound/soc/bcm/rpi-proto.c + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index 0847c54..ee6364b 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -667,6 +667,19 @@ struct platform_device bcm2708_powerman_device = { + }; + #endif + ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO_MODULE ++static struct platform_device snd_rpi_proto_device = { ++ .name = "snd-rpi-proto", ++ .id = 0, ++ .num_resources = 0, ++}; ++static struct i2c_board_info __initdata snd_rpi_proto_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8731", 0x1a) ++ }, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -807,6 +820,12 @@ void __init bcm2708_init(void) + bcm_register_device(&snd_pcm1794a_codec_device); + #endif + ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO_MODULE ++ bcm_register_device(&snd_rpi_proto_device); ++ i2c_register_board_info(1, snd_rpi_proto_i2c_devices, ++ ARRAY_SIZE(snd_rpi_proto_i2c_devices)); ++#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/rpi-proto.c b/sound/soc/bcm/rpi-proto.c +new file mode 100644 +index 0000000..4dc8705 +--- /dev/null ++++ b/sound/soc/bcm/rpi-proto.c +@@ -0,0 +1,130 @@ ++/* ++ * ASoC driver for PROTO AudioCODEC (with a WM8731) ++ * connected to a Raspberry Pi ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8731.h" ++ ++static const unsigned int wm8731_rates_12288000[] = { ++ 8000, 32000, 48000, 96000, ++}; ++ ++static struct snd_pcm_hw_constraint_list wm8731_constraints_12288000 = { ++ .list = wm8731_rates_12288000, ++ .count = ARRAY_SIZE(wm8731_rates_12288000), ++}; ++ ++static int snd_rpi_proto_startup(struct snd_pcm_substream *substream) ++{ ++ /* Setup constraints, because there is a 12.288 MHz XTAL on the board */ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &wm8731_constraints_12288000); ++ return 0; ++} ++ ++static int snd_rpi_proto_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 *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ /* Set proto bclk */ ++ int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2); ++ if (ret < 0){ ++ dev_err(substream->pcm->dev, ++ "Failed to set BCLK ratio %d\n", ret); ++ return ret; ++ } ++ int sysclk = 12288000; /* This is fixed on this board */ ++ ++ /* Set proto sysclk */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, ++ sysclk, SND_SOC_CLOCK_IN); ++ if (ret < 0) { ++ dev_err(substream->pcm->dev, ++ "Failed to set WM8731 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_proto_ops = { ++ .startup = snd_rpi_proto_startup, ++ .hw_params = snd_rpi_proto_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_proto_dai[] = { ++{ ++ .name = "WM8731", ++ .stream_name = "WM8731 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8731-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8731.1-001a", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_proto_ops, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_proto = { ++ .name = "snd_rpi_proto", ++ .dai_link = snd_rpi_proto_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_proto_dai), ++}; ++ ++static int snd_rpi_proto_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_proto.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_proto); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_proto_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_proto); ++} ++ ++static struct platform_driver snd_rpi_proto_driver = { ++ .driver = { ++ .name = "snd-rpi-proto", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_proto_probe, ++ .remove = snd_rpi_proto_remove, ++}; ++ ++module_platform_driver(snd_rpi_proto_driver); ++ ++MODULE_AUTHOR("Florian Meier"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.1 + + +From 6b19389448f13a92ab308b6fa9ade92e3e6c82c3 Mon Sep 17 00:00:00 2001 +From: Peter Budd +Date: Fri, 3 Jan 2014 05:50:49 +0000 +Subject: [PATCH 094/101] Add support for additional ASoC i2s drivers + +--- + sound/soc/bcm/rpi-cs534x.c | 105 +++++++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/rpi-ess9018.c | 92 +++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/rpi-mbed.c | 103 ++++++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/rpi-pcm5102a.c | 93 ++++++++++++++++++++++++++++++++++++++ + sound/soc/bcm/rpi-proto.c | 3 +- + sound/soc/bcm/rpi-tda1541a.c | 92 +++++++++++++++++++++++++++++++++++++ + 6 files changed, 487 insertions(+), 1 deletion(-) + create mode 100644 sound/soc/bcm/rpi-cs534x.c + create mode 100644 sound/soc/bcm/rpi-ess9018.c + create mode 100644 sound/soc/bcm/rpi-mbed.c + create mode 100644 sound/soc/bcm/rpi-pcm5102a.c + create mode 100644 sound/soc/bcm/rpi-tda1541a.c + +diff --git a/sound/soc/bcm/rpi-cs534x.c b/sound/soc/bcm/rpi-cs534x.c +new file mode 100644 +index 0000000..d2a2ad2 +--- /dev/null ++++ b/sound/soc/bcm/rpi-cs534x.c +@@ -0,0 +1,105 @@ ++/* ++ * ASoC driver for CS5343/CS5344 ADC ++ * connected to a Raspberry Pi ++ * ++ * Author: Wojciech M. Zabolotny ++ * Based on rpi-ess9018.c by: 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_cs534x_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_cs534x_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_cs534x_ops = { ++ .hw_params = snd_rpi_cs534x_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_cs534x_dai[] = { ++{ ++ .name = "cs5343", ++ .stream_name = "cs5343 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "cs534x-hifi", ++ .platform_name = "bcm2708-pcm-audio.0", ++ .codec_name = "cs534x-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_cs534x_ops, ++ .init = snd_rpi_cs534x_init, ++}, ++{ ++ .name = "cs5344", ++ .stream_name = "cs5344 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "cs534x-hifi", ++ .platform_name = "bcm2708-pcm-audio.0", ++ .codec_name = "cs534x-codec", ++ .dai_fmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_cs534x_ops, ++ .init = snd_rpi_cs534x_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_cs534x = { ++ .name = "snd_rpi_cs534x", ++ .dai_link = snd_rpi_cs534x_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_cs534x_dai), ++}; ++ ++static int snd_rpi_cs534x_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_cs534x.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_cs534x); ++ if (ret) ++ { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_cs534x_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_cs534x); ++} ++ ++static struct platform_driver snd_rpi_cs534x_driver = { ++ .driver = { ++ .name = "snd-rpi-cs534x", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_cs534x_probe, ++ .remove = snd_rpi_cs534x_remove, ++}; ++ ++module_platform_driver(snd_rpi_cs534x_driver); ++ ++MODULE_AUTHOR("Wojciech M. Zabolotny"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to a cs534x"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/bcm/rpi-ess9018.c b/sound/soc/bcm/rpi-ess9018.c +new file mode 100644 +index 0000000..1d709f5 +--- /dev/null ++++ b/sound/soc/bcm/rpi-ess9018.c +@@ -0,0 +1,92 @@ ++/* ++ * ASoC driver for ESS9018 codec ++ * connected to a Raspberry Pi ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_ess9018_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_ess9018_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_ess9018_ops = { ++ .hw_params = snd_rpi_ess9018_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_ess9018_dai[] = { ++{ ++ .name = "ESS9018", ++ .stream_name = "ESS9018 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "ess9018-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "ess9018-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_ess9018_ops, ++ .init = snd_rpi_ess9018_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_ess9018 = { ++ .name = "snd_rpi_ess9018", ++ .dai_link = snd_rpi_ess9018_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_ess9018_dai), ++}; ++ ++static int snd_rpi_ess9018_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_ess9018.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_ess9018); ++ if (ret) ++ { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_ess9018_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_ess9018); ++} ++ ++static struct platform_driver snd_rpi_ess9018_driver = { ++ .driver = { ++ .name = "snd-rpi-ess9018", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_ess9018_probe, ++ .remove = snd_rpi_ess9018_remove, ++}; ++ ++module_platform_driver(snd_rpi_ess9018_driver); ++ ++MODULE_AUTHOR("Florian Meier"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to a ESS9018"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/bcm/rpi-mbed.c b/sound/soc/bcm/rpi-mbed.c +new file mode 100644 +index 0000000..a14f50c +--- /dev/null ++++ b/sound/soc/bcm/rpi-mbed.c +@@ -0,0 +1,103 @@ ++/* ++ * ASoC driver for mbed AudioCODEC (with a TLV320AIC23b) ++ * connected to a Raspberry Pi ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "../codecs/tlv320aic23.h" ++ ++static int snd_rpi_mbed_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_mbed_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 *codec_dai = rtd->codec_dai; ++ int sysclk; ++ ++ sysclk = 12000000; /* this is fixed on this board */ ++ ++ /* set tlv320aic23 sysclk */ ++ snd_soc_dai_set_sysclk(codec_dai, 0, sysclk, 0); ++ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_mbed_ops = { ++ .hw_params = snd_rpi_mbed_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_mbed_dai[] = { ++{ ++ .name = "TLV320AIC23", ++ .stream_name = "TLV320AIC23 HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tlv320aic23-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tlv320aic23-codec.1-001b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_mbed_ops, ++ .init = snd_rpi_mbed_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_mbed = { ++ .name = "snd_rpi_mbed", ++ .dai_link = snd_rpi_mbed_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_mbed_dai), ++}; ++ ++static int snd_rpi_mbed_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_mbed.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_mbed); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_mbed_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_mbed); ++} ++ ++static struct platform_driver snd_rpi_mbed_driver = { ++ .driver = { ++ .name = "snd-rpi-mbed", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_mbed_probe, ++ .remove = snd_rpi_mbed_remove, ++}; ++ ++module_platform_driver(snd_rpi_mbed_driver); ++ ++MODULE_AUTHOR("Florian Meier"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to mbed AudioCODEC"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/bcm/rpi-pcm5102a.c b/sound/soc/bcm/rpi-pcm5102a.c +new file mode 100644 +index 0000000..1006364 +--- /dev/null ++++ b/sound/soc/bcm/rpi-pcm5102a.c +@@ -0,0 +1,93 @@ ++/* ++ * ASoC driver for PCM5102A codec ++ * connected to a Raspberry Pi ++ * ++ * Author: Francesco Valla, ++ * Based on rpi-ess9018.c by: 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_pcm5102a_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_pcm5102a_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_pcm5102a_ops = { ++ .hw_params = snd_rpi_pcm5102a_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_pcm5102a_dai[] = { ++{ ++ .name = "PCM5102A", ++ .stream_name = "PCM5102A HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm5102a-hifi", ++ .platform_name = "bcm2708-pcm-audio.0", ++ .codec_name = "pcm5102a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_pcm5102a_ops, ++ .init = snd_rpi_pcm5102a_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_pcm5102a = { ++ .name = "snd_rpi_pcm5102a", ++ .dai_link = snd_rpi_pcm5102a_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_pcm5102a_dai), ++}; ++ ++static int snd_rpi_pcm5102a_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_pcm5102a.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_pcm5102a); ++ if (ret) ++ { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_pcm5102a_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_pcm5102a); ++} ++ ++static struct platform_driver snd_rpi_pcm5102a_driver = { ++ .driver = { ++ .name = "snd-rpi-pcm5102a", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_pcm5102a_probe, ++ .remove = snd_rpi_pcm5102a_remove, ++}; ++ ++module_platform_driver(snd_rpi_pcm5102a_driver); ++ ++MODULE_AUTHOR("Francesco Valla"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to a PCM5102A"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c +index 4dc8705..5752af2 100644 +--- a/sound/soc/bcm/rpi-proto.c ++++ b/sound/soc/bcm/rpi-proto.c +@@ -49,9 +49,10 @@ static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream, + int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2); + if (ret < 0){ + dev_err(substream->pcm->dev, +- "Failed to set BCLK ratio %d\n", ret); ++ "Failed to set WM8731 BCLK ratio %d\n", ret); + return ret; + } ++ + int sysclk = 12288000; /* This is fixed on this board */ + + /* Set proto sysclk */ +diff --git a/sound/soc/bcm/rpi-tda1541a.c b/sound/soc/bcm/rpi-tda1541a.c +new file mode 100644 +index 0000000..6115033 +--- /dev/null ++++ b/sound/soc/bcm/rpi-tda1541a.c +@@ -0,0 +1,92 @@ ++/* ++ * ASoC driver for TDA1541A codec ++ * connected to a Raspberry Pi ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++static int snd_rpi_tda1541a_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return 0; ++} ++ ++static int snd_rpi_tda1541a_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_tda1541a_ops = { ++ .hw_params = snd_rpi_tda1541a_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_tda1541a_dai[] = { ++{ ++ .name = "TDA1541A", ++ .stream_name = "TDA1541A HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tda1541a-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tda1541a-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_tda1541a_ops, ++ .init = snd_rpi_tda1541a_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_tda1541a = { ++ .name = "snd_rpi_tda1541a", ++ .dai_link = snd_rpi_tda1541a_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_tda1541a_dai), ++}; ++ ++static int snd_rpi_tda1541a_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_tda1541a.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_tda1541a); ++ if (ret) ++ { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_tda1541a_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_tda1541a); ++} ++ ++static struct platform_driver snd_rpi_tda1541a_driver = { ++ .driver = { ++ .name = "snd-rpi-tda1541a", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_tda1541a_probe, ++ .remove = snd_rpi_tda1541a_remove, ++}; ++ ++module_platform_driver(snd_rpi_tda1541a_driver); ++ ++MODULE_AUTHOR("Florian Meier"); ++MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to a TDA1541A"); ++MODULE_LICENSE("GPL"); +-- +1.8.5.1 + + +From 2080c5620820b812a8ab22522d21e1ad46afc4c9 Mon Sep 17 00:00:00 2001 +From: Peter Budd +Date: Fri, 3 Jan 2014 05:51:53 +0000 +Subject: [PATCH 095/101] Add support for additional ASoC i2s drivers + +--- + arch/arm/mach-bcm2708/bcm2708.c | 135 ++++++++++++++++++++++++++++++++++------ + sound/soc/bcm/Kconfig | 55 +++++++++++++++- + sound/soc/bcm/Makefile | 10 +++ + 3 files changed, 181 insertions(+), 19 deletions(-) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index ee6364b..dfc2a8c 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -641,29 +641,59 @@ struct platform_device bcm2708_powerman_device = { + + #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, ++ .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, ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, + }; + #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, ++ .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, ++ .name = "pcm1794a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_MBED_MODULE ++static struct platform_device snd_rpi_mbed_device = { ++ .name = "snd-rpi-mbed", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++ ++static struct i2c_board_info __initdata snd_rpi_mbed_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("tlv320aic23", 0x1b) ++ }, ++}; ++#endif ++ ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_TDA1541A_MODULE ++static struct platform_device snd_rpi_tda1541a_device = { ++ .name = "snd-rpi-tda1541a", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_rpi_tda1541a_codec_device = { ++ .name = "tda1541a-codec", ++ .id = -1, ++ .num_resources = 0, + }; + #endif + +@@ -673,6 +703,7 @@ struct platform_device bcm2708_powerman_device = { + .id = 0, + .num_resources = 0, + }; ++ + static struct i2c_board_info __initdata snd_rpi_proto_i2c_devices[] = { + { + I2C_BOARD_INFO("wm8731", 0x1a) +@@ -680,6 +711,49 @@ struct platform_device bcm2708_powerman_device = { + }; + #endif + ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_CS534X_MODULE ++static struct platform_device snd_rpi_cs534x_device = { ++ .name = "snd-rpi-cs534x", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_rpi_cs534x_codec_device = { ++ .name = "cs534x-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++ ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_ESS9018_MODULE ++static struct platform_device snd_rpi_ess9018_device = { ++ .name = "snd-rpi-ess9018", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_rpi_ess9018_codec_device = { ++ .name = "ess9018-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PCM5102A_MODULE ++static struct platform_device snd_rpi_pcm5102a_device = { ++ .name = "snd-rpi-pcm5102a", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct platform_device snd_rpi_pcm5102a_codec_device = { ++ .name = "pcm5102a-codec", ++ .id = -1, ++ .num_resources = 0, ++}; ++#endif ++ + int __init bcm_register_device(struct platform_device *pdev) + { + int ret; +@@ -811,19 +885,44 @@ void __init bcm2708_init(void) + #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); ++ bcm_register_device(&snd_hifiberry_dac_device); ++ 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); ++ bcm_register_device(&snd_rpi_dac_device); ++ bcm_register_device(&snd_pcm1794a_codec_device); ++#endif ++ ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_MBED_MODULE ++ bcm_register_device(&snd_rpi_mbed_device); ++ i2c_register_board_info(1, snd_rpi_mbed_i2c_devices, ARRAY_SIZE(snd_rpi_mbed_i2c_devices)); ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_CS534X_MODULE ++ bcm_register_device(&snd_rpi_cs534x_device); ++ bcm_register_device(&snd_rpi_cs534x_codec_device); ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_TDA1541A_MODULE ++ bcm_register_device(&snd_rpi_tda1541a_device); ++ bcm_register_device(&snd_rpi_tda1541a_codec_device); + #endif + + #ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO_MODULE + bcm_register_device(&snd_rpi_proto_device); +- i2c_register_board_info(1, snd_rpi_proto_i2c_devices, +- ARRAY_SIZE(snd_rpi_proto_i2c_devices)); ++ i2c_register_board_info(1, snd_rpi_proto_i2c_devices, ARRAY_SIZE(snd_rpi_proto_i2c_devices)); ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_ESS9018_MODULE ++ bcm_register_device(&snd_rpi_ess9018_device); ++ bcm_register_device(&snd_rpi_ess9018_codec_device); ++#endif ++ ++#ifdef CONFIG_SND_BCM2708_SOC_RPI_CODEC_PCM5102A_MODULE ++ bcm_register_device(&snd_rpi_pcm5102a_device); ++ bcm_register_device(&snd_rpi_pcm5102a_codec_device); + #endif + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 1c1f5cf..60fe399 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -21,4 +21,57 @@ config SND_BCM2708_SOC_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 ++ Say Y or M if you want to add support for RPi-DAC. ++ ++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. ++ ++config SND_BCM2708_SOC_HIFIBERRY_MINI ++ tristate "Support for HifiBerry Mini" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_PCM5102A ++ help ++ Say Y or M if you want to add support for HifiBerry Mini. ++ ++config SND_BCM2708_SOC_RPI_CODEC_MBED ++ tristate "Support for AudioCODEC for mbed (TLV320AIC32B)" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_TLV320AIC3X ++ help ++ Say Y if you want to add support for AudioCODEC for mbed (TLV320AIC32B) ++ ++config SND_BCM2708_SOC_RPI_CODEC_TDA1541A ++ tristate "Support for TDA1541A" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_TDA1541A ++ help ++ Say Y if you want to add support for TDA1541A ++ ++config SND_BCM2708_SOC_RPI_CODEC_PROTO ++ tristate "Support for Audio Codec Board - PROTO (WM8731)" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_WM8731 ++ help ++ Say Y if you want to add support for Audio Codec Board - PROTO (WM8731) ++ ++config SND_BCM2708_SOC_RPI_CODEC_ESS9018 ++ tristate "Support for ESS9018" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_ESS9018 ++ help ++ Say Y if you want to add support for ESS9018 ++ ++config SND_BCM2708_SOC_RPI_CODEC_PCM5102A ++ tristate "Support for PCM5102A" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_PCM5102A ++ help ++ Say Y if you want to add support for PCM5102A +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 95a9d44..eb869fa 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -6,6 +6,16 @@ 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 ++snd-soc-rpi-mbed-objs := rpi-mbed.o ++snd-soc-rpi-tda1541a-objs := rpi-tda1541a.o ++snd-soc-rpi-proto-objs := rpi-proto.o ++snd-soc-rpi-ess9018-objs := rpi-ess9018.o ++snd-soc-rpi-pcm5102a-objs := rpi-pcm5102a.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 ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_MBED) += snd-soc-rpi-mbed.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_TDA1541A) += snd-soc-rpi-tda1541a.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_PROTO) += snd-soc-rpi-proto.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_ESS9018) += snd-soc-rpi-ess9018.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_PCM5102A) += snd-soc-rpi-pcm5102a.o +-- +1.8.5.1 + + +From 07b59f3fec2296012e0607e5eb11467b7ba92158 Mon Sep 17 00:00:00 2001 +From: Peter Budd +Date: Sat, 4 Jan 2014 18:27:33 +0000 +Subject: [PATCH 096/101] Remove compile warning + +--- + sound/soc/bcm/rpi-proto.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c +index 5752af2..c1532d4 100644 +--- a/sound/soc/bcm/rpi-proto.c ++++ b/sound/soc/bcm/rpi-proto.c +@@ -44,6 +44,7 @@ static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream, + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ int sysclk = 12288000; /* This is fixed on this board */ + + /* Set proto bclk */ + int ret = snd_soc_dai_set_bclk_ratio(cpu_dai,32*2); +@@ -53,8 +54,6 @@ static int snd_rpi_proto_hw_params(struct snd_pcm_substream *substream, + return ret; + } + +- int sysclk = 12288000; /* This is fixed on this board */ +- + /* Set proto sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, + sysclk, SND_SOC_CLOCK_IN); +-- +1.8.5.1 + + +From 270dbebf42de7227a06de55c62631d65021b5d97 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:41:23 +0100 +Subject: [PATCH 097/101] ASoC: wm8804: Implement MCLK configuration options, + add 32bit support WM8804 can run with PLL frequencies of 256xfs and 128xfs + for most sample rates. At 192kHz only 128xfs is supported. The existing + driver selects 128xfs automatically for some lower samples rates. By using an + additional mclk_div divider, it is now possible to control the behaviour. + This allows using 256xfs PLL frequency on all sample rates up to 96kHz. It + should allow lower jitter and better signal quality. The behavior has to be + controlled by the sound card driver, because some sample frequency share the + same setting. e.g. 192kHz and 96kHz use 24.576MHz master clock. The only + difference is the MCLK divider. + +This also added support for 32bit data. + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 19 +++++++++++++++---- + sound/soc/codecs/wm8804.h | 4 ++++ + 2 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 1704b1e..7ec8381 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -63,6 +63,7 @@ struct wm8804_priv { + struct regmap *regmap; + struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES]; + struct notifier_block disable_nb[WM8804_NUM_SUPPLIES]; ++ int mclk_div; + }; + + static int txsrc_get(struct snd_kcontrol *kcontrol, +@@ -277,6 +278,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, + blen = 0x1; + break; + case SNDRV_PCM_FORMAT_S24_LE: ++ case SNDRV_PCM_FORMAT_S32_LE: + blen = 0x2; + break; + default: +@@ -318,7 +320,7 @@ struct pll_div { + + #define FIXED_PLL_SIZE ((1ULL << 22) * 10) + static int pll_factors(struct pll_div *pll_div, unsigned int target, +- unsigned int source) ++ unsigned int source, unsigned int mclk_div) + { + u64 Kpart; + unsigned long int K, Ndiv, Nmod, tmp; +@@ -330,7 +332,8 @@ static int pll_factors(struct pll_div *pll_div, unsigned int target, + */ + for (i = 0; i < ARRAY_SIZE(post_table); i++) { + tmp = target * post_table[i].div; +- if (tmp >= 90000000 && tmp <= 100000000) { ++ if ((tmp >= 90000000 && tmp <= 100000000) && ++ (mclk_div == post_table[i].mclkdiv)) { + pll_div->freqmode = post_table[i].freqmode; + pll_div->mclkdiv = post_table[i].mclkdiv; + target *= post_table[i].div; +@@ -387,8 +390,11 @@ static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id, + } else { + int ret; + struct pll_div pll_div; ++ struct wm8804_priv *wm8804; + +- ret = pll_factors(&pll_div, freq_out, freq_in); ++ wm8804 = snd_soc_codec_get_drvdata(codec); ++ ++ ret = pll_factors(&pll_div, freq_out, freq_in, wm8804->mclk_div); + if (ret) + return ret; + +@@ -452,6 +458,7 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai, + int div_id, int div) + { + struct snd_soc_codec *codec; ++ struct wm8804_priv *wm8804; + + codec = dai->codec; + switch (div_id) { +@@ -459,6 +466,10 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai, + snd_soc_update_bits(codec, WM8804_PLL5, 0x30, + (div & 0x3) << 4); + break; ++ case WM8804_MCLK_DIV: ++ wm8804 = snd_soc_codec_get_drvdata(codec); ++ wm8804->mclk_div = div; ++ break; + default: + dev_err(dai->dev, "Unknown clock divider: %d\n", div_id); + return -EINVAL; +@@ -641,7 +652,7 @@ static int wm8804_probe(struct snd_soc_codec *codec) + }; + + #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ +- SNDRV_PCM_FMTBIT_S24_LE) ++ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + + #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \ +diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h +index 8ec14f5..e72d4f4 100644 +--- a/sound/soc/codecs/wm8804.h ++++ b/sound/soc/codecs/wm8804.h +@@ -57,5 +57,9 @@ + #define WM8804_CLKOUT_SRC_OSCCLK 4 + + #define WM8804_CLKOUT_DIV 1 ++#define WM8804_MCLK_DIV 2 ++ ++#define WM8804_MCLKDIV_256FS 0 ++#define WM8804_MCLKDIV_128FS 1 + + #endif /* _WM8804_H */ +-- +1.8.5.1 + + +From e3f9f71cd3fdad3bf5ca7ebc8be91c61ff2a1e47 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:42:08 +0100 +Subject: [PATCH 098/101] ASoC: BCM:Add support for HiFiBerry Digi. Driver is + based on the patched WM8804 driver. + +Signed-off-by: Daniel Matuschek +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_digi.c | 153 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 162 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_digi.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 60fe399..fa82682 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -16,6 +16,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DAC + help + Say Y or M if you want to add support for HifiBerry DAC. + ++config SND_BCM2708_SOC_HIFIBERRY_DIGI ++ tristate "Support for HifiBerry Digi" ++ depends on SND_BCM2708_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index eb869fa..b9845a5 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,6 +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-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-mbed-objs := rpi-mbed.o + snd-soc-rpi-tda1541a-objs := rpi-tda1541a.o +@@ -13,6 +14,7 @@ snd-soc-rpi-ess9018-objs := rpi-ess9018.o + snd-soc-rpi-pcm5102a-objs := rpi-pcm5102a.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_MBED) += snd-soc-rpi-mbed.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_CODEC_TDA1541A) += snd-soc-rpi-tda1541a.o +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +new file mode 100644 +index 0000000..e4f769d +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -0,0 +1,153 @@ ++/* ++ * ASoC Driver for HifiBerry Digi ++ * ++ * Author: Daniel Matuschek ++ * based on the HifiBerry DAC driver by 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 ++ ++#include "../codecs/wm8804.h" ++ ++static int samplerate=44100; ++ ++static int snd_rpi_hifiberry_digi_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_digi_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 *codec_dai = rtd->codec_dai; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ int sysclk = 27000000; /* This is fixed on this board */ ++ ++ long mclk_freq=0; ++ int mclk_div=1; ++ ++ int ret; ++ ++ samplerate = params_rate(params); ++ ++ switch (samplerate) { ++ case 44100: ++ case 48000: ++ case 88200: ++ case 96000: ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ break; ++ case 176400: ++ case 192000: ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ break; ++ default: ++ dev_err(substream->pcm->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate\n"); ++ } ++ ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(substream->pcm->dev, ++ "Failed to set WM8804 SYSCLK: %d\n", ret); ++ return ret; ++ } ++ ++ /* Enable TX output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x0); ++ ++ /* Power on */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai,64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_digi_ops = { ++ .hw_params = snd_rpi_hifiberry_digi_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_digi_dai[] = { ++{ ++ .name = "HifiBerry Digi", ++ .stream_name = "HifiBerry Digi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "wm8804-spdif", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_rpi_hifiberry_digi_ops, ++ .init = snd_rpi_hifiberry_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_digi = { ++ .name = "snd_rpi_hifiberry_digi", ++ .dai_link = snd_rpi_hifiberry_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_digi_dai), ++}; ++ ++static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_digi.dev = &pdev->dev; ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_digi); ++} ++ ++static struct platform_driver snd_rpi_hifiberry_digi_driver = { ++ .driver = { ++ .name = "snd-hifiberry-digi", ++ .owner = THIS_MODULE, ++ }, ++ .probe = snd_rpi_hifiberry_digi_probe, ++ .remove = snd_rpi_hifiberry_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); ++MODULE_LICENSE("GPL v2"); +-- +1.8.5.1 + + +From a770b046477b30ec3c637151da9b97d1d33281ba Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:26:08 +0100 +Subject: [PATCH 099/101] BCM2708: Added support for HiFiBerry Digi board Board + initalization by I2C + +Signed-off-by: Daniel Matuschek +--- + arch/arm/mach-bcm2708/bcm2708.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +index dfc2a8c..1cba3d7 100644 +--- a/arch/arm/mach-bcm2708/bcm2708.c ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -653,6 +653,21 @@ struct platform_device bcm2708_powerman_device = { + }; + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++static struct platform_device snd_hifiberry_digi_device = { ++ .name = "snd-hifiberry-digi", ++ .id = 0, ++ .num_resources = 0, ++}; ++ ++static struct i2c_board_info __initdata snd_wm8804_i2c_devices[] = { ++ { ++ I2C_BOARD_INFO("wm8804", 0x3b) ++ }, ++}; ++ ++#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", +@@ -889,6 +904,11 @@ void __init bcm2708_init(void) + bcm_register_device(&snd_pcm5102a_codec_device); + #endif + ++#if defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) || defined(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI_MODULE) ++ bcm_register_device(&snd_hifiberry_digi_device); ++ i2c_register_board_info(1, snd_wm8804_i2c_devices, ARRAY_SIZE(snd_wm8804_i2c_devices)); ++#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); +-- +1.8.5.1 + + +From f65f9910b310c9b4bec96c2008942cf78b7860c6 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:27:28 +0100 +Subject: [PATCH 100/101] BCM2708: Added HiFiBerry Digi configuration option It + will be compiled as a module by default. This also includes the WM8804 + driver. + +Signed-off-by: Daniel Matuschek +--- + arch/arm/configs/bcmrpi_defconfig | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 61395f4..7b14c76 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -736,8 +736,10 @@ CONFIG_SND_USB_6FIRE=m + CONFIG_SND_SOC=m + CONFIG_SND_SOC_DMAENGINE_PCM=y + CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y ++CONFIG_SND_SOC_WM8804=m + CONFIG_SND_BCM2708_SOC_I2S=m + CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m ++CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m + CONFIG_SND_BCM2708_SOC_RPI_DAC=m + CONFIG_SND_SOC_I2C_AND_SPI=m + CONFIG_SND_SOC_PCM5102A=m +-- +1.8.5.1 + + +From 0bb9f12eb03b5d355f564d3f050c84de27b1ab38 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Thu, 16 Jan 2014 07:36:35 +0100 +Subject: [PATCH 101/101] ASoC: wm8804: Set idle_bias_off to false Idle bias + has been change to remove warning on driver startup + +Signed-off-by: Daniel Matuschek +--- + sound/soc/codecs/wm8804.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 7ec8381..50d0f0c 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -685,7 +685,7 @@ static int wm8804_probe(struct snd_soc_codec *codec) + .suspend = wm8804_suspend, + .resume = wm8804_resume, + .set_bias_level = wm8804_set_bias_level, +- .idle_bias_off = true, ++ .idle_bias_off = false, + + .controls = wm8804_snd_controls, + .num_controls = ARRAY_SIZE(wm8804_snd_controls), +-- +1.8.5.1 +