diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index f14e5021b5..1320cee050 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support.patch @@ -1,7 +1,7 @@ -From d7464704285e698d9fbe1d7fdd1aa8f0b0eb7421 Mon Sep 17 00:00:00 2001 +From 8e8a77fa775396b9d07c4c1706bafd847ac85015 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 27 Apr 2016 17:43:28 +0100 -Subject: [PATCH 001/141] Revert "SUNRPC: Make NFS swap work with multipath" +Subject: [PATCH 001/111] Revert "SUNRPC: Make NFS swap work with multipath" This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. --- @@ -9,10 +9,10 @@ This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 7e0c9bf22df811475385496007cfac321e0422a5..06936855313fe14abac8af7929a7a35381886e9e 100644 +index 2808d550d2730ff8e36b6d8c072c65e1631064c4..b362c2f099941c1f3388507983ffbdd1b4cc1241 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c -@@ -2683,39 +2683,57 @@ void rpc_show_tasks(struct net *net) +@@ -2719,39 +2719,57 @@ void rpc_show_tasks(struct net *net) #endif #if IS_ENABLED(CONFIG_SUNRPC_SWAP) @@ -95,10 +95,10 @@ index 7e0c9bf22df811475385496007cfac321e0422a5..06936855313fe14abac8af7929a7a353 EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate); #endif /* CONFIG_SUNRPC_SWAP */ -From 6ef501bd1aea48c18efb9bb7675c483c21c37656 Mon Sep 17 00:00:00 2001 +From d826431779f00b7a0b267c720155e3fb70c9cd57 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 002/141] smsx95xx: fix crimes against truesize +Subject: [PATCH 002/111] smsx95xx: fix crimes against truesize smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings. @@ -110,10 +110,10 @@ Signed-off-by: Steve Glendinning 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b233d7a0081 100644 +index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62cb78cc1bb 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -75,6 +75,10 @@ static bool turbo_mode = true; +@@ -80,6 +80,10 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -124,7 +124,7 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1795,7 +1799,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1848,7 +1852,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -134,7 +134,7 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 return 1; } -@@ -1813,7 +1818,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1866,7 +1871,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ @@ -145,21 +145,21 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 usbnet_skb_return(dev, ax_skb); } -From 212ebeab1e1561b2b7964f04b55f0ca29fe925ea Mon Sep 17 00:00:00 2001 +From 46327b51faeab20854b57bc999cbdca10e5e1e56 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 003/141] smsc95xx: Disable turbo mode by default +Subject: [PATCH 003/111] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 2ce8d2b7d35b6784b7d4faf85e765b233d7a0081..35ebf75d9949d945b7833ac8cb3c19083045fbd9 100644 +index 116680e3089f16e1e3e9113a3b93e62cb78cc1bb..aa4cb43dcd9ba83b042332bc15a4dce68affce28 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -71,7 +71,7 @@ struct smsc95xx_priv { - u8 suspend_flags; +@@ -76,7 +76,7 @@ struct smsc95xx_priv { + struct usbnet *dev; }; -static bool turbo_mode = true; @@ -168,10 +168,10 @@ index 2ce8d2b7d35b6784b7d4faf85e765b233d7a0081..35ebf75d9949d945b7833ac8cb3c1908 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From 580f083e3acc4172479b101a89e77e2ce2da4f58 Mon Sep 17 00:00:00 2001 +From acd55c74830d7bdaa13469b8363c6a607e1fc346 Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 004/141] add smsc95xx packetsize module_param +Subject: [PATCH 004/111] add smsc95xx packetsize module_param Signed-off-by: Sam Nazarko --- @@ -179,10 +179,10 @@ Signed-off-by: Sam Nazarko 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875769f7798 100644 +index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d73681396b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -79,6 +79,10 @@ static bool truesize_mode = false; +@@ -84,6 +84,10 @@ static bool truesize_mode = false; module_param(truesize_mode, bool, 0644); MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); @@ -193,7 +193,7 @@ index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -960,13 +964,13 @@ static int smsc95xx_reset(struct usbnet *dev) +@@ -1005,13 +1009,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; @@ -213,10 +213,10 @@ index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 7dbc066e994a37e8eb495bf1e9aa857c2f1984e5 Mon Sep 17 00:00:00 2001 +From bd24d215fb9ec317bf643f453a3965560baf4ace Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 005/141] Allow mac address to be set in smsc95xx +Subject: [PATCH 005/111] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -224,7 +224,7 @@ Signed-off-by: popcornmix 1 file changed, 56 insertions(+) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c98fa635e6 100644 +index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9f72bebe3 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -60,6 +60,7 @@ @@ -233,9 +233,9 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) +#define MAC_ADDR_LEN (6) - struct smsc95xx_priv { - u32 mac_cr; -@@ -83,6 +84,10 @@ static int packetsize = 0; + #define CARRIER_CHECK_DELAY (2 * HZ) + +@@ -88,6 +89,10 @@ static int packetsize = 0; module_param(packetsize, int, 0644); MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); @@ -246,7 +246,7 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -772,6 +777,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +@@ -817,6 +822,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } @@ -300,7 +300,7 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 static void smsc95xx_init_mac_address(struct usbnet *dev) { const u8 *mac_addr; -@@ -793,6 +845,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -838,6 +890,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } @@ -312,71 +312,10 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From fe915d32402785e873d7eaed4d96a76016febefe Mon Sep 17 00:00:00 2001 -From: Nicolas Boullis -Date: Sun, 10 Apr 2016 13:23:05 +0200 -Subject: [PATCH 006/141] rtc: ds1307: ensure that any pending alarm is cleared - before a new alarm is enabled -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If a previously-set alarm was disabled and then triggered, it may still -be pending when a new alarm is configured. - -Then, if the alarm is enabled before the pending alarm is cleared, then -an interrupt is immediately raised. - -Unfortunately, when the alarm is cleared and enabled during the same I²C -block write, the chip (at least the DS1339 I have) considers that the -alarm is enabled before it is cleared, and raises an interrupt. - -This patch ensures that the pending alarm is cleared before the alarm is -enabled. - -Signed-off-by: Nicolas Boullis -Signed-off-by: Alexandre Belloni ---- - drivers/rtc/rtc-ds1307.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index ecb7dbae9be9daa0ee96ede34a446a78e8e7debd..e94eb0952286300ec9847cddaf317476ddd05423 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -538,12 +538,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) - buf[5] = 0; - buf[6] = 0; - -- /* optionally enable ALARM1 */ -+ /* disable alarms */ - buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); -- if (t->enabled) { -- dev_dbg(dev, "alarm IRQ armed\n"); -- buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ -- } - buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); - - ret = ds1307->write_block_data(client, -@@ -553,6 +549,13 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) - return ret; - } - -+ /* optionally enable ALARM1 */ -+ if (t->enabled) { -+ dev_dbg(dev, "alarm IRQ armed\n"); -+ buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ -+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, buf[7]); -+ } -+ - return 0; - } - - -From 055f1b1bb388444df7b833fbfee65f916a7c563d Mon Sep 17 00:00:00 2001 +From e92d422ece30aa23fb14842d9debb6c2358002fc Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 9 Mar 2016 13:28:24 +0000 -Subject: [PATCH 007/141] serial: Take care starting a hung-up tty's port +Subject: [PATCH 006/111] serial: Take care starting a hung-up tty's port tty_port_hangup sets a port's tty field to NULL (holding the port lock), but uart_tx_stopped, called from __uart_start (with the port lock), @@ -391,10 +330,10 @@ Signed-off-by: Phil Elwell 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h -index cbfcf38e220def6070e3de57c56ce34f3536bd6c..96bc15aa5c2190287590dc32949d873289858e97 100644 +index a3d7c0d4a03e75016023184a5fea18c91d9d8dbc..d61b4167a03205f917448d0bd71a84d0e1891047 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h -@@ -403,7 +403,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); +@@ -406,7 +406,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); static inline int uart_tx_stopped(struct uart_port *port) { struct tty_struct *tty = port->state->port.tty; @@ -404,10 +343,10 @@ index cbfcf38e220def6070e3de57c56ce34f3536bd6c..96bc15aa5c2190287590dc32949d8732 return 0; } -From 03a2cc0edac61207b37b2bd89da0f3d60216aaf8 Mon Sep 17 00:00:00 2001 +From f3a47d492c05724f55956258fc0111a5917659b5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 008/141] vmstat: Workaround for issue where dirty page count +Subject: [PATCH 007/111] vmstat: Workaround for issue where dirty page count goes negative See: @@ -418,10 +357,10 @@ http://www.spinics.net/lists/linux-mm/msg72236.html 1 file changed, 4 insertions(+) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h -index 73fae8c4a5fb50d94b72f12bed28f98d170f5787..5dd127883ad1dee89dd72be4cccb2ffb069d3521 100644 +index d2da8e053210041bfcefb9e04b59d195880d2d0e..e3258dc35371ee6e528dc02ffc705570c2f555be 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h -@@ -220,7 +220,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) +@@ -222,7 +222,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) { atomic_long_dec(&zone->vm_stat[item]); @@ -434,10 +373,10 @@ index 73fae8c4a5fb50d94b72f12bed28f98d170f5787..5dd127883ad1dee89dd72be4cccb2ffb static inline void __inc_zone_page_state(struct page *page, -From 5c942d7f05053aa268bbdb55eae8a5ee6a5e99be Mon Sep 17 00:00:00 2001 +From e0a17406d94df8d5c79751f5e133120a7a59511f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 009/141] Protect __release_resource against resources without +Subject: [PATCH 008/111] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -465,10 +404,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From 5e8c5f982238dd72d4644df61f4f2140979e1fb4 Mon Sep 17 00:00:00 2001 +From f0cb6129d9a6fcb4bbc8ffddb25061635dda863d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 010/141] mm: Remove the PFN busy warning +Subject: [PATCH 009/111] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -480,10 +419,10 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 898fe3f909f91df712b34d52797e5aca384e418b..5a578b1e37f0e566f9ff930bdf13a4647085c514 100644 +index 8b3e1341b7544608cac4777a37bbd424432488e1..9dba743762508ea1cced150388afa38f7eb2878c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7101,8 +7101,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, +@@ -7452,8 +7452,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, /* Make sure the range is really isolated. */ if (test_pages_isolated(outer_start, end, false)) { @@ -493,10 +432,10 @@ index 898fe3f909f91df712b34d52797e5aca384e418b..5a578b1e37f0e566f9ff930bdf13a464 goto done; } -From f1498b3097cbe3783b462bd39f1b70d18400db87 Mon Sep 17 00:00:00 2001 +From 1d470f1c2c4269e41a6d00ac6ea1ecbed4691c46 Mon Sep 17 00:00:00 2001 From: Robert Tiemann Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 011/141] BCM2835_DT: Fix I2S register map +Subject: [PATCH 010/111] BCM2835_DT: Fix I2S register map --- Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- @@ -504,10 +443,10 @@ Subject: [PATCH 011/141] BCM2835_DT: Fix I2S register map 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -index 1396078d15ac625e737487bb242f79b330796951..2db8294474db47d8c199796d4d50a3a0a8a3cac5 100644 +index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 --- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -@@ -48,8 +48,8 @@ Example: +@@ -74,8 +74,8 @@ Example: bcm2835_i2s: i2s@7e203000 { compatible = "brcm,bcm2835-i2s"; @@ -534,10 +473,10 @@ index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554 dmas = <&dma 2>, <&dma 3>; -From 7a51654f93b5585198cc86ffd989975d8dc3779e Mon Sep 17 00:00:00 2001 +From bb8fde2aa103107b1a523b5dc06ac82157baeed3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 012/141] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 011/111] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -552,7 +491,7 @@ though, so trap them early. 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c -index b6e950d4782a1e020acddb50705efb180fe758b3..bbb92c290448fcabcb468302dfa5762b44b60d4a 100644 +index 72ff1d5c5de67058f4ef22bb233c41b7c737d6e3..de3b3a37a63d00cc82ae4725b2fe8584c084c4dc 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c @@ -175,6 +175,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs) @@ -564,10 +503,10 @@ index b6e950d4782a1e020acddb50705efb180fe758b3..bbb92c290448fcabcb468302dfa5762b #endif } else if (stat) { -From af560bc2c4f7b65aa9b325422439e6daaa7b4789 Mon Sep 17 00:00:00 2001 +From bb1085ea18c518c017e8a2d816eb717901ca6a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 -Subject: [PATCH 013/141] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 012/111] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -585,7 +524,7 @@ Acked-by: Stephen Warren 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 7ef121472cdd4761d059ae9f3eaf26b04ac141a2..b1a5a7b68158c55317418ee87e1df0325f8e4482 100644 +index 68ab6412392a44b84f4519ff04d725a3505f9bcf..b2385da38949e08787b942e73ba287035b401986 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -143,6 +143,7 @@ config ARCH_BCM2835 @@ -696,10 +635,10 @@ index bf9cc5f2e839e845fe1ce65caa672b6212d3ffbc..3f601f98aa884b941fbb84edb349f6c4 } -From fcc8e585f59688079af11a79e8238670b4bb17d8 Mon Sep 17 00:00:00 2001 +From b63ae9dd6cb1f890f4e0b68ef441cb39f3dc6016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 -Subject: [PATCH 014/141] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 013/111] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -795,10 +734,10 @@ index 3f601f98aa884b941fbb84edb349f6c469b940b1..20deb282286834b1f234a65e614b8584 for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From dab253783df6ebfb9d32eeac976f5a7493f1b968 Mon Sep 17 00:00:00 2001 +From d71ea2d5db8b7d9b36665cbe94b1e309353479f8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 015/141] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 014/111] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -819,17 +758,17 @@ index e3c19f30f591115a823467033702ff1b232c5ebc..f4963e3c1dbcd13edb9b97e9dad65438 }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From ecae09c78cf3e1fec1333cc482182044906889ce Mon Sep 17 00:00:00 2001 +From 141208db234695caa842b45a89581fa2e08c3f78 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 -Subject: [PATCH 016/141] serial: 8250: Don't crash when nr_uarts is 0 +Subject: [PATCH 015/111] serial: 8250: Don't crash when nr_uarts is 0 --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c -index 2f4f5ee651db63c040255347b56d0ac385e36415..edc1355f6381410fb79f48e17a2d2f47da66d841 100644 +index 0fbd7c033a251e7d0cb214ed2bbd1ad1f19f0a76..00fc96497968c826978465957454ad73c3fb6042 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -509,6 +509,8 @@ static void __init serial8250_isa_init_ports(void) @@ -842,10 +781,10 @@ index 2f4f5ee651db63c040255347b56d0ac385e36415..edc1355f6381410fb79f48e17a2d2f47 for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; -From 73f388363630c8b173556b874b54744a6afee2b6 Mon Sep 17 00:00:00 2001 +From e80e467e8d44ae69a48b29aa85ec0aecccad634b Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 017/141] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 016/111] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -854,10 +793,10 @@ Signed-off-by: Noralf Tronnes 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 08b1d93da9fedb36e1ae6ed3450221271f25998f..0a23c813397f14e503beb795b1f448124db74b9a 100644 +index fa77165fab2c1348163979da507df17e7168c49b..d11e2e4ea189466e686d762cb6c6fef9111ecf8e 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -373,7 +373,7 @@ static struct gpio_chip bcm2835_gpio_chip = { +@@ -386,7 +386,7 @@ static struct gpio_chip bcm2835_gpio_chip = { .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, .to_irq = bcm2835_gpio_to_irq, @@ -867,10 +806,10 @@ index 08b1d93da9fedb36e1ae6ed3450221271f25998f..0a23c813397f14e503beb795b1f44812 .can_sleep = false, }; -From 20c9618ebd27b09ea497f1232e22aee3b5ba7ec5 Mon Sep 17 00:00:00 2001 +From 26ec4fa6201b9cfceb3b99fefb9093df018f7400 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 018/141] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 017/111] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -891,7 +830,7 @@ the pins are often used for I2S instead. 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe238c7f09cf 100644 +index d11e2e4ea189466e686d762cb6c6fef9111ecf8e..107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ @@ -927,7 +866,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 spinlock_t irq_lock[BCM2835_NUM_BANKS]; }; -@@ -378,17 +379,16 @@ static struct gpio_chip bcm2835_gpio_chip = { +@@ -391,17 +392,16 @@ static struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; @@ -948,7 +887,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; -@@ -396,7 +396,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +@@ -409,7 +409,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } @@ -980,7 +919,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, -@@ -985,8 +1008,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -998,8 +1021,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; @@ -989,7 +928,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); -@@ -1001,10 +1022,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1014,10 +1035,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); @@ -1007,7 +946,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); -@@ -1062,6 +1088,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { +@@ -1074,6 +1100,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { .remove = bcm2835_pinctrl_remove, .driver = { .name = MODULE_NAME, @@ -1016,10 +955,10 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 }, }; -From 1ba175b3d87e3a992c16a1dbdb4ea0ce5aa581ee Mon Sep 17 00:00:00 2001 +From c9eec3c71a1447f4fb118e7b1a1853fd5f38d2a6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 019/141] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 018/111] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -1033,10 +972,10 @@ interface, is unlikely to be a problem. 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index b793bbdb12dca12722a7f0d07a29fe238c7f09cf..8683a1be5ecc45e1e664d5e078f25e6ff0ebe282 100644 +index 107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b..644bdecbcfcb79d3b84a33769265fca5d3d0c9e5 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -1029,6 +1029,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1042,6 +1042,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int len; char *name; pc->irq[i] = irq_of_parse_and_map(np, i); @@ -1046,10 +985,10 @@ index b793bbdb12dca12722a7f0d07a29fe238c7f09cf..8683a1be5ecc45e1e664d5e078f25e6f pc->irq_data[i].irqgroup = i; -From 7025a28c0a51dab1cf83b4dde39ff2f29d8802a5 Mon Sep 17 00:00:00 2001 +From 61a07603237cf3093679b3c319fc6d0bc54e874b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 -Subject: [PATCH 020/141] pinctrl-bcm2835: Return pins to inputs when freed +Subject: [PATCH 019/111] pinctrl-bcm2835: Return pins to inputs when freed When dynamically unloading overlays, it is important that freed pins are restored to being inputs to prevent functions from being enabled in @@ -1061,10 +1000,10 @@ Signed-off-by: Phil Elwell 1 file changed, 11 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54afdd2847 100644 +index 644bdecbcfcb79d3b84a33769265fca5d3d0c9e5..81a66cba2ab0f7e3ae179de7edd10122630e7abc 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -831,6 +831,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = { +@@ -844,6 +844,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = { .dt_free_map = bcm2835_pctl_dt_free_map, }; @@ -1081,7 +1020,7 @@ index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54 static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev) { return BCM2835_FSEL_COUNT; -@@ -890,6 +900,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, +@@ -903,6 +913,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, } static const struct pinmux_ops bcm2835_pmx_ops = { @@ -1090,10 +1029,10 @@ index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54 .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, -From 541fd5da6b0b4f90c60c026de2014ea9f20673dd Mon Sep 17 00:00:00 2001 +From bbf333328d9bca204d88968d9781a46450baddf5 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 021/141] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 020/111] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the @@ -1174,10 +1113,10 @@ index f35cc10772f6670397ea923ad30158270dd68578..5dfe20ffc2866fa6789825016c585175 /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -From 9826498a0561d5ad6adc0aef108c73b52c91232c Mon Sep 17 00:00:00 2001 +From a3538941a4ea2b1cce170ad969b43b66bbba8477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 -Subject: [PATCH 022/141] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 021/111] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1235,365 +1174,10 @@ index 834d67684e205a185971c13ebc6620434eeac788..3b68a8d3501a5dcb1b4790c35d921cf5 static const char * const bcm2835_compat[] = { -From 4e99035ba81f037625f36a5e31b6b10ce582176d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 9 Apr 2015 12:34:11 +0200 -Subject: [PATCH 023/141] dmaengine: bcm2835: Add slave dma support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add slave transfer capability to BCM2835 dmaengine driver. -This patch is pulled from the bcm2708-dmaengine driver in the -Raspberry Pi repo. The work was done by Gellert Weisz. - -Tested using the bcm2835-mmc driver from the same repo. - -Signed-off-by: Noralf Trønnes ---- - drivers/dma/bcm2835-dma.c | 206 ++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 192 insertions(+), 14 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 996c4b00d323ed5c2dd6455f80eb36ed8e9a8b23..b278c663e3b31a7c906dd32d53db5e670f6bbc10 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -1,11 +1,10 @@ - /* - * BCM2835 DMA engine support - * -- * This driver only supports cyclic DMA transfers -- * as needed for the I2S module. -- * - * Author: Florian Meier - * Copyright 2013 -+ * Gellert Weisz -+ * Copyright 2013-2014 - * - * Based on - * OMAP DMAengine support by Russell King -@@ -95,6 +94,8 @@ struct bcm2835_desc { - size_t size; - }; - -+#define BCM2835_DMA_WAIT_CYCLES 0 /* Slow down DMA transfers: 0-31 */ -+ - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 - #define BCM2835_DMA_SOURCE_AD 0x0c -@@ -111,12 +112,16 @@ struct bcm2835_desc { - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - - #define BCM2835_DMA_INT_EN BIT(0) -+#define BCM2835_DMA_WAIT_RESP BIT(3) - #define BCM2835_DMA_D_INC BIT(4) -+#define BCM2835_DMA_D_WIDTH BIT(5) - #define BCM2835_DMA_D_DREQ BIT(6) - #define BCM2835_DMA_S_INC BIT(8) -+#define BCM2835_DMA_S_WIDTH BIT(9) - #define BCM2835_DMA_S_DREQ BIT(10) - - #define BCM2835_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2835_DMA_WAITS(x) (((x) & 0x1f) << 21) - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 -@@ -130,6 +135,14 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+#define MAX_NORMAL_TRANSFER SZ_1G -+/* -+ * Max length on a Lite channel is 65535 bytes. -+ * DMA handles byte-enables on SDRAM reads and writes even on 128-bit accesses, -+ * but byte-enables don't exist on peripheral addresses, so align to 32-bit. -+ */ -+#define MAX_LITE_TRANSFER (SZ_64K - 4) -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -226,12 +239,18 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- /* TODO Only works for cyclic DMA */ -- vchan_cyclic_callback(&d->vd); -- } -+ if (c->cyclic) { -+ vchan_cyclic_callback(&d->vd); - -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, -+ c->chan_base + BCM2835_DMA_CS); -+ -+ } else { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ } -+ } - - spin_unlock_irqrestore(&c->vc.lock, flags); - -@@ -339,8 +358,6 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -358,7 +375,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - struct bcm2835_desc *d; - dma_addr_t dev_addr; - unsigned int es, sync_type; -- unsigned int frame; -+ unsigned int frame, max_size; - int i; - - /* Grab configuration */ -@@ -393,7 +410,12 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - - d->c = c; - d->dir = direction; -- d->frames = buf_len / period_len; -+ if (c->ch >= 8) /* LITE channel */ -+ max_size = MAX_LITE_TRANSFER; -+ else -+ max_size = MAX_NORMAL_TRANSFER; -+ period_len = min(period_len, max_size); -+ d->frames = (buf_len - 1) / (period_len + 1); - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { -@@ -441,17 +463,171 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - BCM2835_DMA_PER_MAP(c->dreq); - - /* Length of a frame */ -- control_block->length = period_len; -+ if (frame != d->frames - 1) -+ control_block->length = period_len; -+ else -+ control_block->length = buf_len - (d->frames - 1) * -+ period_len; - d->size += control_block->length; - - /* - * Next block is the next frame. -- * This DMA engine driver currently only supports cyclic DMA. -+ * This function is called on cyclic DMA transfers. - * Therefore, wrap around at number of frames. - */ - control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr; - } - -+ c->cyclic = true; -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ -+static struct dma_async_tx_descriptor * -+bcm2835_dma_prep_slave_sg(struct dma_chan *chan, -+ struct scatterlist *sgl, -+ unsigned int sg_len, -+ enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ enum dma_slave_buswidth dev_width; -+ struct bcm2835_desc *d; -+ dma_addr_t dev_addr; -+ struct scatterlist *sgent; -+ unsigned int i, sync_type, split_cnt, max_size; -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(chan->device->dev, "direction not supported\n"); -+ return NULL; -+ } -+ -+ if (direction == DMA_DEV_TO_MEM) { -+ dev_addr = c->cfg.src_addr; -+ dev_width = c->cfg.src_addr_width; -+ sync_type = BCM2835_DMA_S_DREQ; -+ } else { -+ dev_addr = c->cfg.dst_addr; -+ dev_width = c->cfg.dst_addr_width; -+ sync_type = BCM2835_DMA_D_DREQ; -+ } -+ -+ /* Bus width translates to the element size (ES) */ -+ switch (dev_width) { -+ case DMA_SLAVE_BUSWIDTH_4_BYTES: -+ break; -+ default: -+ dev_err(chan->device->dev, "buswidth not supported: %i\n", -+ dev_width); -+ return NULL; -+ } -+ -+ /* Allocate and setup the descriptor. */ -+ d = kzalloc(sizeof(*d), GFP_NOWAIT); -+ if (!d) -+ return NULL; -+ -+ d->dir = direction; -+ -+ if (c->ch >= 8) /* LITE channel */ -+ max_size = MAX_LITE_TRANSFER; -+ else -+ max_size = MAX_NORMAL_TRANSFER; -+ -+ /* -+ * Store the length of the SG list in d->frames -+ * taking care to account for splitting up transfers -+ * too large for a LITE channel -+ */ -+ d->frames = 0; -+ for_each_sg(sgl, sgent, sg_len, i) { -+ unsigned int len = sg_dma_len(sgent); -+ -+ d->frames += len / max_size + 1; -+ } -+ -+ /* Allocate memory for control blocks */ -+ d->control_block_size = d->frames * sizeof(struct bcm2835_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 SG entries, create a control block -+ * for each frame and link them together. -+ * Count the number of times an SG entry had to be split -+ * as a result of using a LITE channel -+ */ -+ split_cnt = 0; -+ -+ for_each_sg(sgl, sgent, sg_len, i) { -+ unsigned int j; -+ dma_addr_t addr = sg_dma_address(sgent); -+ unsigned int len = sg_dma_len(sgent); -+ -+ for (j = 0; j < len; j += max_size) { -+ struct bcm2835_dma_cb *control_block = -+ &d->control_block_base[i + split_cnt]; -+ -+ /* Setup addresses */ -+ if (d->dir == DMA_DEV_TO_MEM) { -+ control_block->info = BCM2835_DMA_D_INC | -+ BCM2835_DMA_D_WIDTH | -+ BCM2835_DMA_S_DREQ; -+ control_block->src = dev_addr; -+ control_block->dst = addr + (dma_addr_t)j; -+ } else { -+ control_block->info = BCM2835_DMA_S_INC | -+ BCM2835_DMA_S_WIDTH | -+ BCM2835_DMA_D_DREQ; -+ control_block->src = addr + (dma_addr_t)j; -+ control_block->dst = dev_addr; -+ } -+ -+ /* Common part */ -+ control_block->info |= -+ BCM2835_DMA_WAITS(BCM2835_DMA_WAIT_CYCLES); -+ control_block->info |= BCM2835_DMA_WAIT_RESP; -+ -+ /* Enable */ -+ if (i == sg_len - 1 && len - j <= max_size) -+ control_block->info |= BCM2835_DMA_INT_EN; -+ -+ /* Setup synchronization */ -+ if (sync_type) -+ control_block->info |= sync_type; -+ -+ /* Setup DREQ channel */ -+ if (c->dreq) -+ control_block->info |= -+ BCM2835_DMA_PER_MAP(c->dreq); -+ -+ /* Length of a frame */ -+ control_block->length = min(len - j, max_size); -+ d->size += control_block->length; -+ -+ if (i < sg_len - 1 || len - j > max_size) { -+ /* Next block is the next frame. */ -+ control_block->next = -+ d->control_block_base_phys + -+ sizeof(struct bcm2835_dma_cb) * -+ (i + split_cnt + 1); -+ } else { -+ /* Next block is empty. */ -+ control_block->next = 0; -+ } -+ -+ if (len - j > max_size) -+ split_cnt++; -+ } -+ } -+ -+ c->cyclic = false; -+ - return vchan_tx_prep(&c->vc, &d->vd, flags); - error_cb: - i--; -@@ -620,6 +796,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -+ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -@@ -708,4 +885,5 @@ module_platform_driver(bcm2835_dma_driver); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); -+MODULE_AUTHOR("Gellert Weisz "); - MODULE_LICENSE("GPL v2"); - -From e3e040906062d7c43233c4b3a3572d21349f17d1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 3 Oct 2015 15:58:59 +0200 -Subject: [PATCH 024/141] dmaengine: bcm2835: set residue_granularity field -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -bcm2835-dma supports residue reporting at burst level but didn't report -this via the residue_granularity field. - -Without this field set properly we get playback issues with I2S cards. - -[by HiassofT, taken from bcm2708-dmaengine] -Signed-off-by: Noralf Trønnes ---- - drivers/dma/bcm2835-dma.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b278c663e3b31a7c906dd32d53db5e670f6bbc10..696fb30b4f5a01cda9b98038b8e548368cea05f4 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -802,6 +802,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); - -From b40ce4492e4b78af2c02256f1807ee2d9fc35920 Mon Sep 17 00:00:00 2001 +From 28e89502361a69361bb3c3132d9bfac45ed04719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 025/141] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 022/111] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1607,11 +1191,11 @@ Don't mask out channel 2. Signed-off-by: Noralf Trønnes --- drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++------ - 2 files changed, 25 insertions(+), 7 deletions(-) + drivers/dma/bcm2835-dma.c | 26 +++++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index d96d87c56f2e13a6c85a815626f67b67c9940116..4d0425c820d476fc7e5d5acf12a32de074c91b1d 100644 +index 8c98779a12b134f3688e1076f1e11211c23e2623..ece64af02387ab867e21b7bc9178e0842bf1ecac 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -1624,10 +1208,10 @@ index d96d87c56f2e13a6c85a815626f67b67c9940116..4d0425c820d476fc7e5d5acf12a32de0 select DMA_VIRTUAL_CHANNELS diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f125511f67471 100644 +index 6149b27c33ad0962a19ed411055d9d05bfb252d3..43265b2847d37b3ee8f71b7528eebea1713f263c 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c -@@ -36,6 +36,7 @@ +@@ -37,6 +37,7 @@ #include #include #include @@ -1635,32 +1219,35 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 #include #include #include -@@ -786,6 +787,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -48,6 +49,7 @@ + + #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 + #define BCM2835_DMA_CHAN_NAME_SIZE 8 ++#define BCM2835_DMA_BULK_MASK BIT(0) + + struct bcm2835_dmadev { + struct dma_device ddev; +@@ -921,6 +923,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) + base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); - + rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK); + if (rc) + dev_err(&pdev->dev, "Failed to initialize the legacy API\n"); -+ + od->base = base; - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -@@ -818,11 +823,8 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -958,6 +963,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) goto err_no_dma; } -- /* -- * Do not use the FIQ and BULK channels, -- * because they are used by the GPU. -- */ -- chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); + /* Channel 0 is used by the legacy API */ + chans_available &= ~BCM2835_DMA_BULK_MASK; - - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); -@@ -866,6 +868,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) ++ + /* get irqs for each channel that we support */ + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { + /* skip masked out channels */ +@@ -1032,6 +1040,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) { struct bcm2835_dmadev *od = platform_get_drvdata(pdev); @@ -1668,7 +1255,7 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 dma_async_device_unregister(&od->ddev); bcm2835_dma_free(od); -@@ -881,7 +884,22 @@ static struct platform_driver bcm2835_dma_driver = { +@@ -1047,7 +1056,22 @@ static struct platform_driver bcm2835_dma_driver = { }, }; @@ -1693,138 +1280,10 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From 17879c9ca6c35117102bf91e1cbebc9f4efe6100 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 12:28:30 +0200 -Subject: [PATCH 026/141] bcm2835-dma: Limit cyclic transfers on lite channels - to 32k - -Transfers larger than 32k cause repeated clicking with I2S soundcards. -The exact reason is yet unknown, so limit to 32k as bcm2708-dmaengine -did as an intermediate fix. ---- - drivers/dma/bcm2835-dma.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 5db0a95985b20a2086c65762ea8f125511f67471..6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -144,6 +144,12 @@ struct bcm2835_desc { - */ - #define MAX_LITE_TRANSFER (SZ_64K - 4) - -+/* -+ * Transfers larger than 32k cause issues with the bcm2708-i2s driver, -+ * so limit transfer size to 32k as bcm2708-dmaengine did. -+ */ -+#define MAX_CYCLIC_LITE_TRANSFER SZ_32K -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -412,7 +418,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -+ max_size = MAX_CYCLIC_LITE_TRANSFER; - else - max_size = MAX_NORMAL_TRANSFER; - period_len = min(period_len, max_size); - -From b4c1abeefe17ac4871d90258edd3617137069432 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Mon, 16 Nov 2015 14:05:35 +0000 -Subject: [PATCH 027/141] bcm2835-dma: Fix up convert to DMA pool - ---- - drivers/dma/bcm2835-dma.c | 36 ++++++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 10 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9..d26b6bdbcf1ab33ab92937b889a37e505c925311 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -488,6 +488,17 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - c->cyclic = true; - - return vchan_tx_prep(&c->vc, &d->vd, flags); -+error_cb: -+ i--; -+ for (; i >= 0; i--) { -+ struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -+ -+ dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -+ } -+ -+ kfree(d->cb_list); -+ kfree(d); -+ return NULL; - } - - static struct dma_async_tx_descriptor * -@@ -534,6 +545,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (!d) - return NULL; - -+ d->c = c; - d->dir = direction; - - if (c->ch >= 8) /* LITE channel */ -@@ -553,15 +565,21 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - d->frames += len / max_size + 1; - } - -- /* Allocate memory for control blocks */ -- d->control_block_size = d->frames * sizeof(struct bcm2835_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) { -+ d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -+ if (!d->cb_list) { - kfree(d); - return NULL; - } -+ /* Allocate memory for control blocks */ -+ for (i = 0; i < d->frames; i++) { -+ struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -+ -+ cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -+ &cb_entry->paddr); -+ -+ if (!cb_entry->cb) -+ goto error_cb; -+ } - - /* - * Iterate over all SG entries, create a control block -@@ -578,7 +596,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - - for (j = 0; j < len; j += max_size) { - struct bcm2835_dma_cb *control_block = -- &d->control_block_base[i + split_cnt]; -+ d->cb_list[i + split_cnt].cb; - - /* Setup addresses */ - if (d->dir == DMA_DEV_TO_MEM) { -@@ -620,9 +638,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (i < sg_len - 1 || len - j > max_size) { - /* Next block is the next frame. */ - control_block->next = -- d->control_block_base_phys + -- sizeof(struct bcm2835_dma_cb) * -- (i + split_cnt + 1); -+ d->cb_list[i + split_cnt + 1].paddr; - } else { - /* Next block is empty. */ - control_block->next = 0; - -From 5a3d039eacc45898ee5a4f5b6fcbc97bcdbbe662 Mon Sep 17 00:00:00 2001 +From 0afec8b4eb4cb530d0c7f1dfd01592ce11768032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 15 Aug 2015 20:50:02 +0200 -Subject: [PATCH 028/141] bcm2835: Add support for uart1 +Subject: [PATCH 023/111] bcm2835: Add support for uart1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1881,10 +1340,10 @@ index 3b68a8d3501a5dcb1b4790c35d921cf5fa641ec7..e72e522fbc840c36a39cb6550850b3c6 static const char * const bcm2835_compat[] = { -From b4d7c36503083d12e86a7d4aade6f3addba8ad1c Mon Sep 17 00:00:00 2001 +From 185ef418f969b40b109156015b7fc4f85a36ca46 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 029/141] firmware: Updated mailbox header +Subject: [PATCH 024/111] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 11 +++++++++++ @@ -1947,10 +1406,10 @@ index 3fb357193f09914fe21f8555a4b8613f74f22bc3..227a107214a02deadcca3db202da265e RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, -From e725dd6d02f95b23299281de245e89c5f561cf78 Mon Sep 17 00:00:00 2001 +From 959d644104238b058ba73ce17324ec64c9feb912 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 030/141] Main bcm2708/bcm2709 linux port +Subject: [PATCH 025/111] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -2022,10 +1481,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 arch/arm/mach-bcm2709/vc_mem.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd742bfa6487 100644 +index 90542db1220dbcff5bc7f0d27ce233389a6d780d..437c4c3fd3cead08377098ae89de79c40d804df2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -322,6 +322,52 @@ choice +@@ -324,6 +324,52 @@ choice default ARM_SINGLE_ARMV7M if !MMU default ARCH_MULTIPLATFORM if MMU @@ -2078,7 +1537,7 @@ index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd74 config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU -@@ -721,6 +767,9 @@ config ARCH_VIRT +@@ -725,6 +771,9 @@ config ARCH_VIRT # Kconfigs may be included either alphabetically (according to the # plat- suffix) or along side the corresponding mach-* source. # @@ -2089,10 +1548,10 @@ index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd74 source "arch/arm/mach-alpine/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 1098e91d6d3f34ff5ca9abd4784dd1793897115c..e11967517b52614b4babf9e8cbafd0f920aaf208 100644 +index 19a3dcf5eb2e5600563cbcd47599ba458a546260..a15dd5cde577cc014de4063b7881d2ce03198df8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -1302,6 +1302,14 @@ choice +@@ -1294,6 +1294,14 @@ choice options; the platform specific options are deprecated and will be soon removed. @@ -2108,7 +1567,7 @@ index 1098e91d6d3f34ff5ca9abd4784dd1793897115c..e11967517b52614b4babf9e8cbafd0f9 config DEBUG_EXYNOS_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 8c3ce2ac44c4a675e091e8b107f1dd04f5f0b299..c4d7d102840699013aca416a1e7b8d14110be166 100644 +index 274e8a6582f1cd671731d1acbdda6f0f49c358c8..36e8f1e6fc7f169a68aa9476e618b50c79b0b2e3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -153,6 +153,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 @@ -2140,7 +1599,7 @@ index 04286fd9e09ce7a27259c4d375a05a965e3be0ea..ed826280e744828ebb1c5ae6b7a62d70 ENDPROC(__fixup_a_pv_table) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 4adfb46e3ee93276ea506b723eb11e33c57459f4..69aad0ebc902b82a83afd24938cafdfe1686136d 100644 +index 4a803c5a1ff7276859b823a7b9b02dc24ee6e564..c09505c5312860aade6f68f160f657349785d8cd 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -91,6 +91,16 @@ void arch_cpu_idle_exit(void) @@ -4400,7 +3859,7 @@ index 2ed1b8a922ed02b9e3545991873af77b4c1bf871..b52d949ee91d96eb7672fbbb4969bfa1 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index dc2b8997f6e637c0ae83f09b4b6bd4b92bffbf8d..c38fb1af8210f0a494ba58c3b6f1f99e54b88c1e 100644 +index 473974f9590a5cb19da5bf2bccf1e126f45bfb45..dc76b5e1b1f31fa2d802ee3da3dbfda1a88c6574 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o @@ -4413,7 +3872,7 @@ index dc2b8997f6e637c0ae83f09b4b6bd4b92bffbf8d..c38fb1af8210f0a494ba58c3b6f1f99e obj-$(CONFIG_ARCH_ATLAS7) += timer-atlas7.o obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index b03cfcbbac6b949b69c8b2f96ac7d307dd5b54e8..70cad6bd86fa78accb3bb39756442042aa4f2ee0 100644 +index 38853a187607591555c351bc2586b8ac73450b7f..382a22ab9ec6c02395a3be44d0787c15e2ddba8b 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -5,6 +5,9 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o @@ -4425,7 +3884,7 @@ index b03cfcbbac6b949b69c8b2f96ac7d307dd5b54e8..70cad6bd86fa78accb3bb39756442042 +obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_MMP) += irq-mmp.o + obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index 20deb282286834b1f234a65e614b8584688a25d7..c02bf8a9f9970401dc98c4f656c20c35d8070123 100644 --- a/drivers/irqchip/irq-bcm2835.c @@ -4448,10 +3907,10 @@ index 20deb282286834b1f234a65e614b8584688a25d7..c02bf8a9f9970401dc98c4f656c20c35 } init_FIQ(FIQ_START); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 8dd4d290ab0d8608b9596c18da8db1096715badb..f7fe8bd8ac26e68b51359b868a1e1eff3e344bdf 100644 +index 45cde8cd39f2434f5f9ec02c702a91a7f6b971c9..6a01ffa629386bdecf85e5a4736f7c27133869ab 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -291,6 +291,7 @@ struct mmc_host { +@@ -302,6 +302,7 @@ struct mmc_host { #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) #define MMC_CAP2_NO_WRITE_PROTECT (1 << 18) /* No physical write protect pin, assume that card is always read-write */ #define MMC_CAP2_NO_SDIO (1 << 19) /* Do not send SDIO commands during initialization */ @@ -4460,38 +3919,36 @@ index 8dd4d290ab0d8608b9596c18da8db1096715badb..f7fe8bd8ac26e68b51359b868a1e1eff mmc_pm_flag_t pm_caps; /* supported pm features */ -From 98808be09a0e8a3b6781d7110c44a7dde78eb825 Mon Sep 17 00:00:00 2001 +From bc4a3b0949122d757a7bb93cf9bc2181af7777a9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 031/141] reboot: Use power off rather than busy spinning when +Subject: [PATCH 026/111] reboot: Use power off rather than busy spinning when halt is requested --- - arch/arm/kernel/reboot.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) + arch/arm/kernel/reboot.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c -index 71a2ff9ec4900c58677f12114c85c82e8cfaa575..812c15ee02742f4d1578895ac13e1e983a9ce3da 100644 +index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 --- a/arch/arm/kernel/reboot.c +++ b/arch/arm/kernel/reboot.c -@@ -102,11 +102,7 @@ void machine_shutdown(void) +@@ -102,9 +102,7 @@ void machine_shutdown(void) */ void machine_halt(void) { - local_irq_disable(); - smp_send_stop(); -- -- local_irq_disable(); - while (1); + machine_power_off(); } /* -From 00ccff1596aa4c356db53f7fa48816afa6eb874a Mon Sep 17 00:00:00 2001 +From 122b8acb7c8d60b790ef4665ae12b7f336316c68 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 11 Nov 2015 21:01:15 +0000 -Subject: [PATCH 032/141] squash: include ARCH_BCM2708 / ARCH_BCM2709 +Subject: [PATCH 027/111] squash: include ARCH_BCM2708 / ARCH_BCM2709 --- drivers/char/hw_random/Kconfig | 2 +- @@ -4506,7 +3963,7 @@ Subject: [PATCH 032/141] squash: include ARCH_BCM2708 / ARCH_BCM2709 9 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 67ee8b08ab5318dca13054e6e1e65da9dcd1c000..b3ca2ee0a8f413151d70db1612ebb07e25416748 100644 +index ac51149e977758beb8db91e159175be9525fc13c..7fb001bb8e7609d3640b27cec5ec5180d8dbbcc2 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX @@ -4596,7 +4053,7 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index e4bc1151e04f3c2d7ed0eac8b659ae27244432ba..d996fe7f5b733864f26739aa0988b2466842dc19 100644 +index 42a5c1dddfefaf7414eca1809ef7d1bf75a11628..4c62b88401c5bee3015e74ce95a411d9c62c3dd6 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o @@ -4621,7 +4078,7 @@ index c182efc62c7bc3ffe31d81a539c88c35f55abac9..fe0f845fa21e1a2fa129814358f172ad PWM framework driver for BCM2835 controller (Raspberry Pi) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 9d8c84bb15446a75153d64f94a5900ab165193ac..2a27a37c54d8cf7c28620744147f7dc97771c3e5 100644 +index 4b931ec8d90b610f498a3e317e0523e9d1aa6900..82528961746f960e9851b4c252f42de5f1fbf298 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE @@ -4643,10 +4100,10 @@ index 9d8c84bb15446a75153d64f94a5900ab165193ac..2a27a37c54d8cf7c28620744147f7dc9 This selects a driver for the Broadcom BCM2835 SPI aux master. diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index fb947655badd02de231dd0777e88499c8a552044..8b2de7fb47f34888dd81262e793020afdc2dd44d 100644 +index b4b3e256491bfbe8c05fa0f7830c003541db8720..eaf2e847254e00b457ad37cb4a8c0b2baee8d1a9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -1401,7 +1401,7 @@ config BCM63XX_WDT +@@ -1409,7 +1409,7 @@ config BCM63XX_WDT config BCM2835_WDT tristate "Broadcom BCM2835 hardware watchdog" @@ -4668,10 +4125,10 @@ index 6a834e109f1de47e533d17e87cdc73d8ee86fc4d..c5070aec5996aafb2d9daaf75163e16a select REGMAP_MMIO help -From cd22cb8ce5c5e0d57cc587d3d6ea9e4d9c7b4cce Mon Sep 17 00:00:00 2001 +From 6f0fb5187200ef480efe629d0c758662df204f07 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 033/141] Add dwc_otg driver +Subject: [PATCH 028/111] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -5365,10 +4822,10 @@ index 358ca8dd784fe43700ae070764fa783500a792fe..abaac7c7142d8887c1516957fc52162c return i; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 1ab42bfbecaf6cf7780c87f2ae32a5948e48486e..292a26cefbbc2eee58433d792385f60f88c6a424 100644 +index bee13517676f9b2f00e3cd4e3fd4185f5aaa13c9..844ed26f2743b921e5a81cca1654badde94e05cd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -5044,7 +5044,7 @@ static void port_event(struct usb_hub *hub, int port1) +@@ -5046,7 +5046,7 @@ static void port_event(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0, unused; @@ -5378,10 +4835,10 @@ index 1ab42bfbecaf6cf7780c87f2ae32a5948e48486e..292a26cefbbc2eee58433d792385f60f USB_PORT_FEAT_C_OVER_CURRENT); msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 8e641b5893edb7a6195c34e43248540fbff39aa6..de3ed7d5d3dd3e9b2d20025e0c35a728248f4026 100644 +index ea681f157368f245772ab145073594bf4f6fb273..cb9b9c2df9b8fd7df50fa846b37c3f3d5fab6256 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1909,6 +1909,85 @@ free_interfaces: +@@ -1905,6 +1905,85 @@ free_interfaces: if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -9307,10 +8764,10 @@ index 0000000000000000000000000000000000000000..a896d73f7a9336f5a34015c44ea5a6b0 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index e9d4dde3e9b3dac1990d5dc58c8e6c2e196771a5..867dc98d83eb3cf38b50b52a922d5c543aa70a33 100644 +index d8f5674809e88e4f68d19411473ff752ce6230ef..50322813b65b6d7ddf273db46581c9b58be1c40b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -753,6 +753,19 @@ config USB_HWA_HCD +@@ -762,6 +762,19 @@ config USB_HWA_HCD To compile this driver a module, choose M here: the module will be called "hwa-hc". @@ -9331,10 +8788,10 @@ index e9d4dde3e9b3dac1990d5dc58c8e6c2e196771a5..867dc98d83eb3cf38b50b52a922d5c54 tristate "i.MX21 HCD support" depends on ARM && ARCH_MXC diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index a9ddd3c9ec9499b556789844eaaad5574a01d887..11d7761c61f59f08289a9b9ab78666cb069ba445 100644 +index 6ef785b0ea8ff0b5f4ee3bc40ba22d17c855478f..c28acc1b2877b6ac43604d1968351ce42e9470a5 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile -@@ -73,6 +73,8 @@ obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o +@@ -74,6 +74,8 @@ obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o @@ -65697,10 +65154,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From c195a8976feec61260f4ace36803130c41eebf65 Mon Sep 17 00:00:00 2001 +From c2cb17374b4e4c68ff926fe79c52d6338b93f74d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 034/141] bcm2708 framebuffer driver +Subject: [PATCH 029/111] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -65782,7 +65239,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/video/fbdev/bcm2708_fb.c diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 983280e8d93f3df4030c737978402ada4deaed10..ee72c3a2866f716cd68c646b7c501589a05b48f5 100644 +index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68f7010d1f 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -228,6 +228,20 @@ config FB_TILEBLITTING @@ -65807,7 +65264,7 @@ index 983280e8d93f3df4030c737978402ada4deaed10..ee72c3a2866f716cd68c646b7c501589 tristate "Aeroflex Gaisler framebuffer support" depends on FB && SPARC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index 65fb15075c8f7f150febb09966766287c3aa0e07..df473d825c2e2481a871d794317e56b8d643370f 100644 +index f6731867dd26dfc4318799e5204cd583a5d27670..ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o @@ -69159,10 +68616,10 @@ index 3c14e43b82fefe1d32f591d1b2f61d2cd28d0fa8..7626beb6a5bb8df601ddf0f6e6909d1f +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -From 31bd889b7548e1ded4c0d9f8171541b2a1eba9ca Mon Sep 17 00:00:00 2001 +From b3848db30147e758d2d0f82c5dcfee8f567f0d82 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 035/141] dmaengine: Add support for BCM2708 +Subject: [PATCH 030/111] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69319,10 +68776,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 4d0425c820d476fc7e5d5acf12a32de074c91b1d..b7863f0cf95ca656859a355098aa334e20d121c3 100644 +index ece64af02387ab867e21b7bc9178e0842bf1ecac..ffc92425cbd7bafc23899b7680949e47943f9561 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -474,6 +474,10 @@ config TIMB_DMA +@@ -488,6 +488,10 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. @@ -69334,7 +68791,7 @@ index 4d0425c820d476fc7e5d5acf12a32de074c91b1d..b7863f0cf95ca656859a355098aa334e tristate "AM33xx CPPI41 DMA support" depends on ARCH_OMAP diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile -index 6084127c14866ced0bef9865c8e5d9ffb13c16b6..8188c368a85f12950220942c28791bdc952c8848 100644 +index 614f28b0b739de875823b05a66a62186a1e9f45f..598e44dca3e4a9b33cc206e107226de8e0b34111 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_AT_HDMAC) += at_hdmac.o @@ -69782,10 +69239,10 @@ index 0000000000000000000000000000000000000000..99cc7fdbf543207208bf3638a0d4dbb6 + +#endif /* _PLAT_BCM2708_DMA_H */ -From daa0ba80c2355cafff1e77d3c0e5279fa39431ff Mon Sep 17 00:00:00 2001 +From a81ac3cfae61fc6b814594d419702a2808a731e6 Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 036/141] MMC: added alternative MMC driver +Subject: [PATCH 031/111] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69903,7 +69360,7 @@ index fad660b95809224e3a06abde0709be3d50acf307..b79fe14c18f1fe521fadf8adfc136de6 } EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index e657af0e95fafce5bf65e0127540339dfbbb2ba5..04760616f94ce470a73d7ac99f27631db80849b5 100644 +index 0aa484c10c0a9b93a4aedc885235d95ffe6872e6..36d00eba1df06946fb2bb9bb9dd1f0d847ef8158 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -4,6 +4,35 @@ @@ -71532,10 +70989,10 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 5c1dac87ebf26fc576b27b0a78d2bf2d277f413a Mon Sep 17 00:00:00 2001 +From ea4f732925a77e0c50915b345312cbce996201b8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 037/141] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 032/111] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -71682,12 +71139,12 @@ Signed-off-by: Phil Elwell --- drivers/mmc/host/Kconfig | 10 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 2158 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 2169 insertions(+) + drivers/mmc/host/bcm2835-sdhost.c | 2189 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 2200 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-sdhost.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 04760616f94ce470a73d7ac99f27631db80849b5..259547484f859ae69c65af13bcbb1d06b53e29ac 100644 +index 36d00eba1df06946fb2bb9bb9dd1f0d847ef8158..97650d32a733251076726a0cecb4239906ff3814 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER @@ -71721,10 +71178,10 @@ index 3ba94f0af9b1793aa66d95d8fbd9bb661ca82778..8daaa94ab268495bbbf335ccad5a35e2 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 -index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e599026d43785 +index 0000000000000000000000000000000000000000..d7b6b5a4e31f7aaa76470d3a79ea78a643184855 --- /dev/null +++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,2158 @@ +@@ -0,0 +1,2189 @@ +/* + * BCM2835 SD host driver. + * @@ -71765,6 +71222,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 +#include +#include +#include ++#include +#include +#include +#include @@ -71933,6 +71391,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + struct timeval stop_time; /* when the last stop was issued */ + u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ + u32 delay_after_this_stop; /* minimum time between this stop and subsequent data transfer */ ++ u32 user_overclock_50; /* User's preferred frequency to use when 50MHz is requested (in MHz) */ + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ + u32 overclock; /* Current frequency if overclocked, else zero */ + u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ @@ -72009,7 +71468,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + do { + entry = sdhost_log_buf + idx; + if (entry->event[0] != '\0') -+ pr_err("[%08x] %.4s %x %x\n", ++ pr_info("[%08x] %.4s %x %x\n", + entry->timestamp, + entry->event, + entry->param1, @@ -72051,7 +71510,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + const char *label) +{ + if (cmd) -+ pr_err("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", ++ pr_info("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", + mmc_hostname(host->mmc), + (cmd == host->cmd) ? '>' : ' ', + label, cmd->opcode, cmd->arg, cmd->flags, @@ -72066,7 +71525,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + bcm2835_sdhost_dumpcmd(host, host->mrq->sbc, "sbc"); + bcm2835_sdhost_dumpcmd(host, host->mrq->cmd, "cmd"); + if (host->mrq->data) -+ pr_err("%s: data blocks %x blksz %x - err %d\n", ++ pr_info("%s: data blocks %x blksz %x - err %d\n", + mmc_hostname(host->mmc), + host->mrq->data->blocks, + host->mrq->data->blksz, @@ -72074,53 +71533,53 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + bcm2835_sdhost_dumpcmd(host, host->mrq->stop, "stop"); + } + -+ pr_err("%s: =========== REGISTER DUMP ===========\n", ++ pr_info("%s: =========== REGISTER DUMP ===========\n", + mmc_hostname(host->mmc)); + -+ pr_err("%s: SDCMD 0x%08x\n", ++ pr_info("%s: SDCMD 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCMD)); -+ pr_err("%s: SDARG 0x%08x\n", ++ pr_info("%s: SDARG 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDARG)); -+ pr_err("%s: SDTOUT 0x%08x\n", ++ pr_info("%s: SDTOUT 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDTOUT)); -+ pr_err("%s: SDCDIV 0x%08x\n", ++ pr_info("%s: SDCDIV 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCDIV)); -+ pr_err("%s: SDRSP0 0x%08x\n", ++ pr_info("%s: SDRSP0 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP0)); -+ pr_err("%s: SDRSP1 0x%08x\n", ++ pr_info("%s: SDRSP1 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP1)); -+ pr_err("%s: SDRSP2 0x%08x\n", ++ pr_info("%s: SDRSP2 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP2)); + pr_err("%s: SDRSP3 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP3)); -+ pr_err("%s: SDHSTS 0x%08x\n", ++ pr_info("%s: SDHSTS 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHSTS)); -+ pr_err("%s: SDVDD 0x%08x\n", ++ pr_info("%s: SDVDD 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDVDD)); -+ pr_err("%s: SDEDM 0x%08x\n", ++ pr_info("%s: SDEDM 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDEDM)); -+ pr_err("%s: SDHCFG 0x%08x\n", ++ pr_info("%s: SDHCFG 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHCFG)); -+ pr_err("%s: SDHBCT 0x%08x\n", ++ pr_info("%s: SDHBCT 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBCT)); -+ pr_err("%s: SDHBLC 0x%08x\n", ++ pr_info("%s: SDHBLC 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBLC)); + -+ pr_err("%s: ===========================================\n", ++ pr_info("%s: ===========================================\n", + mmc_hostname(host->mmc)); +} + @@ -72335,7 +71794,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + (fsm_state != SDEDM_FSM_READCRC)) { + hsts = bcm2835_sdhost_read(host, + SDHSTS); -+ pr_err("%s: fsm %x, hsts %x\n", ++ pr_info("%s: fsm %x, hsts %x\n", + mmc_hostname(host->mmc), + fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) @@ -72425,7 +71884,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + (fsm_state != SDEDM_FSM_WRITESTART2)) { + hsts = bcm2835_sdhost_read(host, + SDHSTS); -+ pr_err("%s: fsm %x, hsts %x\n", ++ pr_info("%s: fsm %x, hsts %x\n", + mmc_hostname(host->mmc), + fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) @@ -72680,9 +72139,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + + while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { + if (timeout == 0) { -+ pr_err("%s: previous command never completed.\n", ++ pr_warn("%s: previous command never completed.\n", + mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); + cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + return false; @@ -72940,10 +72400,12 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + + /* Check for errors */ + if (sdcmd & SDCMD_NEW_FLAG) { -+ pr_err("%s: command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; ++ if (host->debug) { ++ pr_err("%s: command %d never completed.\n", ++ mmc_hostname(host->mmc), host->cmd->opcode); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ host->cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + return; + } else if (sdcmd & SDCMD_FAIL_FLAG) { @@ -72965,15 +72427,14 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + } else { + if (sdhsts & SDHSTS_CMD_TIME_OUT) { + if (host->debug) -+ pr_err("%s: command %d timeout\n", ++ pr_warn("%s: command %d timeout\n", + mmc_hostname(host->mmc), + host->cmd->opcode); + host->cmd->error = -ETIMEDOUT; + } else { -+ pr_err("%s: unexpected command %d error\n", ++ pr_warn("%s: unexpected command %d error\n", + mmc_hostname(host->mmc), + host->cmd->opcode); -+ bcm2835_sdhost_dumpregs(host); + host->cmd->error = -EILSEQ; + } + tasklet_schedule(&host->finish_tasklet); @@ -73097,8 +72558,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + } else if (intmask & SDHSTS_CMD_TIME_OUT) + host->cmd->error = -ETIMEDOUT; + -+ log_dump(); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) { ++ log_dump(); ++ bcm2835_sdhost_dumpregs(host); ++ } + } + else + bcm2835_sdhost_finish_command(host, NULL); @@ -73322,7 +72785,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + host->overclock_50 = (clock/MHZ); + + if (clock != host->overclock) { -+ pr_warn("%s: overclocking to %dHz\n", ++ pr_info("%s: overclocking to %dHz\n", + mmc_hostname(host->mmc), clock); + host->overclock = clock; + } @@ -73332,6 +72795,11 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + pr_warn("%s: cancelling overclock\n", + mmc_hostname(host->mmc)); + } ++ } else if (input_clock == 0) { ++ /* Reset the preferred overclock when the clock is stopped. ++ * This always happens during initialisation. */ ++ host->overclock_50 = host->user_overclock_50; ++ host->overclock = 0; + } + + /* Set the timeout to 500ms */ @@ -73405,13 +72873,15 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + log_event("REQ<", (u32)mrq, edm); + if ((fsm != SDEDM_FSM_IDENTMODE) && + (fsm != SDEDM_FSM_DATAMODE)) { -+ pr_err("%s: previous command (%d) not complete (EDM %x)\n", -+ mmc_hostname(host->mmc), -+ bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK, -+ edm); + log_event("REQ!", (u32)mrq, edm); -+ log_dump(); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) { ++ pr_warn("%s: previous command (%d) not complete (EDM %x)\n", ++ mmc_hostname(host->mmc), ++ bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK, ++ edm); ++ log_dump(); ++ bcm2835_sdhost_dumpregs(host); ++ } + mrq->cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + mmiowb(); @@ -73541,16 +73011,19 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + mrq = host->mrq; + + /* Drop the overclock after any data corruption, or after any -+ error overclocked */ ++ * error while overclocked. Ignore errors for status commands, ++ * as they are likely when a card is ejected. */ + if (host->overclock) { -+ if ((mrq->cmd && mrq->cmd->error) || ++ if ((mrq->cmd && mrq->cmd->error && ++ (mrq->cmd->opcode != MMC_SEND_STATUS)) || + (mrq->data && mrq->data->error) || -+ (mrq->stop && mrq->stop->error)) { ++ (mrq->stop && mrq->stop->error) || ++ (mrq->sbc && mrq->sbc->error)) { + host->overclock_50--; + pr_warn("%s: reducing overclock due to errors\n", + mmc_hostname(host->mmc)); + host->reset_clock = 1; -+ mrq->cmd->error = -EILSEQ; ++ mrq->cmd->error = -ETIMEDOUT; + mrq->cmd->retries = 1; + } + } @@ -73575,6 +73048,21 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + mmc_hostname(host->mmc), err); + } + ++ /* The SDHOST block doesn't report any errors for a disconnected ++ interface. All cards and SDIO devices should report some supported ++ voltage range, so a zero response to SEND_OP_COND, IO_SEND_OP_COND ++ or APP_SEND_OP_COND can be treated as an error. */ ++ if (((mrq->cmd->opcode == MMC_SEND_OP_COND) || ++ (mrq->cmd->opcode == SD_IO_SEND_OP_COND) || ++ (mrq->cmd->opcode == SD_APP_OP_COND)) && ++ (mrq->cmd->error == 0) && ++ (mrq->cmd->resp[0] == 0)) { ++ mrq->cmd->error = -ETIMEDOUT; ++ if (host->debug) ++ pr_info("%s: faking timeout due to zero OCR\n", ++ mmc_hostname(host->mmc)); ++ } ++ + mmc_request_done(host->mmc, mrq); + log_event("TSK>", (u32)mrq, 0); +} @@ -73750,7 +73238,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + &host->delay_after_stop); + of_property_read_u32(node, + "brcm,overclock-50", -+ &host->overclock_50); ++ &host->user_overclock_50); + of_property_read_u32(node, + "brcm,pio-limit", + &host->pio_limit); @@ -73884,10 +73372,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From 86d53b10b81d69a9dfe12830bd6237987e3a01b6 Mon Sep 17 00:00:00 2001 +From 324d21e6e89ecb598e332f431fffb01464462c6d Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 038/141] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards +Subject: [PATCH 033/111] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards Some SD cards have been found that corrupt data when small blocks are erased. Add a quirk to indicate that ERASE should not be used, @@ -73916,10 +73404,10 @@ Signed-off-by: Phil Elwell 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73ce9dca60 100644 +index c5472e3c923126097fd93f2abf31402a1717c228..c55094303b087eb944baf28d4023ab72a61206d5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c -@@ -132,6 +132,13 @@ enum { +@@ -133,6 +133,13 @@ enum { module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); @@ -73933,7 +73421,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 static inline int mmc_blk_part_switch(struct mmc_card *card, struct mmc_blk_data *md); static int get_card_status(struct mmc_card *card, u32 *status, int retries); -@@ -2532,6 +2539,17 @@ static const struct mmc_fixup blk_fixups[] = +@@ -2576,6 +2583,17 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), @@ -73951,7 +73439,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 END_FIXUP }; -@@ -2539,6 +2557,7 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2583,6 +2601,7 @@ static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; char cap_str[10]; @@ -73959,7 +73447,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 /* * Check that the card supports the command class(es) we need. -@@ -2546,7 +2565,16 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2590,7 +2609,16 @@ static int mmc_blk_probe(struct mmc_card *card) if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; @@ -73977,7 +73465,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 md = mmc_blk_alloc(card); if (IS_ERR(md)) -@@ -2554,9 +2582,14 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2598,9 +2626,14 @@ static int mmc_blk_probe(struct mmc_card *card) string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); @@ -73995,10 +73483,10 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 if (mmc_blk_alloc_parts(card, md)) goto out; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index 9eba56c68ca134f02a8328fe6bcd4ea0bcc7a45f..4b1ff84e016f6ba2a9387c54d999205696f056f7 100644 +index 8b4dfd45433b73c1ccf6fe4cd4f9ca3338546cff..376ca5e984f1d7e0a10bb6e90893cf81a331c8fa 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c -@@ -2253,7 +2253,8 @@ EXPORT_SYMBOL(mmc_erase); +@@ -2260,7 +2260,8 @@ EXPORT_SYMBOL(mmc_erase); int mmc_can_erase(struct mmc_card *card) { if ((card->host->caps & MMC_CAP_ERASE) && @@ -74023,10 +73511,10 @@ index eb0151bac50c1fd796f479d017bc3c3d7017c9e9..fa4e6454456747f02a10621f4f4da3ac unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ -From 7ff65cec357efd357309ae92f0d605aa6c29419a Mon Sep 17 00:00:00 2001 +From b7a07a2134d0240e10a33263740f2b37e8ee1a92 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 039/141] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 034/111] cma: Add vc_cma driver to enable use of CMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -74058,7 +73546,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 include/linux/broadcom/vc_cma.h diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 3ec0766ed5e97a80390f3e8dcbe009c4414c9cf2..aec9337379b730de016972fb523bebb7a7c6aff7 100644 +index 601f64fcc8908bad887a2f3fd70cd23fdf34ad1c..a23a93cfa57f01f37777f42fc241f62958fdf1c1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -4,6 +4,8 @@ @@ -75369,10 +74857,10 @@ index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e + +#endif /* VC_CMA_H */ -From a32fde0621d166157b384b2c7ebecb3ef0b071be Mon Sep 17 00:00:00 2001 +From fd23e9dc16915a406af9bda180f64d882b92b160 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 040/141] bcm2708: alsa sound driver +Subject: [PATCH 035/111] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78109,10 +77597,10 @@ index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294 + +#endif // _VC_AUDIO_DEFS_H_ -From b2b5fec96343d4169965d38e32f0710d4ca58fc7 Mon Sep 17 00:00:00 2001 +From 11380abf87d0d53e0243f3178cdab81f4d4449a5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 041/141] bcm2708 vchiq driver +Subject: [PATCH 036/111] bcm2708 vchiq driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78342,13 +77830,13 @@ Signed-off-by: Phil Elwell .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + .../interface/vchiq_arm/vchiq_2835_arm.c | 586 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2920 +++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2921 +++++++++++++++ .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ .../interface/vchiq_arm/vchiq_build_info.h | 37 + .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + .../interface/vchiq_arm/vchiq_connected.c | 120 + .../interface/vchiq_arm/vchiq_connected.h | 50 + - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3929 ++++++++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3933 ++++++++++++++++++++ .../vc04_services/interface/vchiq_arm/vchiq_core.h | 712 ++++ .../interface/vchiq_arm/vchiq_debugfs.c | 383 ++ .../interface/vchiq_arm/vchiq_debugfs.h | 52 + @@ -78363,7 +77851,7 @@ Signed-off-by: Phil Elwell .../vc04_services/interface/vchiq_arm/vchiq_util.c | 156 + .../vc04_services/interface/vchiq_arm/vchiq_util.h | 82 + .../interface/vchiq_arm/vchiq_version.c | 59 + - 37 files changed, 12831 insertions(+) + 37 files changed, 12836 insertions(+) create mode 100644 drivers/misc/vc04_services/Kconfig create mode 100644 drivers/misc/vc04_services/Makefile create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -80635,10 +80123,10 @@ index 0000000000000000000000000000000000000000..4cb5bff237288a4ee80d80ba53a2efe9 +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947dbd860cf90 +index 0000000000000000000000000000000000000000..2dfccafc765b2211bd7b8ead5e9e52bd8fe13913 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2920 @@ +@@ -0,0 +1,2921 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -80705,10 +80193,10 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db +#define VCHIQ_MINOR 0 + +/* Some per-instance constants */ -+#define MAX_COMPLETIONS 16 ++#define MAX_COMPLETIONS 128 +#define MAX_SERVICES 64 +#define MAX_ELEMENTS 8 -+#define MSG_QUEUE_SIZE 64 ++#define MSG_QUEUE_SIZE 128 + +#define KEEPALIVE_VER 1 +#define KEEPALIVE_VER_MIN KEEPALIVE_VER @@ -80849,28 +80337,24 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + void *bulk_userdata) +{ + VCHIQ_COMPLETION_DATA_T *completion; ++ int insert; + DEBUG_INITIALISE(g_state.local) + -+ mutex_lock(&instance->completion_mutex); -+ -+ while (instance->completion_insert == -+ (instance->completion_remove + MAX_COMPLETIONS)) { ++ insert = instance->completion_insert; ++ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + -+ mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } + -+ mutex_lock(&instance->completion_mutex); + if (instance->closing) { -+ mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; @@ -80878,9 +80362,7 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + -+ completion = -+ &instance->completions[instance->completion_insert & -+ (MAX_COMPLETIONS - 1)]; ++ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; @@ -80901,12 +80383,9 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) -+ user_service->message_available_pos = -+ instance->completion_insert; ++ user_service->message_available_pos = insert; + -+ instance->completion_insert++; -+ -+ mutex_unlock(&instance->completion_mutex); ++ instance->completion_insert = ++insert; + + up(&instance->insert_event); + @@ -81436,6 +80915,7 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + instance->completion_insert) + && !instance->closing) { + int rc; ++ + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); @@ -81450,24 +80930,29 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + -+ /* A read memory barrier is needed to stop prefetch of a stale -+ ** completion record -+ */ -+ rmb(); -+ + if (ret == 0) { + int msgbufcount = args.msgbufcount; ++ int remove; ++ ++ remove = instance->completion_remove; ++ + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; -+ if (instance->completion_remove == -+ instance->completion_insert) ++ ++ if (remove == instance->completion_insert) + break; ++ + completion = &instance->completions[ -+ instance->completion_remove & -+ (MAX_COMPLETIONS - 1)]; ++ remove & (MAX_COMPLETIONS - 1)]; ++ ++ ++ /* A read memory barrier is needed to prevent ++ ** the prefetch of a stale completion record ++ */ ++ rmb(); + + service = completion->service_userdata; + user_service = service->base.userdata; @@ -81544,7 +81029,11 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + break; + } + -+ instance->completion_remove++; ++ /* Ensure that the above copy has completed ++ ** before advancing the remove pointer. */ ++ mb(); ++ ++ instance->completion_remove = ++remove; + } + + if (msgbufcount != args.msgbufcount) { @@ -84087,10 +83576,10 @@ index 0000000000000000000000000000000000000000..863b3e335c1aa4bbe7f8652e0e6c3713 +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 -index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02bc41e599 +index 0000000000000000000000000000000000000000..71a3bedc55314f3b22dbff40c05dedf03b5e7169 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -0,0 +1,3929 @@ +@@ -0,0 +1,3933 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -84703,15 +84192,15 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + -+ /* Use a read memory barrier to ensure that any state that may have -+ ** been modified by another thread is not masked by stale prefetched -+ ** values. */ -+ rmb(); -+ + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + ++ /* Use a memory barrier to ensure that any state that may have been ++ ** modified by another thread is not masked by stale prefetched ++ ** values. */ ++ mb(); ++ + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & @@ -84719,6 +84208,8 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + ++ rmb(); ++ + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); @@ -84834,6 +84325,8 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + up(&state->data_quota_event); + } + ++ mb(); ++ + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } @@ -91472,10 +90965,10 @@ index 0000000000000000000000000000000000000000..b6bfa21155e431e93bfb2c149d324371 + return vchiq_build_time; +} -From 88c8fc95a876e0a12cad4e4ea94b904087942b5b Mon Sep 17 00:00:00 2001 +From 1a022d55ba03192671ab57aee87137e870501a88 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 042/141] vc_mem: Add vc_mem driver +Subject: [PATCH 037/111] vc_mem: Add vc_mem driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -92480,10 +91973,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 8f6250cfb01812b76468450bd5b444cf9cb9f7a0 Mon Sep 17 00:00:00 2001 +From cceb483e245cc42f3bb2f96246080169084a8509 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 043/141] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 038/111] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -96901,10 +96394,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 7f32d45509743fd6e65691b064c8b1644f8a438c Mon Sep 17 00:00:00 2001 +From bd88b185bd5e789da9df304bceb13516d8fb68e3 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 044/141] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 039/111] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -97215,10 +96708,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From 18d5337bc159f0728bfced87cd74c1a80d5e9e85 Mon Sep 17 00:00:00 2001 +From e72622a4c692d9f85f4056d834804d738a6a3ce5 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 045/141] Add SMI driver +Subject: [PATCH 040/111] Add SMI driver Signed-off-by: Luke Wren --- @@ -99169,10 +98662,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From f758a1fea224d404f0e66b1f18310335971c7f64 Mon Sep 17 00:00:00 2001 +From 9d19676cd43462eeb3ff112f34566d179c5bc59a Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 046/141] Add SMI NAND driver +Subject: [PATCH 041/111] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -99537,10 +99030,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From 82bb93197112611f2a8b0c35f4a89db9ecb8f79e Mon Sep 17 00:00:00 2001 +From 883e2b3ab1545d31654c899b2175dba96718a477 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 047/141] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 042/111] lirc: added support for RaspberryPi GPIO lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others See: https://github.com/raspberrypi/linux/issues/525 @@ -100389,10 +99882,10 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From 1015e8e096b836dc67a178f535272a7255cb5821 Mon Sep 17 00:00:00 2001 +From 36561a4595f5e2fa6f0faedd5883be17dfc922d1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 048/141] Add cpufreq driver +Subject: [PATCH 043/111] Add cpufreq driver Signed-off-by: popcornmix --- @@ -100403,10 +99896,10 @@ Signed-off-by: popcornmix create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 14b1f9393b057e106d7b068883ce486ea70239ec..c6e8bd553878a81d41cbe110930fb2791d787cc2 100644 +index d89b8afe23b6956b6c48e19c87cecc081e7725a1..465c727bb3ba70249409728d8f643a0002c6779c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -229,6 +229,15 @@ config ARM_STI_CPUFREQ +@@ -220,6 +220,15 @@ config ARM_STI_CPUFREQ this config option if you wish to add CPUFreq support for STi based SoCs. @@ -100423,10 +99916,10 @@ index 14b1f9393b057e106d7b068883ce486ea70239ec..c6e8bd553878a81d41cbe110930fb279 bool "Tegra20 CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 9e63fb1b09f815fa70e1c4d908707ba39989f8fa..9e55083a9b247b86c2a29c9b268111918c10a7b9 100644 +index 0a9b6a093646bd1dd60ee092e362b24527f0ef1e..92a628a670c12c39c2be73fc91f65da5fdafd397 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -74,6 +74,7 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o +@@ -75,6 +75,7 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o @@ -100654,10 +100147,10 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 3d10279adf0c0a1af20c8ec8427b3af1b8cb9868 Mon Sep 17 00:00:00 2001 +From 7540e4b3f77cb70cd77899f6cd80479e4f743599 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 049/141] Added hwmon/thermal driver for reporting core +Subject: [PATCH 044/111] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -100678,10 +100171,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index 3c3dc4a3d52cfb4685bdcbd2c62b55d33447804d..6789340aa1ce5d3711d23a87aafdd7e3c4793643 100644 +index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8abd31de94b 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -292,6 +292,13 @@ config INTEL_POWERCLAMP +@@ -282,6 +282,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -100696,10 +100189,10 @@ index 3c3dc4a3d52cfb4685bdcbd2c62b55d33447804d..6789340aa1ce5d3711d23a87aafdd7e3 tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index 8e9cbc3b5679ae221bcdd5d6bb82e91ebcfb3f1d..497014c0b271731daa831f7dbd5df0a6ca1ebe69 100644 +index 10b07c14f8a9f75363323d0c69542606d8dfed96..ac19930164fdcc773035a95af8136ec2f36fc8b7 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -38,6 +38,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o +@@ -39,6 +39,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o @@ -100823,10 +100316,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From bb69f1bafb8f1c4554094967a71bcc6565490294 Mon Sep 17 00:00:00 2001 +From cfbbb92f0c0496445cc97151580ea8b9a6d3e9d9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 050/141] Add Chris Boot's i2c driver +Subject: [PATCH 045/111] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -100917,7 +100410,7 @@ Set the BSC_CLKT clock streching timeout to 35ms as per SMBus specs. create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 0967e1a5b3a25f1d351f83adb40f7bad0c52c659..c11fce150e1e371d17432af29ea96ab0a6c28d5d 100644 +index f167021b8c2178b8a9544bd7d750648c641f6c85..85e2de31c26cd03d5815fe397d47b461ad65359c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" @@ -101483,10 +100976,10 @@ index 0000000000000000000000000000000000000000..c9b8e5cb1702e4b20e45214d81a7a40a +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From f2d4d11ef62907fa1baf51a856f9332350924ed9 Mon Sep 17 00:00:00 2001 +From 05cb723448582453691babf82541facfbb50defb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 -Subject: [PATCH 051/141] char: broadcom: Add vcio module +Subject: [PATCH 046/111] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101712,10 +101205,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From 89c0d29a525e784395e31862107e739ba787d0df Mon Sep 17 00:00:00 2001 +From ef21300b02abfc74b007a8bb4a66eda2bf3a88c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 -Subject: [PATCH 052/141] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 047/111] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101821,10 +101314,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 5a34e7fd4ff8b982785fda482d43ac50a476e3e5 Mon Sep 17 00:00:00 2001 +From 15948d937b12b2f04caf507d3ac39e044de22ed8 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 053/141] bcm2835: add v4l2 camera device +Subject: [PATCH 048/111] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -102196,14 +101689,22 @@ Signed-off-by: Slawomir Stepien bcm2835-camera: Fix max/min error when looping over cameras/resolutions See: https://github.com/raspberrypi/linux/issues/1447#issuecomment-221303506 + +BCM2835-V4L2: Correct handling for BGR24 vs RGB24. + +There was a bug in the GPU firmware that had reversed these +two formats. +Detect the old firmware, and reverse the formats if necessary. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> --- Documentation/video4linux/bcm2835-v4l2.txt | 60 + drivers/media/platform/Kconfig | 2 + drivers/media/platform/Makefile | 2 + drivers/media/platform/bcm2835/Kconfig | 25 + drivers/media/platform/bcm2835/Makefile | 5 + - drivers/media/platform/bcm2835/bcm2835-camera.c | 1982 ++++++++++++++++++++++ - drivers/media/platform/bcm2835/bcm2835-camera.h | 144 ++ + drivers/media/platform/bcm2835/bcm2835-camera.c | 2015 ++++++++++++++++++++++ + drivers/media/platform/bcm2835/bcm2835-camera.h | 145 ++ drivers/media/platform/bcm2835/controls.c | 1345 +++++++++++++++ drivers/media/platform/bcm2835/mmal-common.h | 53 + drivers/media/platform/bcm2835/mmal-encodings.h | 127 ++ @@ -102212,9 +101713,9 @@ See: https://github.com/raspberrypi/linux/issues/1447#issuecomment-221303506 drivers/media/platform/bcm2835/mmal-msg-port.h | 107 ++ drivers/media/platform/bcm2835/mmal-msg.h | 404 +++++ drivers/media/platform/bcm2835/mmal-parameters.h | 689 ++++++++ - drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 +++++++++++++++++++++ + drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++ drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++ - 17 files changed, 7170 insertions(+) + 17 files changed, 7204 insertions(+) create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt create mode 100644 drivers/media/platform/bcm2835/Kconfig create mode 100644 drivers/media/platform/bcm2835/Makefile @@ -102298,7 +101799,7 @@ index 0000000000000000000000000000000000000000..c585a8fadf91c5a04453e442fc29ed89 + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 201f5c296a951a24b35f5a0495af7b77b121acfd..b798ab852b51379b9e2b12aac158b86fff12315f 100644 +index 84e041c0a70e5b2634282f8605f7473efce3ac48..895c7182799dbccebb88e6545be8c5b281fe8518 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -102367,10 +101868,10 @@ index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d6 +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c new file mode 100644 -index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd004c92cd3 +index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478809eb161 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -0,0 +1,1982 @@ +@@ -0,0 +1,2015 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -102488,7 +101989,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + .name = "RGB24 (LE)", + .fourcc = V4L2_PIX_FMT_RGB24, + .flags = 0, -+ .mmal = MMAL_ENCODING_BGR24, ++ .mmal = MMAL_ENCODING_RGB24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, @@ -102560,7 +102061,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + .name = "RGB24 (BE)", + .fourcc = V4L2_PIX_FMT_BGR24, + .flags = 0, -+ .mmal = MMAL_ENCODING_RGB24, ++ .mmal = MMAL_ENCODING_BGR24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, @@ -103434,6 +102935,13 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + else + camera_port->format.encoding = mfmt->mmal; + ++ if (dev->rgb_bgr_swapped) { ++ if (camera_port->format.encoding == MMAL_ENCODING_RGB24) ++ camera_port->format.encoding = MMAL_ENCODING_BGR24; ++ else if (camera_port->format.encoding == MMAL_ENCODING_BGR24) ++ camera_port->format.encoding = MMAL_ENCODING_RGB24; ++ } ++ + camera_port->format.encoding_variant = 0; + camera_port->es.video.width = f->fmt.pix.width; + camera_port->es.video.height = f->fmt.pix.height; @@ -103944,12 +103452,17 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + return ret; +} + ++#define MAX_SUPPORTED_ENCODINGS 20 ++ +/* MMAL instance and component init */ +static int __init mmal_init(struct bm2835_mmal_dev *dev) +{ + int ret; + struct mmal_es_format *format; + u32 bool_true = 1; ++ u32 supported_encodings[MAX_SUPPORTED_ENCODINGS]; ++ int param_size; ++ struct vchiq_mmal_component *camera; + + ret = vchiq_mmal_init(&dev->instance); + if (ret < 0) @@ -103961,21 +103474,48 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + if (ret < 0) + goto unreg_mmal; + -+ if (dev->component[MMAL_COMPONENT_CAMERA]->outputs < -+ MMAL_CAMERA_PORT_COUNT) { ++ camera = dev->component[MMAL_COMPONENT_CAMERA]; ++ if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { + ret = -EINVAL; + goto unreg_camera; + } + + ret = set_camera_parameters(dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA], ++ camera, + dev); + if (ret < 0) + goto unreg_camera; + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW].format; ++ /* There was an error in the firmware that meant the camera component ++ * produced BGR instead of RGB. ++ * This is now fixed, but in order to support the old firmwares, we ++ * have to check. ++ */ ++ dev->rgb_bgr_swapped = true; ++ param_size = sizeof(supported_encodings); ++ ret = vchiq_mmal_port_parameter_get(dev->instance, ++ &camera->output[MMAL_CAMERA_PORT_CAPTURE], ++ MMAL_PARAMETER_SUPPORTED_ENCODINGS, ++ &supported_encodings, ++ ¶m_size); ++ if (ret == 0) { ++ int i; ++ ++ for (i = 0; i < param_size/sizeof(u32); i++) { ++ if (supported_encodings[i] == MMAL_ENCODING_BGR24) { ++ /* Found BGR24 first - old firmware. */ ++ break; ++ } ++ if (supported_encodings[i] == MMAL_ENCODING_RGB24) { ++ /* Found RGB24 first ++ * new firmware, so use RGB24. ++ */ ++ dev->rgb_bgr_swapped = false; ++ break; ++ } ++ } ++ } ++ format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; @@ -103989,9 +103529,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + format->es->video.frame_rate.num = 0; /* Rely on fps_range */ + format->es->video.frame_rate.den = 1; + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO].format; ++ format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; @@ -104006,14 +103544,11 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + format->es->video.frame_rate.den = 1; + + vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO], ++ &camera->output[MMAL_CAMERA_PORT_VIDEO], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE].format; ++ format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + @@ -104035,8 +103570,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; + + vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE], ++ &camera->output[MMAL_CAMERA_PORT_CAPTURE], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + @@ -104355,10 +103889,10 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 +module_exit(bm2835_mmal_exit); diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h new file mode 100644 -index 0000000000000000000000000000000000000000..13f426f5ecdffeab714d658a6f8b76e63af5fcdb +index 0000000000000000000000000000000000000000..e6aeb7e7e381de65d6c6586205069a4c5cd33274 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -0,0 +1,144 @@ +@@ -0,0 +1,145 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -104470,6 +104004,7 @@ index 0000000000000000000000000000000000000000..13f426f5ecdffeab714d658a6f8b76e6 + unsigned int camera_num; + unsigned int max_width; + unsigned int max_height; ++ unsigned int rgb_bgr_swapped; +}; + +int bm2835_mmal_init_controls( @@ -109514,10 +109049,10 @@ index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7d + +#endif /* MMAL_VCHIQ_H */ -From 9d7240665df60a5e171ae73b048b2744135f5ca5 Mon Sep 17 00:00:00 2001 +From 2be247eeb689931f548636200e5b64c51daa3248 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 054/141] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 049/111] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -110029,10 +109564,10 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + return $trailer; +} -From 5237958e088b2951852b983ccaf0cc0d8fca3833 Mon Sep 17 00:00:00 2001 +From 4c81180311f93a3c6ed0f526f19d138a5c8c69cb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 055/141] scripts/dtc: Update to upstream version 1.4.1 +Subject: [PATCH 050/111] scripts/dtc: Update to upstream version 1.4.1 Includes the new localfixups format. @@ -110065,10 +109600,10 @@ Signed-off-by: Phil Elwell 10 files changed, 1029 insertions(+), 654 deletions(-) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c -index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66aa0e632c3 100644 +index 386f9563313f713f896236814de35811d145d121..2164d8fe5f98f123bbf74aa25e69891b31bd8c64 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c -@@ -458,6 +458,8 @@ static void fixup_phandle_references(struct check *c, struct node *dt, +@@ -482,6 +482,8 @@ static void fixup_phandle_references(struct check *c, struct node *dt, struct node *node, struct property *prop) { struct marker *m = prop->val.markers; @@ -110077,7 +109612,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a struct node *refnode; cell_t phandle; -@@ -466,11 +468,70 @@ static void fixup_phandle_references(struct check *c, struct node *dt, +@@ -490,11 +492,70 @@ static void fixup_phandle_references(struct check *c, struct node *dt, refnode = get_node_by_ref(dt, m->ref); if (! refnode) { @@ -110150,7 +109685,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a phandle = get_node_phandle(dt, refnode); *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } -@@ -652,6 +713,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, +@@ -676,6 +737,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, } TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); @@ -110196,7 +109731,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, -@@ -670,6 +770,8 @@ static struct check *check_table[] = { +@@ -696,6 +796,8 @@ static struct check *check_table[] = { &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, @@ -112656,7 +112191,7 @@ index 56212c8df660396b1d9bf6752e1121990e0789ab..f163b22b14b806b637c9fe996efd0276 void delete_labels(struct label **labels); diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c -index bd99fa2d33b85e873bd00178d6390d70f4afaa0d..238513780a5ba08c70d3995f45c35817fbabeb45 100644 +index ec14954f5810de3ad7262d5ee60e21b23565c155..f8f1e34b781f8c85d36a3d03f84ea5fe39f2e4b2 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -255,6 +255,204 @@ static int stringtable_insert(struct data *d, const char *str) @@ -112876,75 +112411,17 @@ index bd99fa2d33b85e873bd00178d6390d70f4afaa0d..238513780a5ba08c70d3995f45c35817 } diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h -index 11d93e6d8220c45d737175d22af4ab0ccaf871a1..2595dfda020fd9e03f0beff5006f229d5e393151 100644 +index ad9b05ae698b0495ecbda42ffcf4743555313a27..2595dfda020fd9e03f0beff5006f229d5e393151 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ --#define DTC_VERSION "DTC 1.4.1-gb06e55c8" +-#define DTC_VERSION "DTC 1.4.1-g53bf130b" +#define DTC_VERSION "DTC 1.4.1-g25efc119" -From b12e21f48fc616a5f49aa52e9cdf8a1bb9e4df1d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 056/141] fdt: Add support for the CONFIG_CMDLINE_EXTEND option - ---- - drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- - 1 file changed, 24 insertions(+), 5 deletions(-) - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 3349d2aa66346335fa3c84e485668bdbf77f6e52..1e2660514450f3f7a9d7e50c1d8cd94eb3381f48 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -960,19 +960,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); -- if (p != NULL && l > 0) -- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE - * is set in which case we override whatever was found earlier. -+ * -+ * However, it can be useful to be able to treat the default as -+ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. - */ -+ ((char *)data)[0] = '\0'; -+ - #ifdef CONFIG_CMDLINE --#ifndef CONFIG_CMDLINE_FORCE -- if (!((char *)data)[0]) -+ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ -+ if (p != NULL && l > 0) { -+#if defined(CONFIG_CMDLINE_EXTEND) -+ int len = strlen(data); -+ if (len > 0) { -+ strlcat(data, " ", COMMAND_LINE_SIZE); -+ len++; -+ } -+ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); -+#elif defined(CONFIG_CMDLINE_FORCE) -+ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); -+#else -+ /* Neither extend nor force - just override */ -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ } -+#else /* CONFIG_CMDLINE */ -+ if (p != NULL && l > 0) -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", (char*)data); - -From 1bf8aae5799796f3db0674dabfdcca5fd7976d49 Mon Sep 17 00:00:00 2001 +From 9e47d686a2c50cd8e20ce11f4430494df04fab12 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 057/141] BCM2708: Add core Device Tree support +Subject: [PATCH 051/111] BCM2708: Add core Device Tree support Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -113011,32 +112488,34 @@ squash: Add cprman to dt BCM270X_DT: Use clk_core for I2C interfaces --- arch/arm/boot/dts/Makefile | 31 + - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 154 +++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 144 +++ + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 164 +++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 154 +++ arch/arm/boot/dts/bcm2708-rpi-cm.dts | 102 ++ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 52 + arch/arm/boot/dts/bcm2708.dtsi | 40 + - arch/arm/boot/dts/bcm2708_common.dtsi | 438 ++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 154 +++ + arch/arm/boot/dts/bcm2708_common.dtsi | 471 ++++++++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 164 +++ arch/arm/boot/dts/bcm2709.dtsi | 102 ++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 201 ++++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 211 ++++ arch/arm/boot/dts/bcm2710.dtsi | 102 ++ arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ++ arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 + - arch/arm/boot/dts/overlays/Makefile | 99 ++ - arch/arm/boot/dts/overlays/README | 1161 ++++++++++++++++++++ + arch/arm/boot/dts/overlays/Makefile | 106 ++ + arch/arm/boot/dts/overlays/README | 1229 ++++++++++++++++++++ .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 53 + + arch/arm/boot/dts/overlays/ads1015-overlay.dts | 98 ++ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 89 ++ .../dts/overlays/akkordion-iqdacplus-overlay.dts | 46 + arch/arm/boot/dts/overlays/at86rf233-overlay.dts | 57 + .../audioinjector-wm8731-audio-overlay.dts | 39 + .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + arch/arm/boot/dts/overlays/dht11-overlay.dts | 39 + + .../boot/dts/overlays/dionaudio-loco-overlay.dts | 39 + arch/arm/boot/dts/overlays/dpi24-overlay.dts | 31 + arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 20 + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 29 + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 53 + - arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 45 + + arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 44 + .../boot/dts/overlays/gpio-poweroff-overlay.dts | 34 + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 + .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 + @@ -113044,16 +112523,17 @@ BCM270X_DT: Use clk_core for I2C interfaces .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 93 ++ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 +++ - arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 28 + + arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 43 + arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 +++ .../boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 26 + - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 73 ++ .../arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 61 + .../arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 37 + .../boot/dts/overlays/i2s-gpio28-31-overlay.dts | 18 + arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts | 13 + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 43 + - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 43 + + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 46 + + .../overlays/iqaudio-digi-wm8804-audio-overlay.dts | 47 + .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 43 + .../boot/dts/overlays/justboom-digi-overlay.dts | 39 + arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 + @@ -113064,7 +112544,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/mz61581-overlay.dts | 117 ++ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 27 + .../boot/dts/overlays/pi3-disable-bt-overlay.dts | 46 + - .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 ++ + .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 102 ++ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 106 ++ arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 ++ @@ -113082,6 +112562,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 + arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 47 + .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 81 ++ + .../boot/dts/overlays/sc16is752-spi1-overlay.dts | 61 + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 32 + arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts | 36 + arch/arm/boot/dts/overlays/sdio-overlay.dts | 36 + @@ -113090,6 +112571,8 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 ++ arch/arm/boot/dts/overlays/smi-overlay.dts | 37 + .../boot/dts/overlays/spi-gpio35-39-overlay.dts | 31 + + arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 + + arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 26 + arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 57 + arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 ++ arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 81 ++ @@ -113098,12 +112581,12 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 ++++ arch/arm/boot/dts/overlays/uart1-overlay.dts | 38 + - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 129 +++ + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 136 +++ arch/arm/boot/dts/overlays/vga666-overlay.dts | 30 + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 + arch/arm/boot/dts/overlays/wittypi-overlay.dts | 44 + - 93 files changed, 7269 insertions(+) + 99 files changed, 7749 insertions(+) create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts @@ -113119,12 +112602,14 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/Makefile create mode 100644 arch/arm/boot/dts/overlays/README create mode 100644 arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/ads1015-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/at86rf233-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dht11-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dpi24-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc-otg-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc2-overlay.dts @@ -113147,6 +112632,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/justboom-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/justboom-digi-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts @@ -113175,6 +112661,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-sense-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdio-overlay.dts @@ -113183,6 +112670,8 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/smi-nand-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/smi-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts @@ -113198,7 +112687,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/wittypi-overlay.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd0f7d812c 100644 +index 414b42710a366fc0f5708765d4ff0786e53a2b5b..93f2529ccbdfedb4b4e54898abf44911b47d2656 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1,5 +1,26 @@ @@ -113228,10 +112717,10 @@ index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -839,10 +860,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb +@@ -892,10 +913,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb + dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ + aspeed-ast2500-evb.dtb + +targets += dtbs dtbs_install +targets += $(dtb-y) @@ -113251,10 +112740,10 @@ index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd +endif diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts new file mode 100644 -index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6e2eee966 +index 0000000000000000000000000000000000000000..db2705afa4e2229c961fe88bcae46233a4ce4542 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,154 @@ +@@ -0,0 +1,164 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -113294,6 +112783,11 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -113377,6 +112871,11 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -113411,10 +112910,10 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf8023681478bcc +index 0000000000000000000000000000000000000000..beae0371477cc41f27006ef3f1ef7268839177df --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,144 @@ +@@ -0,0 +1,154 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -113454,6 +112953,11 @@ index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf80236 + brcm,pins = <28 29 30 31>; + brcm,function = <6>; /* alt2 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -113531,6 +113035,11 @@ index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf80236 + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -113773,10 +113282,10 @@ index 0000000000000000000000000000000000000000..f5a44cd4fef0ee221ed6ae1c43ca81da +}; diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f347098219d468 +index 0000000000000000000000000000000000000000..74434b986e3fbb257debfc79caef9fa68f750043 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,438 @@ +@@ -0,0 +1,471 @@ +#include "dt-bindings/clock/bcm2835.h" +#include +#include "dt-bindings/power/raspberrypi-power.h" @@ -113835,10 +113344,32 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + <1 24>, + <1 25>, + <1 26>, -+ <1 27>; ++ /* dma channel 11-14 share one irq */ ++ <1 27>, ++ <1 27>, ++ <1 27>, ++ <1 27>, ++ /* unused shared irq for all channels */ ++ <1 28>; ++ interrupt-names = "dma0", ++ "dma1", ++ "dma2", ++ "dma3", ++ "dma4", ++ "dma5", ++ "dma6", ++ "dma7", ++ "dma8", ++ "dma9", ++ "dma10", ++ "dma11", ++ "dma12", ++ "dma13", ++ "dma14", ++ "dma-shared-all"; + + #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x0f35>; ++ brcm,dma-channel-mask = <0x7f34>; + }; + + intc: interrupt-controller@7e00b200 { @@ -113940,7 +113471,7 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + * add more gpios if necessary as <&gpio 6 1> + * (but do not forget to make them output!) + */ -+ cs-gpios = <0>, <0>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; + }; + + i2c0: i2c@7e205000 { @@ -113959,6 +113490,17 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + status = "disabled"; + }; + ++ dpi: dpi@7e208000 { ++ compatible = "brcm,bcm2835-dpi"; ++ reg = <0x7e208000 0x8c>; ++ clocks = <&cprman BCM2835_CLOCK_VPU>, ++ <&cprman BCM2835_CLOCK_DPI>; ++ clock-names = "core", "pixel"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + pixelvalve1: pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; @@ -114217,10 +113759,10 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 +}; diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff857a2603 +index 0000000000000000000000000000000000000000..eca72bd0d6e891b0096ac97b68c2da92199aa851 --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,154 @@ +@@ -0,0 +1,164 @@ +/dts-v1/; + +#include "bcm2709.dtsi" @@ -114260,6 +113802,11 @@ index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -114343,6 +113890,11 @@ index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -114485,10 +114037,10 @@ index 0000000000000000000000000000000000000000..a8cfd7c4df5bcf7692d13882833c9785 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfaff14c151 +index 0000000000000000000000000000000000000000..a72e6e5a0ac0b2492db3d8034a5196b3e19ae008 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,201 @@ +@@ -0,0 +1,211 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -114552,6 +114104,11 @@ index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfa + brcm,function; + brcm,pull; + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 41>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -114656,6 +114213,11 @@ index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfa + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + chosen { + bootargs = "8250.nr_uarts=1"; @@ -114935,10 +114497,10 @@ index 0000000000000000000000000000000000000000..9c4000fc686a9882b9ddde24fdcf937d +}; diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822924924cd +index 0000000000000000000000000000000000000000..7e740c894436e8fd9ed9b451e5b1f7888806922f --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,99 @@ +@@ -0,0 +1,106 @@ +ifeq ($(CONFIG_OF),y) + +# Overlays for the Raspberry Pi platform @@ -114954,15 +114516,17 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +endif + +dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo +dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo +dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo +dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo +dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo +dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo +dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo +dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo +dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo @@ -114972,19 +114536,21 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo +dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2s-mmap.dtbo +dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo +dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo +dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo @@ -115009,20 +114575,23 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo +dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo +dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo +dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo +dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo +dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo @@ -115040,10 +114609,10 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +clean-files := *.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README new file mode 100644 -index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776fe84e52a +index 0000000000000000000000000000000000000000..780bf6dda5a6694cb312140329120fda3b0c2f61 --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,1161 @@ +@@ -0,0 +1,1229 @@ +Introduction +============ + @@ -115214,6 +114783,28 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: ads1015 ++Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C ++Load: dtoverlay=ads1015,= ++Params: addr I2C bus address of device. Set based on how the ++ addr pin is wired. (default=0x48 assumes addr ++ is pulled to GND) ++ cha_enable Enable virtual channel a. (default=true) ++ cha_cfg Set the configuration for virtual channel a. ++ (default=4 configures this channel for the ++ voltage at A0 with respect to GND) ++ cha_datarate Set the datarate (samples/sec) for this channel. ++ (default=4 sets 1600 sps) ++ cha_gain Set the gain of the Programmable Gain ++ Amplifier for this channel. (default=2 sets the ++ full scale of the channel to 2.048 Volts) ++ ++ Channel (ch) parameters can be set for each enabled channel. ++ A maximum of 4 channels can be enabled (letters a thru d). ++ For more information refer to the device datasheet at: ++ http://www.ti.com/lit/ds/symlink/ads1015.pdf ++ ++ +Name: ads7846 +Info: ADS7846 Touch controller +Load: dtoverlay=ads7846,= @@ -115292,6 +114883,12 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + (default 4) + + ++Name: dionaudio-loco ++Info: Configures the Dion Audio LOCO DAC-AMP ++Load: dtoverlay=dionaudio-loco ++Params: ++ ++ +Name: dpi24 +Info: Overlay for a generic 24-bit DPI display + This uses GPIOs 0-27 (so no I2C, uart etc.), and activates the output @@ -115491,6 +115088,9 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + + trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) + ++ wakeup-source Specify that the RTC can be used as a wakeup ++ source ++ + +Name: i2c0-bcm2708 +Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations @@ -115561,6 +115161,19 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) ++ auto_mute_amp If specified, unmute/mute the IQaudIO amp when ++ starting/stopping audio playback. ++ unmute_amp If specified, unmute the IQaudIO amp once when ++ the DAC driver module loads. ++ ++ ++Name: iqaudio-digi-wm8804-audio ++Info: Configures the IQAudIO Digi WM8804 audio card ++Load: dtoverlay=iqaudio-digi-wm8804-audio,= ++Params: card_name Override the default, "IQAudIODigi", card name. ++ dai_name Override the default, "IQAudIO Digi", dai name. ++ dai_stream_name Override the default, "IQAudIO Digi HiFi", ++ dai stream name. + + +Name: justboom-dac @@ -115616,7 +115229,7 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + + +Name: mcp23017 -+Info: Configures the MCP23017 I2C port expander ++Info: Configures the MCP23017 I2C GPIO expander +Load: dtoverlay=mcp23017,= +Params: gpiopin Gpio pin connected to the INTA output of the + MCP23017 (default: 4) @@ -115708,7 +115321,9 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + N.B. It is also necessary to edit /lib/systemd/system/hciuart.service + and replace ttyAMA0 with ttyS0, unless you have a system with udev rules + that create /dev/serial0 and /dev/serial1, in which case use -+ /dev/serial1 instead because it will always be correct. ++ /dev/serial1 instead because it will always be correct. Furthermore, ++ you must also set core_freq=250 in config.txt or the miniuart will not ++ work. +Load: dtoverlay=pi3-miniuart-bt +Params: + @@ -115894,6 +115509,16 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: sc16is752-spi1 ++Info: Overlay for the NXP SC16IS752 Dual UART with SPI Interface ++ Enables the chip on SPI1. ++ N.B.: spi1 is only accessible on devices with a 40pin header, eg: ++ A+, B+, Zero and PI2 B; as well as the Compute Module. ++ ++Load: dtoverlay=sc16is752-spi1,= ++Params: int_pin GPIO used for IRQ (default 24) ++ ++ +Name: sdhost +Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock. + N.B. This overlay is designed for situations where the mmc driver is @@ -115996,6 +115621,18 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: spi-rtc ++Info: Adds support for a number of SPI Real Time Clock devices ++Load: dtoverlay=spi-rtc,= ++Params: pcf2123 Select the PCF2123 device ++ ++ ++Name: spi0-hw-cs ++Info: Re-enables hardware CS/CE (chip selects) for SPI0 ++Load: dtoverlay=spi0-hw-cs ++Params: ++ ++ +Name: spi1-1cs +Info: Enables spi1 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node @@ -116264,6 +115901,110 @@ index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c6 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/ads1015-overlay.dts b/arch/arm/boot/dts/overlays/ads1015-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..02b9de46299bae8f22e1a665a482c0cb99cd30c9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts +@@ -0,0 +1,98 @@ ++/* ++ * 2016 - Erik Sejr ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ /* ----------- ADS1015 ------------ */ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ads1015: ads1015 { ++ compatible = "ti,ads1015"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "i2c_arm/ads1015"; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_a: channel_a { ++ reg = <4>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_b: channel_b { ++ reg = <5>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_c: channel_c { ++ reg = <6>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_d: channel_d { ++ reg = <7>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ addr = <&ads1015>,"reg:0"; ++ cha_enable = <0>,"=1"; ++ cha_cfg = <&channel_a>,"reg:0"; ++ cha_gain = <&channel_a>,"ti,gain:0"; ++ cha_datarate = <&channel_a>,"ti,datarate:0"; ++ chb_enable = <0>,"=2"; ++ chb_cfg = <&channel_b>,"reg:0"; ++ chb_gain = <&channel_b>,"ti,gain:0"; ++ chb_datarate = <&channel_b>,"ti,datarate:0"; ++ chc_enable = <0>,"=3"; ++ chc_cfg = <&channel_c>,"reg:0"; ++ chc_gain = <&channel_c>,"ti,gain:0"; ++ chc_datarate = <&channel_c>,"ti,datarate:0"; ++ chd_enable = <0>,"=4"; ++ chd_cfg = <&channel_d>,"reg:0"; ++ chd_gain = <&channel_d>,"ti,gain:0"; ++ chd_datarate = <&channel_d>,"ti,datarate:0"; ++ }; ++ ++}; diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..edf2dc9d5d5f6830508edabf2d04c42d27ba9b41 @@ -116593,6 +116334,51 @@ index 0000000000000000000000000000000000000000..9bf67fd57bada3c3e06c09744fb18476 + <&dht11>,"gpios:4"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..3930f412bca4454c6673fb19859e607b360bc6c3 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for Dion Audio LOCO DAC-AMP ++ ++/* ++ * PCM5242 DAC (in hardware mode) and TPA3118 AMP. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "dionaudio,loco-pcm5242-tpa3118"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/dpi24-overlay.dts b/arch/arm/boot/dts/overlays/dpi24-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..e4dbe40218a008ef4028c1214740c3d6bc574724 @@ -116752,10 +116538,10 @@ index 0000000000000000000000000000000000000000..db8a8feed94c010e368065fdd88b0286 +}; diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..a2d6bc79f4cd2604e6c65c000668cbb228327fe6 +index 0000000000000000000000000000000000000000..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 --- /dev/null +++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -@@ -0,0 +1,45 @@ +@@ -0,0 +1,44 @@ +// Definitions for ir-gpio module +/dts-v1/; +/plugin/; @@ -116794,8 +116580,7 @@ index 0000000000000000000000000000000000000000..a2d6bc79f4cd2604e6c65c000668cbb2 + __overrides__ { + // parameters + gpio_pin = <&gpio_ir>,"gpios:4", -+ <&gpio_ir_pins>,"brcm,pins:0", -+ <&gpio_ir_pins>,"brcm,pull:0"; // pin number ++ <&gpio_ir_pins>,"brcm,pins:0"; // pin number + gpio_pull = <&gpio_ir_pins>,"brcm,pull:0"; // pull-up/down state + + rc-map-name = <&gpio_ir>,"linux,rc-map-name"; // default rc map @@ -117288,10 +117073,10 @@ index 0000000000000000000000000000000000000000..8018aebde8e557f45ffd63eb86f6c7a1 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..2a2dc986770cfb036492ba8de19cbaff521c5fd5 +index 0000000000000000000000000000000000000000..b72b32e936774d901bc253b06e025c2dd48bdb1b --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -@@ -0,0 +1,28 @@ +@@ -0,0 +1,43 @@ +// Overlay for i2c_gpio bitbanging host bus. +/dts-v1/; +/plugin/; @@ -117313,6 +117098,21 @@ index 0000000000000000000000000000000000000000..2a2dc986770cfb036492ba8de19cbaff + }; + }; + }; ++ ++ fragment@1 { ++ target-path = "/aliases"; ++ __overlay__ { ++ i2c_gpio = "/i2c@0"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/__symbols__"; ++ __overlay__ { ++ i2c_gpio = "/i2c@0"; ++ }; ++ }; ++ + __overrides__ { + i2c_gpio_sda = <&i2c_gpio>,"gpios:4"; + i2c_gpio_scl = <&i2c_gpio>,"gpios:16"; @@ -117499,10 +117299,10 @@ index 0000000000000000000000000000000000000000..d1ffd2326669e46ad68939f94713cc99 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..40656474dfc16505433221a745c1d129c2737399 +index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194fa3462435 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,69 @@ +@@ -0,0 +1,73 @@ +// Definitions for several I2C based Real Time Clocks +/dts-v1/; +/plugin/; @@ -117570,6 +117370,10 @@ index 0000000000000000000000000000000000000000..40656474dfc16505433221a745c1d129 + pcf8523 = <&pcf8523>,"status"; + pcf8563 = <&pcf8563>,"status"; + trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; ++ wakeup-source = <&ds1339>,"wakeup-source?", ++ <&ds3231>,"wakeup-source?", ++ <&mcp7940x>,"wakeup-source?", ++ <&mcp7941x>,"wakeup-source?"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts @@ -117776,10 +117580,10 @@ index 0000000000000000000000000000000000000000..0d35c85382bb5766b3eeb9de1bd4a946 +}; diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..1d0663e19e7bf7395957ae49b501e5b15ecf3881 +index 0000000000000000000000000000000000000000..d4bad8742a985e2f15eed19ca52ef283a74fefb9 --- /dev/null +++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +// Definitions for IQaudIO DAC+ +/dts-v1/; +/plugin/; @@ -117812,15 +117616,71 @@ index 0000000000000000000000000000000000000000..1d0663e19e7bf7395957ae49b501e5b1 + + fragment@2 { + target = <&sound>; -+ frag2: __overlay__ { ++ iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; + i2s-controller = <&i2s>; ++ mute-gpios = <&gpio 22 0>; ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ 24db_digital_gain = <&iqaudio_dac>,"iqaudio,24db_digital_gain?"; ++ auto_mute_amp = <&iqaudio_dac>,"iqaudio-dac,auto-mute-amp?"; ++ unmute_amp = <&iqaudio_dac>,"iqaudio-dac,unmute-amp?"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..da4fbfdfdbbbcf2505b9eb4789ddb779ec72cea8 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +@@ -0,0 +1,47 @@ ++// Definitions for IQAudIO Digi WM8804 audio board ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8804@3b { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ // DVDD-supply = <®_3v3>; ++ // PVDD-supply = <®_3v3>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ wm8804_digi: __overlay__ { ++ compatible = "iqaudio,wm8804-digi"; ++ i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + __overrides__ { -+ 24db_digital_gain = <&frag2>,"iqaudio,24db_digital_gain?"; ++ card_name = <&wm8804_digi>,"wm8804-digi,card-name"; ++ dai_name = <&wm8804_digi>,"wm8804-digi,dai-name"; ++ dai_stream_name = <&wm8804_digi>,"wm8804-digi,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts @@ -119331,7 +119191,7 @@ index 0000000000000000000000000000000000000000..c021d02bb75ff5ceb5c5066d00e4bca9 +}; diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..1523eae9c39997aa68cfa583ada92a92395bb1e0 +index 0000000000000000000000000000000000000000..a442c8f0ec01b7503f32e070683a984e895f5668 --- /dev/null +++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts @@ -0,0 +1,34 @@ @@ -119350,7 +119210,7 @@ index 0000000000000000000000000000000000000000..1523eae9c39997aa68cfa583ada92a92 + }; + + fragment@1 { -+ target = <&soc>; ++ target-path = "/"; + __overlay__ { + pcm1794a-codec { + #sound-dai-cells = <0>; @@ -119672,6 +119532,73 @@ index 0000000000000000000000000000000000000000..16b1247bfa618ff85936ddf78c3aea58 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..d0a9e82dbea143e80249064873d8b9f0b56b2eaa +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts +@@ -0,0 +1,61 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&gpio>; ++ __overlay__ { ++ spi1_pins: spi1_pins { ++ brcm,pins = <19 20 21>; ++ brcm,function = <3>; /* alt4 */ ++ }; ++ ++ spi1_cs_pins: spi1_cs_pins { ++ brcm,pins = <18>; ++ brcm,function = <1>; /* output */ ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ frag1: __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pins &spi1_cs_pins>; ++ cs-gpios = <&gpio 18 1>; ++ status = "okay"; ++ ++ sc16is752: sc16is752@0 { ++ compatible = "nxp,sc16is752"; ++ reg = <0>; /* CE0 */ ++ clocks = <&sc16is752_clk>; ++ interrupt-parent = <&gpio>; ++ interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */ ++ #gpio-controller; ++ #gpio-cells = <2>; ++ spi-max-frequency = <4000000>; ++ ++ sc16is752_clk: sc16is752_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <14745600>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&aux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <&sc16is752>,"interrupts:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..a431177a1c9d320d5432ea448ad4d0f696c34525 @@ -120002,6 +119929,77 @@ index 0000000000000000000000000000000000000000..9648063d5963f2f6ec8f31038f3af582 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..88d1800d63c9f6727b46d4e590c8e96c671c3755 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spidev0>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ rtc-pcf2123@0 { ++ compatible = "nxp,rtc-pcf2123"; ++ spi-max-frequency = <5000000>; ++ spi-cs-high = <1>; ++ reg = <0>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ pcf2123 = <0>, "=0=1"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..ef9845f7184ee1ea90e8bdc23493b1cbbdc21896 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device tree overlay to re-enable hardware CS for SPI0 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0_cs_pins>; ++ __overlay__ { ++ brcm,pins = <8 7>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..71c243947004fa887998065df9c259b50edfa428 @@ -120728,10 +120726,10 @@ index 0000000000000000000000000000000000000000..fa73e1feaeb1bf53a6755e81a998e71c +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..a4ca2cabd4cd19d3a82ad1135604dfa52784fb3f +index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -0,0 +1,129 @@ +@@ -0,0 +1,136 @@ +/* + * vc4-kms-v3d-overlay.dts + */ @@ -120853,6 +120851,13 @@ index 0000000000000000000000000000000000000000..a4ca2cabd4cd19d3a82ad1135604dfa5 + }; + }; + ++ fragment@15 { ++ target-path = "/soc/dma"; ++ __overlay__ { ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; @@ -121040,10 +121045,10 @@ index 0000000000000000000000000000000000000000..8498134fdbb3912e9ce18282b53084d8 + +}; -From 02be32ed3334f0edb4fcf4d61917c66c8442e0c0 Mon Sep 17 00:00:00 2001 +From 3e5b57715228496ea48c118917cb557d5c69ad74 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 20:00:21 +0000 -Subject: [PATCH 058/141] BCM270X_DT: Add a .dtbo target, use for overlays +Subject: [PATCH 052/111] BCM270X_DT: Add a .dtbo target, use for overlays Change the filenames and extensions to keep the pre-DDT style of overlay (-overlay.dtb) distinct from new ones that use a @@ -121105,10 +121110,10 @@ index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d24 .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index ddf83d0181e73d30fb86f68c0fa0a3f888335c0c..c819ddc5b7662eb03c158f9d8fcf8fe965bf577b 100644 +index e7df0f5db7ec273f45b755668815ce96ba1ffe46..8f50f48329b9460b7268322ea4fd99cf764134ec 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -306,6 +306,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ +@@ -311,6 +311,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) @@ -121126,10 +121131,10 @@ index ddf83d0181e73d30fb86f68c0fa0a3f888335c0c..c819ddc5b7662eb03c158f9d8fcf8fe9 # Bzip2 -From d19413c0965c18171ae81168fbc7b726496c7496 Mon Sep 17 00:00:00 2001 +From 6a36f694a362e7836a7ee1c0763920ff90ff8d1e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 8 Apr 2016 17:43:27 +0100 -Subject: [PATCH 059/141] BCM270X_DT: Don't generate "linux,phandle" props +Subject: [PATCH 053/111] BCM270X_DT: Don't generate "linux,phandle" props The EPAPR standard says to use "phandle" properties to store phandles, rather than the deprecated "linux,phandle" version. By default, dtc @@ -121142,10 +121147,10 @@ Signed-off-by: Phil Elwell 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index c819ddc5b7662eb03c158f9d8fcf8fe965bf577b..b36099ab736a1373f61067a26c6e0d599d6c9a35 100644 +index 8f50f48329b9460b7268322ea4fd99cf764134ec..c1c3ceb265a3fd223b8a2a0a548ddad34f88ef4e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -308,7 +308,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE +@@ -313,7 +313,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE quiet_cmd_dtco = DTCO $@ cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ @@ -121155,10 +121160,10 @@ index c819ddc5b7662eb03c158f9d8fcf8fe965bf577b..b36099ab736a1373f61067a26c6e0d59 -d $(depfile).dtc.tmp $(dtc-tmp) ; \ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) -From 1f046b8270b489dae7f2b58bff14930c274ea875 Mon Sep 17 00:00:00 2001 +From 2f0ee24bd8b41a4c6616319f888f805e65db0159 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 060/141] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 054/111] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -121188,7 +121193,7 @@ See: https://github.com/raspberrypi/linux/issues/1064 create mode 100644 drivers/leds/trigger/ledtrig-input.c diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 61143f55597e42f9b45fe4efe33a1c51614b22b4..e98df59ae47faf14b0cde1d6330a1d75b5ceb651 100644 +index 8229f063b483c77cf993891cb2bc2e7e9239ee6a..7a960e0bc2c7f918c880f724c22c773818f7df23 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -46,8 +46,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, @@ -121232,10 +121237,10 @@ index 61143f55597e42f9b45fe4efe33a1c51614b22b4..e98df59ae47faf14b0cde1d6330a1d75 state = !!gpiod_get_value_cansleep(led_dat->gpiod); else diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig -index 5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034..eb98cca4c239e5bb5c4abf7c731021ae56f3e91d 100644 +index 9893d911390daa4dd77986065ebde50b517d6b72..fbbe765e2fd2a593c2b1b40f71e4cb63d6339d80 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig -@@ -108,4 +108,11 @@ config LEDS_TRIGGER_CAMERA +@@ -116,6 +116,13 @@ config LEDS_TRIGGER_CAMERA This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. @@ -121246,16 +121251,19 @@ index 5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034..eb98cca4c239e5bb5c4abf7c731021ae + This allows the GPIOs assigned to be LEDs to be initialised to inputs. + If unsure, say Y. + - endif # LEDS_TRIGGERS + config LEDS_TRIGGER_PANIC + bool "LED Panic Trigger" + depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile -index 1abf48dacf7ebfcfb8208f7ae7bdf29d7c11ba32..c03afdc34404a406a658326bcf28a2f22b4f4122 100644 +index 8cc64a4f4e255c1dd9fafde1ccd72d5a08ccbd5b..9452fe5640fec612f0e5e6a072d1af26d855847d 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o +@@ -9,4 +9,5 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o + obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o diff --git a/drivers/leds/trigger/ledtrig-input.c b/drivers/leds/trigger/ledtrig-input.c new file mode 100644 index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05bae063e3b @@ -121317,13 +121325,13 @@ index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05b +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h -index f203a8f89d30d0f3e214b43d2c72efea1bdad9f9..555cf15e87ee03c75d4bd836a3341645b020e857 100644 +index e5e7f2e80a54dd2f15737a3ef478287458641f6e..68086e559d963ed06a0ceb916f9b1555b213ddf8 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -50,6 +50,9 @@ struct led_classdev { - #define LED_SYSFS_DISABLE (1 << 22) - #define LED_DEV_CAP_FLASH (1 << 23) - #define LED_HW_PLUGGABLE (1 << 24) +@@ -52,6 +52,9 @@ struct led_classdev { + #define LED_DEV_CAP_FLASH (1 << 24) + #define LED_HW_PLUGGABLE (1 << 25) + #define LED_PANIC_INDICATOR (1 << 26) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT (1 << 30) +#define SET_GPIO_OUTPUT (1 << 31) @@ -121331,10 +121339,10 @@ index f203a8f89d30d0f3e214b43d2c72efea1bdad9f9..555cf15e87ee03c75d4bd836a3341645 /* Set LED brightness level * Must not sleep. Use brightness_set_blocking for drivers -From 9470cbd8875a8bdfd64b8dc63d7fd1a0174f14eb Mon Sep 17 00:00:00 2001 +From ea2507545d3bab2dcacab277a315e73e1d6e47de Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 061/141] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 055/111] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -121349,7 +121357,7 @@ Signed-off-by: Siarhei Siamashka 2 files changed, 35 insertions(+) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index 4e73b6f6b1c0547877af572dfca953748d9eabc3..d3a8cc3f7dde67e904c695edac39a97b9beab678 100644 +index 76c1ad96fb37d4f07bbde6462f54825f566acbac..1d3b35ec8e393aac43dca0ec4566f7a7d0d8998a 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) @@ -121427,10 +121435,10 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6d #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -From 572db909d29b86ecb3be3013d26a1238467dbde5 Mon Sep 17 00:00:00 2001 +From 87bd3668ff68813fed9de9d49038b3e46ecf771f Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 062/141] Speed up console framebuffer imageblit function +Subject: [PATCH 056/111] 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 @@ -121639,10 +121647,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From f8dff723eaf7d7a34d25c6ff717d03bb2fc7c0da Mon Sep 17 00:00:00 2001 +From 55a2f849b57c8ba767bdb979eab54a4072aeaa90 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 063/141] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 057/111] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) 1-wire: Add support for configuring pin for w1-gpio kernel module @@ -121808,10 +121816,10 @@ index a373ae69d9f6ef8a5925dbd5004cd5e9b8fc5c05..080e5976e2a6b75965ed753ddf29648c } diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 56a49ba41d83c0945203827946ba35dcb79897b0..881d72879b27fed8697ded8962e2f7c16796837d 100644 +index 129895f562b06630b464f2579dc9e5bdc105f35e..737a75b594c69716eae8d37479a40031b3045494 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h -@@ -171,6 +171,12 @@ struct w1_bus_master +@@ -173,6 +173,12 @@ struct w1_bus_master u8 (*set_pullup)(void *, int); @@ -121850,7 +121858,7 @@ index 20f766afa4c7d7b8116565687541f84184fe61f4..c4fbdb1f25e961f9f7bacbac7b52a6d7 mutex_lock(&w1_mlock); /* Search for the first available id (starting at 1). */ diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c -index 282092421cc9ee29d541e8722139387d0060c7db..fd0550f263f789b94038fd2fb2931022333029c2 100644 +index f4bc8c100a01b1f04a62ebca2528c51c05f40520..77527e37c7e749754cd3dc2241cdcb64f178166c 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) @@ -121892,10 +121900,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From c9fed34e3fbeb6d2573dc0a4caa6f68dc8d8a9cd Mon Sep 17 00:00:00 2001 +From 528bf1a9250bf36da5a68a23e567f159fe6b2d84 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 064/141] config: Enable CONFIG_MEMCG, but leave it disabled +Subject: [PATCH 058/111] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -121903,10 +121911,10 @@ Subject: [PATCH 064/141] config: Enable CONFIG_MEMCG, but leave it disabled 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414c0df239b 100644 +index 75c0ff00aca60d298062755539e83cbfeaffaaf2..d3db7d24554254f8a33adb2ff9a0540262c78caa 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5587,7 +5587,7 @@ int __init cgroup_init_early(void) +@@ -5591,7 +5591,7 @@ int __init cgroup_init_early(void) return 0; } @@ -121915,7 +121923,7 @@ index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414 /** * cgroup_init - cgroup initialization -@@ -6117,6 +6117,28 @@ static int __init cgroup_no_v1(char *str) +@@ -6121,6 +6121,28 @@ static int __init cgroup_no_v1(char *str) } __setup("cgroup_no_v1=", cgroup_no_v1); @@ -121945,2970 +121953,24 @@ index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414 * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -From e8b127ec4acfb3783529d0df323a2255bd647529 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 065/141] 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 | 5 ++++ - sound/soc/codecs/Makefile | 2 ++ - sound/soc/codecs/pcm5102a.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 77 insertions(+) - create mode 100644 sound/soc/codecs/pcm5102a.c - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 7ef3a0c16478d707b1ef843aecf0631a51813fb1..4308f90e688fce37f982ad4af0891a2411bcf420 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -100,6 +100,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_RT298 if I2C - select SND_SOC_RT5514 if I2C - select SND_SOC_RT5616 if I2C -+ select SND_SOC_PCM5102A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -631,6 +632,10 @@ config SND_SOC_RT5616 - tristate "Realtek RT5616 CODEC" - depends on I2C - -+config SND_SOC_PCM5102A -+ tristate -+ depends on I2C -+ - config SND_SOC_RT5631 - tristate "Realtek ALC5631/RT5631 CODEC" - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 185a712a7fe763bbba79fa1f4969cf5ba5424753..75220170be30c6144d503900e0f66ecd8de9ba6f 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -98,6 +98,7 @@ snd-soc-rt286-objs := rt286.o - snd-soc-rt298-objs := rt298.o - snd-soc-rt5514-objs := rt5514.o - snd-soc-rt5616-objs := rt5616.o -+snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-rt5645-objs := rt5645.o -@@ -307,6 +308,7 @@ obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o - obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o - obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o - obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.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_RT5645) += snd-soc-rt5645.o -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -new file mode 100644 -index 0000000000000000000000000000000000000000..7c6598e717c523bc2e717861492a622ce66486c7 ---- /dev/null -+++ b/sound/soc/codecs/pcm5102a.c -@@ -0,0 +1,70 @@ -+/* -+ * 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 const struct of_device_id pcm5102a_of_match[] = { -+ { .compatible = "ti,pcm5102a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm5102a_of_match); -+ -+static struct platform_driver pcm5102a_codec_driver = { -+ .probe = pcm5102a_probe, -+ .remove = pcm5102a_remove, -+ .driver = { -+ .name = "pcm5102a-codec", -+ .owner = THIS_MODULE, -+ .of_match_table = pcm5102a_of_match, -+ }, -+}; -+ -+module_platform_driver(pcm5102a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 977c8d769c949e7cf637af908b296870de72c356 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 066/141] 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 | 4 ++ - sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 134 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index c5070aec5996aafb2d9daaf75163e16a29bc6892..ce81f14a88d08c90fb565cf3d60321a9b9a1fcee 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -7,3 +7,10 @@ config SND_BCM2835_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2835 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 || SND_BCM2835_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 bc816b71e5a40958953bf7bf7e7bd08342e87738..b877d386363d935deefda3664089a4ae5b33b889 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o - - obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,123 @@ -+/* -+ * 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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_dac_driver = { -+ .driver = { -+ .name = "snd-hifiberry-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dac_of_match, -+ }, -+ .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"); - -From bc7c4a474d3dc6280e3934bb217a6d8ca962465c Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 067/141] ASoC: Add support for Rpi-DAC - ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-dac.c | 119 ++++++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/Kconfig | 9 ++++ - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm1794a.c | 69 +++++++++++++++++++++++++ - 6 files changed, 208 insertions(+) - create mode 100644 sound/soc/bcm/rpi-dac.c - create mode 100644 sound/soc/codecs/pcm1794a.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index ce81f14a88d08c90fb565cf3d60321a9b9a1fcee..900de22369a66758bbe49861238b647bd2ca037e 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -14,3 +14,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 || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM1794A -+ help -+ Say Y or M if you want to add support for RPi-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b877d386363d935deefda3664089a4ae5b33b889..99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,5 +5,7 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1337a1c73 ---- /dev/null -+++ b/sound/soc/bcm/rpi-dac.c -@@ -0,0 +1,119 @@ -+/* -+ * 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 = "RPi-DAC", -+ .stream_name = "RPi-DAC 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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_rpi_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_rpi_dac_of_match[] = { -+ { .compatible = "rpi,rpi-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_rpi_dac_of_match); -+ -+static struct platform_driver snd_rpi_rpi_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_rpi_dac_of_match, -+ }, -+ .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 4308f90e688fce37f982ad4af0891a2411bcf420..513ab55fdc67af50f110f13ed6f6d6bb3740561e 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -101,6 +101,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_RT5514 if I2C - select SND_SOC_RT5616 if I2C - select SND_SOC_PCM5102A if I2C -+ select SND_SOC_PCM1794A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -632,6 +633,14 @@ config SND_SOC_RT5616 - tristate "Realtek RT5616 CODEC" - depends on I2C - -+config SND_SOC_RT298 -+ tristate -+ depends on I2C -+ -+config SND_SOC_PCM1794A -+ tristate -+ depends on I2C -+ - config SND_SOC_PCM5102A - tristate - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 75220170be30c6144d503900e0f66ecd8de9ba6f..b87e84543459776026be1b9a598fcc0c65abe987 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -98,6 +98,7 @@ snd-soc-rt286-objs := rt286.o - snd-soc-rt298-objs := rt298.o - snd-soc-rt5514-objs := rt5514.o - snd-soc-rt5616-objs := rt5616.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 -@@ -308,6 +309,7 @@ obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o - obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o - obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o - obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.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 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd843e17f4 ---- /dev/null -+++ b/sound/soc/codecs/pcm1794a.c -@@ -0,0 +1,69 @@ -+/* -+ * 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 const struct of_device_id pcm1794a_of_match[] = { -+ { .compatible = "ti,pcm1794a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm1794a_of_match); -+ -+static struct platform_driver pcm1794a_codec_driver = { -+ .probe = pcm1794a_probe, -+ .remove = pcm1794a_remove, -+ .driver = { -+ .name = "pcm1794a-codec", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(pcm1794a_of_match), -+ }, -+}; -+ -+module_platform_driver(pcm1794a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 0f8e1f220bc0e4baf68c3e75884372e61cbde386 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 068/141] 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 | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, - blen = 0x1; - break; - case 24: -+ case 32: - blen = 0x2; - break; - default: -@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { - }; - - #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 | \ -@@ -543,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { - }; - - static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { -- .idle_bias_off = true, -+ .idle_bias_off = false, - - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), - -From 5cb10ee9bb63758c8d125bb00222f3c543c647ad Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 069/141] ASoC: BCM:Add support for HiFiBerry Digi. Driver is - based on the patched WM8804 driver. - -Signed-off-by: Daniel Matuschek - -Add a parameter to turn off SPDIF output if no audio is playing - -This patch adds the paramater auto_shutdown_output to the kernel module. -Default behaviour of the module is the same, but when auto_shutdown_output -is set to 1, the SPDIF oputput will shutdown if no stream is playing. - -bugfix for 32kHz sample rate, was missing - -HiFiBerry Digi: set SPDIF status bits for sample rate - -The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. -While this is optional, some DACs and receivers do not accept this signal. This patch -adds the sample rate bits in the SPDIF status block. ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 233 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_digi.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 900de22369a66758bbe49861238b647bd2ca037e..a34aff27bb3010f58773edb942adccc193ea0d26 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -15,6 +15,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 || SND_BCM2835_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 || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb..4d53c58dc6ba41116d1fa210b6ba08ee75526dd2 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,7 +5,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 - - 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 -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,224 @@ -+/* -+ * 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 short int auto_shutdown_output = 0; -+module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); -+ -+ -+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_startup(struct snd_pcm_substream *substream) { -+ /* turn on digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { -+ /* turn off output */ -+ if (auto_shutdown_output) { -+ /* turn off output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); -+ } -+} -+ -+ -+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 sampling_freq=1; -+ -+ int ret; -+ -+ samplerate = params_rate(params); -+ -+ if (samplerate<=96000) { -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ } -+ -+ switch (samplerate) { -+ case 32000: -+ sampling_freq=0x03; -+ break; -+ case 44100: -+ sampling_freq=0x00; -+ break; -+ case 48000: -+ sampling_freq=0x02; -+ break; -+ case 88200: -+ sampling_freq=0x08; -+ break; -+ case 96000: -+ sampling_freq=0x0a; -+ break; -+ case 176400: -+ sampling_freq=0x0c; -+ break; -+ case 192000: -+ sampling_freq=0x0e; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); -+ } -+ -+ 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(codec->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); -+ -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ -+ 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, -+ .startup = snd_rpi_hifiberry_digi_startup, -+ .shutdown = snd_rpi_hifiberry_digi_shutdown, -+}; -+ -+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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_digi_driver = { -+ .driver = { -+ .name = "snd-hifiberry-digi", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_digi_of_match, -+ }, -+ .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"); - -From f021cdc4838896508164acaa687458ecd4e95499 Mon Sep 17 00:00:00 2001 -From: Gordon Garrity -Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 070/141] Add IQaudIO Sound Card support for Raspberry Pi - -Set a limit of 0dB on Digital Volume Control - -The main volume control in the PCM512x DAC has a range up to -+24dB. This is dangerously loud and can potentially cause massive -clipping in the output stages. Therefore this sets a sensible -limit of 0dB for this control. - -Allow up to 24dB digital gain to be applied when using IQAudIO DAC+ - -24db_digital_gain DT param can be used to specify that PCM512x -codec "Digital" volume control should not be limited to 0dB gain, -and if specified will allow the full 24dB gain. - -Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt - -Add the ability to set the card name, dai name and dai stream name, from -dt config. - -Signed-off-by: DigitalDreamtime ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio-dac.c | 148 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 157 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio-dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index a34aff27bb3010f58773edb942adccc193ea0d26..38dcdd975b406b9308e151f5d3a80dbca5163be5 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -28,3 +28,10 @@ config SND_BCM2708_SOC_RPI_DAC - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. -+ -+config SND_BCM2708_SOC_IQAUDIO_DAC -+ tristate "Support for IQaudIO-DAC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ help -+ Say Y or M if you want to add support for IQaudIO-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 4d53c58dc6ba41116d1fa210b6ba08ee75526dd2..08e4dc55757855fedec6845b82fc5f9f91f1584b 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,7 +7,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - 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-iqaudio-dac-objs := iqaudio-dac.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -new file mode 100644 -index 0000000000000000000000000000000000000000..b6b6dcf6e5a420d2c39d220b91928cd8ca832de7 ---- /dev/null -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,148 @@ -+/* -+ * ASoC Driver for IQaudIO 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 bool digital_gain_0db_limit = true; -+ -+static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ if (digital_gain_0db_limit) -+ { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ 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_iqaudio_dac_ops = { -+ .hw_params = snd_rpi_iqaudio_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { -+{ -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_iqaudio_dac_ops, -+ .init = snd_rpi_iqaudio_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_dac = { -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_iqaudio_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), -+}; -+ -+static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_card *card = &snd_rpi_iqaudio_dac; -+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool(pdev->dev.of_node, -+ "iqaudio,24db_digital_gain"); -+ if (of_property_read_string(pdev->dev.of_node, "card_name", -+ &card->name)) -+ card->name = "IQaudIODAC"; -+ if (of_property_read_string(pdev->dev.of_node, "dai_name", -+ &dai->name)) -+ dai->name = "IQaudIO DAC"; -+ if (of_property_read_string(pdev->dev.of_node, "dai_stream_name", -+ &dai->stream_name)) -+ dai->stream_name = "IQaudIO DAC HiFi"; -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); -+} -+ -+static const struct of_device_id iqaudio_of_match[] = { -+ { .compatible = "iqaudio,iqaudio-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, iqaudio_of_match); -+ -+static struct platform_driver snd_rpi_iqaudio_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-iqaudio-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = iqaudio_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_dac_probe, -+ .remove = snd_rpi_iqaudio_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); -+MODULE_LICENSE("GPL v2"); - -From 603759fab8f1f7fd294436cd617921e8ee310971 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 071/141] hid: Reduce default mouse polling interval to 60Hz - -Reduces overhead when using X ---- - drivers/hid/usbhid/hid-core.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400dfd5834f3 100644 ---- a/drivers/hid/usbhid/hid-core.c -+++ b/drivers/hid/usbhid/hid-core.c -@@ -49,7 +49,7 @@ - * Module parameters. - */ - --static unsigned int hid_mousepoll_interval; -+static unsigned int hid_mousepoll_interval = ~0; - module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); - MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -@@ -1083,8 +1083,12 @@ static int usbhid_start(struct hid_device *hid) - } - - /* Change the polling interval of mice. */ -- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) -- interval = hid_mousepoll_interval; -+ if (hid->collection->usage == HID_GD_MOUSE) { -+ if (hid_mousepoll_interval == ~0 && interval < 16) -+ interval = 16; -+ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) -+ interval = hid_mousepoll_interval; -+ } - - ret = -ENOMEM; - if (usb_endpoint_dir_in(endpoint)) { - -From 80768052b3fdd23fd2cda99d1ee135f0680031b1 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 072/141] Added support for HiFiBerry DAC+ - -The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses -a different codec chip (PCM5122), therefore a new driver is necessary. - -Add support for the HiFiBerry DAC+ Pro. - -The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators. - -An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame. - -Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+ - -24db_digital_gain DT param can be used to specify that PCM512x -codec "Digital" volume control should not be limited to 0dB gain, -and if specified will allow the full 24dB gain. - -Add dt param to force HiFiBerry DAC+ Pro into slave mode - -"dtoverlay=hifiberry-dacplus,slave" - -Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode, -with Pi as master for bit and frame clock. - -Signed-off-by: DigitalDreamtime ---- - drivers/clk/Makefile | 1 + - drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/pcm512x.c | 3 +- - 6 files changed, 530 insertions(+), 1 deletion(-) - create mode 100644 drivers/clk/clk-hifiberry-dacpro.c - create mode 100644 sound/soc/bcm/hifiberry_dacplus.c - -diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 46869d696e4d7bba3962719fb9464684a2bb4c91..a202e6f0f294f5dd077871d6accf891f30c027ba 100644 ---- a/drivers/clk/Makefile -+++ b/drivers/clk/Makefile -@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o - obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o - obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o - obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o - obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o - obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o - obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o -diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c -new file mode 100644 -index 0000000000000000000000000000000000000000..3e35d455f4559bc0100a1e268eeb200f7c10df7e ---- /dev/null -+++ b/drivers/clk/clk-hifiberry-dacpro.c -@@ -0,0 +1,160 @@ -+/* -+ * Clock Driver for HiFiBerry DAC Pro -+ * -+ * Author: Stuart MacLean -+ * Copyright 2015 -+ * -+ * 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 -+ -+/* Clock rate of CLK44EN attached to GPIO6 pin */ -+#define CLK_44EN_RATE 22579200UL -+/* Clock rate of CLK48EN attached to GPIO3 pin */ -+#define CLK_48EN_RATE 24576000UL -+ -+/** -+ * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro -+ * @hw: clk_hw for the common clk framework -+ * @mode: 0 => CLK44EN, 1 => CLK48EN -+ */ -+struct clk_hifiberry_hw { -+ struct clk_hw hw; -+ uint8_t mode; -+}; -+ -+#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) -+ -+static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { -+ { .compatible = "hifiberry,dacpro-clk",}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); -+ -+static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : -+ CLK_48EN_RATE; -+} -+ -+static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long *parent_rate) -+{ -+ long actual_rate; -+ -+ if (rate <= CLK_44EN_RATE) { -+ actual_rate = (long)CLK_44EN_RATE; -+ } else if (rate >= CLK_48EN_RATE) { -+ actual_rate = (long)CLK_48EN_RATE; -+ } else { -+ long diff44Rate = (long)(rate - CLK_44EN_RATE); -+ long diff48Rate = (long)(CLK_48EN_RATE - rate); -+ -+ if (diff44Rate < diff48Rate) -+ actual_rate = (long)CLK_44EN_RATE; -+ else -+ actual_rate = (long)CLK_48EN_RATE; -+ } -+ return actual_rate; -+} -+ -+ -+static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate) -+{ -+ unsigned long actual_rate; -+ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); -+ -+ actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, -+ &parent_rate); -+ clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; -+ return 0; -+} -+ -+ -+const struct clk_ops clk_hifiberry_dacpro_rate_ops = { -+ .recalc_rate = clk_hifiberry_dacpro_recalc_rate, -+ .round_rate = clk_hifiberry_dacpro_round_rate, -+ .set_rate = clk_hifiberry_dacpro_set_rate, -+}; -+ -+static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) -+{ -+ int ret; -+ struct clk_hifiberry_hw *proclk; -+ struct clk *clk; -+ struct device *dev; -+ struct clk_init_data init; -+ -+ dev = &pdev->dev; -+ -+ proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); -+ if (!proclk) -+ return -ENOMEM; -+ -+ init.name = "clk-hifiberry-dacpro"; -+ init.ops = &clk_hifiberry_dacpro_rate_ops; -+ init.flags = CLK_IS_ROOT | CLK_IS_BASIC; -+ init.parent_names = NULL; -+ init.num_parents = 0; -+ -+ proclk->mode = 0; -+ proclk->hw.init = &init; -+ -+ clk = devm_clk_register(dev, &proclk->hw); -+ if (!IS_ERR(clk)) { -+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, -+ clk); -+ } else { -+ dev_err(dev, "Fail to register clock driver\n"); -+ kfree(proclk); -+ ret = PTR_ERR(clk); -+ } -+ return ret; -+} -+ -+static int clk_hifiberry_dacpro_remove(struct platform_device *pdev) -+{ -+ of_clk_del_provider(pdev->dev.of_node); -+ return 0; -+} -+ -+static struct platform_driver clk_hifiberry_dacpro_driver = { -+ .probe = clk_hifiberry_dacpro_probe, -+ .remove = clk_hifiberry_dacpro_remove, -+ .driver = { -+ .name = "clk-hifiberry-dacpro", -+ .of_match_table = clk_hifiberry_dacpro_dt_ids, -+ }, -+}; -+ -+static int __init clk_hifiberry_dacpro_init(void) -+{ -+ return platform_driver_register(&clk_hifiberry_dacpro_driver); -+} -+core_initcall(clk_hifiberry_dacpro_init); -+ -+static void __exit clk_hifiberry_dacpro_exit(void) -+{ -+ platform_driver_unregister(&clk_hifiberry_dacpro_driver); -+} -+module_exit(clk_hifiberry_dacpro_exit); -+ -+MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:clk-hifiberry-dacpro"); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 38dcdd975b406b9308e151f5d3a80dbca5163be5..8c338b5803042ad3834ee46a8dc93f53c53953f6 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -15,6 +15,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_DACPLUS -+ tristate "Support for HifiBerry DAC+" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x -+ 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 || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 08e4dc55757855fedec6845b82fc5f9f91f1584b..a29538e56b62ef6e7098b81b81e1389a22beeafa 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,11 +5,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -new file mode 100644 -index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,358 @@ -+/* -+ * ASoC Driver for HiFiBerry DAC+ / DAC Pro -+ * -+ * Author: Daniel Matuschek, Stuart MacLean -+ * Copyright 2014-2015 -+ * based on code by Florian Meier -+ * -+ * 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 -+#include -+ -+#include "../codecs/pcm512x.h" -+ -+#define HIFIBERRY_DACPRO_NOCLOCK 0 -+#define HIFIBERRY_DACPRO_CLK44EN 1 -+#define HIFIBERRY_DACPRO_CLK48EN 2 -+ -+struct pcm512x_priv { -+ struct regmap *regmap; -+ struct clk *sclk; -+}; -+ -+/* Clock rate of CLK44EN attached to GPIO6 pin */ -+#define CLK_44EN_RATE 22579200UL -+/* Clock rate of CLK48EN attached to GPIO3 pin */ -+#define CLK_48EN_RATE 24576000UL -+ -+static bool slave; -+static bool snd_rpi_hifiberry_is_dacpro; -+static bool digital_gain_0db_limit = true; -+ -+static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_codec *codec, -+ int clk_id) -+{ -+ switch (clk_id) { -+ case HIFIBERRY_DACPRO_NOCLOCK: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x00); -+ break; -+ case HIFIBERRY_DACPRO_CLK44EN: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x20); -+ break; -+ case HIFIBERRY_DACPRO_CLK48EN: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x04); -+ break; -+ } -+} -+ -+static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_codec *codec) -+{ -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x24, 0x24); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_codec *codec) -+{ -+ int sck; -+ -+ sck = snd_soc_read(codec, PCM512x_RATE_DET_4); -+ return (!(sck & 0x40)); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep( -+ struct snd_soc_codec *codec) -+{ -+ msleep(2); -+ return snd_rpi_hifiberry_dacplus_is_sclk(codec); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_codec *codec) -+{ -+ bool isClk44EN, isClk48En, isNoClk; -+ -+ snd_rpi_hifiberry_dacplus_clk_gpio(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK44EN); -+ isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_NOCLOCK); -+ isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK48EN); -+ isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ return (isClk44EN && isClk48En && !isNoClk); -+} -+ -+static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate) -+{ -+ int type; -+ -+ switch (sample_rate) { -+ case 11025: -+ case 22050: -+ case 44100: -+ case 88200: -+ case 176400: -+ type = HIFIBERRY_DACPRO_CLK44EN; -+ break; -+ default: -+ type = HIFIBERRY_DACPRO_CLK48EN; -+ break; -+ } -+ return type; -+} -+ -+static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_codec *codec, -+ int sample_rate) -+{ -+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); -+ -+ if (!IS_ERR(pcm512x->sclk)) { -+ int ctype; -+ -+ ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate); -+ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN) -+ ? CLK_44EN_RATE : CLK_48EN_RATE); -+ snd_rpi_hifiberry_dacplus_select_clk(codec, ctype); -+ } -+} -+ -+static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ struct pcm512x_priv *priv; -+ -+ if (slave) -+ snd_rpi_hifiberry_is_dacpro = false; -+ else -+ snd_rpi_hifiberry_is_dacpro = -+ snd_rpi_hifiberry_dacplus_is_pro_card(codec); -+ -+ if (snd_rpi_hifiberry_is_dacpro) { -+ struct snd_soc_dai_link *dai = rtd->dai_link; -+ -+ dai->name = "HiFiBerry DAC+ Pro"; -+ dai->stream_name = "HiFiBerry DAC+ Pro HiFi"; -+ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM; -+ -+ snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11); -+ snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03); -+ snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63); -+ } else { -+ priv = snd_soc_codec_get_drvdata(codec); -+ priv->sclk = ERR_PTR(-ENOENT); -+ } -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); -+ -+ if (digital_gain_0db_limit) -+ { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_update_rate_den( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); -+ struct snd_ratnum *rats_no_pll; -+ unsigned int num = 0, den = 0; -+ int err; -+ -+ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL); -+ if (!rats_no_pll) -+ return -ENOMEM; -+ -+ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; -+ rats_no_pll->den_min = 1; -+ rats_no_pll->den_max = 128; -+ rats_no_pll->den_step = 1; -+ -+ err = snd_interval_ratnum(hw_param_interval(params, -+ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den); -+ if (err >= 0 && den) { -+ params->rate_num = num; -+ params->rate_den = den; -+ } -+ -+ devm_kfree(rtd->dev, rats_no_pll); -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro( -+ struct snd_soc_dai *cpu_dai, struct snd_pcm_hw_params *params) -+{ -+ int bratio = snd_pcm_format_physical_width(params_format(params)) -+ * params_channels(params); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio); -+} -+ -+static int snd_rpi_hifiberry_dacplus_hw_params( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ int ret; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ if (snd_rpi_hifiberry_is_dacpro) { -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_rpi_hifiberry_dacplus_set_sclk(codec, -+ params_rate(params)); -+ -+ ret = snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro(cpu_dai, -+ params); -+ if (!ret) -+ ret = snd_rpi_hifiberry_dacplus_update_rate_den( -+ substream, params); -+ } else { -+ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+ } -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_startup( -+ struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_dacplus_shutdown( -+ struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { -+ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, -+ .startup = snd_rpi_hifiberry_dacplus_startup, -+ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { -+{ -+ .name = "HiFiBerry DAC+", -+ .stream_name = "HiFiBerry DAC+ HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004d", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dacplus_ops, -+ .init = snd_rpi_hifiberry_dacplus_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dacplus = { -+ .name = "snd_rpi_hifiberry_dacplus", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_hifiberry_dacplus_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -+}; -+ -+static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai; -+ -+ dai = &snd_rpi_hifiberry_dacplus_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool( -+ pdev->dev.of_node, "hifiberry,24db_digital_gain"); -+ slave = of_property_read_bool(pdev->dev.of_node, -+ "hifiberry-dacplus,slave"); -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); -+} -+ -+static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dacplus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { -+ .driver = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, -+ }, -+ .probe = snd_rpi_hifiberry_dacplus_probe, -+ .remove = snd_rpi_hifiberry_dacplus_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dacplus_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c -index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 ---- a/sound/soc/codecs/pcm512x.c -+++ b/sound/soc/codecs/pcm512x.c -@@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, - int fssp; - int gpio; - -- lrclk_div = snd_soc_params_to_frame_size(params); -+ lrclk_div = snd_pcm_format_physical_width(params_format(params)) -+ * params_channels(params); - if (lrclk_div == 0) { - dev_err(dev, "No LRCLK?\n"); - return -EINVAL; - -From 4c27bbc1e655e55b28889b902af5c5a5be6172e4 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 073/141] Added driver for HiFiBerry Amp amplifier add-on board - -The driver contains a low-level hardware driver for the TAS5713 and the -drivers for the Raspberry Pi I2S subsystem. - -TAS5713: return error if initialisation fails - -Existing TAS5713 driver logs errors during initialisation, but does not return -an error code. Therefore even if initialisation fails, the driver will still be -loaded, but won't work. This patch fixes this. I2C communication error will now -reported correctly by a non-zero return code. - -HiFiBerry Amp: fix device-tree problems - -Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. ---- - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 722 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_amp.c - create mode 100644 sound/soc/codecs/tas5713.c - create mode 100644 sound/soc/codecs/tas5713.h - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8c338b5803042ad3834ee46a8dc93f53c53953f6..7677c898773e6dd87c3ef385e380aa42c85e66d8 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -29,6 +29,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - -+config SND_BCM2708_SOC_HIFIBERRY_AMP -+ tristate "Support for the HifiBerry Amp" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_TAS5713 -+ help -+ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index a29538e56b62ef6e7098b81b81e1389a22beeafa..30db4951129c2d853c5cf631f4cd1263926692d0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,11 +7,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -new file mode 100644 -index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,128 @@ -+/* -+ * ASoC Driver for HifiBerry AMP -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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_amp_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ // ToDo: init of the dsp-registers. -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_amp_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, 64); -+} -+ -+static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -+ .hw_params = snd_rpi_hifiberry_amp_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -+ { -+ .name = "HifiBerry AMP", -+ .stream_name = "HifiBerry AMP HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "tas5713-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "tas5713.1-001b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_amp_ops, -+ .init = snd_rpi_hifiberry_amp_init, -+ }, -+}; -+ -+ -+static struct snd_soc_card snd_rpi_hifiberry_amp = { -+ .name = "snd_rpi_hifiberry_amp", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_hifiberry_amp_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -+}; -+ -+static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-amp", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -+ -+ -+static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_amp.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -+ -+ if (ret != 0) { -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); -+} -+ -+ -+static struct platform_driver snd_rpi_hifiberry_amp_driver = { -+ .driver = { -+ .name = "snd-hifiberry-amp", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_amp_of_match, -+ }, -+ .probe = snd_rpi_hifiberry_amp_probe, -+ .remove = snd_rpi_hifiberry_amp_remove, -+}; -+ -+ -+module_platform_driver(snd_rpi_hifiberry_amp_driver); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 513ab55fdc67af50f110f13ed6f6d6bb3740561e..ebcfbfd843db89e8ca86b318d2783c850079c15a 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -129,6 +129,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -+ select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4 if I2C -@@ -759,6 +760,9 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - -+config SND_SOC_TAS5713 -+ tristate -+ - config SND_SOC_TLV320AIC23 - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index b87e84543459776026be1b9a598fcc0c65abe987..9974a13a2c7ef4a9c476c34faa133ecc7e687272 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -132,6 +132,7 @@ snd-soc-sti-sas-objs := sti-sas.o - snd-soc-tas5086-objs := tas5086.o - snd-soc-tas571x-objs := tas571x.o - snd-soc-tfa9879-objs := tfa9879.o -+snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -340,6 +341,7 @@ obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o - obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o - obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o -+obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9b2713861dcbed751842ca29c88eb1eae5867411 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,369 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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 -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "tas5713.h" -+ -+ -+static struct i2c_client *i2c; -+ -+struct tas5713_priv { -+ struct regmap *regmap; -+ int mclk_div; -+ struct snd_soc_codec *codec; -+}; -+ -+static struct tas5713_priv *priv_data; -+ -+ -+ -+ -+/* -+ * _ _ ___ _ ___ _ _ -+ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -+ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -+ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -+ * -+ */ -+ -+static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -+ -+ -+static const struct snd_kcontrol_new tas5713_snd_controls[] = { -+ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -+ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) -+}; -+ -+ -+ -+ -+/* -+ * __ __ _ _ ___ _ -+ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -+ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -+ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ u16 blen = 0x00; -+ -+ struct snd_soc_codec *codec; -+ codec = dai->codec; -+ priv_data->codec = dai->codec; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ blen = 0x03; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ blen = 0x1; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ blen = 0x04; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ blen = 0x05; -+ break; -+ default: -+ dev_err(dai->dev, "Unsupported word length: %u\n", -+ params_format(params)); -+ return -EINVAL; -+ } -+ -+ // set word length -+ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -+ -+ return 0; -+} -+ -+ -+static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ unsigned int val = 0; -+ -+ struct tas5713_priv *tas5713; -+ struct snd_soc_codec *codec = dai->codec; -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ if (mute) { -+ val = TAS5713_SOFT_MUTE_ALL; -+ } -+ -+ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); -+} -+ -+ -+static const struct snd_soc_dai_ops tas5713_dai_ops = { -+ .hw_params = tas5713_hw_params, -+ .mute_stream = tas5713_mute_stream, -+}; -+ -+ -+static struct snd_soc_dai_driver tas5713_dai = { -+ .name = "tas5713-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_48000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -+ }, -+ .ops = &tas5713_dai_ops, -+}; -+ -+ -+ -+ -+/* -+ * ___ _ ___ _ -+ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -+ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -+ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_remove(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ return 0; -+} -+ -+ -+static int tas5713_probe(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ int i, ret; -+ -+ i2c = container_of(codec->dev, struct i2c_client, dev); -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Trim oscillator -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ if (ret < 0) return ret; -+ msleep(1000); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Clock mode: 44/48kHz, MCLK=64xfs -+ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ if (ret < 0) return ret; -+ -+ // I2S 24bit -+ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ if (ret < 0) return ret; -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ if (ret < 0) return ret; -+ -+ // Set volume to 0db -+ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ if (ret < 0) return ret; -+ -+ // Now start programming the default initialization sequence -+ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -+ ret = i2c_master_send(i2c, -+ tas5713_init_sequence[i].data, -+ tas5713_init_sequence[i].size); -+ if (ret < 0) { -+ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -+ } -+ } -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -+ .probe = tas5713_probe, -+ .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+}; -+ -+ -+ -+ -+/* -+ * ___ ___ ___ ___ _ -+ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -+ * | | / / (__ | |) | '_| \ V / -_) '_| -+ * |___/___\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static const struct reg_default tas5713_reg_defaults[] = { -+ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -+ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -+ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -+ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB -+}; -+ -+ -+static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case TAS5713_DEVICE_ID: -+ case TAS5713_ERROR_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+ -+static const struct of_device_id tas5713_of_match[] = { -+ { .compatible = "ti,tas5713", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, tas5713_of_match); -+ -+ -+static struct regmap_config tas5713_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = TAS5713_MAX_REGISTER, -+ .volatile_reg = tas5713_reg_volatile, -+ -+ .cache_type = REGCACHE_RBTREE, -+ .reg_defaults = tas5713_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), -+}; -+ -+ -+static int tas5713_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ int ret; -+ -+ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -+ if (IS_ERR(priv_data->regmap)) { -+ ret = PTR_ERR(priv_data->regmap); -+ return ret; -+ } -+ -+ i2c_set_clientdata(i2c, priv_data); -+ -+ ret = snd_soc_register_codec(&i2c->dev, -+ &soc_codec_dev_tas5713, &tas5713_dai, 1); -+ -+ return ret; -+} -+ -+ -+static int tas5713_i2c_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_codec(&i2c->dev); -+ i2c_set_clientdata(i2c, NULL); -+ -+ kfree(priv_data); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id tas5713_i2c_id[] = { -+ { "tas5713", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -+ -+ -+static struct i2c_driver tas5713_i2c_driver = { -+ .driver = { -+ .name = "tas5713", -+ .owner = THIS_MODULE, -+ .of_match_table = tas5713_of_match, -+ }, -+ .probe = tas5713_i2c_probe, -+ .remove = tas5713_i2c_remove, -+ .id_table = tas5713_i2c_id -+}; -+ -+ -+static int __init tas5713_modinit(void) -+{ -+ int ret = 0; -+ -+ ret = i2c_add_driver(&tas5713_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -+ ret); -+ } -+ -+ return ret; -+} -+module_init(tas5713_modinit); -+ -+ -+static void __exit tas5713_exit(void) -+{ -+ i2c_del_driver(&tas5713_i2c_driver); -+} -+module_exit(tas5713_exit); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for TAS5713"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8f612a342 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.h -@@ -0,0 +1,210 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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. -+ */ -+ -+#ifndef _TAS5713_H -+#define _TAS5713_H -+ -+ -+// TAS5713 I2C-bus register addresses -+ -+#define TAS5713_CLOCK_CTRL 0x00 -+#define TAS5713_DEVICE_ID 0x01 -+#define TAS5713_ERROR_STATUS 0x02 -+#define TAS5713_SYSTEM_CTRL1 0x03 -+#define TAS5713_SERIAL_DATA_INTERFACE 0x04 -+#define TAS5713_SYSTEM_CTRL2 0x05 -+#define TAS5713_SOFT_MUTE 0x06 -+#define TAS5713_VOL_MASTER 0x07 -+#define TAS5713_VOL_CH1 0x08 -+#define TAS5713_VOL_CH2 0x09 -+#define TAS5713_VOL_HEADPHONE 0x0A -+#define TAS5713_VOL_CONFIG 0x0E -+#define TAS5713_MODULATION_LIMIT 0x10 -+#define TAS5713_IC_DLY_CH1 0x11 -+#define TAS5713_IC_DLY_CH2 0x12 -+#define TAS5713_IC_DLY_CH3 0x13 -+#define TAS5713_IC_DLY_CH4 0x14 -+ -+#define TAS5713_START_STOP_PERIOD 0x1A -+#define TAS5713_OSC_TRIM 0x1B -+#define TAS5713_BKND_ERR 0x1C -+ -+#define TAS5713_INPUT_MUX 0x20 -+#define TAS5713_SRC_SELECT_CH4 0x21 -+#define TAS5713_PWM_MUX 0x25 -+ -+#define TAS5713_CH1_BQ0 0x29 -+#define TAS5713_CH1_BQ1 0x2A -+#define TAS5713_CH1_BQ2 0x2B -+#define TAS5713_CH1_BQ3 0x2C -+#define TAS5713_CH1_BQ4 0x2D -+#define TAS5713_CH1_BQ5 0x2E -+#define TAS5713_CH1_BQ6 0x2F -+#define TAS5713_CH1_BQ7 0x58 -+#define TAS5713_CH1_BQ8 0x59 -+ -+#define TAS5713_CH2_BQ0 0x30 -+#define TAS5713_CH2_BQ1 0x31 -+#define TAS5713_CH2_BQ2 0x32 -+#define TAS5713_CH2_BQ3 0x33 -+#define TAS5713_CH2_BQ4 0x34 -+#define TAS5713_CH2_BQ5 0x35 -+#define TAS5713_CH2_BQ6 0x36 -+#define TAS5713_CH2_BQ7 0x5C -+#define TAS5713_CH2_BQ8 0x5D -+ -+#define TAS5713_CH4_BQ0 0x5A -+#define TAS5713_CH4_BQ1 0x5B -+#define TAS5713_CH3_BQ0 0x5E -+#define TAS5713_CH3_BQ1 0x5F -+ -+#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B -+#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C -+#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E -+#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F -+#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 -+#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 -+#define TAS5713_DRC_CTRL 0x46 -+ -+#define TAS5713_BANK_SW_CTRL 0x50 -+#define TAS5713_CH1_OUTPUT_MIXER 0x51 -+#define TAS5713_CH2_OUTPUT_MIXER 0x52 -+#define TAS5713_CH1_INPUT_MIXER 0x53 -+#define TAS5713_CH2_INPUT_MIXER 0x54 -+#define TAS5713_OUTPUT_POST_SCALE 0x56 -+#define TAS5713_OUTPUT_PRESCALE 0x57 -+ -+#define TAS5713_IDF_POST_SCALE 0x62 -+ -+#define TAS5713_CH1_INLINE_MIXER 0x70 -+#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 -+#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 -+#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 -+#define TAS5713_CH2_INLINE_MIXER 0x74 -+#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 -+#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 -+#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -+ -+#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 -+#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -+ -+#define TAS5713_REGISTER_COUNT 0x46 -+#define TAS5713_MAX_REGISTER 0xF9 -+ -+ -+// Bitmasks for registers -+#define TAS5713_SOFT_MUTE_ALL 0x07 -+ -+ -+ -+struct tas5713_init_command { -+ const int size; -+ const char *const data; -+}; -+ -+static const struct tas5713_init_command tas5713_init_sequence[] = { -+ -+ // Trim oscillator -+ { .size = 2, .data = "\x1B\x00" }, -+ // System control register 1 (0x03): block DC -+ { .size = 2, .data = "\x03\x80" }, -+ // Mute everything -+ { .size = 2, .data = "\x05\x40" }, -+ // Modulation limit register (0x10): 97.7% -+ { .size = 2, .data = "\x10\x02" }, -+ // Interchannel delay registers -+ // (0x11, 0x12, 0x13, and 0x14): BD mode -+ { .size = 2, .data = "\x11\xB8" }, -+ { .size = 2, .data = "\x12\x60" }, -+ { .size = 2, .data = "\x13\xA0" }, -+ { .size = 2, .data = "\x14\x48" }, -+ // PWM shutdown group register (0x19): no shutdown -+ { .size = 2, .data = "\x19\x00" }, -+ // Input multiplexer register (0x20): BD mode -+ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -+ // PWM output mux register (0x25) -+ // Channel 1 --> OUTA, channel 1 neg --> OUTB -+ // Channel 2 --> OUTC, channel 2 neg --> OUTD -+ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -+ // DRC control (0x46): DRC off -+ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -+ // BKND_ERR register (0x1C): 299ms reset period -+ { .size = 2, .data = "\x1C\x07" }, -+ // Mute channel 3 -+ { .size = 2, .data = "\x0A\xFF" }, -+ // Volume configuration register (0x0E): volume slew 512 steps -+ { .size = 2, .data = "\x0E\x90" }, -+ // Clock control register (0x00): 44/48kHz, MCLK=64xfs -+ { .size = 2, .data = "\x00\x60" }, -+ // Bank switch and eq control (0x50): no bank switching -+ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -+ // Volume registers (0x07, 0x08, 0x09, 0x0A) -+ { .size = 2, .data = "\x07\x20" }, -+ { .size = 2, .data = "\x08\x30" }, -+ { .size = 2, .data = "\x09\x30" }, -+ { .size = 2, .data = "\x0A\xFF" }, -+ // 0x72, 0x73, 0x76, 0x77 input mixer: -+ // no intermix between channels -+ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -+ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -+ // no inline DRC inmix -+ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -+ // 0x56, 0x57 Output scale -+ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -+ // 0x3B, 0x3c -+ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ // 0x51, 0x52: output mixer -+ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ // PEQ defaults -+ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+}; -+ -+ -+#endif /* _TAS5713_H */ - -From 419495c7b6f7f29a8977453e02116b12fd0419f4 Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 074/141] Update ds1307 driver for device-tree support - -Signed-off-by: Ryan Coe ---- - drivers/rtc/rtc-ds1307.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index e94eb0952286300ec9847cddaf317476ddd05423..f5d93be977142d306c787547736e8722bfe51b3c 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -1608,6 +1608,14 @@ static int ds1307_remove(struct i2c_client *client) - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id ds1307_of_match[] = { -+ { .compatible = "maxim,ds1307" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ds1307_of_match); -+#endif -+ - static struct i2c_driver ds1307_driver = { - .driver = { - .name = "rtc-ds1307", - -From 1345cf9552dd55512240e16e076c3f67b018363c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 075/141] enc28j60: Add device tree compatible string and an - overlay - ---- - drivers/net/ethernet/microchip/enc28j60.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c -index 86ea17e7ba7bff17f40755663e1b10b7d7b4cbcc..a1b20c146eb8f3d9af757b79c19be96ed43adfba 100644 ---- a/drivers/net/ethernet/microchip/enc28j60.c -+++ b/drivers/net/ethernet/microchip/enc28j60.c -@@ -1630,9 +1630,16 @@ static int enc28j60_remove(struct spi_device *spi) - return 0; - } - -+static const struct of_device_id enc28j60_of_match[] = { -+ { .compatible = "microchip,enc28j60", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, enc28j60_of_match); -+ - static struct spi_driver enc28j60_driver = { - .driver = { - .name = DRV_NAME, -+ .of_match_table = enc28j60_of_match, - }, - .probe = enc28j60_probe, - .remove = enc28j60_remove, - -From 52b97cb78e02a4f2d606d47fd7b350f518f9dfca Mon Sep 17 00:00:00 2001 -From: Waldemar Brodkorb -Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 076/141] Add driver for rpi-proto - -Forward port of 3.10.x driver from https://github.com/koalo -We are using a custom board and would like to use rpi 3.18.x -kernel. Patch works fine for our embedded system. - -URL to the audio chip: -http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ - -Playback tested with devicetree enabled. - -Signed-off-by: Waldemar Brodkorb ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 163 insertions(+) - create mode 100644 sound/soc/bcm/rpi-proto.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7677c898773e6dd87c3ef385e380aa42c85e66d8..8669a9ac9734c465c7dc3f40c864f71b68a6de75 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -43,6 +43,13 @@ config SND_BCM2708_SOC_RPI_DAC - help - Say Y or M if you want to add support for RPi-DAC. - -+config SND_BCM2708_SOC_RPI_PROTO -+ tristate "Support for Rpi-PROTO" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8731 -+ help -+ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). -+ - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 30db4951129c2d853c5cf631f4cd1263926692d0..4f5ab1fa4414e64a164eaa4575ffaa06d1cbf332 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -9,6 +9,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -16,4 +17,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed6772b19a2d ---- /dev/null -+++ b/sound/soc/bcm/rpi-proto.c -@@ -0,0 +1,154 @@ -+/* -+ * 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_codec *codec = rtd->codec; -+ 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); -+ if (ret < 0){ -+ dev_err(codec->dev, -+ "Failed to set BCLK ratio %d\n", ret); -+ return ret; -+ } -+ -+ /* Set proto sysclk */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, -+ sysclk, SND_SOC_CLOCK_IN); -+ if (ret < 0) { -+ dev_err(codec->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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_proto_of_match[] = { -+ { .compatible = "rpi,rpi-proto", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); -+ -+static struct platform_driver snd_rpi_proto_driver = { -+ .driver = { -+ .name = "snd-rpi-proto", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_proto_of_match, -+ }, -+ .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"); - -From 8b79a80ed03b0aa97088181f1d3d599be28ced1d Mon Sep 17 00:00:00 2001 +From f909136a4636faf8d7fd30fce66104b487b2ecff Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 077/141] config: Add default configs +Subject: [PATCH 059/111] config: Add default configs --- - arch/arm/configs/bcm2709_defconfig | 1279 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1289 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2568 insertions(+) + arch/arm/configs/bcm2709_defconfig | 1288 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1296 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2584 insertions(+) create mode 100644 arch/arm/configs/bcm2709_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483e32c7fd8 +index 0000000000000000000000000000000000000000..af34386096ebc5b3c7d7cf60120e5ad48ba635b8 --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1279 @@ +@@ -0,0 +1,1288 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +CONFIG_LOCALVERSION="-v7" @@ -124925,6 +121987,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_FREEZER=y @@ -124944,6 +122007,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y @@ -124976,6 +122040,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y @@ -125309,7 +122374,6 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m -+CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y @@ -125466,6 +122530,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m @@ -125525,6 +122590,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_GPIO_BCM_VIRT=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m @@ -125767,12 +122833,15 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -125949,6 +123018,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m @@ -125970,9 +123040,9 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_R9701=m @@ -125982,6 +123052,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_BCM2708=y @@ -126190,10 +123261,10 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44a922c0ea +index 0000000000000000000000000000000000000000..da2df3d30e15a55a34b45d3ebbf98e906da6379c --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1289 @@ +@@ -0,0 +1,1296 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +# CONFIG_LOCALVERSION_AUTO is not set @@ -126209,6 +123280,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_FREEZER=y @@ -126228,6 +123300,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y @@ -126587,7 +123660,6 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m -+CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y @@ -126744,6 +123816,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m @@ -126772,7 +123845,6 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y -+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y @@ -126802,6 +123874,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m @@ -127044,12 +124117,15 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -127241,6 +124317,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m @@ -127262,9 +124339,9 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_R9701=m @@ -127274,6 +124351,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_BCM2708=y @@ -127484,10 +124562,49 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 7e74308c1c5da500e6e745656092196ba3c683f0 Mon Sep 17 00:00:00 2001 +From aa15290cdeac3133072d8ea98a4197d32f13cbf0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 14 Jul 2014 22:02:09 +0100 +Subject: [PATCH 060/111] hid: Reduce default mouse polling interval to 60Hz + +Reduces overhead when using X +--- + drivers/hid/usbhid/hid-core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400dfd5834f3 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -49,7 +49,7 @@ + * Module parameters. + */ + +-static unsigned int hid_mousepoll_interval; ++static unsigned int hid_mousepoll_interval = ~0; + module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); + MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); + +@@ -1083,8 +1083,12 @@ static int usbhid_start(struct hid_device *hid) + } + + /* Change the polling interval of mice. */ +- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) +- interval = hid_mousepoll_interval; ++ if (hid->collection->usage == HID_GD_MOUSE) { ++ if (hid_mousepoll_interval == ~0 && interval < 16) ++ interval = 16; ++ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) ++ interval = hid_mousepoll_interval; ++ } + + ret = -ENOMEM; + if (usb_endpoint_dir_in(endpoint)) { + +From 8d8a8564c00e70c5606af68c4acdb8c5e2ac8cf8 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 078/141] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 061/111] rpi-ft5406: Add touchscreen driver for pi LCD display Fix driver detection failure Check that the buffer response is non-zero meaning the touchscreen was detected @@ -127782,10 +124899,10 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +MODULE_DESCRIPTION("Touchscreen driver for memory based FT5406"); +MODULE_LICENSE("GPL"); -From 9f1c48411136e52a5ee06ceb154ebc20a4636df8 Mon Sep 17 00:00:00 2001 +From caa5f748c7c34919061a800d3b9600aeef93ae3f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 079/141] Improve __copy_to_user and __copy_from_user +Subject: [PATCH 062/111] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -129341,10 +126458,10 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From 7c1b0f68ed1f587b0bf3755ec32f8045695d9507 Mon Sep 17 00:00:00 2001 +From 626055cab99e810168105994b1368f783545728f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 080/141] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 063/111] gpio-poweroff: Allow it to work on Raspberry Pi The Raspberry Pi firmware manages the power-down and reboot process. To do this it installs a pm_power_off handler, causing @@ -129379,10 +126496,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From 7899a439b21e546e9d0999fcc25f0c6ef3c05c4c Mon Sep 17 00:00:00 2001 +From f62be97894117c25b4f8bbad415770b21f09a919 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 081/141] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 064/111] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -129592,7 +126709,7 @@ index 0000000000000000000000000000000000000000..6a416769065d2198344792eb02d8e38d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index eea61e349e26afe4b0f9d52a3f036877f0e2403a..d2c3b724604a6ce660bbeffc754288c9168c447e 100644 +index 1bcf601de5bcea35c6844362811213bfd9b406c7..c264e883b54f4538a64db1536e9583193b322014 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -10,6 +10,14 @@ config MFD_CORE @@ -129611,10 +126728,10 @@ index eea61e349e26afe4b0f9d52a3f036877f0e2403a..d2c3b724604a6ce660bbeffc754288c9 tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 5eaa6465d0a6e2bf20df77951b573b4c0ccc477f..8dc2dde11a22226ef4ed91b0eb69dfc9b4b84298 100644 +index 42a66e19e191da93b5036cd9fd8bb9e1cb1340bd..8806f37c52ec1a378804acdf4184ef6729aa815a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -203,3 +203,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o +@@ -205,3 +205,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o @@ -129784,10 +126901,10 @@ index 0000000000000000000000000000000000000000..eea9312dc96a496ce846b0c5a83e6e4f +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index ee72c3a2866f716cd68c646b7c501589a05b48f5..5be1a31a836a0528975f259fabb793bef4d2aa71 100644 +index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae8072fdf9bc 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -2502,3 +2502,16 @@ config FB_SM712 +@@ -2501,3 +2501,16 @@ config FB_SM712 This driver is also available as a module. The module will be called sm712fb. If you want to compile it as a module, say M here and read . @@ -129805,10 +126922,10 @@ index ee72c3a2866f716cd68c646b7c501589a05b48f5..5be1a31a836a0528975f259fabb793be + help + This is the framebuffer driver for the Raspberry Pi Sense HAT diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index df473d825c2e2481a871d794317e56b8d643370f..474c5673b275a82d60ad08ddf3bdc13879d3722a 100644 +index ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2..459f9d1d4a37bb386c207df0f3aab581b9eb5e9e 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o +@@ -148,6 +148,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_MXS) += mxsfb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o @@ -130248,10 +127365,2863 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 20ba6b1d6362b32aac1fa3dc6f073d1046b7b27a Mon Sep 17 00:00:00 2001 +From f8f8a656cd3bf3fbeeeaa821ac7f11dd7071979e Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:19:08 +0100 +Subject: [PATCH 065/111] 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 | 4 ++ + sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 134 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index c5070aec5996aafb2d9daaf75163e16a29bc6892..ce81f14a88d08c90fb565cf3d60321a9b9a1fcee 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -7,3 +7,10 @@ config SND_BCM2835_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2835 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 || SND_BCM2835_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 bc816b71e5a40958953bf7bf7e7bd08342e87738..b877d386363d935deefda3664089a4ae5b33b889 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o + + obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -0,0 +1,123 @@ ++/* ++ * 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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_dac_driver = { ++ .driver = { ++ .name = "snd-hifiberry-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dac_of_match, ++ }, ++ .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"); + +From 6f6c153a71efcace4d50c009ff7103c6a872004c Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Mon, 25 Jan 2016 15:48:59 +0000 +Subject: [PATCH 066/111] ASoC: Add support for Rpi-DAC + +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-dac.c | 119 ++++++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/Kconfig | 5 ++ + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/pcm1794a.c | 69 +++++++++++++++++++++++++ + 6 files changed, 204 insertions(+) + create mode 100644 sound/soc/bcm/rpi-dac.c + create mode 100644 sound/soc/codecs/pcm1794a.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index ce81f14a88d08c90fb565cf3d60321a9b9a1fcee..900de22369a66758bbe49861238b647bd2ca037e 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -14,3 +14,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 || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM1794A ++ help ++ Say Y or M if you want to add support for RPi-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index b877d386363d935deefda3664089a4ae5b33b889..99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,5 +5,7 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1337a1c73 +--- /dev/null ++++ b/sound/soc/bcm/rpi-dac.c +@@ -0,0 +1,119 @@ ++/* ++ * 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 = "RPi-DAC", ++ .stream_name = "RPi-DAC 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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_rpi_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_rpi_dac_of_match[] = { ++ { .compatible = "rpi,rpi-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_rpi_dac_of_match); ++ ++static struct platform_driver snd_rpi_rpi_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_rpi_dac_of_match, ++ }, ++ .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 f3fb98f0a995bb41dd473ccc4443164e404c9883..4a53fa058a6837b93d2e66b15fda7183cf355058 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -93,6 +93,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM1681 if I2C + select SND_SOC_PCM179X_I2C if I2C + select SND_SOC_PCM179X_SPI if SPI_MASTER ++ select SND_SOC_PCM1794A if I2C + select SND_SOC_PCM3008 + select SND_SOC_PCM3168A_I2C if I2C + select SND_SOC_PCM3168A_SPI if SPI_MASTER +@@ -648,6 +649,10 @@ config SND_SOC_RT5616 + tristate "Realtek RT5616 CODEC" + depends on I2C + ++config SND_SOC_PCM1794A ++ tristate ++ depends on I2C ++ + config SND_SOC_RT5631 + tristate "Realtek ALC5631/RT5631 CODEC" + depends on I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 0f548fd34ca3fd9e8a1b080cd2d38a480c3c5212..96b312249d197b2083b157d1c07eb106bc34ba7f 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -87,6 +87,7 @@ snd-soc-pcm1681-objs := pcm1681.o + snd-soc-pcm179x-codec-objs := pcm179x.o + snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o + snd-soc-pcm179x-spi-objs := pcm179x-spi.o ++snd-soc-pcm1794a-objs := pcm1794a.o + snd-soc-pcm3008-objs := pcm3008.o + snd-soc-pcm3168a-objs := pcm3168a.o + snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o +@@ -309,6 +310,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o + obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o ++obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o +diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c +new file mode 100644 +index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd843e17f4 +--- /dev/null ++++ b/sound/soc/codecs/pcm1794a.c +@@ -0,0 +1,69 @@ ++/* ++ * 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 const struct of_device_id pcm1794a_of_match[] = { ++ { .compatible = "ti,pcm1794a", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcm1794a_of_match); ++ ++static struct platform_driver pcm1794a_codec_driver = { ++ .probe = pcm1794a_probe, ++ .remove = pcm1794a_remove, ++ .driver = { ++ .name = "pcm1794a-codec", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pcm1794a_of_match), ++ }, ++}; ++ ++module_platform_driver(pcm1794a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From b3591796ac8c05287e949d01fad785b9d2311e9c Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:41:23 +0100 +Subject: [PATCH 067/111] 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 | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, + blen = 0x1; + break; + case 24: ++ case 32: + blen = 0x2; + break; + default: +@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { + }; + + #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 | \ +@@ -543,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { + }; + + static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { +- .idle_bias_off = true, ++ .idle_bias_off = false, + + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + +From 8e7395e59afaa7f683db84c4737c9235917e0144 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:42:08 +0100 +Subject: [PATCH 068/111] ASoC: BCM:Add support for HiFiBerry Digi. Driver is + based on the patched WM8804 driver. + +Signed-off-by: Daniel Matuschek + +Add a parameter to turn off SPDIF output if no audio is playing + +This patch adds the paramater auto_shutdown_output to the kernel module. +Default behaviour of the module is the same, but when auto_shutdown_output +is set to 1, the SPDIF oputput will shutdown if no stream is playing. + +bugfix for 32kHz sample rate, was missing + +HiFiBerry Digi: set SPDIF status bits for sample rate + +The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. +While this is optional, some DACs and receivers do not accept this signal. This patch +adds the sample rate bits in the SPDIF status block. +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 233 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_digi.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 900de22369a66758bbe49861238b647bd2ca037e..a34aff27bb3010f58773edb942adccc193ea0d26 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -15,6 +15,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 || SND_BCM2835_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 || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb..4d53c58dc6ba41116d1fa210b6ba08ee75526dd2 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,7 +5,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 + + 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 +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -0,0 +1,224 @@ ++/* ++ * 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 short int auto_shutdown_output = 0; ++module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++ ++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_startup(struct snd_pcm_substream *substream) { ++ /* turn on digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { ++ /* turn off output */ ++ if (auto_shutdown_output) { ++ /* turn off output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++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 sampling_freq=1; ++ ++ int ret; ++ ++ samplerate = params_rate(params); ++ ++ if (samplerate<=96000) { ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq=0x03; ++ break; ++ case 44100: ++ sampling_freq=0x00; ++ break; ++ case 48000: ++ sampling_freq=0x02; ++ break; ++ case 88200: ++ sampling_freq=0x08; ++ break; ++ case 96000: ++ sampling_freq=0x0a; ++ break; ++ case 176400: ++ sampling_freq=0x0c; ++ break; ++ case 192000: ++ sampling_freq=0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ 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(codec->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); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ 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, ++ .startup = snd_rpi_hifiberry_digi_startup, ++ .shutdown = snd_rpi_hifiberry_digi_shutdown, ++}; ++ ++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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_digi_driver = { ++ .driver = { ++ .name = "snd-hifiberry-digi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_digi_of_match, ++ }, ++ .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"); + +From d8399bf3bd675104993779d1862d57fbbd31128a Mon Sep 17 00:00:00 2001 +From: Gordon Garrity +Date: Sat, 8 Mar 2014 16:56:57 +0000 +Subject: [PATCH 069/111] Add IQaudIO Sound Card support for Raspberry Pi + +Set a limit of 0dB on Digital Volume Control + +The main volume control in the PCM512x DAC has a range up to ++24dB. This is dangerously loud and can potentially cause massive +clipping in the output stages. Therefore this sets a sensible +limit of 0dB for this control. + +Allow up to 24dB digital gain to be applied when using IQAudIO DAC+ + +24db_digital_gain DT param can be used to specify that PCM512x +codec "Digital" volume control should not be limited to 0dB gain, +and if specified will allow the full 24dB gain. + +Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt + +Add the ability to set the card name, dai name and dai stream name, from +dt config. + +Signed-off-by: DigitalDreamtime + +IQaudIO: auto-mute for AMP+ and DigiAMP+ + +IQAudIO amplifier mute via GPIO22. Add dt params for "one-shot" unmute +and auto mute. + +Revision 2, auto mute implementing HiassofT suggestion to mute/unmute +using set_bias_level, rather than startup/shutdown.... +"By default DAPM waits 5 seconds (pmdown_time) before shutting down +playback streams so a close/stop immediately followed by open/start +doesn't trigger an amp mute+unmute." + +Tested on both AMP+ (via DAC+) and DigiAMP+, with both options... + +dtoverlay=iqaudio-dacplus,unmute_amp + "one-shot" unmute when kernel module loads. + +dtoverlay=iqaudio-dacplus,auto_mute_amp + Unmute amp when ALSA device opened by a client. Mute, with 5 second delay + when ALSA device closed. (Re-opening the device within the 5 second close + window, will cancel mute.) + +Revision 4, using gpiod. + +Revision 5, clean-up formatting before adding mute code. + - Convert tab plus 4 space formatting to 2x tab + - Remove '// NOT USED' commented code + +Revision 6, don't attempt to "one-shot" unmute amp, unless card is +successfully registered. + +Signed-off-by: DigitalDreamtime +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio-dac.c | 234 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 243 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio-dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a34aff27bb3010f58773edb942adccc193ea0d26..38dcdd975b406b9308e151f5d3a80dbca5163be5 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -28,3 +28,10 @@ config SND_BCM2708_SOC_RPI_DAC + select SND_SOC_PCM1794A + help + Say Y or M if you want to add support for RPi-DAC. ++ ++config SND_BCM2708_SOC_IQAUDIO_DAC ++ tristate "Support for IQaudIO-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ help ++ Say Y or M if you want to add support for IQaudIO-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 4d53c58dc6ba41116d1fa210b6ba08ee75526dd2..08e4dc55757855fedec6845b82fc5f9f91f1584b 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,7 +7,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + 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-iqaudio-dac-objs := iqaudio-dac.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +new file mode 100644 +index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097249d6777 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -0,0 +1,234 @@ ++/* ++ * ASoC Driver for IQaudIO 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 ++#include ++ ++static bool digital_gain_0db_limit = true; ++ ++static struct gpio_desc *mute_gpio; ++ ++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ if (digital_gain_0db_limit) ++ { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_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); ++} ++ ++static void snd_rpi_iqaudio_gpio_mute(struct snd_soc_card *card) ++{ ++ if (mute_gpio) { ++ dev_info(card->dev, "%s: muting amp using GPIO22\n", ++ __func__); ++ gpiod_set_value_cansleep(mute_gpio, 0); ++ } ++} ++ ++static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card) ++{ ++ if (mute_gpio) { ++ dev_info(card->dev, "%s: un-muting amp using GPIO22\n", ++ __func__); ++ gpiod_set_value_cansleep(mute_gpio, 1); ++ } ++} ++ ++static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) ++{ ++ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ ++ if (dapm->dev != codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_PREPARE: ++ if (dapm->bias_level != SND_SOC_BIAS_STANDBY) ++ break; ++ ++ /* UNMUTE AMP */ ++ snd_rpi_iqaudio_gpio_unmute(card); ++ ++ break; ++ case SND_SOC_BIAS_STANDBY: ++ if (dapm->bias_level != SND_SOC_BIAS_PREPARE) ++ break; ++ ++ /* MUTE AMP */ ++ snd_rpi_iqaudio_gpio_mute(card); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { ++ .hw_params = snd_rpi_iqaudio_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { ++{ ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_iqaudio_dac_ops, ++ .init = snd_rpi_iqaudio_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_dac = { ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_iqaudio_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), ++}; ++ ++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ bool gpio_unmute = false; ++ ++ snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_card *card = &snd_rpi_iqaudio_dac; ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; ++ bool auto_gpio_mute = false; ++ ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "iqaudio,24db_digital_gain"); ++ ++ if (of_property_read_string(pdev->dev.of_node, "card_name", ++ &card->name)) ++ card->name = "IQaudIODAC"; ++ ++ if (of_property_read_string(pdev->dev.of_node, "dai_name", ++ &dai->name)) ++ dai->name = "IQaudIO DAC"; ++ ++ if (of_property_read_string(pdev->dev.of_node, ++ "dai_stream_name", &dai->stream_name)) ++ dai->stream_name = "IQaudIO DAC HiFi"; ++ ++ /* gpio_unmute - one time unmute amp using GPIO */ ++ gpio_unmute = of_property_read_bool(pdev->dev.of_node, ++ "iqaudio-dac,unmute-amp"); ++ ++ /* auto_gpio_mute - mute/unmute amp using GPIO */ ++ auto_gpio_mute = of_property_read_bool(pdev->dev.of_node, ++ "iqaudio-dac,auto-mute-amp"); ++ ++ if (auto_gpio_mute || gpio_unmute) { ++ mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(mute_gpio)) { ++ ret = PTR_ERR(mute_gpio); ++ dev_err(&pdev->dev, ++ "Failed to get mute gpio: %d\n", ret); ++ return ret; ++ } ++ ++ if (auto_gpio_mute && mute_gpio) ++ snd_rpi_iqaudio_dac.set_bias_level = ++ snd_rpi_iqaudio_set_bias_level; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ return ret; ++ } ++ ++ if (gpio_unmute && mute_gpio) ++ snd_rpi_iqaudio_gpio_unmute(&snd_rpi_iqaudio_dac); ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) ++{ ++ snd_rpi_iqaudio_gpio_mute(&snd_rpi_iqaudio_dac); ++ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); ++} ++ ++static const struct of_device_id iqaudio_of_match[] = { ++ { .compatible = "iqaudio,iqaudio-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, iqaudio_of_match); ++ ++static struct platform_driver snd_rpi_iqaudio_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-iqaudio-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = iqaudio_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_dac_probe, ++ .remove = snd_rpi_iqaudio_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); ++MODULE_LICENSE("GPL v2"); + +From e3b89bd7a255c275dd778e5f871304feb30986c1 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 10:06:56 +0200 +Subject: [PATCH 070/111] Added support for HiFiBerry DAC+ + +The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses +a different codec chip (PCM5122), therefore a new driver is necessary. + +Add support for the HiFiBerry DAC+ Pro. + +The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators. + +An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame. + +Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+ + +24db_digital_gain DT param can be used to specify that PCM512x +codec "Digital" volume control should not be limited to 0dB gain, +and if specified will allow the full 24dB gain. + +Add dt param to force HiFiBerry DAC+ Pro into slave mode + +"dtoverlay=hifiberry-dacplus,slave" + +Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode, +with Pi as master for bit and frame clock. + +Signed-off-by: DigitalDreamtime +--- + drivers/clk/Makefile | 1 + + drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/pcm512x.c | 3 +- + 6 files changed, 530 insertions(+), 1 deletion(-) + create mode 100644 drivers/clk/clk-hifiberry-dacpro.c + create mode 100644 sound/soc/bcm/hifiberry_dacplus.c + +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index dcc5e698ff6dd4d61255dd274dafadb1af239161..1f7a766d4edb9c6115486b8ec4d9017b5f87b074 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o + obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o + obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o + obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o + obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o + obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o + obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o +diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c +new file mode 100644 +index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b9019606c +--- /dev/null ++++ b/drivers/clk/clk-hifiberry-dacpro.c +@@ -0,0 +1,160 @@ ++/* ++ * Clock Driver for HiFiBerry DAC Pro ++ * ++ * Author: Stuart MacLean ++ * Copyright 2015 ++ * ++ * 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 ++ ++/* Clock rate of CLK44EN attached to GPIO6 pin */ ++#define CLK_44EN_RATE 22579200UL ++/* Clock rate of CLK48EN attached to GPIO3 pin */ ++#define CLK_48EN_RATE 24576000UL ++ ++/** ++ * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro ++ * @hw: clk_hw for the common clk framework ++ * @mode: 0 => CLK44EN, 1 => CLK48EN ++ */ ++struct clk_hifiberry_hw { ++ struct clk_hw hw; ++ uint8_t mode; ++}; ++ ++#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) ++ ++static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { ++ { .compatible = "hifiberry,dacpro-clk",}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); ++ ++static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : ++ CLK_48EN_RATE; ++} ++ ++static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long *parent_rate) ++{ ++ long actual_rate; ++ ++ if (rate <= CLK_44EN_RATE) { ++ actual_rate = (long)CLK_44EN_RATE; ++ } else if (rate >= CLK_48EN_RATE) { ++ actual_rate = (long)CLK_48EN_RATE; ++ } else { ++ long diff44Rate = (long)(rate - CLK_44EN_RATE); ++ long diff48Rate = (long)(CLK_48EN_RATE - rate); ++ ++ if (diff44Rate < diff48Rate) ++ actual_rate = (long)CLK_44EN_RATE; ++ else ++ actual_rate = (long)CLK_48EN_RATE; ++ } ++ return actual_rate; ++} ++ ++ ++static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ unsigned long actual_rate; ++ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); ++ ++ actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, ++ &parent_rate); ++ clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; ++ return 0; ++} ++ ++ ++const struct clk_ops clk_hifiberry_dacpro_rate_ops = { ++ .recalc_rate = clk_hifiberry_dacpro_recalc_rate, ++ .round_rate = clk_hifiberry_dacpro_round_rate, ++ .set_rate = clk_hifiberry_dacpro_set_rate, ++}; ++ ++static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct clk_hifiberry_hw *proclk; ++ struct clk *clk; ++ struct device *dev; ++ struct clk_init_data init; ++ ++ dev = &pdev->dev; ++ ++ proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); ++ if (!proclk) ++ return -ENOMEM; ++ ++ init.name = "clk-hifiberry-dacpro"; ++ init.ops = &clk_hifiberry_dacpro_rate_ops; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = NULL; ++ init.num_parents = 0; ++ ++ proclk->mode = 0; ++ proclk->hw.init = &init; ++ ++ clk = devm_clk_register(dev, &proclk->hw); ++ if (!IS_ERR(clk)) { ++ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, ++ clk); ++ } else { ++ dev_err(dev, "Fail to register clock driver\n"); ++ kfree(proclk); ++ ret = PTR_ERR(clk); ++ } ++ return ret; ++} ++ ++static int clk_hifiberry_dacpro_remove(struct platform_device *pdev) ++{ ++ of_clk_del_provider(pdev->dev.of_node); ++ return 0; ++} ++ ++static struct platform_driver clk_hifiberry_dacpro_driver = { ++ .probe = clk_hifiberry_dacpro_probe, ++ .remove = clk_hifiberry_dacpro_remove, ++ .driver = { ++ .name = "clk-hifiberry-dacpro", ++ .of_match_table = clk_hifiberry_dacpro_dt_ids, ++ }, ++}; ++ ++static int __init clk_hifiberry_dacpro_init(void) ++{ ++ return platform_driver_register(&clk_hifiberry_dacpro_driver); ++} ++core_initcall(clk_hifiberry_dacpro_init); ++ ++static void __exit clk_hifiberry_dacpro_exit(void) ++{ ++ platform_driver_unregister(&clk_hifiberry_dacpro_driver); ++} ++module_exit(clk_hifiberry_dacpro_exit); ++ ++MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:clk-hifiberry-dacpro"); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 38dcdd975b406b9308e151f5d3a80dbca5163be5..8c338b5803042ad3834ee46a8dc93f53c53953f6 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -15,6 +15,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_DACPLUS ++ tristate "Support for HifiBerry DAC+" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x ++ 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 || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 08e4dc55757855fedec6845b82fc5f9f91f1584b..a29538e56b62ef6e7098b81b81e1389a22beeafa 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,11 +5,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +new file mode 100644 +index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -0,0 +1,358 @@ ++/* ++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro ++ * ++ * Author: Daniel Matuschek, Stuart MacLean ++ * Copyright 2014-2015 ++ * based on code by Florian Meier ++ * ++ * 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 ++#include ++ ++#include "../codecs/pcm512x.h" ++ ++#define HIFIBERRY_DACPRO_NOCLOCK 0 ++#define HIFIBERRY_DACPRO_CLK44EN 1 ++#define HIFIBERRY_DACPRO_CLK48EN 2 ++ ++struct pcm512x_priv { ++ struct regmap *regmap; ++ struct clk *sclk; ++}; ++ ++/* Clock rate of CLK44EN attached to GPIO6 pin */ ++#define CLK_44EN_RATE 22579200UL ++/* Clock rate of CLK48EN attached to GPIO3 pin */ ++#define CLK_48EN_RATE 24576000UL ++ ++static bool slave; ++static bool snd_rpi_hifiberry_is_dacpro; ++static bool digital_gain_0db_limit = true; ++ ++static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_codec *codec, ++ int clk_id) ++{ ++ switch (clk_id) { ++ case HIFIBERRY_DACPRO_NOCLOCK: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x00); ++ break; ++ case HIFIBERRY_DACPRO_CLK44EN: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x20); ++ break; ++ case HIFIBERRY_DACPRO_CLK48EN: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x04); ++ break; ++ } ++} ++ ++static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_codec *codec) ++{ ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x24, 0x24); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_codec *codec) ++{ ++ int sck; ++ ++ sck = snd_soc_read(codec, PCM512x_RATE_DET_4); ++ return (!(sck & 0x40)); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep( ++ struct snd_soc_codec *codec) ++{ ++ msleep(2); ++ return snd_rpi_hifiberry_dacplus_is_sclk(codec); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_codec *codec) ++{ ++ bool isClk44EN, isClk48En, isNoClk; ++ ++ snd_rpi_hifiberry_dacplus_clk_gpio(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK44EN); ++ isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_NOCLOCK); ++ isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK48EN); ++ isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ return (isClk44EN && isClk48En && !isNoClk); ++} ++ ++static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate) ++{ ++ int type; ++ ++ switch (sample_rate) { ++ case 11025: ++ case 22050: ++ case 44100: ++ case 88200: ++ case 176400: ++ type = HIFIBERRY_DACPRO_CLK44EN; ++ break; ++ default: ++ type = HIFIBERRY_DACPRO_CLK48EN; ++ break; ++ } ++ return type; ++} ++ ++static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_codec *codec, ++ int sample_rate) ++{ ++ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); ++ ++ if (!IS_ERR(pcm512x->sclk)) { ++ int ctype; ++ ++ ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate); ++ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN) ++ ? CLK_44EN_RATE : CLK_48EN_RATE); ++ snd_rpi_hifiberry_dacplus_select_clk(codec, ctype); ++ } ++} ++ ++static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct pcm512x_priv *priv; ++ ++ if (slave) ++ snd_rpi_hifiberry_is_dacpro = false; ++ else ++ snd_rpi_hifiberry_is_dacpro = ++ snd_rpi_hifiberry_dacplus_is_pro_card(codec); ++ ++ if (snd_rpi_hifiberry_is_dacpro) { ++ struct snd_soc_dai_link *dai = rtd->dai_link; ++ ++ dai->name = "HiFiBerry DAC+ Pro"; ++ dai->stream_name = "HiFiBerry DAC+ Pro HiFi"; ++ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM; ++ ++ snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11); ++ snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03); ++ snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63); ++ } else { ++ priv = snd_soc_codec_get_drvdata(codec); ++ priv->sclk = ERR_PTR(-ENOENT); ++ } ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); ++ ++ if (digital_gain_0db_limit) ++ { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_update_rate_den( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); ++ struct snd_ratnum *rats_no_pll; ++ unsigned int num = 0, den = 0; ++ int err; ++ ++ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL); ++ if (!rats_no_pll) ++ return -ENOMEM; ++ ++ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; ++ rats_no_pll->den_min = 1; ++ rats_no_pll->den_max = 128; ++ rats_no_pll->den_step = 1; ++ ++ err = snd_interval_ratnum(hw_param_interval(params, ++ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den); ++ if (err >= 0 && den) { ++ params->rate_num = num; ++ params->rate_den = den; ++ } ++ ++ devm_kfree(rtd->dev, rats_no_pll); ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro( ++ struct snd_soc_dai *cpu_dai, struct snd_pcm_hw_params *params) ++{ ++ int bratio = snd_pcm_format_physical_width(params_format(params)) ++ * params_channels(params); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio); ++} ++ ++static int snd_rpi_hifiberry_dacplus_hw_params( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ int ret; ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ if (snd_rpi_hifiberry_is_dacpro) { ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_rpi_hifiberry_dacplus_set_sclk(codec, ++ params_rate(params)); ++ ++ ret = snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro(cpu_dai, ++ params); ++ if (!ret) ++ ret = snd_rpi_hifiberry_dacplus_update_rate_den( ++ substream, params); ++ } else { ++ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++ } ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_startup( ++ struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_dacplus_shutdown( ++ struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { ++ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, ++ .startup = snd_rpi_hifiberry_dacplus_startup, ++ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { ++{ ++ .name = "HiFiBerry DAC+", ++ .stream_name = "HiFiBerry DAC+ HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dacplus_ops, ++ .init = snd_rpi_hifiberry_dacplus_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dacplus = { ++ .name = "snd_rpi_hifiberry_dacplus", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_hifiberry_dacplus_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), ++}; ++ ++static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai; ++ ++ dai = &snd_rpi_hifiberry_dacplus_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "hifiberry,24db_digital_gain"); ++ slave = of_property_read_bool(pdev->dev.of_node, ++ "hifiberry-dacplus,slave"); ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); ++} ++ ++static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dacplus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { ++ .driver = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_dacplus_probe, ++ .remove = snd_rpi_hifiberry_dacplus_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dacplus_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c +index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, + int fssp; + int gpio; + +- lrclk_div = snd_soc_params_to_frame_size(params); ++ lrclk_div = snd_pcm_format_physical_width(params_format(params)) ++ * params_channels(params); + if (lrclk_div == 0) { + dev_err(dev, "No LRCLK?\n"); + return -EINVAL; + +From 5d2e827ef45aeb4bad9c5881b213b093b4c35cd9 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 11:09:58 +0200 +Subject: [PATCH 071/111] Added driver for HiFiBerry Amp amplifier add-on board + +The driver contains a low-level hardware driver for the TAS5713 and the +drivers for the Raspberry Pi I2S subsystem. + +TAS5713: return error if initialisation fails + +Existing TAS5713 driver logs errors during initialisation, but does not return +an error code. Therefore even if initialisation fails, the driver will still be +loaded, but won't work. This patch fixes this. I2C communication error will now +reported correctly by a non-zero return code. + +HiFiBerry Amp: fix device-tree problems + +Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. +--- + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ + sound/soc/codecs/Kconfig | 4 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ + 7 files changed, 722 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_amp.c + create mode 100644 sound/soc/codecs/tas5713.c + create mode 100644 sound/soc/codecs/tas5713.h + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8c338b5803042ad3834ee46a8dc93f53c53953f6..7677c898773e6dd87c3ef385e380aa42c85e66d8 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -29,6 +29,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. + ++config SND_BCM2708_SOC_HIFIBERRY_AMP ++ tristate "Support for the HifiBerry Amp" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_TAS5713 ++ help ++ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index a29538e56b62ef6e7098b81b81e1389a22beeafa..30db4951129c2d853c5cf631f4cd1263926692d0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,11 +7,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o ++snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_amp.c +@@ -0,0 +1,128 @@ ++/* ++ * ASoC Driver for HifiBerry AMP ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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_amp_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ // ToDo: init of the dsp-registers. ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_amp_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, 64); ++} ++ ++static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { ++ .hw_params = snd_rpi_hifiberry_amp_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { ++ { ++ .name = "HifiBerry AMP", ++ .stream_name = "HifiBerry AMP HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tas5713-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tas5713.1-001b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_amp_ops, ++ .init = snd_rpi_hifiberry_amp_init, ++ }, ++}; ++ ++ ++static struct snd_soc_card snd_rpi_hifiberry_amp = { ++ .name = "snd_rpi_hifiberry_amp", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_hifiberry_amp_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), ++}; ++ ++static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-amp", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); ++ ++ ++static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_amp.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); ++ ++ if (ret != 0) { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); ++} ++ ++ ++static struct platform_driver snd_rpi_hifiberry_amp_driver = { ++ .driver = { ++ .name = "snd-hifiberry-amp", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_amp_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_amp_probe, ++ .remove = snd_rpi_hifiberry_amp_remove, ++}; ++ ++ ++module_platform_driver(snd_rpi_hifiberry_amp_driver); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 4a53fa058a6837b93d2e66b15fda7183cf355058..010fd5f0338988fd58095cf7d2bfbad82aa62b2c 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER ++ select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4_I2C if I2C +@@ -774,6 +775,9 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C + ++config SND_SOC_TAS5713 ++ tristate ++ + config SND_SOC_TLV320AIC23 + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 96b312249d197b2083b157d1c07eb106bc34ba7f..2f39e6b9d488ea5341ba40282eef12dac899e6af 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -135,6 +135,7 @@ snd-soc-tas5086-objs := tas5086.o + snd-soc-tas571x-objs := tas571x.o + snd-soc-tas5720-objs := tas5720.o + snd-soc-tfa9879-objs := tfa9879.o ++snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -347,6 +348,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o + obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o ++obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9b2713861dcbed751842ca29c88eb1eae5867411 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.c +@@ -0,0 +1,369 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "tas5713.h" ++ ++ ++static struct i2c_client *i2c; ++ ++struct tas5713_priv { ++ struct regmap *regmap; ++ int mclk_div; ++ struct snd_soc_codec *codec; ++}; ++ ++static struct tas5713_priv *priv_data; ++ ++ ++ ++ ++/* ++ * _ _ ___ _ ___ _ _ ++ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ ++ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< ++ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ ++ * ++ */ ++ ++static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); ++ ++ ++static const struct snd_kcontrol_new tas5713_snd_controls[] = { ++ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), ++ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) ++}; ++ ++ ++ ++ ++/* ++ * __ __ _ _ ___ _ ++ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ ++ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| ++ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ u16 blen = 0x00; ++ ++ struct snd_soc_codec *codec; ++ codec = dai->codec; ++ priv_data->codec = dai->codec; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ blen = 0x03; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ blen = 0x1; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ blen = 0x04; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ blen = 0x05; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported word length: %u\n", ++ params_format(params)); ++ return -EINVAL; ++ } ++ ++ // set word length ++ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); ++ ++ return 0; ++} ++ ++ ++static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ unsigned int val = 0; ++ ++ struct tas5713_priv *tas5713; ++ struct snd_soc_codec *codec = dai->codec; ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ if (mute) { ++ val = TAS5713_SOFT_MUTE_ALL; ++ } ++ ++ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); ++} ++ ++ ++static const struct snd_soc_dai_ops tas5713_dai_ops = { ++ .hw_params = tas5713_hw_params, ++ .mute_stream = tas5713_mute_stream, ++}; ++ ++ ++static struct snd_soc_dai_driver tas5713_dai = { ++ .name = "tas5713-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), ++ }, ++ .ops = &tas5713_dai_ops, ++}; ++ ++ ++ ++ ++/* ++ * ___ _ ___ _ ++ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ ++ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| ++ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_remove(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ return 0; ++} ++ ++ ++static int tas5713_probe(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ int i, ret; ++ ++ i2c = container_of(codec->dev, struct i2c_client, dev); ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Trim oscillator ++ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); ++ if (ret < 0) return ret; ++ msleep(1000); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Clock mode: 44/48kHz, MCLK=64xfs ++ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); ++ if (ret < 0) return ret; ++ ++ // I2S 24bit ++ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); ++ if (ret < 0) return ret; ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); ++ if (ret < 0) return ret; ++ ++ // Set volume to 0db ++ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); ++ if (ret < 0) return ret; ++ ++ // Now start programming the default initialization sequence ++ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { ++ ret = i2c_master_send(i2c, ++ tas5713_init_sequence[i].data, ++ tas5713_init_sequence[i].size); ++ if (ret < 0) { ++ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); ++ } ++ } ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { ++ .probe = tas5713_probe, ++ .remove = tas5713_remove, ++ .controls = tas5713_snd_controls, ++ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++}; ++ ++ ++ ++ ++/* ++ * ___ ___ ___ ___ _ ++ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ ++ * | | / / (__ | |) | '_| \ V / -_) '_| ++ * |___/___\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static const struct reg_default tas5713_reg_defaults[] = { ++ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB ++ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB ++ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB ++ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB ++}; ++ ++ ++static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case TAS5713_DEVICE_ID: ++ case TAS5713_ERROR_STATUS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++ ++static const struct of_device_id tas5713_of_match[] = { ++ { .compatible = "ti,tas5713", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, tas5713_of_match); ++ ++ ++static struct regmap_config tas5713_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .max_register = TAS5713_MAX_REGISTER, ++ .volatile_reg = tas5713_reg_volatile, ++ ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = tas5713_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), ++}; ++ ++ ++static int tas5713_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ int ret; ++ ++ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); ++ if (!priv_data) ++ return -ENOMEM; ++ ++ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); ++ if (IS_ERR(priv_data->regmap)) { ++ ret = PTR_ERR(priv_data->regmap); ++ return ret; ++ } ++ ++ i2c_set_clientdata(i2c, priv_data); ++ ++ ret = snd_soc_register_codec(&i2c->dev, ++ &soc_codec_dev_tas5713, &tas5713_dai, 1); ++ ++ return ret; ++} ++ ++ ++static int tas5713_i2c_remove(struct i2c_client *i2c) ++{ ++ snd_soc_unregister_codec(&i2c->dev); ++ i2c_set_clientdata(i2c, NULL); ++ ++ kfree(priv_data); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id tas5713_i2c_id[] = { ++ { "tas5713", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); ++ ++ ++static struct i2c_driver tas5713_i2c_driver = { ++ .driver = { ++ .name = "tas5713", ++ .owner = THIS_MODULE, ++ .of_match_table = tas5713_of_match, ++ }, ++ .probe = tas5713_i2c_probe, ++ .remove = tas5713_i2c_remove, ++ .id_table = tas5713_i2c_id ++}; ++ ++ ++static int __init tas5713_modinit(void) ++{ ++ int ret = 0; ++ ++ ret = i2c_add_driver(&tas5713_i2c_driver); ++ if (ret) { ++ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", ++ ret); ++ } ++ ++ return ret; ++} ++module_init(tas5713_modinit); ++ ++ ++static void __exit tas5713_exit(void) ++{ ++ i2c_del_driver(&tas5713_i2c_driver); ++} ++module_exit(tas5713_exit); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for TAS5713"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +new file mode 100644 +index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8f612a342 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.h +@@ -0,0 +1,210 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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. ++ */ ++ ++#ifndef _TAS5713_H ++#define _TAS5713_H ++ ++ ++// TAS5713 I2C-bus register addresses ++ ++#define TAS5713_CLOCK_CTRL 0x00 ++#define TAS5713_DEVICE_ID 0x01 ++#define TAS5713_ERROR_STATUS 0x02 ++#define TAS5713_SYSTEM_CTRL1 0x03 ++#define TAS5713_SERIAL_DATA_INTERFACE 0x04 ++#define TAS5713_SYSTEM_CTRL2 0x05 ++#define TAS5713_SOFT_MUTE 0x06 ++#define TAS5713_VOL_MASTER 0x07 ++#define TAS5713_VOL_CH1 0x08 ++#define TAS5713_VOL_CH2 0x09 ++#define TAS5713_VOL_HEADPHONE 0x0A ++#define TAS5713_VOL_CONFIG 0x0E ++#define TAS5713_MODULATION_LIMIT 0x10 ++#define TAS5713_IC_DLY_CH1 0x11 ++#define TAS5713_IC_DLY_CH2 0x12 ++#define TAS5713_IC_DLY_CH3 0x13 ++#define TAS5713_IC_DLY_CH4 0x14 ++ ++#define TAS5713_START_STOP_PERIOD 0x1A ++#define TAS5713_OSC_TRIM 0x1B ++#define TAS5713_BKND_ERR 0x1C ++ ++#define TAS5713_INPUT_MUX 0x20 ++#define TAS5713_SRC_SELECT_CH4 0x21 ++#define TAS5713_PWM_MUX 0x25 ++ ++#define TAS5713_CH1_BQ0 0x29 ++#define TAS5713_CH1_BQ1 0x2A ++#define TAS5713_CH1_BQ2 0x2B ++#define TAS5713_CH1_BQ3 0x2C ++#define TAS5713_CH1_BQ4 0x2D ++#define TAS5713_CH1_BQ5 0x2E ++#define TAS5713_CH1_BQ6 0x2F ++#define TAS5713_CH1_BQ7 0x58 ++#define TAS5713_CH1_BQ8 0x59 ++ ++#define TAS5713_CH2_BQ0 0x30 ++#define TAS5713_CH2_BQ1 0x31 ++#define TAS5713_CH2_BQ2 0x32 ++#define TAS5713_CH2_BQ3 0x33 ++#define TAS5713_CH2_BQ4 0x34 ++#define TAS5713_CH2_BQ5 0x35 ++#define TAS5713_CH2_BQ6 0x36 ++#define TAS5713_CH2_BQ7 0x5C ++#define TAS5713_CH2_BQ8 0x5D ++ ++#define TAS5713_CH4_BQ0 0x5A ++#define TAS5713_CH4_BQ1 0x5B ++#define TAS5713_CH3_BQ0 0x5E ++#define TAS5713_CH3_BQ1 0x5F ++ ++#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B ++#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C ++#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E ++#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F ++#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 ++#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 ++#define TAS5713_DRC_CTRL 0x46 ++ ++#define TAS5713_BANK_SW_CTRL 0x50 ++#define TAS5713_CH1_OUTPUT_MIXER 0x51 ++#define TAS5713_CH2_OUTPUT_MIXER 0x52 ++#define TAS5713_CH1_INPUT_MIXER 0x53 ++#define TAS5713_CH2_INPUT_MIXER 0x54 ++#define TAS5713_OUTPUT_POST_SCALE 0x56 ++#define TAS5713_OUTPUT_PRESCALE 0x57 ++ ++#define TAS5713_IDF_POST_SCALE 0x62 ++ ++#define TAS5713_CH1_INLINE_MIXER 0x70 ++#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 ++#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 ++#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 ++#define TAS5713_CH2_INLINE_MIXER 0x74 ++#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 ++#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 ++#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 ++ ++#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 ++#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 ++ ++#define TAS5713_REGISTER_COUNT 0x46 ++#define TAS5713_MAX_REGISTER 0xF9 ++ ++ ++// Bitmasks for registers ++#define TAS5713_SOFT_MUTE_ALL 0x07 ++ ++ ++ ++struct tas5713_init_command { ++ const int size; ++ const char *const data; ++}; ++ ++static const struct tas5713_init_command tas5713_init_sequence[] = { ++ ++ // Trim oscillator ++ { .size = 2, .data = "\x1B\x00" }, ++ // System control register 1 (0x03): block DC ++ { .size = 2, .data = "\x03\x80" }, ++ // Mute everything ++ { .size = 2, .data = "\x05\x40" }, ++ // Modulation limit register (0x10): 97.7% ++ { .size = 2, .data = "\x10\x02" }, ++ // Interchannel delay registers ++ // (0x11, 0x12, 0x13, and 0x14): BD mode ++ { .size = 2, .data = "\x11\xB8" }, ++ { .size = 2, .data = "\x12\x60" }, ++ { .size = 2, .data = "\x13\xA0" }, ++ { .size = 2, .data = "\x14\x48" }, ++ // PWM shutdown group register (0x19): no shutdown ++ { .size = 2, .data = "\x19\x00" }, ++ // Input multiplexer register (0x20): BD mode ++ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, ++ // PWM output mux register (0x25) ++ // Channel 1 --> OUTA, channel 1 neg --> OUTB ++ // Channel 2 --> OUTC, channel 2 neg --> OUTD ++ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, ++ // DRC control (0x46): DRC off ++ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, ++ // BKND_ERR register (0x1C): 299ms reset period ++ { .size = 2, .data = "\x1C\x07" }, ++ // Mute channel 3 ++ { .size = 2, .data = "\x0A\xFF" }, ++ // Volume configuration register (0x0E): volume slew 512 steps ++ { .size = 2, .data = "\x0E\x90" }, ++ // Clock control register (0x00): 44/48kHz, MCLK=64xfs ++ { .size = 2, .data = "\x00\x60" }, ++ // Bank switch and eq control (0x50): no bank switching ++ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, ++ // Volume registers (0x07, 0x08, 0x09, 0x0A) ++ { .size = 2, .data = "\x07\x20" }, ++ { .size = 2, .data = "\x08\x30" }, ++ { .size = 2, .data = "\x09\x30" }, ++ { .size = 2, .data = "\x0A\xFF" }, ++ // 0x72, 0x73, 0x76, 0x77 input mixer: ++ // no intermix between channels ++ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, ++ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: ++ // no inline DRC inmix ++ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, ++ // 0x56, 0x57 Output scale ++ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, ++ // 0x3B, 0x3c ++ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ // 0x51, 0x52: output mixer ++ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ // PEQ defaults ++ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++}; ++ ++ ++#endif /* _TAS5713_H */ + +From a071d287ae26904607ae671615e7d54e20eee74c Mon Sep 17 00:00:00 2001 +From: Ryan Coe +Date: Sat, 31 Jan 2015 18:25:49 -0700 +Subject: [PATCH 072/111] Update ds1307 driver for device-tree support + +Signed-off-by: Ryan Coe +--- + drivers/rtc/rtc-ds1307.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 821d9c089cdb48a40a244d1c18ab912d6f0b9432..409ed8e449e54ea6751185b1c0760cfc8aaaf59e 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1610,6 +1610,14 @@ static int ds1307_remove(struct i2c_client *client) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id ds1307_of_match[] = { ++ { .compatible = "maxim,ds1307" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ds1307_of_match); ++#endif ++ + static struct i2c_driver ds1307_driver = { + .driver = { + .name = "rtc-ds1307", + +From c1c82394785fd988a7b800782009558c4464a316 Mon Sep 17 00:00:00 2001 +From: Waldemar Brodkorb +Date: Wed, 25 Mar 2015 09:26:17 +0100 +Subject: [PATCH 073/111] Add driver for rpi-proto + +Forward port of 3.10.x driver from https://github.com/koalo +We are using a custom board and would like to use rpi 3.18.x +kernel. Patch works fine for our embedded system. + +URL to the audio chip: +http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ + +Playback tested with devicetree enabled. + +Signed-off-by: Waldemar Brodkorb +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 163 insertions(+) + create mode 100644 sound/soc/bcm/rpi-proto.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 7677c898773e6dd87c3ef385e380aa42c85e66d8..8669a9ac9734c465c7dc3f40c864f71b68a6de75 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -43,6 +43,13 @@ config SND_BCM2708_SOC_RPI_DAC + help + Say Y or M if you want to add support for RPi-DAC. + ++config SND_BCM2708_SOC_RPI_PROTO ++ tristate "Support for Rpi-PROTO" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8731 ++ help ++ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). ++ + config SND_BCM2708_SOC_IQAUDIO_DAC + tristate "Support for IQaudIO-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 30db4951129c2d853c5cf631f4cd1263926692d0..4f5ab1fa4414e64a164eaa4575ffaa06d1cbf332 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -9,6 +9,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -16,4 +17,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed6772b19a2d +--- /dev/null ++++ b/sound/soc/bcm/rpi-proto.c +@@ -0,0 +1,154 @@ ++/* ++ * 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_codec *codec = rtd->codec; ++ 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); ++ if (ret < 0){ ++ dev_err(codec->dev, ++ "Failed to set BCLK ratio %d\n", ret); ++ return ret; ++ } ++ ++ /* Set proto sysclk */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, ++ sysclk, SND_SOC_CLOCK_IN); ++ if (ret < 0) { ++ dev_err(codec->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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_proto_of_match[] = { ++ { .compatible = "rpi,rpi-proto", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); ++ ++static struct platform_driver snd_rpi_proto_driver = { ++ .driver = { ++ .name = "snd-rpi-proto", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_proto_of_match, ++ }, ++ .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"); + +From e7dd0527b17927b2e94d04e13edf24506f812e2e Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 082/141] RaspiDAC3 support +Subject: [PATCH 074/111] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -130500,10 +130470,10 @@ index 0000000000000000000000000000000000000000..e7422e2dd3d70622a48ab3b2e1929869 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 562cf8a575b110278e6caeab401b0fd2460c6bfe Mon Sep 17 00:00:00 2001 +From 3573e75f6f331207b9bd31a2ba536b7e109bc0c1 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:02:34 +0100 -Subject: [PATCH 083/141] tpa6130a2: Add headphone switch control +Subject: [PATCH 075/111] tpa6130a2: Add headphone switch control Signed-off-by: Jan Grulich --- @@ -130594,2079 +130564,10 @@ index 11d85c5c787addb8d8add7fc2b52ab91cc49b63d..3caaa17e28e91e995d6781ca7f88b747 /* -From 71796389ee6b2fd23b047bc51d7f525228a5cfa2 Mon Sep 17 00:00:00 2001 -From: P33M -Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 084/141] rpi_display: add backlight driver and overlay - -Add a mailbox-driven backlight controller for the Raspberry Pi DSI -touchscreen display. Requires updated GPU firmware to recognise the -mailbox request. - -Signed-off-by: Gordon Hollingworth ---- - drivers/video/backlight/Kconfig | 6 ++ - drivers/video/backlight/Makefile | 1 + - drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 drivers/video/backlight/rpi_backlight.c - -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -265,6 +265,12 @@ config BACKLIGHT_PWM - If you have a LCD backlight adjustable by PWM, say Y to enable - this driver. - -+config BACKLIGHT_RPI -+ tristate "Raspberry Pi display firmware driven backlight" -+ help -+ If you have the Raspberry Pi DSI touchscreen display, say Y to -+ enable the mailbox-controlled backlight driver. -+ - config BACKLIGHT_DA903X - tristate "Backlight Driver for DA9030/DA9034 using WLED" - depends on PMIC_DA903X -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o - obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o - obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -+obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o -diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c -new file mode 100644 -index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad ---- /dev/null -+++ b/drivers/video/backlight/rpi_backlight.c -@@ -0,0 +1,119 @@ -+/* -+ * rpi_bl.c - Backlight controller through VPU -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rpi_backlight { -+ struct device *dev; -+ struct device *fbdev; -+ struct rpi_firmware *fw; -+}; -+ -+static int rpi_backlight_update_status(struct backlight_device *bl) -+{ -+ struct rpi_backlight *gbl = bl_get_data(bl); -+ int brightness = bl->props.brightness; -+ int ret; -+ -+ if (bl->props.power != FB_BLANK_UNBLANK || -+ bl->props.fb_blank != FB_BLANK_UNBLANK || -+ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) -+ brightness = 0; -+ -+ ret = rpi_firmware_property(gbl->fw, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, -+ &brightness, sizeof(brightness)); -+ if (ret) { -+ dev_err(gbl->dev, "Failed to set brightness\n"); -+ return ret; -+ } -+ -+ if (brightness < 0) { -+ dev_err(gbl->dev, "Backlight change failed\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+} -+ -+static const struct backlight_ops rpi_backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .update_status = rpi_backlight_update_status, -+}; -+ -+static int rpi_backlight_probe(struct platform_device *pdev) -+{ -+ struct backlight_properties props; -+ struct backlight_device *bl; -+ struct rpi_backlight *gbl; -+ struct device_node *fw_node; -+ -+ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); -+ if (gbl == NULL) -+ return -ENOMEM; -+ -+ gbl->dev = &pdev->dev; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ gbl->fw = rpi_firmware_get(fw_node); -+ if (!gbl->fw) -+ return -EPROBE_DEFER; -+ -+ memset(&props, 0, sizeof(props)); -+ props.type = BACKLIGHT_RAW; -+ props.max_brightness = 255; -+ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), -+ &pdev->dev, gbl, &rpi_backlight_ops, -+ &props); -+ if (IS_ERR(bl)) { -+ dev_err(&pdev->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ bl->props.brightness = 255; -+ backlight_update_status(bl); -+ -+ platform_set_drvdata(pdev, bl); -+ return 0; -+} -+ -+static const struct of_device_id rpi_backlight_of_match[] = { -+ { .compatible = "raspberrypi,rpi-backlight" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); -+ -+static struct platform_driver rpi_backlight_driver = { -+ .driver = { -+ .name = "rpi-backlight", -+ .of_match_table = of_match_ptr(rpi_backlight_of_match), -+ }, -+ .probe = rpi_backlight_probe, -+}; -+ -+module_platform_driver(rpi_backlight_driver); -+ -+MODULE_AUTHOR("Gordon Hollingworth "); -+MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); -+MODULE_LICENSE("GPL"); - -From 824452ae388cddf8cfa2aff4c7cf3978dff74165 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 085/141] bcm2835-virtgpio: Virtual GPIO driver - -Add a virtual GPIO driver that uses the firmware mailbox interface to -request that the VPU toggles LEDs. ---- - drivers/gpio/Kconfig | 6 ++ - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/gpio/gpio-bcm-virt.c - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 5f3429f0bf46970fcf376c79dca6633cd7469d5a..86cb971105296fea399bc3c51b69ba0a8834f9e6 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -142,6 +142,12 @@ config GPIO_BCM_KONA - help - Turn on GPIO support for Broadcom "Kona" chips. - -+config GPIO_BCM_VIRT -+ bool "Broadcom Virt GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ help -+ Turn on virtual GPIO support for Broadcom BCM283X chips. -+ - config GPIO_BRCMSTB - tristate "BRCMSTB GPIO support" - default y if (ARCH_BRCMSTB || BMIPS_GENERIC) -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index 1e0b74f3b1ed98021f3d05b067b749b7cb1c652d..908596d99ce7b0390bfdec32a27de996efdeccd3 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o - obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -new file mode 100644 -index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -0,0 +1,179 @@ -+/* -+ * brcmvirt GPIO driver -+ * -+ * Copyright (C) 2012,2013 Dom Cobley -+ * Based on gpio-clps711x.c by Alexander Shiyan -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "brcmvirt-gpio" -+#define NUM_GPIO 2 -+ -+struct brcmvirt_gpio { -+ struct gpio_chip gc; -+ u32 __iomem *ts_base; -+ /* two packed 16-bit counts of enabled and disables -+ Allows host to detect a brief enable that was missed */ -+ u32 enables_disables[NUM_GPIO]; -+}; -+ -+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return -EINVAL; -+} -+ -+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return 0; -+} -+ -+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ unsigned v; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ v = readl(gpio->ts_base + off); -+ return (v >> off) & 1; -+} -+ -+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ u16 enables, disables; -+ s16 diff; -+ bool lit; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ enables = gpio->enables_disables[off] >> 16; -+ disables = gpio->enables_disables[off] >> 0; -+ diff = (s16)(enables - disables); -+ lit = diff > 0; -+ if ((val && lit) || (!val && !lit)) -+ return; -+ if (val) -+ enables++; -+ else -+ disables++; -+ diff = (s16)(enables - disables); -+ BUG_ON(diff != 0 && diff != 1); -+ gpio->enables_disables[off] = (enables << 16) | (disables << 0); -+ writel(gpio->enables_disables[off], gpio->ts_base + off); -+} -+ -+static int brcmvirt_gpio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmvirt_gpio *ucb; -+ u32 gpiovirtbuf; -+ int err = 0; -+ -+ fw_node = of_parse_phandle(np, "firmware", 0); -+ if (!fw_node) { -+ dev_err(dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err) { -+ dev_err(dev, "Failed to get gpiovirtbuf\n"); -+ goto err; -+ } -+ -+ if (!gpiovirtbuf) { -+ dev_err(dev, "No virtgpio buffer\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); -+ if (!ucb) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ // mmap the physical memory -+ gpiovirtbuf &= ~0xc0000000; -+ ucb->ts_base = ioremap(gpiovirtbuf, 4096); -+ if (ucb->ts_base == NULL) { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ //ucb->gc.dev = dev; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 100; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmvirt_gpio_dir_in; -+ ucb->gc.direction_output = brcmvirt_gpio_dir_out; -+ ucb->gc.get = brcmvirt_gpio_get; -+ ucb->gc.set = brcmvirt_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto err; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+err: -+ return err; -+ -+} -+ -+static int brcmvirt_gpio_remove(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ iounmap(ucb->ts_base); -+ return err; -+} -+ -+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-virtgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); -+ -+static struct platform_driver brcmvirt_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), -+ }, -+ .probe = brcmvirt_gpio_probe, -+ .remove = brcmvirt_gpio_remove, -+}; -+module_platform_driver(brcmvirt_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dom Cobley "); -+MODULE_DESCRIPTION("brcmvirt GPIO driver"); -+MODULE_ALIAS("platform:brcmvirt-gpio"); - -From 2e0d36e08a5adcb7987977e75105354a5757cc81 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 4 Mar 2016 12:49:09 +0000 -Subject: [PATCH 086/141] DRM_VC4: Allow to be built for ARCH_BCM270x - ---- - drivers/gpu/drm/vc4/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index 584810474e5b84b211a5cbda681ea04c41bc0055..870fea56438d718c3887f1192afdab176e72e38f 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - -From 974384491624ce3930e1883e12c2fa3064fed752 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 087/141] amba_pl011: Don't use DT aliases for numbering - -The pl011 driver looks for DT aliases of the form "serial", -and if found uses as the device ID. This can cause -/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the -other serial port is provided by the 8250 driver which doesn't -use the same logic. ---- - drivers/tty/serial/amba-pl011.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 7c198e0a3178ae2ab9805c9f317c722d18b2dadf..4f9e97b8a8eeaf0a728a419e3d6614533cb67f4b 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2413,7 +2413,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, - if (IS_ERR(base)) - return PTR_ERR(base); - -+ /* Don't use DT serial aliases - it causes the device to -+ be renumbered to ttyAMA1 if it is the second serial port in the -+ system, even though the other one is ttyS0. The 8250 driver -+ doesn't use this logic, so always remains ttyS0. - index = pl011_probe_dt_alias(index, dev); -+ */ - - uap->old_cr = 0; - uap->port.dev = dev; - -From 37beef929ac285a1f38408254579cca1bb0021b3 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 088/141] OF: DT-Overlay configfs interface - -This is a port of Pantelis Antoniou's v3 port that makes use of the -new upstreamed configfs support for binary attributes. - -Original commit message: - -Add a runtime interface to using configfs for generic device tree overlay -usage. With it its possible to use device tree overlays without having -to use a per-platform overlay manager. - -Please see Documentation/devicetree/configfs-overlays.txt for more info. - -Changes since v2: -- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) -- Created a documentation entry -- Slight rewording in Kconfig - -Changes since v1: -- of_resolve() -> of_resolve_phandles(). - -Originally-signed-off-by: Pantelis Antoniou -Signed-off-by: Phil Elwell - -DT configfs: Fix build errors on other platforms - -Signed-off-by: Phil Elwell - -DT configfs: fix build error - -There is an error when compiling rpi-4.6.y branch: - CC drivers/of/configfs.o -drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .default_groups = of_cfs_def_groups, - ^ -drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') - -The .default_groups is linked list since commit -1ae1602de028acaa42a0f6ff18d19756f8e825c6. -This commit uses configfs_add_default_group to fix this problem. - -Signed-off-by: Slawomir Stepien ---- - Documentation/devicetree/configfs-overlays.txt | 31 +++ - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/configfs.c | 311 +++++++++++++++++++++++++ - 4 files changed, 350 insertions(+) - create mode 100644 Documentation/devicetree/configfs-overlays.txt - create mode 100644 drivers/of/configfs.c - -diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt -new file mode 100644 -index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad ---- /dev/null -+++ b/Documentation/devicetree/configfs-overlays.txt -@@ -0,0 +1,31 @@ -+Howto use the configfs overlay interface. -+ -+A device-tree configfs entry is created in /config/device-tree/overlays -+and and it is manipulated using standard file system I/O. -+Note that this is a debug level interface, for use by developers and -+not necessarily something accessed by normal users due to the -+security implications of having direct access to the kernel's device tree. -+ -+* To create an overlay you mkdir the directory: -+ -+ # mkdir /config/device-tree/overlays/foo -+ -+* Either you echo the overlay firmware file to the path property file. -+ -+ # echo foo.dtbo >/config/device-tree/overlays/foo/path -+ -+* Or you cat the contents of the overlay to the dtbo file -+ -+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo -+ -+The overlay file will be applied, and devices will be created/destroyed -+as required. -+ -+To remove it simply rmdir the directory. -+ -+ # rmdir /config/device-tree/overlays/foo -+ -+The rationalle of the dual interface (firmware & direct copy) is that each is -+better suited to different use patterns. The firmware interface is what's -+intended to be used by hardware managers in the kernel, while the copy interface -+make sense for developers (since it avoids problems with namespaces). -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index e2a48415d9691059f1beb2afee7f134019d65ecf..7e5e6c4e77e070692cab0ed2e4b827c08c0a1c29 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -112,4 +112,11 @@ config OF_OVERLAY - While this option is selected automatically when needed, you can - enable it manually to improve device tree unit test coverage. - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index 156c072b31177eab081de4e54ab28b7815e32c95..46c8f5754ed84410d7dea83bfedcbdebf3f85453 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o -diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..68f889d9fa1dc19d18964aa9fd208137ed51f013 ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,311 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static int create_overlay(struct cfs_overlay_item *overlay, void *blob) -+{ -+ int err; -+ -+ /* unflatten the tree */ -+ of_fdt_unflatten_tree(blob, &overlay->overlay); -+ if (overlay->overlay == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ err = -EINVAL; -+ goto out_err; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ /* mark it as detached */ -+ of_node_set_flag(overlay->overlay, OF_DETACHED); -+ -+ /* perform resolution */ -+ err = of_resolve_phandles(overlay->overlay); -+ if (err != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto out_err; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ err = of_overlay_create(overlay->overlay); -+ if (err < 0) { -+ pr_err("%s: Failed to create overlay (err=%d)\n", -+ __func__, err); -+ goto out_err; -+ } -+ overlay->ov_id = err; -+ -+out_err: -+ return err; -+} -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = create_overlay(overlay, (void *)overlay->fw->data); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id >= 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = create_overlay(overlay, overlay->dtbo); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id >= 0) -+ of_overlay_destroy(overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->ov_id = -1; -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); - -From dd2cbdf281925d7bf1d6b8417b6c231f082d30ea Mon Sep 17 00:00:00 2001 -From: Cheong2K -Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 089/141] brcm: adds support for BCM43341 wifi - ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index 43fd3f402ebad89f89f7d5f8afdce9613d87b5de..c3c7c799c62014cada37bed43dfa32ac4df5757e 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -606,6 +606,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); -+BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); -@@ -622,6 +623,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), -+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -index 699f2c2782ee9d898a25c95e0c5d45744d0777ff..15598b3687a213d8c00d45965a6b9351759f47fc 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -@@ -35,6 +35,7 @@ - #define BRCM_CC_4330_CHIP_ID 0x4330 - #define BRCM_CC_4334_CHIP_ID 0x4334 - #define BRCM_CC_43340_CHIP_ID 43340 -+#define BRCM_CC_43341_CHIP_ID 43341 - #define BRCM_CC_43362_CHIP_ID 43362 - #define BRCM_CC_4335_CHIP_ID 0x4335 - #define BRCM_CC_4339_CHIP_ID 0x4339 - -From 369253d684cda53c5e59a6bba7e1dbae18be0c45 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 17:25:59 +0000 -Subject: [PATCH 090/141] brcmfmac: Disable power management - -Disable wireless power saving in the brcmfmac WLAN driver. This is a -temporary measure until the connectivity loss resulting from power -saving is resolved. - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index d5c2a27573b45cdfcbb72bf32dedc1dcd0af82da..5a08f59fdfdaa9bd9fef3cd2344c0772b75371cc 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2623,6 +2623,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, - * preference in cfg struct to apply this to - * FW later while initializing the dongle - */ -+ pr_info("power management disabled\n"); -+ enabled = false; - cfg->pwr_save = enabled; - if (!check_vif_up(ifp->vif)) { - - -From 06b146ccc00624225d4dabd803369dcc4a9781b0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Apr 2016 17:13:47 +0100 -Subject: [PATCH 091/141] brcmfmac: Use original country code as a fallback - -Commit 73345fd212980d2e28a5c6d83801c903bd773680: - - brcmfmac: Configure country code using device specific settings - -prevents region codes from working on devices that lack a region code -translation table. In the event of an absent table, preserve the old -behaviour of using the provided code as-is. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 5a08f59fdfdaa9bd9fef3cd2344c0772b75371cc..ceba7b6909b2b2bf4045c5f7640d531f497b505f 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6516,12 +6516,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - struct brcmfmac_pd_cc *country_codes; - struct brcmfmac_pd_cc_entry *cc; - s32 found_index; -+ char ccode[BRCMF_COUNTRY_BUF_SZ]; -+ int rev; - int i; - -+ memcpy(ccode, alpha2, sizeof(ccode)); -+ rev = -1; -+ - country_codes = drvr->settings->country_codes; - if (!country_codes) { -- brcmf_dbg(TRACE, "No country codes configured for device\n"); -- return -EINVAL; -+ brcmf_dbg(TRACE, "No country codes configured for device" -+ " - use requested value\n"); -+ goto use_input_value; - } - - if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -6545,10 +6551,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - brcmf_dbg(TRACE, "No country code match found\n"); - return -EINVAL; - } -- memset(ccreq, 0, sizeof(*ccreq)); -- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); -- memcpy(ccreq->ccode, country_codes->table[found_index].cc, -+ rev = country_codes->table[found_index].rev; -+ memcpy(ccode, country_codes->table[found_index].cc, - BRCMF_COUNTRY_BUF_SZ); -+ -+use_input_value: -+ memset(ccreq, 0, sizeof(*ccreq)); -+ ccreq->rev = cpu_to_le32(rev); -+ memcpy(ccreq->ccode, ccode, sizeof(ccode)); - ccreq->country_abbrev[0] = alpha2[0]; - ccreq->country_abbrev[1] = alpha2[1]; - ccreq->country_abbrev[2] = 0; - -From 007bfc89dd5acef6db652e14fa1b3c99bad17c94 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 19 May 2016 15:36:09 +0100 -Subject: [PATCH 092/141] brcmfmac: Plug memory leak in brcmf_fill_bss_param - -See: https://github.com/raspberrypi/linux/issues/1471 - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index ceba7b6909b2b2bf4045c5f7640d531f497b505f..afb01540261e99c87209aaa53aef439eb297f7c2 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2413,7 +2413,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) - WL_BSS_INFO_MAX); - if (err) { - brcmf_err("Failed to get bss info (%d)\n", err); -- return; -+ goto out_err; - } - si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); - si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); -@@ -2425,6 +2425,9 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) - si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; - if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; -+ -+out_err: -+ kfree(buf); - } - - static s32 - -From f2f7ef4bb245c425305c0edb901357c3cf84b8e8 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 093/141] hci_h5: Don't send conf_req when ACTIVE - -Without this patch, a modem and kernel can continuously bombard each -other with conf_req and conf_rsp messages, in a demented game of tag. ---- - drivers/bluetooth/hci_h5.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) - h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_req, 2) == 0) { - h5_link_control(hu, conf_rsp, 2); -- h5_link_control(hu, conf_req, 3); -+ if (h5->state != H5_ACTIVE) -+ h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_rsp, 2) == 0) { - if (H5_HDR_LEN(hdr) > 2) - h5->tx_win = (data[2] & 0x07); - -From 74f2b9d0a28818a144d4b2a5480c33f948dc19c6 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 22 Jan 2016 13:06:39 -0800 -Subject: [PATCH 094/141] drm/vc4: Add a debugfs node for tracking execution - state. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 1 + - drivers/gpu/drm/vc4/vc4_gem.c | 14 ++++++++++++++ - 3 files changed, 16 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c -index d76ad10b07fda3bb674f45c2151e621c60633364..a99aa8676af774977778edfa2604b6b9df31a4dc 100644 ---- a/drivers/gpu/drm/vc4/vc4_debugfs.c -+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c -@@ -17,6 +17,7 @@ - - static const struct drm_info_list vc4_debugfs_list[] = { - {"bo_stats", vc4_bo_stats_debugfs, 0}, -+ {"gem_exec", vc4_gem_exec_debugfs, 0}, - {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, - {"hvs_regs", vc4_hvs_debugfs_regs, 0}, - {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index fa2ad15d4f62b8baea68e09b52f4edf1c70bb6b6..f0929867b2337eaf781d64860c70cafd006c41b7 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -440,6 +440,7 @@ void vc4_job_handle_completed(struct vc4_dev *vc4); - int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)); -+int vc4_gem_exec_debugfs(struct seq_file *m, void *arg); - - /* vc4_hdmi.c */ - extern struct platform_driver vc4_hdmi_driver; -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 8d4384f8b78d2dbe88df720db6df67c0e1a31e53..aa4517c294540ac7ebc5c8c1da6b9d147409fcb4 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -32,6 +32,20 @@ - #include "vc4_regs.h" - #include "vc4_trace.h" - -+#ifdef CONFIG_DEBUG_FS -+int vc4_gem_exec_debugfs(struct seq_file *m, void *unused) -+{ -+ struct drm_info_node *node = (struct drm_info_node *)m->private; -+ struct drm_device *dev = node->minor->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ -+ seq_printf(m, "Emitted seqno: 0x%016llx\n", vc4->emit_seqno); -+ seq_printf(m, "Finished seqno: 0x%016llx\n", vc4->finished_seqno); -+ -+ return 0; -+} -+#endif /* CONFIG_DEBUG_FS */ -+ - static void - vc4_queue_hangcheck(struct drm_device *dev) - { - -From a6b2cb6f6413cb7800a8d7bdcf73084f768f6848 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 25 Jan 2016 13:03:33 -0800 -Subject: [PATCH 095/141] drm/vc4: Include vc4_drm.h in uapi in downstream - build. - -Signed-off-by: Eric Anholt ---- - include/uapi/drm/Kbuild | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild -index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 ---- a/include/uapi/drm/Kbuild -+++ b/include/uapi/drm/Kbuild -@@ -15,6 +15,7 @@ header-y += radeon_drm.h - header-y += savage_drm.h - header-y += sis_drm.h - header-y += tegra_drm.h -+header-y += vc4_drm.h - header-y += via_drm.h - header-y += vmwgfx_drm.h - header-y += msm_drm.h - -From 6283aa9ef68d0c97b0b9623ff53f8461c62e2c8d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 30 Mar 2016 17:23:15 +0100 -Subject: [PATCH 096/141] cpufreq: Temporarily ignore io_is_busy=1 - -To speed testing of the new sdhost driver that adapts to changes in -core_freq, hack the on-demand governor to treat io_is_busy=1 as -io_is_busy=0. The io_is_busy feature can still be forced using -io_is_busy=2. - -Signed-off-by: Phil Elwell ---- - drivers/cpufreq/cpufreq_ondemand.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c -index acd80272ded67b46ad651cb0eceb92bdf71e26d7..72c5a4c7d6e40bd7407c769c0f6c418fb15df665 100644 ---- a/drivers/cpufreq/cpufreq_ondemand.c -+++ b/drivers/cpufreq/cpufreq_ondemand.c -@@ -216,7 +216,12 @@ static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; -- dbs_data->io_is_busy = !!input; -+ // XXX temporary hack -+ if (input > 1) -+ input = 1; -+ else -+ input = 0; -+ dbs_data->io_is_busy = input; - - /* we need to re-evaluate prev_cpu_idle */ - gov_update_cpu_data(dbs_data); - -From 5e9758439d0e513703384a808b1e09f0896e9359 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Apr 2016 16:59:24 +0100 -Subject: [PATCH 097/141] Revert "ASoC: bcm2835: move to use the clock - framework" - -This reverts commit 517e7a1537ae4663268be5d0c0ec62c563b9fc99. ---- - sound/soc/bcm/bcm2835-i2s.c | 284 ++++++++++++++++++++++++++++++++++---------- - 1 file changed, 220 insertions(+), 64 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 1c1f2210387b26e9551959378f6792f18648652e..3303d5f58082f68b68b535b2bdf7ce8d14cafcc4 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - - #include -@@ -47,6 +46,55 @@ - #include - #include - -+/* Clock registers */ -+#define BCM2835_CLK_PCMCTL_REG 0x00 -+#define BCM2835_CLK_PCMDIV_REG 0x04 -+ -+/* Clock register settings */ -+#define BCM2835_CLK_PASSWD (0x5a000000) -+#define BCM2835_CLK_PASSWD_MASK (0xff000000) -+#define BCM2835_CLK_MASH(v) ((v) << 9) -+#define BCM2835_CLK_FLIP BIT(8) -+#define BCM2835_CLK_BUSY BIT(7) -+#define BCM2835_CLK_KILL BIT(5) -+#define BCM2835_CLK_ENAB BIT(4) -+#define BCM2835_CLK_SRC(v) (v) -+ -+#define BCM2835_CLK_SHIFT (12) -+#define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) -+#define BCM2835_CLK_DIVF(v) (v) -+#define BCM2835_CLK_DIVF_MASK (0xFFF) -+ -+enum { -+ BCM2835_CLK_MASH_0 = 0, -+ BCM2835_CLK_MASH_1, -+ BCM2835_CLK_MASH_2, -+ BCM2835_CLK_MASH_3, -+}; -+ -+enum { -+ BCM2835_CLK_SRC_GND = 0, -+ BCM2835_CLK_SRC_OSC, -+ BCM2835_CLK_SRC_DBG0, -+ BCM2835_CLK_SRC_DBG1, -+ BCM2835_CLK_SRC_PLLA, -+ BCM2835_CLK_SRC_PLLC, -+ BCM2835_CLK_SRC_PLLD, -+ BCM2835_CLK_SRC_HDMI, -+}; -+ -+/* Most clocks are not useable (freq = 0) */ -+static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { -+ [BCM2835_CLK_SRC_GND] = 0, -+ [BCM2835_CLK_SRC_OSC] = 19200000, -+ [BCM2835_CLK_SRC_DBG0] = 0, -+ [BCM2835_CLK_SRC_DBG1] = 0, -+ [BCM2835_CLK_SRC_PLLA] = 0, -+ [BCM2835_CLK_SRC_PLLC] = 0, -+ [BCM2835_CLK_SRC_PLLD] = 500000000, -+ [BCM2835_CLK_SRC_HDMI] = 0, -+}; -+ - /* I2S registers */ - #define BCM2835_I2S_CS_A_REG 0x00 - #define BCM2835_I2S_FIFO_A_REG 0x04 -@@ -110,6 +158,10 @@ - #define BCM2835_I2S_INT_RXR BIT(1) - #define BCM2835_I2S_INT_TXW BIT(0) - -+/* I2S DMA interface */ -+/* FIXME: Needs IOMMU support */ -+#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) -+ - /* General device struct */ - struct bcm2835_i2s_dev { - struct device *dev; -@@ -117,23 +169,21 @@ struct bcm2835_i2s_dev { - unsigned int fmt; - unsigned int bclk_ratio; - -- struct regmap *i2s_regmap; -- struct clk *clk; -- bool clk_prepared; -+ struct regmap *i2s_regmap; -+ struct regmap *clk_regmap; - }; - - static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) - { -+ /* Start the clock if in master mode */ - unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; - -- if (dev->clk_prepared) -- return; -- - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: -- clk_prepare_enable(dev->clk); -- dev->clk_prepared = true; -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); - break; - default: - break; -@@ -142,9 +192,28 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) - - static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) - { -- if (dev->clk_prepared) -- clk_disable_unprepare(dev->clk); -- dev->clk_prepared = false; -+ uint32_t clkreg; -+ int timeout = 1000; -+ -+ /* Stop clock */ -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD); -+ -+ /* Wait for the BUSY flag going down */ -+ while (--timeout) { -+ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); -+ if (!(clkreg & BCM2835_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, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, -+ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); -+ } - } - - static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, -@@ -154,7 +223,8 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - uint32_t syncval; - uint32_t csreg; - uint32_t i2s_active_state; -- bool clk_was_prepared; -+ uint32_t clkreg; -+ uint32_t clk_active_state; - uint32_t off; - uint32_t clr; - -@@ -168,10 +238,15 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); - i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); - -+ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); -+ clk_active_state = clkreg & BCM2835_CLK_ENAB; -+ - /* Start clock if not running */ -- clk_was_prepared = dev->clk_prepared; -- if (!clk_was_prepared) -- bcm2835_i2s_start_clock(dev); -+ if (!clk_active_state) { -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); -+ } - - /* Stop I2S module */ - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); -@@ -205,7 +280,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - dev_err(dev->dev, "I2S SYNC error!\n"); - - /* Stop clock if it was not running before */ -- if (!clk_was_prepared) -+ if (!clk_active_state) - bcm2835_i2s_stop_clock(dev); - - /* Restore I2S state */ -@@ -234,9 +309,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { - struct bcm2835_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 = BCM2835_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; - - /* -@@ -258,9 +343,11 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - 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; -@@ -269,12 +356,69 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - /* If bclk_ratio already set, use that one. */ - if (dev->bclk_ratio) - bclk_ratio = dev->bclk_ratio; -- else -- /* otherwise calculate a fitting block ratio */ -- bclk_ratio = 2 * data_length; - -- /* set target clock rate*/ -- clk_set_rate(dev->clk, sampling_rate * 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 = BCM2835_CLK_SRC_OSC; -+ mash = BCM2835_CLK_MASH_0; -+ -+ if (bcm2835_clk_freq[clk_src] % target_frequency == 0 -+ && bit_master && frame_master) { -+ divi = bcm2835_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 = BCM2835_CLK_SRC_PLLD; -+ mash = BCM2835_CLK_MASH_1; -+ -+ dividend = bcm2835_clk_freq[clk_src]; -+ dividend <<= BCM2835_CLK_SHIFT; -+ do_div(dividend, target_frequency); -+ divi = dividend >> BCM2835_CLK_SHIFT; -+ divf = dividend & BCM2835_CLK_DIVF_MASK; -+ } -+ -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD -+ | BCM2835_CLK_DIVI(divi) -+ | BCM2835_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD -+ | BCM2835_CLK_MASH(mash) -+ | BCM2835_CLK_SRC(clk_src)); - - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; -@@ -548,7 +692,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { - .trigger = bcm2835_i2s_trigger, - .hw_params = bcm2835_i2s_hw_params, - .set_fmt = bcm2835_i2s_set_dai_fmt, -- .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, -+ .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio - }; - - static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) -@@ -606,14 +750,34 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) - }; - } - --static const struct regmap_config bcm2835_regmap_config = { -- .reg_bits = 32, -- .reg_stride = 4, -- .val_bits = 32, -- .max_register = BCM2835_I2S_GRAY_REG, -- .precious_reg = bcm2835_i2s_precious_reg, -- .volatile_reg = bcm2835_i2s_volatile_reg, -- .cache_type = REGCACHE_RBTREE, -+static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2835_CLK_PCMCTL_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config bcm2835_regmap_config[] = { -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2835_I2S_GRAY_REG, -+ .precious_reg = bcm2835_i2s_precious_reg, -+ .volatile_reg = bcm2835_i2s_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2835_CLK_PCMDIV_REG, -+ .volatile_reg = bcm2835_clk_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, - }; - - static const struct snd_soc_component_driver bcm2835_i2s_component = { -@@ -623,50 +787,42 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - static int bcm2835_i2s_probe(struct platform_device *pdev) - { - struct bcm2835_i2s_dev *dev; -+ int i; - int ret; -- struct resource *mem; -- void __iomem *base; -- const __be32 *addr; -- dma_addr_t dma_base; -+ 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, -+ &bcm2835_regmap_config[i]); -+ if (IS_ERR(regmap[i])) -+ return PTR_ERR(regmap[i]); -+ } - - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - -- /* get the clock */ -- dev->clk_prepared = false; -- dev->clk = devm_clk_get(&pdev->dev, NULL); -- if (IS_ERR(dev->clk)) { -- dev_err(&pdev->dev, "could not get clk: %ld\n", -- PTR_ERR(dev->clk)); -- return PTR_ERR(dev->clk); -- } -- -- /* Request ioarea */ -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(&pdev->dev, mem); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base, -- &bcm2835_regmap_config); -- if (IS_ERR(dev->i2s_regmap)) -- return PTR_ERR(dev->i2s_regmap); -- -- /* Set the DMA address - we have to parse DT ourselves */ -- addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); -- if (!addr) { -- dev_err(&pdev->dev, "could not get DMA-register address\n"); -- return -EINVAL; -- } -- dma_base = be32_to_cpup(addr); -+ dev->i2s_regmap = regmap[0]; -+ dev->clk_regmap = regmap[1]; - -+ /* Set the DMA address */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -- dma_base + BCM2835_I2S_FIFO_A_REG; -+ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -+ + BCM2835_VCMMU_SHIFT; - - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -- dma_base + BCM2835_I2S_FIFO_A_REG; -+ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -+ + BCM2835_VCMMU_SHIFT; - - /* Set the bus width */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = - -From 4ced68a9916e83d80a0a17cae13fe1ab890b8c4b Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 16:44:05 +0200 -Subject: [PATCH 098/141] bcm2835-i2s: get base address for DMA from devicetree - -Code copied from spi-bcm2835. Get physical address from devicetree -instead of using hardcoded constant. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++-------- - 1 file changed, 12 insertions(+), 8 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 3303d5f58082f68b68b535b2bdf7ce8d14cafcc4..0f25db4cd198c0a511e8a205b0cb2be62ba94adf 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { - #define BCM2835_I2S_INT_RXR BIT(1) - #define BCM2835_I2S_INT_TXW BIT(0) - --/* I2S DMA interface */ --/* FIXME: Needs IOMMU support */ --#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) -- - /* General device struct */ - struct bcm2835_i2s_dev { - struct device *dev; -@@ -791,6 +788,15 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - int ret; - struct regmap *regmap[2]; - struct resource *mem[2]; -+ const __be32 *addr; -+ dma_addr_t dma_reg_base; -+ -+ addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); -+ if (!addr) { -+ dev_err(&pdev->dev, "could not get DMA-register address\n"); -+ return -ENODEV; -+ } -+ dma_reg_base = be32_to_cpup(addr); - - /* Request both ioareas */ - for (i = 0; i <= 1; i++) { -@@ -817,12 +823,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - - /* Set the DMA address */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -- + BCM2835_VCMMU_SHIFT; -+ dma_reg_base + BCM2835_I2S_FIFO_A_REG; - - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -- + BCM2835_VCMMU_SHIFT; -+ dma_reg_base + BCM2835_I2S_FIFO_A_REG; - - /* Set the bus width */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = - -From 56e0cbbd52af08a2064dd94403957bd3a6775f2a Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:21:16 +0200 -Subject: [PATCH 099/141] bcm2835-i2s: add 24bit support, update bclk_ratio to - more correct values - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit 62c05a0b5328d9376d39c9e74da10b8a2465c234 ("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 - -RPi commit 3e8c672bc4e92d457aa4654bbb4cfd79a18a2327 ("bcm2708-i2s: -Update bclk_ratio to more correct values") - -Discussion about blck_ratio affecting sound quality: -https://github.com/raspberrypi/linux/issues/681 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 0f25db4cd198c0a511e8a205b0cb2be62ba94adf..0f35d7c0f4026bb50a7223461b907b9797bd9a05 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -340,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - data_length = 16; -- bclk_ratio = 40; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ data_length = 24; -+ bclk_ratio = 50; - break; - case SNDRV_PCM_FORMAT_S32_LE: - data_length = 32; -- bclk_ratio = 80; -+ bclk_ratio = 100; - break; - default: - return -EINVAL; -@@ -420,7 +424,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; - -- if (data_length > 24) -+ if (data_length >= 24) - format |= BCM2835_I2S_CHWEX; - - format |= BCM2835_I2S_CHWID((data_length-8)&0xf); -@@ -711,6 +715,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { -@@ -718,6 +723,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, - -From 23d9e41cac43d6ce057b9b15ae3db92b1cd67200 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:25:51 +0200 -Subject: [PATCH 100/141] bcm2835-i2s: setup clock only if CPU is clock master - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit c14827ecdaa36607f6110f9ce8df96e698672191 ("bcm2708: Allow -option card devices to be configured via DT") - -Original work by Zoltan Szenczi, committed to RPi tree by -Phil Elwell. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 28 +++++++++++++++++++--------- - 1 file changed, 19 insertions(+), 9 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 0f35d7c0f4026bb50a7223461b907b9797bd9a05..d5e412302811ed8b007fc53f0aa2b5ddd12774b6 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -411,15 +411,25 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - divf = dividend & BCM2835_CLK_DIVF_MASK; - } - -- /* Set clock divider */ -- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD -- | BCM2835_CLK_DIVI(divi) -- | BCM2835_CLK_DIVF(divf)); -- -- /* Setup clock, but don't start it yet */ -- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD -- | BCM2835_CLK_MASH(mash) -- | BCM2835_CLK_SRC(clk_src)); -+ /* Clock should only be set up here if CPU is clock master */ -+ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ case SND_SOC_DAIFMT_CBS_CFM: -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, -+ BCM2835_CLK_PASSWD -+ | BCM2835_CLK_DIVI(divi) -+ | BCM2835_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD -+ | BCM2835_CLK_MASH(mash) -+ | BCM2835_CLK_SRC(clk_src)); -+ break; -+ default: -+ break; -+ } - - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; - -From c3e9993c137b57996503171e72763ef7df1ce43b Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:49:51 +0200 -Subject: [PATCH 101/141] bcm2835-i2s: Eliminate debugfs directory error - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit fd7d7a3dbe9262d16971ef81c234ed28c6499dd7 ("bcm2708: -Eliminate i2s debugfs directory error") - -Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') -to avoid the name clash when registering debugfs entries. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index d5e412302811ed8b007fc53f0aa2b5ddd12774b6..2d29050e739b0af02d0f5122d18178b61c024bea 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -782,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { - .precious_reg = bcm2835_i2s_precious_reg, - .volatile_reg = bcm2835_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, -+ .name = "i2s", - }, - { - .reg_bits = 32, -@@ -790,6 +791,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { - .max_register = BCM2835_CLK_PCMDIV_REG, - .volatile_reg = bcm2835_clk_volatile_reg, - .cache_type = REGCACHE_RBTREE, -+ .name = "clk", - }, - }; - - -From f88b870ca6cb55cc9be59b4d3c3d3ba35b0305e1 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:35:20 +0200 -Subject: [PATCH 102/141] bcm2835-i2s: Register PCM device - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit ba46b4935a23aa2caac1855ead52a035d4776680 ("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 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 23 ++++++++++++++++++++++- - 1 file changed, 22 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 2d29050e739b0af02d0f5122d18178b61c024bea..ce93ef0579ab142c788736f0d309c92636b8983d 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -799,6 +799,25 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - .name = "bcm2835-i2s-comp", - }; - -+static const struct snd_pcm_hardware bcm2835_pcm_hardware = { -+ .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, -+ .periods_min = 2, -+ .periods_max = 255, -+ .buffer_bytes_max = 128 * PAGE_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &bcm2835_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ - static int bcm2835_i2s_probe(struct platform_device *pdev) - { - struct bcm2835_i2s_dev *dev; -@@ -870,7 +889,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - return ret; - } - -- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, -+ &bcm2835_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); - if (ret) { - dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); - return ret; - -From 0e8d7503a489cb6bd5980bb2bbf10b7560bad8c9 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:55:21 +0200 -Subject: [PATCH 103/141] bcm2835-i2s: Enable MMAP support via a DT property - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit 7ee829fd77a30127db5d0b3c7d79b8718166e568 ("bcm2708-i2s: -Enable MMAP support via a DT property and overlay") - -The i2s driver used to claim to support MMAP, but that feature was disabled -when some problems were found. Add the ability to enable this feature -through Device Tree, using the i2s-mmap overlay. - -See: #1004 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index ce93ef0579ab142c788736f0d309c92636b8983d..6f60c2cebb412524bb0e30d0339fe556680e8637 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -799,7 +799,7 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - .name = "bcm2835-i2s-comp", - }; - --static const struct snd_pcm_hardware bcm2835_pcm_hardware = { -+static struct snd_pcm_hardware bcm2835_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX, - .formats = SNDRV_PCM_FMTBIT_S16_LE | -@@ -835,6 +835,11 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - } - dma_reg_base = be32_to_cpup(addr); - -+ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) -+ bcm2835_pcm_hardware.info |= -+ SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID; -+ - /* Request both ioareas */ - for (i = 0; i <= 1; i++) { - void __iomem *base; - -From 5862cb36220cb6b57b8553ed54d2764ff89a083a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 Apr 2016 15:44:14 +0100 -Subject: [PATCH 104/141] bcm2835-i2s: Reduce the TX DREQ threshold - -TX FIFO overrun is thought to be the cause of channel swapping, so -reducing the DREQ threshold seems reasonable and appears to be -effective. - -See: https://github.com/raspberrypi/linux/issues/1417 - -Signed-off-by: Phil Elwell ---- - sound/soc/bcm/bcm2835-i2s.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 6f60c2cebb412524bb0e30d0339fe556680e8637..b26f9587dec01d62606df3f47b3ef00c908fa05b 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -555,15 +555,22 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - - /* Setup the DMA parameters */ - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, -- BCM2835_I2S_RXTHR(1) -- | BCM2835_I2S_TXTHR(1) -- | BCM2835_I2S_DMAEN, 0xffffffff); -+ BCM2835_I2S_RXTHR(3) -+ | BCM2835_I2S_TXTHR(3) -+ | BCM2835_I2S_DMAEN, -+ BCM2835_I2S_RXTHR(1) -+ | BCM2835_I2S_TXTHR(1) -+ | BCM2835_I2S_DMAEN); - - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, -- BCM2835_I2S_TX_PANIC(0x10) -- | BCM2835_I2S_RX_PANIC(0x30) -- | BCM2835_I2S_TX(0x30) -- | BCM2835_I2S_RX(0x20), 0xffffffff); -+ BCM2835_I2S_TX_PANIC(0x7f) -+ | BCM2835_I2S_RX_PANIC(0x7f) -+ | BCM2835_I2S_TX(0x7f) -+ | BCM2835_I2S_RX(0x7f), -+ BCM2835_I2S_TX_PANIC(0x10) -+ | BCM2835_I2S_RX_PANIC(0x30) -+ | BCM2835_I2S_TX(0x20) -+ | BCM2835_I2S_RX(0x20)); - - /* Clear FIFOs */ - bcm2835_i2s_clear_fifos(dev, true, true); - -From afc742b15306af6aca77683b0737a013a9d48488 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Oct 2015 11:32:14 -0700 -Subject: [PATCH 105/141] drm/vc4: Force HDMI to connected. - -For some reason on the downstream tree, the HPD GPIO isn't working. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d8b864925fd38757cdc12e72d5ea102f32d2af09..136847ea795c58b8f0b2363a36242de512a01f83 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -166,6 +166,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - struct drm_device *dev = connector->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - -+ return connector_status_connected; -+ - if (vc4->hdmi->hpd_gpio) { - if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ - vc4->hdmi->hpd_active_low) - -From 0c089d1889103454a70b10a1adfc6a1095d273e5 Mon Sep 17 00:00:00 2001 +From 46c3097c1776e1fe84731643d691527a1cc856fa Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 106/141] Add Support for JustBoom Audio boards +Subject: [PATCH 076/111] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -132675,46 +130576,14 @@ rather than a struct snd_soc_codec *. Signed-off-by: Phil Elwell --- - arch/arm/configs/bcm2709_defconfig | 4 +- - arch/arm/configs/bcmrpi_defconfig | 4 +- - sound/soc/bcm/Kconfig | 14 +++ - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/justboom-dac.c | 162 ++++++++++++++++++++++++++++ - sound/soc/bcm/justboom-digi.c | 215 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 399 insertions(+), 4 deletions(-) + sound/soc/bcm/Kconfig | 14 +++ + sound/soc/bcm/Makefile | 4 + + sound/soc/bcm/justboom-dac.c | 162 +++++++++++++++++++++++++++++++ + sound/soc/bcm/justboom-digi.c | 215 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 395 insertions(+) create mode 100644 sound/soc/bcm/justboom-dac.c create mode 100644 sound/soc/bcm/justboom-digi.c -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index f42c5ebcbff904746a282a3d6fb13483e32c7fd8..055ecfcfea6df119dda49a1ffdb1e5a34ccef0c0 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -856,8 +856,8 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m - CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 8bd02073ab8f35ef28db5fcd628e3e44a922c0ea..8e0b51f853c055beb9fc6e8bf18f3ee2e54d6010 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -848,8 +848,8 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m - CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig index 1a3f8264403d64690fef60d41df38d21d3eb6030..e2e2782a2f8af27c1782993bd63747b620f26e1e 100644 --- a/sound/soc/bcm/Kconfig @@ -133152,33 +131021,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 699848abef604bd891a88c4c85825f699b9e9eea Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 19 Apr 2016 15:55:02 -0700 -Subject: [PATCH 107/141] ARM: bcm2708: Enable building power domain driver. - -Signed-off-by: Eric Anholt ---- - drivers/soc/bcm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index 3066edea184d765a670ded0cead470597654abc1..e23518142ceac6651641cc30c327d60dded319d5 100644 ---- a/drivers/soc/bcm/Kconfig -+++ b/drivers/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config RASPBERRYPI_POWER - bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on RASPBERRYPI_FIRMWARE=y - select PM_GENERIC_DOMAINS if PM - select PM_GENERIC_DOMAINS_OF if PM - -From ce8f9a782faff6c9d9af11ca0ecd8ea9927c87eb Mon Sep 17 00:00:00 2001 +From a774bf62b65352d425d75c064ade27e67e4d51b0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 108/141] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 077/111] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -133360,21 +131206,25 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From 2612db33ceeb9fe17f9581ddcf4e90dc534bd3d5 Mon Sep 17 00:00:00 2001 +From 50e698a0f5934beb1044d987d0fde684fc57583b Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 109/141] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 078/111] New AudioInjector.net Pi soundcard with low jitter audio in and out. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. Adds the dts overlay and updates the Makefile and README. Updates the relevant defconfig files to enable building for the Raspberry Pi. Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions. + +Added support for headphones, microphone and bclk_ratio settings. + +This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 3 + - sound/soc/bcm/audioinjector-pi-soundcard.c | 142 +++++++++++++++++++++++++++++ - 3 files changed, 152 insertions(+) + sound/soc/bcm/audioinjector-pi-soundcard.c | 191 +++++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+) create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig @@ -133412,10 +131262,10 @@ index d3124f579475524a739ced533f6dff69394eee1c..3353192be30394bd595423dccec17838 + diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c new file mode 100644 -index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc160a485281 +index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7c68d9e99 --- /dev/null +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -0,0 +1,142 @@ +@@ -0,0 +1,191 @@ +/* + * ASoC Driver for AudioInjector Pi add on soundcard + * @@ -133447,16 +131297,56 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 + +#include "../codecs/wm8731.h" + ++static const unsigned int bcm2835_rates_12000000[] = { ++ 32000, 44100, 48000, 96000, 88200, ++}; ++ ++static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { ++ .list = bcm2835_rates_12000000, ++ .count = ARRAY_SIZE(bcm2835_rates_12000000), ++}; ++ ++static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) ++{ ++ /* Setup constraints, because there is a 12 MHz XTAL on the board */ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &bcm2835_constraints_12000000); ++ return 0; ++} ++ ++static int snd_audioinjector_pi_soundcard_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; ++ ++ switch (params_rate(params)){ ++ case 8000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); ++ case 32000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); ++ case 44100: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); ++ case 48000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); ++ case 88200: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); ++ case 96000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ default: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ } ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = { ++ .startup = snd_audioinjector_pi_soundcard_startup, ++ .hw_params = snd_audioinjector_pi_soundcard_hw_params, ++}; ++ +static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) +{ -+ struct snd_soc_dapm_context *dapm = &rtd->card->dapm; -+ -+ // not connected -+ snd_soc_dapm_nc_pin(dapm, "Mic Bias"); -+ snd_soc_dapm_nc_pin(dapm, "MICIN"); -+ snd_soc_dapm_nc_pin(dapm, "RHPOUT"); -+ snd_soc_dapm_nc_pin(dapm, "LHPOUT"); -+ + return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); +} + @@ -133468,30 +131358,39 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 + .codec_dai_name = "wm8731-hifi", + .platform_name = "bcm2835-i2s.0", + .codec_name = "wm8731.1-001a", ++ .ops = &snd_audioinjector_pi_soundcard_ops, + .init = audioinjector_pi_soundcard_dai_init, + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, + }, +}; + +static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_LINE("Line In Jacks", NULL), ++ SND_SOC_DAPM_MIC("Microphone", NULL), +}; + -+/* Corgi machine connections to the codec pins */ +static const struct snd_soc_dapm_route audioinjector_audio_map[] = { ++ /* headphone connected to LHPOUT, RHPOUT */ ++ {"Headphone Jack", NULL, "LHPOUT"}, ++ {"Headphone Jack", NULL, "RHPOUT"}, ++ + /* speaker connected to LOUT, ROUT */ + {"Ext Spk", NULL, "ROUT"}, + {"Ext Spk", NULL, "LOUT"}, + + /* line inputs */ + {"Line In Jacks", NULL, "Line Input"}, ++ ++ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ ++ {"Microphone", NULL, "Mic Bias"}, +}; + +static struct snd_soc_card snd_soc_audioinjector = { + .name = "audioinjector-pi-soundcard", + .dai_link = audioinjector_pi_soundcard_dai, -+ .num_links = 1, ++ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), + + .dapm_widgets = wm8731_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), @@ -133559,225 +131458,327 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From c7b2ab47d4bfb5efecae620fc045435228f877bf Mon Sep 17 00:00:00 2001 -From: Dave Stevenson <6by9@users.noreply.github.com> -Date: Wed, 25 May 2016 23:25:36 +0100 -Subject: [PATCH 110/141] BCM2835-V4L2: Correct handling for BGR24 vs RGB24. +From 1f2eac04eced09d8ac3697b73155cc3db05c1a26 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Thu, 30 Jun 2016 18:38:42 +0100 +Subject: [PATCH 079/111] Add IQAudIO Digi WM8804 board support -There was a bug in the GPU firmware that had reversed these -two formats. -Detect the old firmware, and reverse the formats if necessary. +Support IQAudIO Digi board with iqaudio_digi machine driver and + iqaudio-digi-wm8804-audio overlay. -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> +NB. Machine driver is a cut and paste of hifiberry_digi code, with format + and general cleanup to comply with kernel coding standards. + +Signed-off-by: DigitalDreamtime --- - drivers/media/platform/bcm2835/bcm2835-camera.c | 69 ++++++++++++++++++------- - drivers/media/platform/bcm2835/bcm2835-camera.h | 1 + - 2 files changed, 52 insertions(+), 18 deletions(-) + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio_digi.c | 239 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 248 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio_digi.c -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index 1b16c63315195c043c41d6676ecfedd004c92cd3..70f4db2741037381e638d1dda5a95478809eb161 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -115,7 +115,7 @@ static struct mmal_fmt formats[] = { - .name = "RGB24 (LE)", - .fourcc = V4L2_PIX_FMT_RGB24, - .flags = 0, -- .mmal = MMAL_ENCODING_BGR24, -+ .mmal = MMAL_ENCODING_RGB24, - .depth = 24, - .mmal_component = MMAL_COMPONENT_CAMERA, - .ybbp = 3, -@@ -187,7 +187,7 @@ static struct mmal_fmt formats[] = { - .name = "RGB24 (BE)", - .fourcc = V4L2_PIX_FMT_BGR24, - .flags = 0, -- .mmal = MMAL_ENCODING_RGB24, -+ .mmal = MMAL_ENCODING_BGR24, - .depth = 24, - .mmal_component = MMAL_COMPONENT_CAMERA, - .ybbp = 3, -@@ -1061,6 +1061,13 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev, - else - camera_port->format.encoding = mfmt->mmal; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index e2e40eda90f447a4700767071715e263bfa9a6e7..616f47e72a2300df0ed79f082c67ba0af13067ee 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -71,6 +71,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC + help + Say Y or M if you want to add support for IQaudIO-DAC. -+ if (dev->rgb_bgr_swapped) { -+ if (camera_port->format.encoding == MMAL_ENCODING_RGB24) -+ camera_port->format.encoding = MMAL_ENCODING_BGR24; -+ else if (camera_port->format.encoding == MMAL_ENCODING_BGR24) -+ camera_port->format.encoding = MMAL_ENCODING_RGB24; ++config SND_BCM2708_SOC_IQAUDIO_DIGI ++ tristate "Support for IQAudIO Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for IQAudIO Digital IO board. ++ + config SND_BCM2708_SOC_RASPIDAC3 + tristate "Support for RaspiDAC Rev.3x" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 3353192be30394bd595423dccec17838e3054a1d..fb3e44d2668bda0494751d4e6c925f34a5ce2bc3 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -14,6 +14,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o ++snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + +@@ -27,6 +28,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + +diff --git a/sound/soc/bcm/iqaudio_digi.c b/sound/soc/bcm/iqaudio_digi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e7816319639e39d65 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio_digi.c +@@ -0,0 +1,239 @@ ++/* ++ * ASoC Driver for IQAudIO WM8804 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 short int auto_shutdown_output; ++module_param(auto_shutdown_output, short, ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++static int snd_rpi_iqaudio_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_iqaudio_digi_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn on digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ ++ return 0; ++} ++ ++static void snd_rpi_iqaudio_digi_shutdown(struct snd_pcm_substream *substream) ++{ ++ if (auto_shutdown_output) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn off digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++static int snd_rpi_iqaudio_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 sampling_freq = 1; ++ ++ int ret; ++ ++ int samplerate = params_rate(params); ++ ++ if (samplerate <= 96000) { ++ mclk_freq = samplerate * 256; ++ mclk_div = WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq = samplerate * 128; ++ mclk_div = WM8804_MCLKDIV_128FS; + } + - camera_port->format.encoding_variant = 0; - camera_port->es.video.width = f->fmt.pix.width; - camera_port->es.video.height = f->fmt.pix.height; -@@ -1571,12 +1578,17 @@ static int set_camera_parameters(struct vchiq_mmal_instance *instance, - return ret; - } - -+#define MAX_SUPPORTED_ENCODINGS 20 ++ switch (samplerate) { ++ case 32000: ++ sampling_freq = 0x03; ++ break; ++ case 44100: ++ sampling_freq = 0x00; ++ break; ++ case 48000: ++ sampling_freq = 0x02; ++ break; ++ case 88200: ++ sampling_freq = 0x08; ++ break; ++ case 96000: ++ sampling_freq = 0x0a; ++ break; ++ case 176400: ++ sampling_freq = 0x0c; ++ break; ++ case 192000: ++ sampling_freq = 0x0e; ++ break; ++ default: ++ dev_err(codec->dev, "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } + - /* MMAL instance and component init */ - static int __init mmal_init(struct bm2835_mmal_dev *dev) - { - int ret; - struct mmal_es_format *format; - u32 bool_true = 1; -+ u32 supported_encodings[MAX_SUPPORTED_ENCODINGS]; -+ int param_size; -+ struct vchiq_mmal_component *camera; - - ret = vchiq_mmal_init(&dev->instance); - if (ret < 0) -@@ -1588,21 +1600,48 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - if (ret < 0) - goto unreg_mmal; - -- if (dev->component[MMAL_COMPONENT_CAMERA]->outputs < -- MMAL_CAMERA_PORT_COUNT) { -+ camera = dev->component[MMAL_COMPONENT_CAMERA]; -+ if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { - ret = -EINVAL; - goto unreg_camera; - } - - ret = set_camera_parameters(dev->instance, -- dev->component[MMAL_COMPONENT_CAMERA], -+ camera, - dev); - if (ret < 0) - goto unreg_camera; - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_PREVIEW].format; -+ /* There was an error in the firmware that meant the camera component -+ * produced BGR instead of RGB. -+ * This is now fixed, but in order to support the old firmwares, we -+ * have to check. -+ */ -+ dev->rgb_bgr_swapped = true; -+ param_size = sizeof(supported_encodings); -+ ret = vchiq_mmal_port_parameter_get(dev->instance, -+ &camera->output[MMAL_CAMERA_PORT_CAPTURE], -+ MMAL_PARAMETER_SUPPORTED_ENCODINGS, -+ &supported_encodings, -+ ¶m_size); -+ if (ret == 0) { -+ int i; ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); + -+ for (i = 0; i < param_size/sizeof(u32); i++) { -+ if (supported_encodings[i] == MMAL_ENCODING_BGR24) { -+ /* Found BGR24 first - old firmware. */ -+ break; -+ } -+ if (supported_encodings[i] == MMAL_ENCODING_RGB24) { -+ /* Found RGB24 first -+ * new firmware, so use RGB24. -+ */ -+ dev->rgb_bgr_swapped = false; -+ break; -+ } ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->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); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_digi_ops = { ++ .hw_params = snd_rpi_iqaudio_digi_hw_params, ++ .startup = snd_rpi_iqaudio_digi_startup, ++ .shutdown = snd_rpi_iqaudio_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_digi_dai[] = { ++{ ++ .name = "IQAudIO Digi", ++ .stream_name = "IQAudIO 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_iqaudio_digi_ops, ++ .init = snd_rpi_iqaudio_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_digi = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_iqaudio_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_digi_dai), ++}; ++ ++static int snd_rpi_iqaudio_digi_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &snd_rpi_iqaudio_digi; ++ char *prefix = "wm8804-digi,"; ++ char prop[128]; ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_iqaudio_digi.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_digi_dai[0]; ++ struct device_node *i2s_node; ++ ++ i2s_node = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; + } ++ ++ snprintf(prop, sizeof(prop), "%scard-name", prefix); ++ of_property_read_string(np, prop, &card->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-name", prefix); ++ of_property_read_string(np, prop, &dai->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-stream-name", prefix); ++ of_property_read_string(np, prop, &dai->stream_name); + } -+ format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; -@@ -1616,9 +1655,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - format->es->video.frame_rate.num = 0; /* Rely on fps_range */ - format->es->video.frame_rate.den = 1; - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_VIDEO].format; -+ format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; -@@ -1633,14 +1670,11 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - format->es->video.frame_rate.den = 1; - - vchiq_mmal_port_parameter_set(dev->instance, -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_VIDEO], -+ &camera->output[MMAL_CAMERA_PORT_VIDEO], - MMAL_PARAMETER_NO_IMAGE_PADDING, - &bool_true, sizeof(bool_true)); - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_CAPTURE].format; -+ format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - -@@ -1662,8 +1696,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; - - vchiq_mmal_port_parameter_set(dev->instance, -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_CAPTURE], -+ &camera->output[MMAL_CAMERA_PORT_CAPTURE], - MMAL_PARAMETER_NO_IMAGE_PADDING, - &bool_true, sizeof(bool_true)); - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h -index 13f426f5ecdffeab714d658a6f8b76e63af5fcdb..e6aeb7e7e381de65d6c6586205069a4c5cd33274 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.h -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -109,6 +109,7 @@ struct bm2835_mmal_dev { - unsigned int camera_num; - unsigned int max_width; - unsigned int max_height; -+ unsigned int rgb_bgr_swapped; - }; - - int bm2835_mmal_init_controls( ++ ++ ret = snd_soc_register_card(card); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_digi); ++} ++ ++static const struct of_device_id snd_rpi_iqaudio_digi_of_match[] = { ++ { .compatible = "iqaudio,wm8804-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_iqaudio_digi_of_match); ++ ++static struct platform_driver snd_rpi_iqaudio_digi_driver = { ++ .driver = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_iqaudio_digi_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_digi_probe, ++ .remove = snd_rpi_iqaudio_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); ++MODULE_LICENSE("GPL v2"); -From 4630382072020373bf103fca3e5fbb0d59111e52 Mon Sep 17 00:00:00 2001 +From 3163272227b6e87a808cbc2834b93bfa3ad03674 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 111/141] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 080/111] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + sound/soc/bcm/Kconfig | 8 + sound/soc/bcm/Makefile | 2 + sound/soc/bcm/digidac1-soundcard.c | 422 +++++++++++++++++++++++++++++++++++++ - 5 files changed, 434 insertions(+) + 3 files changed, 432 insertions(+) create mode 100644 sound/soc/bcm/digidac1-soundcard.c -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 055ecfcfea6df119dda49a1ffdb1e5a34ccef0c0..1643dab1f04fdca37c71eb66cfc3c2a81bff9094 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -862,6 +862,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 8e0b51f853c055beb9fc6e8bf18f3ee2e54d6010..d936b43acaf2f28331e75b42b9f2bb7ff3fdbdf8 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -854,6 +854,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index e2e40eda90f447a4700767071715e263bfa9a6e7..fa11cd792824f21424a3b798336b676d33181a43 100644 +index 616f47e72a2300df0ed79f082c67ba0af13067ee..a7e4e25ccf2de23f7a3793af66f795825e69fbb8 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -92,3 +92,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD +@@ -99,3 +99,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD select SND_SOC_WM8731 help Say Y or M if you want to add support for audioinjector.net Pi Hat @@ -133790,19 +131791,19 @@ index e2e40eda90f447a4700767071715e263bfa9a6e7..fa11cd792824f21424a3b798336b676d + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 3353192be30394bd595423dccec17838e3054a1d..a9448fdcd6bcc4e4cb96e985fbe758aea002ddd8 100644 +index fb3e44d2668bda0494751d4e6c925f34a5ce2bc3..781037a9e323834ba62ec55c6cf28a95c769c2cb 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -17,6 +17,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o + snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o +snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -29,4 +30,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +@@ -31,4 +32,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o +obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o @@ -134236,2791 +132237,2436 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From 86c24bce60588df5dc50e7a7e44913500f20e913 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 21:56:40 +0100 -Subject: [PATCH 112/141] BCM270X_DT: Fix rpi-dac overlay +From 9dc99dadefde0b3bb0140831fdda208c72f776c7 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Sat, 2 Jul 2016 16:26:19 +0100 +Subject: [PATCH 081/111] Add support for Dion Audio LOCO DAC-AMP HAT -The rpi-dac overlay is almost identical to the hifiberry-dac overlay - -the codec used is different but it also doesn't sit on the I2C bus. As -a result, when the overlays were modified for dynamic loading and it -was discovered that the hifiberry-dac overlay didn't work any more, the -the rpi-dac overlay was also broken. +Using dedicated machine driver and pcm5102a codec driver. -The failure was caused by the fact that outside a bus, device names are -constructed from the concatenation of the path elements leading to it, -so moving the codec instantiation inside /soc caused the device name -to get a "soc" added, breaking ALSA's naming. - -See: http://forum.kodi.tv/showthread.php?tid=269814&pid=2349776#pid2349776 - -Signed-off-by: Phil Elwell +Signed-off-by: DigitalDreamtime --- - arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 3 +- + sound/soc/bcm/dionaudio_loco.c | 121 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 130 insertions(+), 1 deletion(-) + create mode 100644 sound/soc/bcm/dionaudio_loco.c -diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -index 1523eae9c39997aa68cfa583ada92a92395bb1e0..a442c8f0ec01b7503f32e070683a984e895f5668 100644 ---- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -@@ -13,7 +13,7 @@ - }; - - fragment@1 { -- target = <&soc>; -+ target-path = "/"; - __overlay__ { - pcm1794a-codec { - #sound-dai-cells = <0>; - -From 0a0d01b64325a8ca5a165e1b35c2dac59540aecc Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 22:21:47 +0100 -Subject: [PATCH 113/141] BCM270X_DT: Add mcp23017 to the overlay Makefile - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 0adb5b92c047cb7e12871cf75515f822924924cd..c514bbfe7384f58d5db4e861d842bd772cc4e51a 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -44,6 +44,7 @@ dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo - dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo - -From 71097672c9df575ce85171b6e94f6e403cda43fb Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 23:01:01 +0100 -Subject: [PATCH 114/141] BCM270X_DT: Sort entries to placate check script - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c514bbfe7384f58d5db4e861d842bd772cc4e51a..ed62846e18e4d3098169f05a1a8ba16caf1619aa 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -18,10 +18,10 @@ dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo - dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo - dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo - dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo - dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo - dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo - dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo -@@ -31,10 +31,10 @@ dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo -@@ -73,16 +73,16 @@ dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo - dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo - dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo - dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo - -From 789888ba7c35e13bde91ca45d714002118f574d4 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sat, 4 Jun 2016 11:30:48 +0200 -Subject: [PATCH 115/141] gpio-ir overlay: gpio_pin shouldn't change pull - setting - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -index a2d6bc79f4cd2604e6c65c000668cbb228327fe6..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 100644 ---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -@@ -36,8 +36,7 @@ - __overrides__ { - // parameters - gpio_pin = <&gpio_ir>,"gpios:4", -- <&gpio_ir_pins>,"brcm,pins:0", -- <&gpio_ir_pins>,"brcm,pull:0"; // pin number -+ <&gpio_ir_pins>,"brcm,pins:0"; // pin number - gpio_pull = <&gpio_ir_pins>,"brcm,pull:0"; // pull-up/down state - - rc-map-name = <&gpio_ir>,"linux,rc-map-name"; // default rc map - -From 5a5bfc2ef28f207f1b73666d392fe375241facbb Mon Sep 17 00:00:00 2001 -From: Nicolas Boullis -Date: Sat, 4 Jun 2016 00:57:06 +0200 -Subject: [PATCH 116/141] Implement a "wakeup-source" option for the i2c-rtc - DeviceTree overlay. - -See: https://github.com/raspberrypi/linux/pull/1511 ---- - arch/arm/boot/dts/overlays/README | 3 +++ - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 4 ++++ - 2 files changed, 7 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 1516cc2e1616bb5e0cb519e05eee6776fe84e52a..628cff3fc60a13b26b3f2f572573884df480c7bf 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -445,6 +445,9 @@ Params: ds1307 Select the DS1307 device - - trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) - -+ wakeup-source Specify that the RTC can be used as a wakeup -+ source +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a7e4e25ccf2de23f7a3793af66f795825e69fbb8..8873fd8adce1d17cb543251f5cdc6ac8f4bf523d 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -107,3 +107,10 @@ config SND_DIGIDAC1_SOUNDCARD + select SND_SOC_WM8741 + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. + ++config SND_BCM2708_SOC_DIONAUDIO_LOCO ++ tristate "Support for Dion Audio LOCO DAC-AMP" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5102a ++ help ++ Say Y or M if you want to add support for Dion Audio LOCO. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 781037a9e323834ba62ec55c6cf28a95c769c2cb..17f70f951322239696623c2347e5d846bbef2369 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -18,6 +18,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o ++snd-soc-dionaudio-loco-objs := dionaudio_loco.o - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -index 40656474dfc16505433221a745c1d129c2737399..8b6f978155c02409eeb7c83353b8194fa3462435 100644 ---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -65,5 +65,9 @@ - pcf8523 = <&pcf8523>,"status"; - pcf8563 = <&pcf8563>,"status"; - trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; -+ wakeup-source = <&ds1339>,"wakeup-source?", -+ <&ds3231>,"wakeup-source?", -+ <&mcp7940x>,"wakeup-source?", -+ <&mcp7941x>,"wakeup-source?"; - }; - }; - -From 4cd5ee7be97df04ab1877b1640ec905d7c474f0f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 6 Jun 2016 09:23:37 +0100 -Subject: [PATCH 117/141] BCM270X_DT: Make i2c-gpio usable by other overlays - -Modify the i2c-gpio overlay to export symbol i2c-gpio for use by other -overlays. Export the alias as well for good measure. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -index 2a2dc986770cfb036492ba8de19cbaff521c5fd5..b72b32e936774d901bc253b06e025c2dd48bdb1b 100644 ---- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -@@ -19,6 +19,21 @@ - }; - }; - }; -+ -+ fragment@1 { -+ target-path = "/aliases"; -+ __overlay__ { -+ i2c_gpio = "/i2c@0"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/__symbols__"; -+ __overlay__ { -+ i2c_gpio = "/i2c@0"; -+ }; -+ }; -+ - __overrides__ { - i2c_gpio_sda = <&i2c_gpio>,"gpios:4"; - i2c_gpio_scl = <&i2c_gpio>,"gpios:16"; - -From 500f0fe6429f3f12379db02d70a41aa98c319e4f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:13 +0000 -Subject: [PATCH 118/141] Revert "bcm2835-dma: Fix up convert to DMA pool" - -This reverts commit ec2e48fda22c57cab56a4332d1a095f91c919493. ---- - drivers/dma/bcm2835-dma.c | 36 ++++++++++-------------------------- - 1 file changed, 10 insertions(+), 26 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index d26b6bdbcf1ab33ab92937b889a37e505c925311..6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -488,17 +488,6 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - c->cyclic = true; - - return vchan_tx_prep(&c->vc, &d->vd, flags); --error_cb: -- i--; -- for (; i >= 0; i--) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -33,4 +34,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - -- dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -- } -- -- kfree(d->cb_list); -- kfree(d); -- return NULL; - } - - static struct dma_async_tx_descriptor * -@@ -545,7 +534,6 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (!d) - return NULL; - -- d->c = c; - d->dir = direction; - - if (c->ch >= 8) /* LITE channel */ -@@ -565,21 +553,15 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - d->frames += len / max_size + 1; - } - -- d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -- if (!d->cb_list) { -+ /* Allocate memory for control blocks */ -+ d->control_block_size = d->frames * sizeof(struct bcm2835_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; - } -- /* Allocate memory for control blocks */ -- for (i = 0; i < d->frames; i++) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -- -- cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -- &cb_entry->paddr); -- -- if (!cb_entry->cb) -- goto error_cb; -- } - - /* - * Iterate over all SG entries, create a control block -@@ -596,7 +578,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - - for (j = 0; j < len; j += max_size) { - struct bcm2835_dma_cb *control_block = -- d->cb_list[i + split_cnt].cb; -+ &d->control_block_base[i + split_cnt]; - - /* Setup addresses */ - if (d->dir == DMA_DEV_TO_MEM) { -@@ -638,7 +620,9 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (i < sg_len - 1 || len - j > max_size) { - /* Next block is the next frame. */ - control_block->next = -- d->cb_list[i + split_cnt + 1].paddr; -+ d->control_block_base_phys + -+ sizeof(struct bcm2835_dma_cb) * -+ (i + split_cnt + 1); - } else { - /* Next block is empty. */ - control_block->next = 0; - -From 0e0bf40b1ed256811118c2f1a09364c397622506 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:22 +0000 -Subject: [PATCH 119/141] Revert "bcm2835-dma: Limit cyclic transfers on lite - channels to 32k" - -This reverts commit 052c2005b6ecedc5abad86632f5781adda310aa7. ---- - drivers/dma/bcm2835-dma.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9..5db0a95985b20a2086c65762ea8f125511f67471 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -144,12 +144,6 @@ struct bcm2835_desc { - */ - #define MAX_LITE_TRANSFER (SZ_64K - 4) - --/* -- * Transfers larger than 32k cause issues with the bcm2708-i2s driver, -- * so limit transfer size to 32k as bcm2708-dmaengine did. -- */ --#define MAX_CYCLIC_LITE_TRANSFER SZ_32K -- - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -418,7 +412,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_CYCLIC_LITE_TRANSFER; -+ max_size = MAX_LITE_TRANSFER; - else - max_size = MAX_NORMAL_TRANSFER; - period_len = min(period_len, max_size); - -From d78219d3a8c093856a13c745f74f0015dcca48c5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:30 +0000 -Subject: [PATCH 120/141] Revert "dmaengine: bcm2835: Load driver early and - support legacy API" - -This reverts commit 6f56fff39c811953809b011f59c49a2122c4d173. ---- - drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 30 ++++++------------------------ - 2 files changed, 7 insertions(+), 25 deletions(-) - -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index b7863f0cf95ca656859a355098aa334e20d121c3..1acfa84be0d1f74f5a830b04cab05ba7fa0841ab 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 5db0a95985b20a2086c65762ea8f125511f67471..696fb30b4f5a01cda9b98038b8e548368cea05f4 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -787,10 +786,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (IS_ERR(base)) - return PTR_ERR(base); - -- rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK); -- if (rc) -- dev_err(&pdev->dev, "Failed to initialize the legacy API\n"); -- - od->base = base; - - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -@@ -823,8 +818,11 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- /* Channel 0 is used by the legacy API */ -- chans_available &= ~BCM2835_DMA_BULK_MASK; -+ /* -+ * Do not use the FIQ and BULK channels, -+ * because they are used by the GPU. -+ */ -+ chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); - - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); -@@ -868,7 +866,6 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - { - struct bcm2835_dmadev *od = platform_get_drvdata(pdev); - -- bcm_dmaman_remove(pdev); - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); - -@@ -884,22 +881,7 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --static int bcm2835_dma_init(void) --{ -- return platform_driver_register(&bcm2835_dma_driver); --} -- --static void bcm2835_dma_exit(void) --{ -- platform_driver_unregister(&bcm2835_dma_driver); --} -- --/* -- * Load after serial driver (arch_initcall) so we see the messages if it fails, -- * but before drivers (module_init) that need a DMA channel. -- */ --subsys_initcall(bcm2835_dma_init); --module_exit(bcm2835_dma_exit); -+module_platform_driver(bcm2835_dma_driver); - - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - -From e7fbd84691eb79a03d7bd28d4713ad72213750a7 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:37 +0000 -Subject: [PATCH 121/141] Revert "dmaengine: bcm2835: Add slave dma support" - -This reverts commit 8a349301238aabb40c9da5ca8c8492b6b8d146f6. ---- - drivers/dma/bcm2835-dma.c | 206 ++++------------------------------------------ - 1 file changed, 14 insertions(+), 192 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 696fb30b4f5a01cda9b98038b8e548368cea05f4..2d72fe81243fbbcc92f52e1935ed48b6cbc23665 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -1,10 +1,11 @@ - /* - * BCM2835 DMA engine support - * -+ * This driver only supports cyclic DMA transfers -+ * as needed for the I2S module. -+ * - * Author: Florian Meier - * Copyright 2013 -- * Gellert Weisz -- * Copyright 2013-2014 - * - * Based on - * OMAP DMAengine support by Russell King -@@ -94,8 +95,6 @@ struct bcm2835_desc { - size_t size; - }; - --#define BCM2835_DMA_WAIT_CYCLES 0 /* Slow down DMA transfers: 0-31 */ -- - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 - #define BCM2835_DMA_SOURCE_AD 0x0c -@@ -112,16 +111,12 @@ struct bcm2835_desc { - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - - #define BCM2835_DMA_INT_EN BIT(0) --#define BCM2835_DMA_WAIT_RESP BIT(3) - #define BCM2835_DMA_D_INC BIT(4) --#define BCM2835_DMA_D_WIDTH BIT(5) - #define BCM2835_DMA_D_DREQ BIT(6) - #define BCM2835_DMA_S_INC BIT(8) --#define BCM2835_DMA_S_WIDTH BIT(9) - #define BCM2835_DMA_S_DREQ BIT(10) - - #define BCM2835_DMA_PER_MAP(x) ((x) << 16) --#define BCM2835_DMA_WAITS(x) (((x) & 0x1f) << 21) - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 -@@ -135,14 +130,6 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - --#define MAX_NORMAL_TRANSFER SZ_1G --/* -- * Max length on a Lite channel is 65535 bytes. -- * DMA handles byte-enables on SDRAM reads and writes even on 128-bit accesses, -- * but byte-enables don't exist on peripheral addresses, so align to 32-bit. -- */ --#define MAX_LITE_TRANSFER (SZ_64K - 4) -- - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -239,19 +226,13 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- if (c->cyclic) { -- vchan_cyclic_callback(&d->vd); -- -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, -- c->chan_base + BCM2835_DMA_CS); -- -- } else { -- vchan_cookie_complete(&c->desc->vd); -- bcm2835_dma_start_desc(c); -- } -+ /* TODO Only works for cyclic DMA */ -+ vchan_cyclic_callback(&d->vd); - } - -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -+ - spin_unlock_irqrestore(&c->vc.lock, flags); - - return IRQ_HANDLED; -@@ -358,6 +339,8 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -375,7 +358,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - struct bcm2835_desc *d; - dma_addr_t dev_addr; - unsigned int es, sync_type; -- unsigned int frame, max_size; -+ unsigned int frame; - int i; - - /* Grab configuration */ -@@ -410,12 +393,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - - d->c = c; - d->dir = direction; -- if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -- else -- max_size = MAX_NORMAL_TRANSFER; -- period_len = min(period_len, max_size); -- d->frames = (buf_len - 1) / (period_len + 1); -+ d->frames = buf_len / period_len; - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { -@@ -463,171 +441,17 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - BCM2835_DMA_PER_MAP(c->dreq); - - /* Length of a frame */ -- if (frame != d->frames - 1) -- control_block->length = period_len; -- else -- control_block->length = buf_len - (d->frames - 1) * -- period_len; -+ control_block->length = period_len; - d->size += control_block->length; - - /* - * Next block is the next frame. -- * This function is called on cyclic DMA transfers. -+ * This DMA engine driver currently only supports cyclic DMA. - * Therefore, wrap around at number of frames. - */ - control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr; - } - -- c->cyclic = true; -- -- return vchan_tx_prep(&c->vc, &d->vd, flags); --} -- --static struct dma_async_tx_descriptor * --bcm2835_dma_prep_slave_sg(struct dma_chan *chan, -- struct scatterlist *sgl, -- unsigned int sg_len, -- enum dma_transfer_direction direction, -- unsigned long flags, void *context) --{ -- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -- enum dma_slave_buswidth dev_width; -- struct bcm2835_desc *d; -- dma_addr_t dev_addr; -- struct scatterlist *sgent; -- unsigned int i, sync_type, split_cnt, max_size; -- -- if (!is_slave_direction(direction)) { -- dev_err(chan->device->dev, "direction not supported\n"); -- return NULL; -- } -- -- if (direction == DMA_DEV_TO_MEM) { -- dev_addr = c->cfg.src_addr; -- dev_width = c->cfg.src_addr_width; -- sync_type = BCM2835_DMA_S_DREQ; -- } else { -- dev_addr = c->cfg.dst_addr; -- dev_width = c->cfg.dst_addr_width; -- sync_type = BCM2835_DMA_D_DREQ; -- } -- -- /* Bus width translates to the element size (ES) */ -- switch (dev_width) { -- case DMA_SLAVE_BUSWIDTH_4_BYTES: -- break; -- default: -- dev_err(chan->device->dev, "buswidth not supported: %i\n", -- dev_width); -- return NULL; -- } -- -- /* Allocate and setup the descriptor. */ -- d = kzalloc(sizeof(*d), GFP_NOWAIT); -- if (!d) -- return NULL; -- -- d->dir = direction; -- -- if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -- else -- max_size = MAX_NORMAL_TRANSFER; -- -- /* -- * Store the length of the SG list in d->frames -- * taking care to account for splitting up transfers -- * too large for a LITE channel -- */ -- d->frames = 0; -- for_each_sg(sgl, sgent, sg_len, i) { -- unsigned int len = sg_dma_len(sgent); -- -- d->frames += len / max_size + 1; -- } -- -- /* Allocate memory for control blocks */ -- d->control_block_size = d->frames * sizeof(struct bcm2835_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 SG entries, create a control block -- * for each frame and link them together. -- * Count the number of times an SG entry had to be split -- * as a result of using a LITE channel -- */ -- split_cnt = 0; -- -- for_each_sg(sgl, sgent, sg_len, i) { -- unsigned int j; -- dma_addr_t addr = sg_dma_address(sgent); -- unsigned int len = sg_dma_len(sgent); -- -- for (j = 0; j < len; j += max_size) { -- struct bcm2835_dma_cb *control_block = -- &d->control_block_base[i + split_cnt]; -- -- /* Setup addresses */ -- if (d->dir == DMA_DEV_TO_MEM) { -- control_block->info = BCM2835_DMA_D_INC | -- BCM2835_DMA_D_WIDTH | -- BCM2835_DMA_S_DREQ; -- control_block->src = dev_addr; -- control_block->dst = addr + (dma_addr_t)j; -- } else { -- control_block->info = BCM2835_DMA_S_INC | -- BCM2835_DMA_S_WIDTH | -- BCM2835_DMA_D_DREQ; -- control_block->src = addr + (dma_addr_t)j; -- control_block->dst = dev_addr; -- } -- -- /* Common part */ -- control_block->info |= -- BCM2835_DMA_WAITS(BCM2835_DMA_WAIT_CYCLES); -- control_block->info |= BCM2835_DMA_WAIT_RESP; -- -- /* Enable */ -- if (i == sg_len - 1 && len - j <= max_size) -- control_block->info |= BCM2835_DMA_INT_EN; -- -- /* Setup synchronization */ -- if (sync_type) -- control_block->info |= sync_type; -- -- /* Setup DREQ channel */ -- if (c->dreq) -- control_block->info |= -- BCM2835_DMA_PER_MAP(c->dreq); -- -- /* Length of a frame */ -- control_block->length = min(len - j, max_size); -- d->size += control_block->length; -- -- if (i < sg_len - 1 || len - j > max_size) { -- /* Next block is the next frame. */ -- control_block->next = -- d->control_block_base_phys + -- sizeof(struct bcm2835_dma_cb) * -- (i + split_cnt + 1); -- } else { -- /* Next block is empty. */ -- control_block->next = 0; -- } -- -- if (len - j > max_size) -- split_cnt++; -- } -- } -- -- c->cyclic = false; -- - return vchan_tx_prep(&c->vc, &d->vd, flags); - error_cb: - i--; -@@ -796,7 +620,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -- od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -@@ -886,5 +709,4 @@ module_platform_driver(bcm2835_dma_driver); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); --MODULE_AUTHOR("Gellert Weisz "); - MODULE_LICENSE("GPL v2"); - -From 6f4cc15d3c4cb1787fa599075a8d55df3d3136c8 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:56 -0700 -Subject: [PATCH 122/141] dmaengine: bcm2835: remove unnecessary masking of dma - channels - -The original patch contained 3 dma channels that were masked out. - -These - as far as research and discussions show - are a -artefacts remaining from the downstream legacy dma-api. - -Right now down-stream still includes a legacy api used only -in a single (downstream only) driver (bcm2708_fb) that requires -2D DMA for speedup (DMA-channel 0). -Formerly the sd-card support driver also was using this legacy -api (DMA-channel 2), but since has been moved over to use -dmaengine directly. - -The DMA-channel 3 is already masked out in the devicetree in -the default property "brcm,dma-channel-mask = <0x7f35>;" - -So we can remove the whole masking of DMA channels. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 9 --------- - 1 file changed, 9 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 2d72fe81243fbbcc92f52e1935ed48b6cbc23665..e4ca980049bab83ddbb58435c662e4a30321d4f8 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -123,9 +123,6 @@ struct bcm2835_desc { - #define BCM2835_DMA_DATA_TYPE_S32 4 - #define BCM2835_DMA_DATA_TYPE_S128 16 - --#define BCM2835_DMA_BULK_MASK BIT(0) --#define BCM2835_DMA_FIQ_MASK (BIT(2) | BIT(3)) -- - /* Valid only for channels 0 - 14, 15 has its own base address */ - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) -@@ -641,12 +638,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- /* -- * Do not use the FIQ and BULK channels, -- * because they are used by the GPU. -- */ -- chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); -- - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); - if (irq < 0) - -From 595eb44ddbba0e43280f2993be27f8b49f2f3f5f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:57 -0700 -Subject: [PATCH 123/141] dmaengine: bcm2835: add additional defines for - DMA-registers - -Add additional defines describing the DMA registers -as well as adding some more documentation to those registers. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 57 ++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 49 insertions(+), 8 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index e4ca980049bab83ddbb58435c662e4a30321d4f8..a1d851aa5b182f9b0f4d6c2ab719b1ade2167c11 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -97,26 +97,67 @@ struct bcm2835_desc { - - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 -+#define BCM2835_DMA_TI 0x08 - #define BCM2835_DMA_SOURCE_AD 0x0c - #define BCM2835_DMA_DEST_AD 0x10 --#define BCM2835_DMA_NEXTCB 0x1C -+#define BCM2835_DMA_LEN 0x14 -+#define BCM2835_DMA_STRIDE 0x18 -+#define BCM2835_DMA_NEXTCB 0x1c -+#define BCM2835_DMA_DEBUG 0x20 - - /* DMA CS Control and Status bits */ --#define BCM2835_DMA_ACTIVE BIT(0) --#define BCM2835_DMA_INT BIT(2) -+#define BCM2835_DMA_ACTIVE BIT(0) /* activate the DMA */ -+#define BCM2835_DMA_END BIT(1) /* current CB has ended */ -+#define BCM2835_DMA_INT BIT(2) /* interrupt status */ -+#define BCM2835_DMA_DREQ BIT(3) /* DREQ state */ - #define BCM2835_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ - #define BCM2835_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ --#define BCM2835_DMA_ERR BIT(8) -+#define BCM2835_DMA_WAITING_FOR_WRITES BIT(6) /* waiting for last -+ * AXI-write to ack -+ */ -+#define BCM2835_DMA_ERR BIT(8) -+#define BCM2835_DMA_PRIORITY(x) ((x & 15) << 16) /* AXI priority */ -+#define BCM2835_DMA_PANIC_PRIORITY(x) ((x & 15) << 20) /* panic priority */ -+/* current value of TI.BCM2835_DMA_WAIT_RESP */ -+#define BCM2835_DMA_WAIT_FOR_WRITES BIT(28) -+#define BCM2835_DMA_DIS_DEBUG BIT(29) /* disable debug pause signal */ - #define BCM2835_DMA_ABORT BIT(30) /* Stop current CB, go to next, WO */ - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - -+/* Transfer information bits - also bcm2835_cb.info field */ - #define BCM2835_DMA_INT_EN BIT(0) -+#define BCM2835_DMA_TDMODE BIT(1) /* 2D-Mode */ -+#define BCM2835_DMA_WAIT_RESP BIT(3) /* wait for AXI-write to be acked */ - #define BCM2835_DMA_D_INC BIT(4) --#define BCM2835_DMA_D_DREQ BIT(6) -+#define BCM2835_DMA_D_WIDTH BIT(5) /* 128bit writes if set */ -+#define BCM2835_DMA_D_DREQ BIT(6) /* enable DREQ for destination */ -+#define BCM2835_DMA_D_IGNORE BIT(7) /* ignore destination writes */ - #define BCM2835_DMA_S_INC BIT(8) --#define BCM2835_DMA_S_DREQ BIT(10) -- --#define BCM2835_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2835_DMA_S_WIDTH BIT(9) /* 128bit writes if set */ -+#define BCM2835_DMA_S_DREQ BIT(10) /* enable SREQ for source */ -+#define BCM2835_DMA_S_IGNORE BIT(11) /* ignore source reads - read 0 */ -+#define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12) -+#define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */ -+#define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* add DMA-wait cycles */ -+#define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */ -+ -+/* debug register bits */ -+#define BCM2835_DMA_DEBUG_LAST_NOT_SET_ERR BIT(0) -+#define BCM2835_DMA_DEBUG_FIFO_ERR BIT(1) -+#define BCM2835_DMA_DEBUG_READ_ERR BIT(2) -+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_SHIFT 4 -+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_BITS 4 -+#define BCM2835_DMA_DEBUG_ID_SHIFT 16 -+#define BCM2835_DMA_DEBUG_ID_BITS 9 -+#define BCM2835_DMA_DEBUG_STATE_SHIFT 16 -+#define BCM2835_DMA_DEBUG_STATE_BITS 9 -+#define BCM2835_DMA_DEBUG_VERSION_SHIFT 25 -+#define BCM2835_DMA_DEBUG_VERSION_BITS 3 -+#define BCM2835_DMA_DEBUG_LITE BIT(28) -+ -+/* shared registers for all dma channels */ -+#define BCM2835_DMA_INT_STATUS 0xfe0 -+#define BCM2835_DMA_ENABLE 0xff0 - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 - -From 55d60dc6c0c2571736495f5bc7beac5e3c76d1da Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:58 -0700 -Subject: [PATCH 124/141] dmaengine: bcm2835: move cyclic member from - bcm2835_chan into bcm2835_desc - -In preparation to consolidating code we move the cyclic member -into the bcm_2835_desc structure. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index a1d851aa5b182f9b0f4d6c2ab719b1ade2167c11..b3bc382fd1998324d6034e203afdd77a4d7ad168 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -73,7 +73,6 @@ struct bcm2835_chan { - struct list_head node; - - struct dma_slave_config cfg; -- bool cyclic; - unsigned int dreq; - - int ch; -@@ -93,6 +92,8 @@ struct bcm2835_desc { - - unsigned int frames; - size_t size; -+ -+ bool cyclic; - }; - - #define BCM2835_DMA_CS 0x00 -@@ -377,8 +378,6 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -432,6 +431,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - d->frames = buf_len / period_len; -+ d->cyclic = true; - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { - -From 17068219bf274d789d6a25faf73cb20a653f23f6 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:59 -0700 -Subject: [PATCH 125/141] dmaengine: bcm2835: move controlblock chain - generation into separate method - -In preparation of adding slave_sg functionality this patch moves the -generation/allocation of bcm2835_desc and the building of -the corresponding DMA-control-block chain from bcm2835_dma_prep_dma_cyclic -into the newly created method bcm2835_dma_create_cb_chain. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 294 +++++++++++++++++++++++++++++++--------------- - 1 file changed, 198 insertions(+), 96 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b3bc382fd1998324d6034e203afdd77a4d7ad168..4db0e232fab8e3422d4c28a164ed67f0676981f2 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -88,12 +88,12 @@ struct bcm2835_desc { - struct virt_dma_desc vd; - enum dma_transfer_direction dir; - -- struct bcm2835_cb_entry *cb_list; -- - unsigned int frames; - size_t size; - - bool cyclic; -+ -+ struct bcm2835_cb_entry cb_list[]; - }; - - #define BCM2835_DMA_CS 0x00 -@@ -169,6 +169,13 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+/* how many frames of max_len size do we need to transfer len bytes */ -+static inline size_t bcm2835_dma_frames_for_length(size_t len, -+ size_t max_len) -+{ -+ return DIV_ROUND_UP(len, max_len); -+} -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -185,19 +192,161 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( - return container_of(t, struct bcm2835_desc, vd.tx); - } - --static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) -+static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) - { -- struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd); -- int i; -+ size_t i; - - for (i = 0; i < desc->frames; i++) - dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb, - desc->cb_list[i].paddr); - -- kfree(desc->cb_list); - kfree(desc); - } - -+static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) -+{ -+ bcm2835_dma_free_cb_chain( -+ container_of(vd, struct bcm2835_desc, vd)); -+} -+ -+static void bcm2835_dma_create_cb_set_length( -+ struct bcm2835_chan *chan, -+ struct bcm2835_dma_cb *control_block, -+ size_t len, -+ size_t period_len, -+ size_t *total_len, -+ u32 finalextrainfo) -+{ -+ /* set the length */ -+ control_block->length = len; -+ -+ /* finished if we have no period_length */ -+ if (!period_len) -+ return; -+ -+ /* -+ * period_len means: that we need to generate -+ * transfers that are terminating at every -+ * multiple of period_len - this is typically -+ * used to set the interrupt flag in info -+ * which is required during cyclic transfers -+ */ -+ -+ /* have we filled in period_length yet? */ -+ if (*total_len + control_block->length < period_len) -+ return; -+ -+ /* calculate the length that remains to reach period_length */ -+ control_block->length = period_len - *total_len; -+ -+ /* reset total_length for next period */ -+ *total_len = 0; -+ -+ /* add extrainfo bits in info */ -+ control_block->info |= finalextrainfo; -+} -+ -+/** -+ * bcm2835_dma_create_cb_chain - create a control block and fills data in -+ * -+ * @chan: the @dma_chan for which we run this -+ * @direction: the direction in which we transfer -+ * @cyclic: it is a cyclic transfer -+ * @info: the default info bits to apply per controlblock -+ * @frames: number of controlblocks to allocate -+ * @src: the src address to assign (if the S_INC bit is set -+ * in @info, then it gets incremented) -+ * @dst: the dst address to assign (if the D_INC bit is set -+ * in @info, then it gets incremented) -+ * @buf_len: the full buffer length (may also be 0) -+ * @period_len: the period length when to apply @finalextrainfo -+ * in addition to the last transfer -+ * this will also break some control-blocks early -+ * @finalextrainfo: additional bits in last controlblock -+ * (or when period_len is reached in case of cyclic) -+ * @gfp: the GFP flag to use for allocation -+ */ -+static struct bcm2835_desc *bcm2835_dma_create_cb_chain( -+ struct dma_chan *chan, enum dma_transfer_direction direction, -+ bool cyclic, u32 info, u32 finalextrainfo, size_t frames, -+ dma_addr_t src, dma_addr_t dst, size_t buf_len, -+ size_t period_len, gfp_t gfp) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ size_t len = buf_len, total_len; -+ size_t frame; -+ struct bcm2835_desc *d; -+ struct bcm2835_cb_entry *cb_entry; -+ struct bcm2835_dma_cb *control_block; -+ -+ /* allocate and setup the descriptor. */ -+ d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), -+ gfp); -+ if (!d) -+ return NULL; -+ -+ d->c = c; -+ d->dir = direction; -+ d->cyclic = cyclic; -+ -+ /* -+ * Iterate over all frames, create a control block -+ * for each frame and link them together. -+ */ -+ for (frame = 0, total_len = 0; frame < frames; d->frames++, frame++) { -+ cb_entry = &d->cb_list[frame]; -+ cb_entry->cb = dma_pool_alloc(c->cb_pool, gfp, -+ &cb_entry->paddr); -+ if (!cb_entry->cb) -+ goto error_cb; -+ -+ /* fill in the control block */ -+ control_block = cb_entry->cb; -+ control_block->info = info; -+ control_block->src = src; -+ control_block->dst = dst; -+ control_block->stride = 0; -+ control_block->next = 0; -+ /* set up length in control_block if requested */ -+ if (buf_len) { -+ /* calculate length honoring period_length */ -+ bcm2835_dma_create_cb_set_length( -+ c, control_block, -+ len, period_len, &total_len, -+ cyclic ? finalextrainfo : 0); -+ -+ /* calculate new remaining length */ -+ len -= control_block->length; -+ } -+ -+ /* link this the last controlblock */ -+ if (frame) -+ d->cb_list[frame - 1].cb->next = cb_entry->paddr; -+ -+ /* update src and dst and length */ -+ if (src && (info & BCM2835_DMA_S_INC)) -+ src += control_block->length; -+ if (dst && (info & BCM2835_DMA_D_INC)) -+ dst += control_block->length; -+ -+ /* Length of total transfer */ -+ d->size += control_block->length; -+ } -+ -+ /* the last frame requires extra flags */ -+ d->cb_list[d->frames - 1].cb->info |= finalextrainfo; -+ -+ /* detect a size missmatch */ -+ if (buf_len && (d->size != buf_len)) -+ goto error_cb; -+ -+ return d; -+error_cb: -+ bcm2835_dma_free_cb_chain(d); -+ -+ return NULL; -+} -+ - static int bcm2835_dma_abort(void __iomem *chan_base) - { - unsigned long cs; -@@ -391,12 +540,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - unsigned long flags) - { - struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -- enum dma_slave_buswidth dev_width; - struct bcm2835_desc *d; -- dma_addr_t dev_addr; -- unsigned int es, sync_type; -- unsigned int frame; -- int i; -+ dma_addr_t src, dst; -+ u32 info = BCM2835_DMA_WAIT_RESP; -+ u32 extra = BCM2835_DMA_INT_EN; -+ size_t frames; - - /* Grab configuration */ - if (!is_slave_direction(direction)) { -@@ -404,104 +552,58 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - return NULL; - } - -- if (direction == DMA_DEV_TO_MEM) { -- dev_addr = c->cfg.src_addr; -- dev_width = c->cfg.src_addr_width; -- sync_type = BCM2835_DMA_S_DREQ; -- } else { -- dev_addr = c->cfg.dst_addr; -- dev_width = c->cfg.dst_addr_width; -- sync_type = BCM2835_DMA_D_DREQ; -- } -- -- /* Bus width translates to the element size (ES) */ -- switch (dev_width) { -- case DMA_SLAVE_BUSWIDTH_4_BYTES: -- es = BCM2835_DMA_DATA_TYPE_S32; -- break; -- default: -+ if (!buf_len) { -+ dev_err(chan->device->dev, -+ "%s: bad buffer length (= 0)\n", __func__); - return NULL; - } - -- /* Now allocate and setup the descriptor. */ -- d = kzalloc(sizeof(*d), GFP_NOWAIT); -- if (!d) -- return NULL; -+ /* -+ * warn if buf_len is not a multiple of period_len - this may leed -+ * to unexpected latencies for interrupts and thus audiable clicks -+ */ -+ if (buf_len % period_len) -+ dev_warn_once(chan->device->dev, -+ "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", -+ __func__, buf_len, period_len); - -- d->c = c; -- d->dir = direction; -- d->frames = buf_len / period_len; -- d->cyclic = true; -+ /* Setup DREQ channel */ -+ if (c->dreq != 0) -+ info |= BCM2835_DMA_PER_MAP(c->dreq); - -- d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -- if (!d->cb_list) { -- kfree(d); -- return NULL; -+ if (direction == DMA_DEV_TO_MEM) { -+ if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ src = c->cfg.src_addr; -+ dst = buf_addr; -+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; -+ } else { -+ if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ dst = c->cfg.dst_addr; -+ src = buf_addr; -+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; - } -- /* Allocate memory for control blocks */ -- for (i = 0; i < d->frames; i++) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; - -- cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -- &cb_entry->paddr); -- if (!cb_entry->cb) -- goto error_cb; -- } -+ /* calculate number of frames */ -+ frames = DIV_ROUND_UP(buf_len, period_len); - - /* -- * Iterate over all frames, create a control block -- * for each frame and link them together. -+ * allocate the CB chain -+ * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine -+ * implementation calls prep_dma_cyclic with interrupts disabled. - */ -- for (frame = 0; frame < d->frames; frame++) { -- struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb; -- -- /* Setup adresses */ -- if (d->dir == DMA_DEV_TO_MEM) { -- control_block->info = BCM2835_DMA_D_INC; -- control_block->src = dev_addr; -- control_block->dst = buf_addr + frame * period_len; -- } else { -- control_block->info = BCM2835_DMA_S_INC; -- control_block->src = buf_addr + frame * period_len; -- control_block->dst = dev_addr; -- } -- -- /* Enable interrupt */ -- control_block->info |= BCM2835_DMA_INT_EN; -- -- /* Setup synchronization */ -- if (sync_type != 0) -- control_block->info |= sync_type; -- -- /* Setup DREQ channel */ -- if (c->dreq != 0) -- control_block->info |= -- BCM2835_DMA_PER_MAP(c->dreq); -- -- /* Length of a frame */ -- control_block->length = period_len; -- d->size += control_block->length; -+ d = bcm2835_dma_create_cb_chain(chan, direction, true, -+ info, extra, -+ frames, src, dst, buf_len, -+ period_len, GFP_NOWAIT); -+ if (!d) -+ return NULL; - -- /* -- * 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->cb_list[((frame + 1) % d->frames)].paddr; -- } -+ /* wrap around into a loop */ -+ d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; - - return vchan_tx_prep(&c->vc, &d->vd, flags); --error_cb: -- i--; -- for (; i >= 0; i--) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -- -- dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -- } -- -- kfree(d->cb_list); -- kfree(d); -- return NULL; - } - - static int bcm2835_dma_slave_config(struct dma_chan *chan, - -From 4d44a8902ae85fe42de9d30c52e757acc9425012 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:00 -0700 -Subject: [PATCH 126/141] dmaengine: bcm2835: limit max length based on channel - type - -The bcm2835 dma system has 2 basic types of dma-channels: -* "normal" channels -* "light" channels - -Lite channels are limited in several aspects: -* internal data-structure is 128 bit (not 256) -* does not support BCM2835_DMA_TDMODE (2D) -* DMA length register is limited to 16 bit. - so 0-65535 (not 0-65536 as mentioned in the official datasheet) -* BCM2835_DMA_S/D_IGNORE are not supported - -The detection of the type of mode is implemented by looking at -the LITE bit in the DEBUG register for each channel. -This allows automatic detection. - -Based on this the maximum block size is set to (64K - 4) or to 1G -and this limit is honored during generation of control block -chains. The effect is that when a LITE channel is used more -control blocks are used to do the same transfer (compared -to a normal channel). - -As there are several sources/target DREQS that are 32 bit wide -we need to have the transfer to be a multiple of 4 as this would -break the transfer otherwise. - -This is why the limit of (64K - 4) was chosen over the -alternative of (64K - 4K). - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 29 ++++++++++++++++++++++++++--- - 1 file changed, 26 insertions(+), 3 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 4db0e232fab8e3422d4c28a164ed67f0676981f2..59c5ef36d97059a4f988f083a64f084da02093cd 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -81,6 +81,8 @@ struct bcm2835_chan { - - void __iomem *chan_base; - int irq_number; -+ -+ bool is_lite_channel; - }; - - struct bcm2835_desc { -@@ -169,6 +171,16 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+/* the max dma length for different channels */ -+#define MAX_DMA_LEN SZ_1G -+#define MAX_LITE_DMA_LEN (SZ_64K - 4) -+ -+static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c) -+{ -+ /* lite and normal channels have different max frame length */ -+ return c->is_lite_channel ? MAX_LITE_DMA_LEN : MAX_DMA_LEN; -+} -+ - /* how many frames of max_len size do we need to transfer len bytes */ - static inline size_t bcm2835_dma_frames_for_length(size_t len, - size_t max_len) -@@ -217,8 +229,10 @@ static void bcm2835_dma_create_cb_set_length( - size_t *total_len, - u32 finalextrainfo) - { -- /* set the length */ -- control_block->length = len; -+ size_t max_len = bcm2835_dma_max_frame_length(chan); -+ -+ /* set the length taking lite-channel limitations into account */ -+ control_block->length = min_t(u32, len, max_len); - - /* finished if we have no period_length */ - if (!period_len) -@@ -544,6 +558,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - dma_addr_t src, dst; - u32 info = BCM2835_DMA_WAIT_RESP; - u32 extra = BCM2835_DMA_INT_EN; -+ size_t max_len = bcm2835_dma_max_frame_length(c); - size_t frames; - - /* Grab configuration */ -@@ -586,7 +601,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - } - - /* calculate number of frames */ -- frames = DIV_ROUND_UP(buf_len, period_len); -+ frames = /* number of periods */ -+ DIV_ROUND_UP(buf_len, period_len) * -+ /* number of frames per period */ -+ bcm2835_dma_frames_for_length(period_len, max_len); - - /* - * allocate the CB chain -@@ -685,6 +703,11 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - c->ch = chan_id; - c->irq_number = irq; - -+ /* check in DEBUG register if this is a LITE channel */ -+ if (readl(c->chan_base + BCM2835_DMA_DEBUG) & -+ BCM2835_DMA_DEBUG_LITE) -+ c->is_lite_channel = true; -+ - return 0; - } - - -From d773b94b0b340a9087bc636283e28dd46a53428b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:01 -0700 -Subject: [PATCH 127/141] dmaengine: bcm2835: add slave_sg support to - bcm2835-dma - -Add slave_sg support to bcm2835-dma using shared allocation -code for bcm2835_desc and DMA-control blocks already used by -dma_cyclic. - -Note that bcm2835_dma_callback had to get modified to support -both modes of operation (cyclic and non-cyclic). - -Tested using: -* Hifiberry I2S card (using cyclic DMA) -* fb_st7735r SPI-framebuffer (using slave_sg DMA via spi-bcm2835) -playing BigBuckBunny for audio and video. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 113 ++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 108 insertions(+), 5 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 59c5ef36d97059a4f988f083a64f084da02093cd..b46b12f66f387e0b87aa6d09192071b58da9e953 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -260,6 +260,23 @@ static void bcm2835_dma_create_cb_set_length( - control_block->info |= finalextrainfo; - } - -+static inline size_t bcm2835_dma_count_frames_for_sg( -+ struct bcm2835_chan *c, -+ struct scatterlist *sgl, -+ unsigned int sg_len) -+{ -+ size_t frames = 0; -+ struct scatterlist *sgent; -+ unsigned int i; -+ size_t plength = bcm2835_dma_max_frame_length(c); -+ -+ for_each_sg(sgl, sgent, sg_len, i) -+ frames += bcm2835_dma_frames_for_length( -+ sg_dma_len(sgent), plength); -+ -+ return frames; -+} -+ - /** - * bcm2835_dma_create_cb_chain - create a control block and fills data in - * -@@ -361,6 +378,32 @@ error_cb: - return NULL; - } - -+static void bcm2835_dma_fill_cb_chain_with_sg( -+ struct dma_chan *chan, -+ enum dma_transfer_direction direction, -+ struct bcm2835_cb_entry *cb, -+ struct scatterlist *sgl, -+ unsigned int sg_len) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ size_t max_len = bcm2835_dma_max_frame_length(c); -+ unsigned int i, len; -+ dma_addr_t addr; -+ struct scatterlist *sgent; -+ -+ for_each_sg(sgl, sgent, sg_len, i) { -+ for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent); -+ len > 0; -+ addr += cb->cb->length, len -= cb->cb->length, cb++) { -+ if (direction == DMA_DEV_TO_MEM) -+ cb->cb->dst = addr; -+ else -+ cb->cb->src = addr; -+ cb->cb->length = min(len, max_len); -+ } -+ } -+} -+ - static int bcm2835_dma_abort(void __iomem *chan_base) - { - unsigned long cs; -@@ -428,13 +471,19 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- /* TODO Only works for cyclic DMA */ -- vchan_cyclic_callback(&d->vd); -+ if (d->cyclic) { -+ /* call the cyclic callback */ -+ vchan_cyclic_callback(&d->vd); -+ -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, -+ c->chan_base + BCM2835_DMA_CS); -+ } else { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ } - } - -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -- - spin_unlock_irqrestore(&c->vc.lock, flags); - - return IRQ_HANDLED; -@@ -548,6 +597,58 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - spin_unlock_irqrestore(&c->vc.lock, flags); - } - -+static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( -+ struct dma_chan *chan, -+ struct scatterlist *sgl, unsigned int sg_len, -+ enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ struct bcm2835_desc *d; -+ dma_addr_t src = 0, dst = 0; -+ u32 info = BCM2835_DMA_WAIT_RESP; -+ u32 extra = BCM2835_DMA_INT_EN; -+ size_t frames; -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(chan->device->dev, -+ "%s: bad direction?\n", __func__); -+ return NULL; -+ } -+ -+ if (c->dreq != 0) -+ info |= BCM2835_DMA_PER_MAP(c->dreq); -+ -+ if (direction == DMA_DEV_TO_MEM) { -+ if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ src = c->cfg.src_addr; -+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; -+ } else { -+ if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ dst = c->cfg.dst_addr; -+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; -+ } -+ -+ /* count frames in sg list */ -+ frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len); -+ -+ /* allocate the CB chain */ -+ d = bcm2835_dma_create_cb_chain(chan, direction, false, -+ info, extra, -+ frames, src, dst, 0, 0, -+ GFP_KERNEL); -+ if (!d) -+ return NULL; -+ -+ /* fill in frames with scatterlist pointers */ -+ bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list, -+ sgl, sg_len); -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ - static struct dma_async_tx_descriptor *bcm2835_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, -@@ -778,11 +879,13 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); - dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); - dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); -+ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); - od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; - od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -+ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - -From 0a01d07fac2c8e641d9a33241040637ee91faf10 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:02 -0700 -Subject: [PATCH 128/141] dmaengine: bcm2835: add dma_memcopy support to - bcm2835-dma - -Also added check for an error condition in bcm2835_dma_create_cb_chain -that showed up during development of this patch. - -Tested using dmatest for all enabled channels. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 36 +++++++++++++++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b46b12f66f387e0b87aa6d09192071b58da9e953..cc771cd35dd0c28829b6500421af686be865000b 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -310,6 +310,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( - struct bcm2835_cb_entry *cb_entry; - struct bcm2835_dma_cb *control_block; - -+ if (!frames) -+ return NULL; -+ - /* allocate and setup the descriptor. */ - d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), - gfp); -@@ -597,6 +600,34 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - spin_unlock_irqrestore(&c->vc.lock, flags); - } - -+struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( -+ struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, -+ size_t len, unsigned long flags) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ struct bcm2835_desc *d; -+ u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; -+ u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; -+ size_t max_len = bcm2835_dma_max_frame_length(c); -+ size_t frames; -+ -+ /* if src, dst or len is not given return with an error */ -+ if (!src || !dst || !len) -+ return NULL; -+ -+ /* calculate number of frames */ -+ frames = bcm2835_dma_frames_for_length(len, max_len); -+ -+ /* allocate the CB chain - this also fills in the pointers */ -+ d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, -+ info, extra, frames, -+ src, dst, len, 0, GFP_KERNEL); -+ if (!d) -+ return NULL; -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ - static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( - struct dma_chan *chan, - struct scatterlist *sgl, unsigned int sg_len, -@@ -880,17 +911,20 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); - dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -+ dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask); - od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; - od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; - od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; -+ od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -- od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | -+ BIT(DMA_MEM_TO_MEM); - od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - -From 535e5d3ace534cdf359604c184e9f187ead13095 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 11 Apr 2016 13:29:08 +0000 -Subject: [PATCH 129/141] dmaengine: bcm2835: use platform_get_irq_byname - -Use platform_get_irq_byname to allow for correct mapping of -interrupts to dma channels. - -The currently implemented device tree is unfortunately -implemented with the wrong assumption, that each dma-channel -has its own dma channel, but dma-irq 11 is handling -dma-channel 11-14 and dma-irq 12 is actually a "catch all" -interrupt. - -So here we use the byname variant and require that interrupts -are explicitly named via the interrupts-name property in the -device tree. - -The use of shared interrupts is also implemented. - -As a side-effect this means we can now use dma channels 12, 13 and 14 -in a correct manner - also testing shows that onl using -channels 11 to 14 for spi and i2s works perfectly (when playing -some video) - -Signed-off-by: Martin Sperl -Acked-by: Eric Anholt -Acked-by: Mark Rutland -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 63 insertions(+), 14 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index cc771cd35dd0c28829b6500421af686be865000b..974015193b93cdb398f1157b89b6e2cf5234354e 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -46,6 +46,9 @@ - - #include "virt-dma.h" - -+#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 -+#define BCM2835_DMA_CHAN_NAME_SIZE 8 -+ - struct bcm2835_dmadev { - struct dma_device ddev; - spinlock_t lock; -@@ -81,6 +84,7 @@ struct bcm2835_chan { - - void __iomem *chan_base; - int irq_number; -+ unsigned int irq_flags; - - bool is_lite_channel; - }; -@@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - struct bcm2835_desc *d; - unsigned long flags; - -+ /* check the shared interrupt */ -+ if (c->irq_flags & IRQF_SHARED) { -+ /* check if the interrupt is enabled */ -+ flags = readl(c->chan_base + BCM2835_DMA_CS); -+ /* if not set then we are not the reason for the irq */ -+ if (!(flags & BCM2835_DMA_INT)) -+ return IRQ_NONE; -+ } -+ - spin_lock_irqsave(&c->vc.lock, flags); - - /* Acknowledge interrupt */ -@@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) - return -ENOMEM; - } - -- return request_irq(c->irq_number, -- bcm2835_dma_callback, 0, "DMA IRQ", c); -+ return request_irq(c->irq_number, bcm2835_dma_callback, -+ c->irq_flags, "DMA IRQ", c); - } - - static void bcm2835_dma_free_chan_resources(struct dma_chan *chan) -@@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) - return 0; - } - --static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) -+static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, -+ int irq, unsigned int irq_flags) - { - struct bcm2835_chan *c; - -@@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); - c->ch = chan_id; - c->irq_number = irq; -+ c->irq_flags = irq_flags; - - /* check in DEBUG register if this is a LITE channel */ - if (readl(c->chan_base + BCM2835_DMA_DEBUG) & -@@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - struct resource *res; - void __iomem *base; - int rc; -- int i; -- int irq; -+ int i, j; -+ int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1]; -+ int irq_flags; - uint32_t chans_available; -+ char chan_name[BCM2835_DMA_CHAN_NAME_SIZE]; - - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; -@@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- for (i = 0; i < pdev->num_resources; i++) { -- irq = platform_get_irq(pdev, i); -- if (irq < 0) -- break; -- -- if (chans_available & (1 << i)) { -- rc = bcm2835_dma_chan_init(od, i, irq); -- if (rc) -- goto err_no_dma; -+ /* get irqs for each channel that we support */ -+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { -+ /* skip masked out channels */ -+ if (!(chans_available & (1 << i))) { -+ irq[i] = -1; -+ continue; - } -+ -+ /* get the named irq */ -+ snprintf(chan_name, sizeof(chan_name), "dma%i", i); -+ irq[i] = platform_get_irq_byname(pdev, chan_name); -+ if (irq[i] >= 0) -+ continue; -+ -+ /* legacy device tree case handling */ -+ dev_warn_once(&pdev->dev, -+ "missing interrupts-names property in device tree - legacy interpretation is used"); -+ /* -+ * in case of channel >= 11 -+ * use the 11th interrupt and that is shared -+ */ -+ irq[i] = platform_get_irq(pdev, i < 11 ? i : 11); -+ } -+ -+ /* get irqs for each channel */ -+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { -+ /* skip channels without irq */ -+ if (irq[i] < 0) -+ continue; -+ -+ /* check if there are other channels that also use this irq */ -+ irq_flags = 0; -+ for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++) -+ if ((i != j) && (irq[j] == irq[i])) { -+ irq_flags = IRQF_SHARED; -+ break; -+ } -+ -+ /* initialize the channel */ -+ rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags); -+ if (rc) -+ goto err_no_dma; - } - - dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i); - -From df774079ce9acc952350f182ef76d627b82968f8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 130/141] dmaengine: bcm2835: Load driver early and support - legacy API -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Load driver early since at least bcm2708_fb doesn't support deferred -probing and even if it did, we don't want the video driver deferred. - -Support the legacy DMA API which is needed by bcm2708_fb -(but only using the dedicated dma channel 0). - -Signed-off-by: Noralf Trønnes -Signed-off-by: Martin Sperl ---- - drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 27 ++++++++++++++++++++++++++- - 2 files changed, 27 insertions(+), 2 deletions(-) - -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 1acfa84be0d1f74f5a830b04cab05ba7fa0841ab..b7863f0cf95ca656859a355098aa334e20d121c3 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 974015193b93cdb398f1157b89b6e2cf5234354e..2d7aba118640447854732384351601137b502839 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1021,6 +1022,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - - dev_dbg(&pdev->dev, "Load BCM2835 DMA engine driver\n"); - -+ /* load the legacy api if bit 0 in the mask is cleared */ -+ if ((chans_available & BIT(0)) == 0) { -+ rc = bcm_dmaman_probe(pdev, base, BIT(0)); -+ if (rc) -+ dev_err(&pdev->dev, -+ "Failed to initialize the legacy API\n"); -+ } -+ - return 0; - - err_no_dma: -@@ -1032,6 +1041,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - { - struct bcm2835_dmadev *od = platform_get_drvdata(pdev); - -+ bcm_dmaman_remove(pdev); - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); - -@@ -1047,7 +1057,22 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --module_platform_driver(bcm2835_dma_driver); -+static int bcm2835_dma_init(void) -+{ -+ return platform_driver_register(&bcm2835_dma_driver); -+} -+ -+static void bcm2835_dma_exit(void) -+{ -+ platform_driver_unregister(&bcm2835_dma_driver); -+} -+ ++obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o +diff --git a/sound/soc/bcm/dionaudio_loco.c b/sound/soc/bcm/dionaudio_loco.c +new file mode 100644 +index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98aacb740a +--- /dev/null ++++ b/sound/soc/bcm/dionaudio_loco.c +@@ -0,0 +1,121 @@ +/* -+ * Load after serial driver (arch_initcall) so we see the messages if it fails, -+ * but before drivers (module_init) that need a DMA channel. ++ * ASoC Driver for Dion Audio LOCO DAC-AMP ++ * ++ * Author: Miquel Blauw ++ * Copyright 2016 ++ * ++ * Based on the software of the RPi-DAC writen by Florian Meier ++ * ++ * 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. + */ -+subsys_initcall(bcm2835_dma_init); -+module_exit(bcm2835_dma_exit); - - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - -From 5d00014e188fa1eb67d14f525b2daeebd842cf39 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 16:13:59 +0000 -Subject: [PATCH 131/141] ARM: bcm270x: changed bcrm,dma-channel-mask to mask - out the used channel - -Dma channel0 is used by the legacy api - to avoid confilcts this -needs to get masked out in the device-tree instead of hardcoding it -in the driver. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 6ea37c57f7b1f298c10a599982f347098219d468..d85862e2028487b0c357b3a7cd8e78524abc3c92 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -59,7 +59,7 @@ - <1 27>; - - #dma-cells = <1>; -- brcm,dma-channel-mask = <0x0f35>; -+ brcm,dma-channel-mask = <0x0f34>; - }; - - intc: interrupt-controller@7e00b200 { - -From d99a15e724b68ff99c96abf73b35b1f43c0e14a5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sat, 23 Apr 2016 14:07:03 +0000 -Subject: [PATCH 132/141] ARM: bcm2835: add interrupt-names and apply correct - mapping - -Add interrupt-names properties to dt and apply the correct -mapping between irq and dma channels. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 26 ++++++++++++++++++++++++-- - 1 file changed, 24 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index d85862e2028487b0c357b3a7cd8e78524abc3c92..18a28c8578a322bdef73cdb5ff4131b40f9321e4 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -56,10 +56,32 @@ - <1 24>, - <1 25>, - <1 26>, -- <1 27>; -+ /* dma channel 11-14 share one irq */ -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ /* unused shared irq for all channels */ -+ <1 28>; -+ interrupt-names = "dma0", -+ "dma1", -+ "dma2", -+ "dma3", -+ "dma4", -+ "dma5", -+ "dma6", -+ "dma7", -+ "dma8", -+ "dma9", -+ "dma10", -+ "dma11", -+ "dma12", -+ "dma13", -+ "dma14", -+ "dma-shared-all"; - - #dma-cells = <1>; -- brcm,dma-channel-mask = <0x0f34>; -+ brcm,dma-channel-mask = <0x7f34>; - }; - - intc: interrupt-controller@7e00b200 { - -From 93eb2585bb68f04f5a1ee9ff5f6943d9a8001b7b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sat, 23 Apr 2016 14:20:41 +0000 -Subject: [PATCH 133/141] ARM: bcm2835: make dma-channel-0 available for kms - setups - -Enable the use of dma-channel 0 when using the vc4-kms-v3d overlay. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -index a4ca2cabd4cd19d3a82ad1135604dfa52784fb3f..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 100644 ---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -119,6 +119,13 @@ - }; - }; - -+ fragment@15 { -+ target-path = "/soc/dma"; -+ __overlay__ { -+ brcm,dma-channel-mask = <0x7f35>; -+ }; -+ }; + - __overrides__ { - cma-256 = <0>,"+0-1-2-3-4"; - cma-192 = <0>,"-0+1-2-3-4"; - -From b5c0b88c0005b431c583dec3e210895a994d5a99 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Tue, 7 Jun 2016 19:37:10 +0200 -Subject: [PATCH 134/141] dmaengine: bcm2835: Fix cyclic DMA period splitting - -The code responsible for splitting periods into chunks that -can be handled by the DMA controller missed to update total_len, -the number of bytes processed in the current period, when there -are more chunks to follow. - -Therefore total_len was stuck at 0 and the code didn't work at all. -This resulted in a wrong control block layout and audio issues because -the cyclic DMA callback wasn't executing on period boundaries. - -Fix this by adding the missing total_len update. - -Signed-off-by: Matthias Reichl -Signed-off-by: Martin Sperl -Tested-by: Clive Messer ---- - drivers/dma/bcm2835-dma.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 2d7aba118640447854732384351601137b502839..ea58967594c5a2d712026f50307c2d4de7089e8d 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -252,8 +252,11 @@ static void bcm2835_dma_create_cb_set_length( - */ - - /* have we filled in period_length yet? */ -- if (*total_len + control_block->length < period_len) -+ if (*total_len + control_block->length < period_len) { -+ /* update number of bytes in this period so far */ -+ *total_len += control_block->length; - return; -+ } - - /* calculate the length that remains to reach period_length */ - control_block->length = period_len - *total_len; - -From fffe68c8ea72a81115e92d3bf7791fea189f8eec Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Wed, 8 Jun 2016 13:09:56 +0200 -Subject: [PATCH 135/141] dmaengine: bcm2835: Avoid splitting periods into very - small chunks - -The current cyclic DMA period splitting implementation can generate -very small chunks at the end of each period. For example a 65536 byte -period will be split into a 65532 byte chunk and a 4 byte chunk on -the "lite" DMA channels. - -This increases pressure on the RAM controller as the DMA controller -needs to fetch two control blocks from RAM in quick succession and -could potentially cause latency issues if the RAM is tied up by other -devices. - -We can easily avoid these situations by distributing the remaining -length evenly between the last-but-one and the last chunk, making -sure that split chunks will be at least half the maximum length the -DMA controller can handle. - -This patch checks if the last chunk would be less than half of -the maximum DMA length and if yes distributes the max len+4...max_len*1.5 -bytes evenly between the last 2 chunks. This results in chunk sizes -between max_len/2 and max_len*0.75 bytes. - -Signed-off-by: Matthias Reichl -Signed-off-by: Martin Sperl -Tested-by: Clive Messer ---- - drivers/dma/bcm2835-dma.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index ea58967594c5a2d712026f50307c2d4de7089e8d..0173b912afb26b8f59e623a9055513df34cd3caa 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -253,6 +253,20 @@ static void bcm2835_dma_create_cb_set_length( - - /* have we filled in period_length yet? */ - if (*total_len + control_block->length < period_len) { -+ /* -+ * If the next control block is the last in the period -+ * and it's length would be less than half of max_len -+ * change it so that both control blocks are (almost) -+ * equally long. This avoids generating very short -+ * control blocks (worst case would be 4 bytes) which -+ * might be problematic. We also have to make sure the -+ * new length is a multiple of 4 bytes. -+ */ -+ if (*total_len + control_block->length + max_len / 2 > -+ period_len) { -+ control_block->length = -+ DIV_ROUND_UP(period_len - *total_len, 8) * 4; -+ } - /* update number of bytes in this period so far */ - *total_len += control_block->length; - return; - -From 2a0e397fd871007f34f4de8b515fe3270095dc6b Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 3 Jun 2016 19:29:11 -0700 -Subject: [PATCH 136/141] dmaengine: bcm2835: Fix polling for completion of DMA - with interrupts masked. - -The tx_status hook is supposed to be safe to call from interrupt -context, but it wouldn't ever return completion for the last transfer, -meaning you couldn't poll for DMA completion with interrupts masked. - -This fixes IRQ handling for bcm2835's DSI1, which requires using the -DMA engine to write its registers due to a bug in the AXI bridge. - -Signed-off-by: Eric Anholt ---- - drivers/dma/bcm2835-dma.c | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 0173b912afb26b8f59e623a9055513df34cd3caa..a98e2c2e6888f6351461c25f9f7d2a34330d0a76 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -588,16 +588,16 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, - struct virt_dma_desc *vd; - enum dma_status ret; - unsigned long flags; -+ u32 residue; - - ret = dma_cookie_status(chan, cookie, txstate); -- if (ret == DMA_COMPLETE || !txstate) -+ if (ret == DMA_COMPLETE) - return ret; - - spin_lock_irqsave(&c->vc.lock, flags); - vd = vchan_find_desc(&c->vc, cookie); - if (vd) { -- txstate->residue = -- bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); -+ residue = bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); - } else if (c->desc && c->desc->vd.tx.cookie == cookie) { - struct bcm2835_desc *d = c->desc; - dma_addr_t pos; -@@ -609,11 +609,25 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, - else - pos = 0; - -- txstate->residue = bcm2835_dma_desc_size_pos(d, pos); -+ residue = bcm2835_dma_desc_size_pos(d, pos); ++#include ++#include + -+ /* -+ * If our non-cyclic transfer is done, then report -+ * complete and trigger the next tx now. This lets -+ * the dmaengine API be used synchronously from an IRQ -+ * handler. -+ */ -+ if (!d->cyclic && residue == 0) { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ ret = dma_cookie_status(chan, cookie, txstate); -+ } - } else { -- txstate->residue = 0; -+ residue = 0; - } - -+ dma_set_residue(txstate, residue); ++#include ++#include ++#include ++#include ++#include + - spin_unlock_irqrestore(&c->vc.lock, flags); - - return ret; - -From 5d66079db4c049b62056903bc7f0a125005c0a65 Mon Sep 17 00:00:00 2001 -From: P33M -Date: Thu, 9 Jun 2016 18:53:56 +0100 -Subject: [PATCH 137/141] dwc_otg: add FIQ latency profiling histogram - -Add a sysfs-based FIQ latency profiler that times differences between -start-of-frame interrupts. Stats readout is via the sof_histogram -attribute. - -Writing to the sof_histogram attribute resets the bucket counters. ---- - drivers/usb/host/dwc_otg/dwc_otg_attr.c | 23 ++++++++++++++++- - drivers/usb/host/dwc_otg/dwc_otg_attr.h | 1 + - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 7 +++++- - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 6 +++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 38 ++++++++++++++++++++++++++++- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 7 ++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 2 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 27 ++++++++++++++++++++ - 8 files changed, 108 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -index 9da0c92aaeca2fc393016442cc6578cb4a52c978..e536f7e828174c193b3967f022e32e6f0f3e41d2 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -@@ -1016,6 +1016,26 @@ static ssize_t wr_reg_test_show(struct device *_dev, - - DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0); - -+static ssize_t sof_histogram_reset(struct device *_dev, -+ struct device_attribute *attr, const char *buf, size_t count) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ dwc_otg_hcd_t *hcd = otg_dev->hcd; -+ dwc_otg_hcd_sof_histogram_reset(hcd); -+ return count; -+} -+ -+static ssize_t sof_histogram_show(struct device *_dev, struct device_attribute *attr, char *buf) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ dwc_otg_hcd_t *hcd = otg_dev->hcd; -+ -+ return dwc_otg_hcd_dump_sof_histogram(hcd, buf); -+ -+} -+ -+DEVICE_ATTR(sof_histogram, S_IRUGO | S_IWUSR, sof_histogram_show, sof_histogram_reset); -+ - #ifdef CONFIG_USB_DWC_OTG_LPM - - /** -@@ -1113,7 +1133,7 @@ void dwc_otg_attr_create( - ) - { - int error; -- -+ error = device_create_file(&dev->dev, &dev_attr_sof_histogram); - error = device_create_file(&dev->dev, &dev_attr_regoffset); - error = device_create_file(&dev->dev, &dev_attr_regvalue); - error = device_create_file(&dev->dev, &dev_attr_mode); -@@ -1168,6 +1188,7 @@ void dwc_otg_attr_remove( - #endif - ) - { -+ device_remove_file(&dev->dev, &dev_attr_sof_histogram); - device_remove_file(&dev->dev, &dev_attr_regoffset); - device_remove_file(&dev->dev, &dev_attr_regvalue); - device_remove_file(&dev->dev, &dev_attr_mode); -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -index e10b67f97c522094b553b7675741ba1b3cae293d..f86ed9534c0d36329d60b52b4b05f31ac073b1b5 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -@@ -39,6 +39,7 @@ - */ - extern struct device_attribute dev_attr_regoffset; - extern struct device_attribute dev_attr_regvalue; -+extern struct device_attribute dev_attr_sof_histogram; - - extern struct device_attribute dev_attr_mode; - extern struct device_attribute dev_attr_hnpcapable; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -index 85d82f31cb49631f03b23631882d2b6c063b33db..9f7cec1ddfc761e61ebb208ea234e82545bf1e49 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -@@ -580,8 +580,13 @@ static int notrace noinline fiq_fsm_update_hs_isoc(struct fiq_state *state, int - static int notrace noinline fiq_fsm_do_sof(struct fiq_state *state, int num_channels) - { - hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + HFNUM) }; -- int n; -+ int n, i; - int kick_irq = 0; -+ -+ for (i = FIQ_NR_TIMESTAMPS - 1; i > 0; i--) { -+ state->sof_timestamps[i] = state->sof_timestamps[i - 1]; -+ } -+ state->sof_timestamps[0] = FIQ_READ(STC_LO); - - if ((hfnum.b.frnum & 0x7) == 1) { - /* We cannot issue csplits for transactions in the last frame past (n+1).1 -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -index f9fddfbcffb37f32c808fd78f222b676378398b1..a3e0a784d9567c861410d0d1271d5f95729b5ccb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #if 0 - #define FLAME_ON(x) \ -@@ -80,6 +81,9 @@ do { \ - #define FIQ_WRITE(_addr_,_data_) (*(volatile unsigned int *) (_addr_) = (_data_)) - #define FIQ_READ(_addr_) (*(volatile unsigned int *) (_addr_)) - -+#define FIQ_NR_TIMESTAMPS 32 -+#define STC_LO __io_address(ST_BASE + 0x04) -+ - /* FIQ-ified register definitions. Offsets are from dwc_regs_base. */ - #define GINTSTS 0x014 - #define GINTMSK 0x018 -@@ -339,12 +343,14 @@ struct fiq_state { - fiq_lock_t lock; - mphi_regs_t mphi_regs; - void *dwc_regs_base; -+ void *stc_base; - dma_addr_t dma_base; - struct fiq_dma_blob *fiq_dmab; - void *dummy_send; - gintmsk_data_t gintmsk_saved; - haintmsk_data_t haintmsk_saved; - int mphi_int_count; -+ int sof_timestamps[FIQ_NR_TIMESTAMPS]; - unsigned int fiq_done; - unsigned int kick_np_queues; - unsigned int next_sched_frame; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index 135b611abe08e141c937612ab7baada6b13113fc..cb7ec4af267459494194be54e5321df8326bf3c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -1047,7 +1047,12 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - sizeof(struct fiq_dma_channel) * num_channels); - - DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024); -- -+ -+ for(i = 0; i < NR_BINS; i++) { -+ hcd->histogram_bins[i] = BIN_START + (i * BIN_STRIDE); -+ hcd->histogram_counts[i] = 0; -+ } -+ - /* pointer for debug in fiq_print */ - hcd->fiq_state->fiq_dmab = hcd->fiq_dmab; - if (fiq_fsm_enable) { -@@ -4001,6 +4006,37 @@ int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) - return freed; - } - -+ssize_t dwc_otg_hcd_dump_sof_histogram(dwc_otg_hcd_t *hcd, char *buf) -+{ -+ ssize_t inc = 0, count = 0; -+ int i; -+ inc = sprintf(buf, "FIQ SOF latency histogram:\n Read overflows: %d\n", -+ hcd->sof_timestamp_overflows); -+ if (inc < 0) -+ return inc; -+ else -+ count += inc; -+ -+ for (i = 0; i < NR_BINS; i++) { -+ inc = sprintf(buf + count, " >%dus : %d\n", hcd->histogram_bins[i], hcd->histogram_counts[i]); -+ if (inc < 0) -+ return inc; -+ else -+ count += inc; -+ } -+ return count; -+} -+ -+void dwc_otg_hcd_sof_histogram_reset(dwc_otg_hcd_t *hcd) -+{ -+ int i; -+ unsigned long flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ for(i = 0; i < NR_BINS; i++) -+ hcd->histogram_counts[i] = 0; -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+} -+ - uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) - { - dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index 43dbed9fddbf5491bab33cc6e551b99ca8dce7dc..53ec21b15feebf91ef3ce9d13dbb265a7f856609 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -589,6 +589,13 @@ struct dwc_otg_hcd { - - struct fiq_stack *fiq_stack; - struct fiq_state *fiq_state; -+ int last_sof_timestamp; -+ int sof_timestamp_overflows; -+#define NR_BINS 16 -+#define BIN_STRIDE 5 -+#define BIN_START 100 -+ int histogram_bins[NR_BINS]; -+ int histogram_counts[NR_BINS]; - - /** Virtual address for split transaction DMA bounce buffers */ - struct fiq_dma_blob *fiq_dmab; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -index fb57db09378f4ab95d57cb58aa570a915ccb61c3..6103f7085b417d29eca323c1ed9667c6614c9ecd 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -@@ -411,6 +411,8 @@ extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); - extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, - void *ep_handle); - -+extern ssize_t dwc_otg_hcd_dump_sof_histogram(dwc_otg_hcd_t *hcd, char *buf); -+extern void dwc_otg_hcd_sof_histogram_reset(dwc_otg_hcd_t *hcd); - /** @} */ - - #endif /* __DWC_HCD_IF_H__ */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -index e6b38ac330b72152204c2a6879c20f0ce02ac2e5..a72438c9ed0b45471c736c52248480399511aca3 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -72,6 +72,31 @@ void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...) - } - #endif - -+void dwc_otg_hcd_update_histogram(dwc_otg_hcd_t *hcd) -+{ -+ int i, j, delta; -+ /* Search through the stack of SOF timestamps to find the last congruent timestamp */ -+ for(i = FIQ_NR_TIMESTAMPS - 1; i >= 0; i--) { -+ if ((hcd->last_sof_timestamp - hcd->fiq_state->sof_timestamps[i]) <= 0) -+ break; -+ } -+ if (i < 0) { -+ hcd->sof_timestamp_overflows++; -+ i += 1; -+ } -+ for(; i < FIQ_NR_TIMESTAMPS - 1; i++) { -+ /* Compute deltas, add to histogram buckets */ -+ delta = hcd->fiq_state->sof_timestamps[i] - hcd->fiq_state->sof_timestamps[i+1]; -+ for (j = 0; j < NR_BINS; j++) { -+ if(hcd->histogram_bins[j] >= delta || j == NR_BINS - 1) { -+ hcd->histogram_counts[j]++; -+ break; -+ } -+ } -+ } -+ hcd->last_sof_timestamp = hcd->fiq_state->sof_timestamps[0]; -+} -+ - /** This function handles interrupts for the HCD. */ - int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - { -@@ -104,6 +129,8 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - /* Pull in from the FIQ's disabled mask */ - gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32); - dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0; -+ -+ dwc_otg_hcd_update_histogram(dwc_otg_hcd); - } - - if (fiq_fsm_enable && ( 0x0000FFFF & ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint))) { - -From 5a66165271577b98c21d0828881ba50e957a144e Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Fri, 17 Jun 2016 12:03:39 +1000 -Subject: [PATCH 138/141] Added support for headphones, microphone and - bclk_ratio settings. - -This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. ---- - sound/soc/bcm/audioinjector-pi-soundcard.c | 67 ++++++++++++++++++++++++++---- - 1 file changed, 58 insertions(+), 9 deletions(-) - -diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c -index 39f29e26897226a413b4fa0a11a9bc160a485281..5ff0985e07efb96b95634a65995f09f7c68d9e99 100644 ---- a/sound/soc/bcm/audioinjector-pi-soundcard.c -+++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -29,16 +29,56 @@ - - #include "../codecs/wm8731.h" - --static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) -+static const unsigned int bcm2835_rates_12000000[] = { -+ 32000, 44100, 48000, 96000, 88200, -+}; -+ -+static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { -+ .list = bcm2835_rates_12000000, -+ .count = ARRAY_SIZE(bcm2835_rates_12000000), -+}; -+ -+static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) - { -- struct snd_soc_dapm_context *dapm = &rtd->card->dapm; -+ /* Setup constraints, because there is a 12 MHz XTAL on the board */ -+ snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &bcm2835_constraints_12000000); -+ return 0; -+} - -- // not connected -- snd_soc_dapm_nc_pin(dapm, "Mic Bias"); -- snd_soc_dapm_nc_pin(dapm, "MICIN"); -- snd_soc_dapm_nc_pin(dapm, "RHPOUT"); -- snd_soc_dapm_nc_pin(dapm, "LHPOUT"); -+static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) ++static int snd_rpi_dionaudio_loco_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; + -+ switch (params_rate(params)){ -+ case 8000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); -+ case 32000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); -+ case 44100: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); -+ case 48000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); -+ case 88200: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); -+ case 96000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ default: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ } ++ 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_audioinjector_pi_soundcard_ops = { -+ .startup = snd_audioinjector_pi_soundcard_startup, -+ .hw_params = snd_audioinjector_pi_soundcard_hw_params, ++static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = { ++ .hw_params = snd_rpi_dionaudio_loco_hw_params, +}; - -+static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) ++ ++static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = { +{ - return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); ++ .name = "DionAudio LOCO", ++ .stream_name = "DionAudio LOCO DAC-AMP", ++ .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_dionaudio_loco_ops, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_dionaudio_loco = { ++ .name = "snd_rpi_dionaudio_loco", ++ .dai_link = snd_rpi_dionaudio_loco_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai), ++}; ++ ++static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev) ++{ ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_dionaudio_loco.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0]; ++ struct device_node *i2s_np; ++ ++ i2s_np = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_np) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_np; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_np; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_dionaudio_loco_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco); ++} ++ ++static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = { ++ { .compatible = "dionaudio,loco-pcm5242-tpa3118", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match); ++ ++static struct platform_driver snd_rpi_dionaudio_loco_driver = { ++ .driver = { ++ .name = "snd-dionaudio-loco", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_dionaudio_loco_of_match, ++ }, ++ .probe = snd_rpi_dionaudio_loco_probe, ++ .remove = snd_rpi_dionaudio_loco_remove, ++}; ++ ++module_platform_driver(snd_rpi_dionaudio_loco_driver); ++ ++MODULE_AUTHOR("Miquel Blauw "); ++MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); ++MODULE_LICENSE("GPL v2"); + +From c29ce2592d5e0975b06dffd115c738a8f7ca9be3 Mon Sep 17 00:00:00 2001 +From: Matt Flax +Date: Fri, 17 Jun 2016 14:48:16 +1000 +Subject: [PATCH 082/111] ASoc: wm8731: add 32bit mode. + +commit cf5ef3a299ba32f6ac24c3c6ba18c1b7f1b5475f upstream. + +This patch adds 32 bit word capability to the wm8731 driver. The wm8731 +codec is capable of handling 32 bit word sizes, however that has not +previously been activated in the codec driver. + +Signed-off-by: Matt Flax +Acked-by: Charles Keepax +Signed-off-by: Mark Brown +--- + sound/soc/codecs/wm8731.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c +index 4bcf5f8ece50f3681948a9fbc47b85400d9a8b51..d18261a442560cd2c108c34295bd5b1776a6ebf4 100644 +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -358,6 +358,9 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, + case 24: + iface |= 0x0008; + break; ++ case 32: ++ iface |= 0x000c; ++ break; + } + + wm8731_set_deemph(codec); +@@ -541,7 +544,7 @@ static int wm8731_startup(struct snd_pcm_substream *substream, + #define WM8731_RATES SNDRV_PCM_RATE_8000_96000 + + #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ +- SNDRV_PCM_FMTBIT_S24_LE) ++ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + + static const struct snd_soc_dai_ops wm8731_dai_ops = { + .startup = wm8731_startup, + +From 9b3d81c6b2b35518fc918d777b8b78677cb1658a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:40:58 +0100 +Subject: [PATCH 083/111] Revert "ASoC: bcm2835: Add S16_LE support via packed + DMA transfers" + +This reverts commit beff053c0ef6983897e3481169292e6435ef0a2d. +--- + sound/soc/bcm/bcm2835-i2s.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 6ba20498202ed36906b52096893a88867a79269f..a0026e2d2f0afd700751b1b4fa2523585829173e 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -690,15 +690,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; + +- /* +- * Set the PACK flag to enable S16_LE support (2 S16_LE values +- * packed into 32-bit transfers). +- */ +- dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].flags = +- SND_DMAENGINE_PCM_DAI_FLAG_PACK; +- dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].flags = +- SND_DMAENGINE_PCM_DAI_FLAG_PACK; +- + /* BCLK ratio - use default */ + dev->bclk_ratio = 0; + + +From 9031c85c4614817d9356a6e58e50e98c030f5727 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:01 +0100 +Subject: [PATCH 084/111] Revert "ASoC: bcm2835: setup clock only if CPU is + clock master" + +This reverts commit 60507fe191f524e82986fa737e5b27b4d3ad9289. +--- + sound/soc/bcm/bcm2835-i2s.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index a0026e2d2f0afd700751b1b4fa2523585829173e..d2663e79ece1a2b649377e4a89460aa5a6d150b5 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -276,15 +276,8 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* otherwise calculate a fitting block ratio */ + bclk_ratio = 2 * data_length; + +- /* Clock should only be set up here if CPU is clock master */ +- switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { +- case SND_SOC_DAIFMT_CBS_CFS: +- case SND_SOC_DAIFMT_CBS_CFM: +- clk_set_rate(dev->clk, sampling_rate * bclk_ratio); +- break; +- default: +- break; +- } ++ /* set target clock rate*/ ++ clk_set_rate(dev->clk, sampling_rate * bclk_ratio); + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +From 49d7323355837c4cffd22aa242a8b5d50a2b47e6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:03 +0100 +Subject: [PATCH 085/111] Revert "ASoC: bcm2835: add 24bit support" + +This reverts commit a34b027dca5ea840fbc84121db66488375acfdea. +--- + sound/soc/bcm/bcm2835-i2s.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index d2663e79ece1a2b649377e4a89460aa5a6d150b5..1c1f2210387b26e9551959378f6792f18648652e 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -259,9 +259,6 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + case SNDRV_PCM_FORMAT_S16_LE: + data_length = 16; + break; +- case SNDRV_PCM_FORMAT_S24_LE: +- data_length = 24; +- break; + case SNDRV_PCM_FORMAT_S32_LE: + data_length = 32; + break; +@@ -282,7 +279,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +- if (data_length >= 24) ++ if (data_length > 24) + format |= BCM2835_I2S_CHWEX; + + format |= BCM2835_I2S_CHWID((data_length-8)&0xf); +@@ -573,7 +570,6 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { +@@ -581,7 +577,6 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, + +From 426600f81c84eb9581de55c5c364e402b744d627 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:09 +0100 +Subject: [PATCH 086/111] Revert "ASoC: bcm2835: move to use the clock + framework" + +This reverts commit 517e7a1537ae4663268be5d0c0ec62c563b9fc99. +--- + sound/soc/bcm/bcm2835-i2s.c | 284 ++++++++++++++++++++++++++++++++++---------- + 1 file changed, 220 insertions(+), 64 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 1c1f2210387b26e9551959378f6792f18648652e..3303d5f58082f68b68b535b2bdf7ce8d14cafcc4 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -47,6 +46,55 @@ + #include + #include + ++/* Clock registers */ ++#define BCM2835_CLK_PCMCTL_REG 0x00 ++#define BCM2835_CLK_PCMDIV_REG 0x04 ++ ++/* Clock register settings */ ++#define BCM2835_CLK_PASSWD (0x5a000000) ++#define BCM2835_CLK_PASSWD_MASK (0xff000000) ++#define BCM2835_CLK_MASH(v) ((v) << 9) ++#define BCM2835_CLK_FLIP BIT(8) ++#define BCM2835_CLK_BUSY BIT(7) ++#define BCM2835_CLK_KILL BIT(5) ++#define BCM2835_CLK_ENAB BIT(4) ++#define BCM2835_CLK_SRC(v) (v) ++ ++#define BCM2835_CLK_SHIFT (12) ++#define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) ++#define BCM2835_CLK_DIVF(v) (v) ++#define BCM2835_CLK_DIVF_MASK (0xFFF) ++ ++enum { ++ BCM2835_CLK_MASH_0 = 0, ++ BCM2835_CLK_MASH_1, ++ BCM2835_CLK_MASH_2, ++ BCM2835_CLK_MASH_3, ++}; ++ ++enum { ++ BCM2835_CLK_SRC_GND = 0, ++ BCM2835_CLK_SRC_OSC, ++ BCM2835_CLK_SRC_DBG0, ++ BCM2835_CLK_SRC_DBG1, ++ BCM2835_CLK_SRC_PLLA, ++ BCM2835_CLK_SRC_PLLC, ++ BCM2835_CLK_SRC_PLLD, ++ BCM2835_CLK_SRC_HDMI, ++}; ++ ++/* Most clocks are not useable (freq = 0) */ ++static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { ++ [BCM2835_CLK_SRC_GND] = 0, ++ [BCM2835_CLK_SRC_OSC] = 19200000, ++ [BCM2835_CLK_SRC_DBG0] = 0, ++ [BCM2835_CLK_SRC_DBG1] = 0, ++ [BCM2835_CLK_SRC_PLLA] = 0, ++ [BCM2835_CLK_SRC_PLLC] = 0, ++ [BCM2835_CLK_SRC_PLLD] = 500000000, ++ [BCM2835_CLK_SRC_HDMI] = 0, ++}; ++ + /* I2S registers */ + #define BCM2835_I2S_CS_A_REG 0x00 + #define BCM2835_I2S_FIFO_A_REG 0x04 +@@ -110,6 +158,10 @@ + #define BCM2835_I2S_INT_RXR BIT(1) + #define BCM2835_I2S_INT_TXW BIT(0) + ++/* I2S DMA interface */ ++/* FIXME: Needs IOMMU support */ ++#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) ++ + /* General device struct */ + struct bcm2835_i2s_dev { + struct device *dev; +@@ -117,23 +169,21 @@ struct bcm2835_i2s_dev { + unsigned int fmt; + unsigned int bclk_ratio; + +- struct regmap *i2s_regmap; +- struct clk *clk; +- bool clk_prepared; ++ struct regmap *i2s_regmap; ++ struct regmap *clk_regmap; + }; + + static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) + { ++ /* Start the clock if in master mode */ + unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; + +- if (dev->clk_prepared) +- return; +- + switch (master) { + case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBS_CFM: +- clk_prepare_enable(dev->clk); +- dev->clk_prepared = true; ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); + break; + default: + break; +@@ -142,9 +192,28 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) + + static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) + { +- if (dev->clk_prepared) +- clk_disable_unprepare(dev->clk); +- dev->clk_prepared = false; ++ uint32_t clkreg; ++ int timeout = 1000; ++ ++ /* Stop clock */ ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD); ++ ++ /* Wait for the BUSY flag going down */ ++ while (--timeout) { ++ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); ++ if (!(clkreg & BCM2835_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, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, ++ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); ++ } } -@@ -50,30 +90,39 @@ static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = { - .codec_dai_name = "wm8731-hifi", - .platform_name = "bcm2835-i2s.0", - .codec_name = "wm8731.1-001a", -+ .ops = &snd_audioinjector_pi_soundcard_ops, - .init = audioinjector_pi_soundcard_dai_init, - .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, + static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, +@@ -154,7 +223,8 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + uint32_t syncval; + uint32_t csreg; + uint32_t i2s_active_state; +- bool clk_was_prepared; ++ uint32_t clkreg; ++ uint32_t clk_active_state; + uint32_t off; + uint32_t clr; + +@@ -168,10 +238,15 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); + i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); + ++ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); ++ clk_active_state = clkreg & BCM2835_CLK_ENAB; ++ + /* Start clock if not running */ +- clk_was_prepared = dev->clk_prepared; +- if (!clk_was_prepared) +- bcm2835_i2s_start_clock(dev); ++ if (!clk_active_state) { ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); ++ } + + /* Stop I2S module */ + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); +@@ -205,7 +280,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + dev_err(dev->dev, "I2S SYNC error!\n"); + + /* Stop clock if it was not running before */ +- if (!clk_was_prepared) ++ if (!clk_active_state) + bcm2835_i2s_stop_clock(dev); + + /* Restore I2S state */ +@@ -234,9 +309,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct bcm2835_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 = BCM2835_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; + + /* +@@ -258,9 +343,11 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + 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; +@@ -269,12 +356,69 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* If bclk_ratio already set, use that one. */ + if (dev->bclk_ratio) + bclk_ratio = dev->bclk_ratio; +- else +- /* otherwise calculate a fitting block ratio */ +- bclk_ratio = 2 * data_length; + +- /* set target clock rate*/ +- clk_set_rate(dev->clk, sampling_rate * 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 = BCM2835_CLK_SRC_OSC; ++ mash = BCM2835_CLK_MASH_0; ++ ++ if (bcm2835_clk_freq[clk_src] % target_frequency == 0 ++ && bit_master && frame_master) { ++ divi = bcm2835_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 = BCM2835_CLK_SRC_PLLD; ++ mash = BCM2835_CLK_MASH_1; ++ ++ dividend = bcm2835_clk_freq[clk_src]; ++ dividend <<= BCM2835_CLK_SHIFT; ++ do_div(dividend, target_frequency); ++ divi = dividend >> BCM2835_CLK_SHIFT; ++ divf = dividend & BCM2835_CLK_DIVF_MASK; ++ } ++ ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD ++ | BCM2835_CLK_DIVI(divi) ++ | BCM2835_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD ++ | BCM2835_CLK_MASH(mash) ++ | BCM2835_CLK_SRC(clk_src)); + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; +@@ -548,7 +692,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { + .trigger = bcm2835_i2s_trigger, + .hw_params = bcm2835_i2s_hw_params, + .set_fmt = bcm2835_i2s_set_dai_fmt, +- .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, ++ .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio + }; + + static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) +@@ -606,14 +750,34 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) + }; + } + +-static const struct regmap_config bcm2835_regmap_config = { +- .reg_bits = 32, +- .reg_stride = 4, +- .val_bits = 32, +- .max_register = BCM2835_I2S_GRAY_REG, +- .precious_reg = bcm2835_i2s_precious_reg, +- .volatile_reg = bcm2835_i2s_volatile_reg, +- .cache_type = REGCACHE_RBTREE, ++static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2835_CLK_PCMCTL_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static const struct regmap_config bcm2835_regmap_config[] = { ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2835_I2S_GRAY_REG, ++ .precious_reg = bcm2835_i2s_precious_reg, ++ .volatile_reg = bcm2835_i2s_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ }, ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2835_CLK_PCMDIV_REG, ++ .volatile_reg = bcm2835_clk_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ }, + }; + + static const struct snd_soc_component_driver bcm2835_i2s_component = { +@@ -623,50 +787,42 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + static int bcm2835_i2s_probe(struct platform_device *pdev) + { + struct bcm2835_i2s_dev *dev; ++ int i; + int ret; +- struct resource *mem; +- void __iomem *base; +- const __be32 *addr; +- dma_addr_t dma_base; ++ 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, ++ &bcm2835_regmap_config[i]); ++ if (IS_ERR(regmap[i])) ++ return PTR_ERR(regmap[i]); ++ } + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), + GFP_KERNEL); + if (!dev) + return -ENOMEM; + +- /* get the clock */ +- dev->clk_prepared = false; +- dev->clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(dev->clk)) { +- dev_err(&pdev->dev, "could not get clk: %ld\n", +- PTR_ERR(dev->clk)); +- return PTR_ERR(dev->clk); +- } +- +- /* Request ioarea */ +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- base = devm_ioremap_resource(&pdev->dev, mem); +- if (IS_ERR(base)) +- return PTR_ERR(base); +- +- dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base, +- &bcm2835_regmap_config); +- if (IS_ERR(dev->i2s_regmap)) +- return PTR_ERR(dev->i2s_regmap); +- +- /* Set the DMA address - we have to parse DT ourselves */ +- addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); +- if (!addr) { +- dev_err(&pdev->dev, "could not get DMA-register address\n"); +- return -EINVAL; +- } +- dma_base = be32_to_cpup(addr); ++ dev->i2s_regmap = regmap[0]; ++ dev->clk_regmap = regmap[1]; + ++ /* Set the DMA address */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = +- dma_base + BCM2835_I2S_FIFO_A_REG; ++ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG ++ + BCM2835_VCMMU_SHIFT; + + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = +- dma_base + BCM2835_I2S_FIFO_A_REG; ++ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG ++ + BCM2835_VCMMU_SHIFT; + + /* Set the bus width */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = + +From 6177fc8dc11d1e50040c306c0171b7c42bde4bbf Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 16:44:05 +0200 +Subject: [PATCH 087/111] bcm2835-i2s: get base address for DMA from devicetree + +Code copied from spi-bcm2835. Get physical address from devicetree +instead of using hardcoded constant. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 3303d5f58082f68b68b535b2bdf7ce8d14cafcc4..0f25db4cd198c0a511e8a205b0cb2be62ba94adf 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { + #define BCM2835_I2S_INT_RXR BIT(1) + #define BCM2835_I2S_INT_TXW BIT(0) + +-/* I2S DMA interface */ +-/* FIXME: Needs IOMMU support */ +-#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) +- + /* General device struct */ + struct bcm2835_i2s_dev { + struct device *dev; +@@ -791,6 +788,15 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + int ret; + struct regmap *regmap[2]; + struct resource *mem[2]; ++ const __be32 *addr; ++ dma_addr_t dma_reg_base; ++ ++ addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); ++ if (!addr) { ++ dev_err(&pdev->dev, "could not get DMA-register address\n"); ++ return -ENODEV; ++ } ++ dma_reg_base = be32_to_cpup(addr); + + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { +@@ -817,12 +823,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + + /* Set the DMA address */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = +- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG +- + BCM2835_VCMMU_SHIFT; ++ dma_reg_base + BCM2835_I2S_FIFO_A_REG; + + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = +- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG +- + BCM2835_VCMMU_SHIFT; ++ dma_reg_base + BCM2835_I2S_FIFO_A_REG; + + /* Set the bus width */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = + +From e985f4747dd5ff6f91e500c50c2de8a9457f583d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:21:16 +0200 +Subject: [PATCH 088/111] bcm2835-i2s: add 24bit support, update bclk_ratio to + more correct values + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit 62c05a0b5328d9376d39c9e74da10b8a2465c234 ("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 + +RPi commit 3e8c672bc4e92d457aa4654bbb4cfd79a18a2327 ("bcm2708-i2s: +Update bclk_ratio to more correct values") + +Discussion about blck_ratio affecting sound quality: +https://github.com/raspberrypi/linux/issues/681 + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 0f25db4cd198c0a511e8a205b0cb2be62ba94adf..0f35d7c0f4026bb50a7223461b907b9797bd9a05 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -340,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + data_length = 16; +- bclk_ratio = 40; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ data_length = 24; ++ bclk_ratio = 50; + break; + case SNDRV_PCM_FORMAT_S32_LE: + data_length = 32; +- bclk_ratio = 80; ++ bclk_ratio = 100; + break; + default: + return -EINVAL; +@@ -420,7 +424,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +- if (data_length > 24) ++ if (data_length >= 24) + format |= BCM2835_I2S_CHWEX; + + format |= BCM2835_I2S_CHWID((data_length-8)&0xf); +@@ -711,6 +715,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { +@@ -718,6 +723,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, + +From ab780704d0a48a2d76dcfaca85e980fd0e3f4adc Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:25:51 +0200 +Subject: [PATCH 089/111] bcm2835-i2s: setup clock only if CPU is clock master + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit c14827ecdaa36607f6110f9ce8df96e698672191 ("bcm2708: Allow +option card devices to be configured via DT") + +Original work by Zoltan Szenczi, committed to RPi tree by +Phil Elwell. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 0f35d7c0f4026bb50a7223461b907b9797bd9a05..d5e412302811ed8b007fc53f0aa2b5ddd12774b6 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -411,15 +411,25 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + divf = dividend & BCM2835_CLK_DIVF_MASK; + } + +- /* Set clock divider */ +- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD +- | BCM2835_CLK_DIVI(divi) +- | BCM2835_CLK_DIVF(divf)); +- +- /* Setup clock, but don't start it yet */ +- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD +- | BCM2835_CLK_MASH(mash) +- | BCM2835_CLK_SRC(clk_src)); ++ /* Clock should only be set up here if CPU is clock master */ ++ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, ++ BCM2835_CLK_PASSWD ++ | BCM2835_CLK_DIVI(divi) ++ | BCM2835_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD ++ | BCM2835_CLK_MASH(mash) ++ | BCM2835_CLK_SRC(clk_src)); ++ break; ++ default: ++ break; ++ } + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +From dd3eeab4f8eea34bceb8b247fb502e86f4f20fdb Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:49:51 +0200 +Subject: [PATCH 090/111] bcm2835-i2s: Eliminate debugfs directory error + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit fd7d7a3dbe9262d16971ef81c234ed28c6499dd7 ("bcm2708: +Eliminate i2s debugfs directory error") + +Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') +to avoid the name clash when registering debugfs entries. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index d5e412302811ed8b007fc53f0aa2b5ddd12774b6..2d29050e739b0af02d0f5122d18178b61c024bea 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -782,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { + .precious_reg = bcm2835_i2s_precious_reg, + .volatile_reg = bcm2835_i2s_volatile_reg, + .cache_type = REGCACHE_RBTREE, ++ .name = "i2s", + }, + { + .reg_bits = 32, +@@ -790,6 +791,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { + .max_register = BCM2835_CLK_PCMDIV_REG, + .volatile_reg = bcm2835_clk_volatile_reg, + .cache_type = REGCACHE_RBTREE, ++ .name = "clk", }, }; - static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { -+ SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_LINE("Line In Jacks", NULL), -+ SND_SOC_DAPM_MIC("Microphone", NULL), - }; - --/* Corgi machine connections to the codec pins */ - static const struct snd_soc_dapm_route audioinjector_audio_map[] = { -+ /* headphone connected to LHPOUT, RHPOUT */ -+ {"Headphone Jack", NULL, "LHPOUT"}, -+ {"Headphone Jack", NULL, "RHPOUT"}, -+ - /* speaker connected to LOUT, ROUT */ - {"Ext Spk", NULL, "ROUT"}, - {"Ext Spk", NULL, "LOUT"}, - - /* line inputs */ - {"Line In Jacks", NULL, "Line Input"}, -+ -+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ -+ {"Microphone", NULL, "Mic Bias"}, - }; - - static struct snd_soc_card snd_soc_audioinjector = { - .name = "audioinjector-pi-soundcard", - .dai_link = audioinjector_pi_soundcard_dai, -- .num_links = 1, -+ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), - - .dapm_widgets = wm8731_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), -From ea1af76f40687d058949b6f06eb174425a99e275 Mon Sep 17 00:00:00 2001 -From: Thomas Kriechbaumer -Date: Fri, 3 Jun 2016 09:40:44 +0200 -Subject: [PATCH 139/141] BCM270X_DT: Add spi-rtc overlay on SPI0.0 +From e59331ce7f065c28e1a50831c8546a96deb5d05d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:35:20 +0200 +Subject: [PATCH 091/111] bcm2835-i2s: Register PCM device -Initial version only supports PCF2123 RTC. +Code ported from bcm2708-i2s driver in Raspberry Pi tree. -See: https://github.com/raspberrypi/linux/pull/1510 +RPi commit ba46b4935a23aa2caac1855ead52a035d4776680 ("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 + +Signed-off-by: Matthias Reichl --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 +++++ - arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 ++++++++++++++++++++++++++ - 3 files changed, 40 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/spi-rtc-overlay.dts + sound/soc/bcm/bcm2835-i2s.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index ed62846e18e4d3098169f05a1a8ba16caf1619aa..988884db1861a6f1b032e8e88d812e9721e75d26 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -77,6 +77,7 @@ dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 628cff3fc60a13b26b3f2f572573884df480c7bf..f105bbc3d55caacfedc346699d96cbc6bc611fce 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -953,6 +953,12 @@ Load: dtoverlay=spi-gpio35-39 - Params: +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 2d29050e739b0af02d0f5122d18178b61c024bea..ce93ef0579ab142c788736f0d309c92636b8983d 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -799,6 +799,25 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + .name = "bcm2835-i2s-comp", + }; - -+Name: spi-rtc -+Info: Adds support for a number of SPI Real Time Clock devices -+Load: dtoverlay=spi-rtc,= -+Params: pcf2123 Select the PCF2123 device -+ -+ - Name: spi1-1cs - Info: Enables spi1 with a single chip select (CS) line and associated spidev - dev node. The gpio pin number for the CS line and spidev device node -diff --git a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..88d1800d63c9f6727b46d4e590c8e96c671c3755 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts -@@ -0,0 +1,33 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spidev0>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spi0>; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ rtc-pcf2123@0 { -+ compatible = "nxp,rtc-pcf2123"; -+ spi-max-frequency = <5000000>; -+ spi-cs-high = <1>; -+ reg = <0>; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ pcf2123 = <0>, "=0=1"; -+ }; ++static const struct snd_pcm_hardware bcm2835_pcm_hardware = { ++ .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, ++ .periods_min = 2, ++ .periods_max = 255, ++ .buffer_bytes_max = 128 * PAGE_SIZE, +}; ++ ++static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &bcm2835_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ + static int bcm2835_i2s_probe(struct platform_device *pdev) + { + struct bcm2835_i2s_dev *dev; +@@ -870,7 +889,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + return ret; + } + +- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, ++ &bcm2835_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); + if (ret) { + dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); + return ret; -From a8f2756b03d610c3fd254452e4babef8f18a4eca Mon Sep 17 00:00:00 2001 +From 0eec3739078dcf418f6804e3df7012f8c87618dd Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:55:21 +0200 +Subject: [PATCH 092/111] bcm2835-i2s: Enable MMAP support via a DT property + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit 7ee829fd77a30127db5d0b3c7d79b8718166e568 ("bcm2708-i2s: +Enable MMAP support via a DT property and overlay") + +The i2s driver used to claim to support MMAP, but that feature was disabled +when some problems were found. Add the ability to enable this feature +through Device Tree, using the i2s-mmap overlay. + +See: #1004 + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index ce93ef0579ab142c788736f0d309c92636b8983d..6f60c2cebb412524bb0e30d0339fe556680e8637 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -799,7 +799,7 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + .name = "bcm2835-i2s-comp", + }; + +-static const struct snd_pcm_hardware bcm2835_pcm_hardware = { ++static struct snd_pcm_hardware bcm2835_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX, + .formats = SNDRV_PCM_FMTBIT_S16_LE | +@@ -835,6 +835,11 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + } + dma_reg_base = be32_to_cpup(addr); + ++ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) ++ bcm2835_pcm_hardware.info |= ++ SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID; ++ + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { + void __iomem *base; + +From 5213ee508a24ff0c66e142ffe1fc5a000630dd0e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 21 Apr 2016 15:44:14 +0100 +Subject: [PATCH 093/111] bcm2835-i2s: Reduce the TX DREQ threshold + +TX FIFO overrun is thought to be the cause of channel swapping, so +reducing the DREQ threshold seems reasonable and appears to be +effective. + +See: https://github.com/raspberrypi/linux/issues/1417 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/bcm2835-i2s.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 6f60c2cebb412524bb0e30d0339fe556680e8637..b26f9587dec01d62606df3f47b3ef00c908fa05b 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -555,15 +555,22 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + + /* Setup the DMA parameters */ + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, +- BCM2835_I2S_RXTHR(1) +- | BCM2835_I2S_TXTHR(1) +- | BCM2835_I2S_DMAEN, 0xffffffff); ++ BCM2835_I2S_RXTHR(3) ++ | BCM2835_I2S_TXTHR(3) ++ | BCM2835_I2S_DMAEN, ++ BCM2835_I2S_RXTHR(1) ++ | BCM2835_I2S_TXTHR(1) ++ | BCM2835_I2S_DMAEN); + + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, +- BCM2835_I2S_TX_PANIC(0x10) +- | BCM2835_I2S_RX_PANIC(0x30) +- | BCM2835_I2S_TX(0x30) +- | BCM2835_I2S_RX(0x20), 0xffffffff); ++ BCM2835_I2S_TX_PANIC(0x7f) ++ | BCM2835_I2S_RX_PANIC(0x7f) ++ | BCM2835_I2S_TX(0x7f) ++ | BCM2835_I2S_RX(0x7f), ++ BCM2835_I2S_TX_PANIC(0x10) ++ | BCM2835_I2S_RX_PANIC(0x30) ++ | BCM2835_I2S_TX(0x20) ++ | BCM2835_I2S_RX(0x20)); + + /* Clear FIFOs */ + bcm2835_i2s_clear_fifos(dev, true, true); + +From 1653c95a0b5cd0bc5e215e74472b1d46cc55735c Mon Sep 17 00:00:00 2001 +From: P33M +Date: Wed, 21 Oct 2015 14:55:21 +0100 +Subject: [PATCH 094/111] rpi_display: add backlight driver and overlay + +Add a mailbox-driven backlight controller for the Raspberry Pi DSI +touchscreen display. Requires updated GPU firmware to recognise the +mailbox request. + +Signed-off-by: Gordon Hollingworth +--- + drivers/video/backlight/Kconfig | 6 ++ + drivers/video/backlight/Makefile | 1 + + drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 drivers/video/backlight/rpi_backlight.c + +diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig +index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -265,6 +265,12 @@ config BACKLIGHT_PWM + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + ++config BACKLIGHT_RPI ++ tristate "Raspberry Pi display firmware driven backlight" ++ help ++ If you have the Raspberry Pi DSI touchscreen display, say Y to ++ enable the mailbox-controlled backlight driver. ++ + config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X +diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile +index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o + obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o + obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o ++obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o + obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o + obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o + obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c +new file mode 100644 +index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad +--- /dev/null ++++ b/drivers/video/backlight/rpi_backlight.c +@@ -0,0 +1,119 @@ ++/* ++ * rpi_bl.c - Backlight controller through VPU ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ struct rpi_firmware *fw; ++}; ++ ++static int rpi_backlight_update_status(struct backlight_device *bl) ++{ ++ struct rpi_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness; ++ int ret; ++ ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; ++ ++ ret = rpi_firmware_property(gbl->fw, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, ++ &brightness, sizeof(brightness)); ++ if (ret) { ++ dev_err(gbl->dev, "Failed to set brightness\n"); ++ return ret; ++ } ++ ++ if (brightness < 0) { ++ dev_err(gbl->dev, "Backlight change failed\n"); ++ return -EAGAIN; ++ } ++ ++ return 0; ++} ++ ++static const struct backlight_ops rpi_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = rpi_backlight_update_status, ++}; ++ ++static int rpi_backlight_probe(struct platform_device *pdev) ++{ ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct rpi_backlight *gbl; ++ struct device_node *fw_node; ++ ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; ++ ++ gbl->dev = &pdev->dev; ++ ++ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ if (!fw_node) { ++ dev_err(&pdev->dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ gbl->fw = rpi_firmware_get(fw_node); ++ if (!gbl->fw) ++ return -EPROBE_DEFER; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = 255; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &rpi_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ bl->props.brightness = 255; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ return 0; ++} ++ ++static const struct of_device_id rpi_backlight_of_match[] = { ++ { .compatible = "raspberrypi,rpi-backlight" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); ++ ++static struct platform_driver rpi_backlight_driver = { ++ .driver = { ++ .name = "rpi-backlight", ++ .of_match_table = of_match_ptr(rpi_backlight_of_match), ++ }, ++ .probe = rpi_backlight_probe, ++}; ++ ++module_platform_driver(rpi_backlight_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth "); ++MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); ++MODULE_LICENSE("GPL"); + +From 81774f735f07a2f7d11977c9fab867ed9911df18 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Feb 2016 19:56:04 +0000 +Subject: [PATCH 095/111] bcm2835-virtgpio: Virtual GPIO driver + +Add a virtual GPIO driver that uses the firmware mailbox interface to +request that the VPU toggles LEDs. +--- + drivers/gpio/Kconfig | 6 ++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 186 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-virt.c + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index d7860614f87f532caeb21145c78352d38161b2a3..05ca35a0b2c431c39e1b207f560e1b11f118e6fe 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -143,6 +143,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_BCM_VIRT ++ bool "Broadcom Virt GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) ++ help ++ Turn on virtual GPIO support for Broadcom BCM283X chips. ++ + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index 991598ea3fba09ee9e5724a11f41666d5a95f085..281648f98f5e65baa293719fd48e3f01e62926f0 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o + obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o + obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o ++obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-virt.c +@@ -0,0 +1,179 @@ ++/* ++ * brcmvirt GPIO driver ++ * ++ * Copyright (C) 2012,2013 Dom Cobley ++ * Based on gpio-clps711x.c by Alexander Shiyan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "brcmvirt-gpio" ++#define NUM_GPIO 2 ++ ++struct brcmvirt_gpio { ++ struct gpio_chip gc; ++ u32 __iomem *ts_base; ++ /* two packed 16-bit counts of enabled and disables ++ Allows host to detect a brief enable that was missed */ ++ u32 enables_disables[NUM_GPIO]; ++}; ++ ++static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return -EINVAL; ++} ++ ++static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return 0; ++} ++ ++static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ unsigned v; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ v = readl(gpio->ts_base + off); ++ return (v >> off) & 1; ++} ++ ++static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ u16 enables, disables; ++ s16 diff; ++ bool lit; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ enables = gpio->enables_disables[off] >> 16; ++ disables = gpio->enables_disables[off] >> 0; ++ diff = (s16)(enables - disables); ++ lit = diff > 0; ++ if ((val && lit) || (!val && !lit)) ++ return; ++ if (val) ++ enables++; ++ else ++ disables++; ++ diff = (s16)(enables - disables); ++ BUG_ON(diff != 0 && diff != 1); ++ gpio->enables_disables[off] = (enables << 16) | (disables << 0); ++ writel(gpio->enables_disables[off], gpio->ts_base + off); ++} ++ ++static int brcmvirt_gpio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmvirt_gpio *ucb; ++ u32 gpiovirtbuf; ++ int err = 0; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, ++ &gpiovirtbuf, sizeof(gpiovirtbuf)); ++ ++ if (err) { ++ dev_err(dev, "Failed to get gpiovirtbuf\n"); ++ goto err; ++ } ++ ++ if (!gpiovirtbuf) { ++ dev_err(dev, "No virtgpio buffer\n"); ++ err = -ENOENT; ++ goto err; ++ } ++ ++ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); ++ if (!ucb) { ++ err = -EINVAL; ++ goto err; ++ } ++ ++ // mmap the physical memory ++ gpiovirtbuf &= ~0xc0000000; ++ ucb->ts_base = ioremap(gpiovirtbuf, 4096); ++ if (ucb->ts_base == NULL) { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOENT; ++ goto err; ++ } ++ ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ //ucb->gc.dev = dev; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 100; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmvirt_gpio_dir_in; ++ ucb->gc.direction_output = brcmvirt_gpio_dir_out; ++ ucb->gc.get = brcmvirt_gpio_get; ++ ucb->gc.set = brcmvirt_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ goto err; ++ ++ platform_set_drvdata(pdev, ucb); ++ ++err: ++ return err; ++ ++} ++ ++static int brcmvirt_gpio_remove(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); ++ iounmap(ucb->ts_base); ++ return err; ++} ++ ++static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-virtgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); ++ ++static struct platform_driver brcmvirt_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), ++ }, ++ .probe = brcmvirt_gpio_probe, ++ .remove = brcmvirt_gpio_remove, ++}; ++module_platform_driver(brcmvirt_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dom Cobley "); ++MODULE_DESCRIPTION("brcmvirt GPIO driver"); ++MODULE_ALIAS("platform:brcmvirt-gpio"); + +From 064af96e705f3ff93567cac0465bf928bf33ae41 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 4 Mar 2016 12:49:09 +0000 +Subject: [PATCH 096/111] DRM_VC4: Allow to be built for ARCH_BCM270x + +--- + drivers/gpu/drm/vc4/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig +index e53df59cb139f25f8e6ae916bca93abf0c49e063..f6e938208b73512f20eab46a383ca91bf675a845 100644 +--- a/drivers/gpu/drm/vc4/Kconfig ++++ b/drivers/gpu/drm/vc4/Kconfig +@@ -1,6 +1,6 @@ + config DRM_VC4 + tristate "Broadcom VC4 Graphics" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on DRM + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + +From 4b2c5bb334b191e1aa5b7b96c298e743c3e3cf37 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 23 Feb 2016 17:26:48 +0000 +Subject: [PATCH 097/111] amba_pl011: Don't use DT aliases for numbering + +The pl011 driver looks for DT aliases of the form "serial", +and if found uses as the device ID. This can cause +/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the +other serial port is provided by the 8250 driver which doesn't +use the same logic. +--- + drivers/tty/serial/amba-pl011.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 1b7331e40d795e1ec5482d6a82871bd5ce050b60..a04d27ef682792808301ac2d2bfb67d5802fd7e3 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2414,7 +2414,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, + if (IS_ERR(base)) + return PTR_ERR(base); + ++ /* Don't use DT serial aliases - it causes the device to ++ be renumbered to ttyAMA1 if it is the second serial port in the ++ system, even though the other one is ttyS0. The 8250 driver ++ doesn't use this logic, so always remains ttyS0. + index = pl011_probe_dt_alias(index, dev); ++ */ + + uap->old_cr = 0; + uap->port.dev = dev; + +From 082aed07db3aa644e700e6356da328303db9bba2 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 3 Dec 2014 13:23:28 +0200 +Subject: [PATCH 098/111] OF: DT-Overlay configfs interface + +This is a port of Pantelis Antoniou's v3 port that makes use of the +new upstreamed configfs support for binary attributes. + +Original commit message: + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Originally-signed-off-by: Pantelis Antoniou +Signed-off-by: Phil Elwell + +DT configfs: Fix build errors on other platforms + +Signed-off-by: Phil Elwell + +DT configfs: fix build error + +There is an error when compiling rpi-4.6.y branch: + CC drivers/of/configfs.o +drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] + .default_groups = of_cfs_def_groups, + ^ +drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') + +The .default_groups is linked list since commit +1ae1602de028acaa42a0f6ff18d19756f8e825c6. +This commit uses configfs_add_default_group to fix this problem. + +Signed-off-by: Slawomir Stepien +--- + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 7 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 311 +++++++++++++++++++++++++ + 4 files changed, 350 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c + +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt +new file mode 100644 +index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad +--- /dev/null ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. ++ ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. ++ ++* To create an overlay you mkdir the directory: ++ ++ # mkdir /config/device-tree/overlays/foo ++ ++* Either you echo the overlay firmware file to the path property file. ++ ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path ++ ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index b3bec3aaa45d8a34dd206593fec0c13271034b07..4d9a6ba4c8bed537b41a4ff80600c89d775a1e29 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -115,4 +115,11 @@ config OF_OVERLAY + config OF_NUMA + bool + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,311 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; ++}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ configfs_add_default_group(&of_cfs_overlay_group, ++ &of_cfs_subsys.su_group); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); + +From 68e731d04d752b18a9ea4390ad44877db907a15e Mon Sep 17 00:00:00 2001 +From: Cheong2K +Date: Fri, 26 Feb 2016 18:20:10 +0800 +Subject: [PATCH 099/111] brcm: adds support for BCM43341 wifi + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 67e69bff2545f442c95d80726cbe6ed16584e80d..ea66454a3d7444f51827964aea01bf7573f2b473 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -603,6 +603,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); ++BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); +@@ -620,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 699f2c2782ee9d898a25c95e0c5d45744d0777ff..15598b3687a213d8c00d45965a6b9351759f47fc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -35,6 +35,7 @@ + #define BRCM_CC_4330_CHIP_ID 0x4330 + #define BRCM_CC_4334_CHIP_ID 0x4334 + #define BRCM_CC_43340_CHIP_ID 43340 ++#define BRCM_CC_43341_CHIP_ID 43341 + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 + +From f73574193c7e04c75ce884a9846af4ebbda4fa6f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 9 Mar 2016 17:25:59 +0000 +Subject: [PATCH 100/111] brcmfmac: Disable power management + +Disable wireless power saving in the brcmfmac WLAN driver. This is a +temporary measure until the connectivity loss resulting from power +saving is resolved. + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 62f475e31077ca1fa1df15863f02ee0911c46997..d001128266f462beee5f9672c64ed2c0d9200334 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2699,6 +2699,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ ++ pr_info("power management disabled\n"); ++ enabled = false; + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { + + +From 089cba52a9de814bc56c71d41d4e8bc8a3b6d54e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 28 Apr 2016 17:13:47 +0100 +Subject: [PATCH 101/111] brcmfmac: Use original country code as a fallback + +Commit 73345fd212980d2e28a5c6d83801c903bd773680: + + brcmfmac: Configure country code using device specific settings + +prevents region codes from working on devices that lack a region code +translation table. In the event of an absent table, preserve the old +behaviour of using the provided code as-is. + +Signed-off-by: Phil Elwell +--- + .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index d001128266f462beee5f9672c64ed2c0d9200334..90eb79cc104427597046f2459e6f46de09702784 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6597,12 +6597,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + struct brcmfmac_pd_cc *country_codes; + struct brcmfmac_pd_cc_entry *cc; + s32 found_index; ++ char ccode[BRCMF_COUNTRY_BUF_SZ]; ++ int rev; + int i; + ++ memcpy(ccode, alpha2, sizeof(ccode)); ++ rev = -1; ++ + country_codes = drvr->settings->country_codes; + if (!country_codes) { +- brcmf_dbg(TRACE, "No country codes configured for device\n"); +- return -EINVAL; ++ brcmf_dbg(TRACE, "No country codes configured for device" ++ " - use requested value\n"); ++ goto use_input_value; + } + + if ((alpha2[0] == ccreq->country_abbrev[0]) && +@@ -6626,10 +6632,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + brcmf_dbg(TRACE, "No country code match found\n"); + return -EINVAL; + } +- memset(ccreq, 0, sizeof(*ccreq)); +- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); +- memcpy(ccreq->ccode, country_codes->table[found_index].cc, ++ rev = country_codes->table[found_index].rev; ++ memcpy(ccode, country_codes->table[found_index].cc, + BRCMF_COUNTRY_BUF_SZ); ++ ++use_input_value: ++ memset(ccreq, 0, sizeof(*ccreq)); ++ ccreq->rev = cpu_to_le32(rev); ++ memcpy(ccreq->ccode, ccode, sizeof(ccode)); + ccreq->country_abbrev[0] = alpha2[0]; + ccreq->country_abbrev[1] = alpha2[1]; + ccreq->country_abbrev[2] = 0; + +From 3a98d12b8d4ca8989dfb0ef12bd866251b5bc592 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 May 2016 15:36:09 +0100 +Subject: [PATCH 102/111] brcmfmac: Plug memory leak in brcmf_fill_bss_param + +See: https://github.com/raspberrypi/linux/issues/1471 + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 90eb79cc104427597046f2459e6f46de09702784..27a59a9f7b9c108e728bdc7fc8d95139daec03fc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2473,7 +2473,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) + WL_BSS_INFO_MAX); + if (err) { + brcmf_err("Failed to get bss info (%d)\n", err); +- return; ++ goto out_err; + } + si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); + si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); +@@ -2485,6 +2485,9 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; ++ ++out_err: ++ kfree(buf); + } + + static s32 + +From 7162955f6e9b7b838a3bf8bbe681f819024cecd7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 17 Dec 2015 13:37:07 +0000 +Subject: [PATCH 103/111] hci_h5: Don't send conf_req when ACTIVE + +Without this patch, a modem and kernel can continuously bombard each +other with conf_req and conf_rsp messages, in a demented game of tag. +--- + drivers/bluetooth/hci_h5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) + h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_req, 2) == 0) { + h5_link_control(hu, conf_rsp, 2); +- h5_link_control(hu, conf_req, 3); ++ if (h5->state != H5_ACTIVE) ++ h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_rsp, 2) == 0) { + if (H5_HDR_LEN(hdr) > 2) + h5->tx_win = (data[2] & 0x07); + +From 081af7570d4772f38c75f3ecb6b851a0615b8c61 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Fri, 22 Jan 2016 13:06:39 -0800 +Subject: [PATCH 104/111] drm/vc4: Add a debugfs node for tracking execution + state. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_gem.c | 14 ++++++++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c +index 245115d49c46a1244ef3e460a03fde397f763de8..94f2154c3685255e2e67d225f77dea372eae371a 100644 +--- a/drivers/gpu/drm/vc4/vc4_debugfs.c ++++ b/drivers/gpu/drm/vc4/vc4_debugfs.c +@@ -18,6 +18,7 @@ + static const struct drm_info_list vc4_debugfs_list[] = { + {"bo_stats", vc4_bo_stats_debugfs, 0}, + {"dpi_regs", vc4_dpi_debugfs_regs, 0}, ++ {"gem_exec", vc4_gem_exec_debugfs, 0}, + {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, + {"hvs_regs", vc4_hvs_debugfs_regs, 0}, + {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index 37cac59401d734e047f4cf41cc6a9ecb5bfc6dbc..4a44e727369fe0dd4e2b421ce139e434cd71001e 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -445,6 +445,7 @@ void vc4_job_handle_completed(struct vc4_dev *vc4); + int vc4_queue_seqno_cb(struct drm_device *dev, + struct vc4_seqno_cb *cb, uint64_t seqno, + void (*func)(struct vc4_seqno_cb *cb)); ++int vc4_gem_exec_debugfs(struct seq_file *m, void *arg); + + /* vc4_hdmi.c */ + extern struct platform_driver vc4_hdmi_driver; +diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c +index 46899d6de6753c28c7ca6c721119a28d72792148..cbb1bc0b0db88f1c83ce3a630b2efe67a6995456 100644 +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -32,6 +32,20 @@ + #include "vc4_regs.h" + #include "vc4_trace.h" + ++#ifdef CONFIG_DEBUG_FS ++int vc4_gem_exec_debugfs(struct seq_file *m, void *unused) ++{ ++ struct drm_info_node *node = (struct drm_info_node *)m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ seq_printf(m, "Emitted seqno: 0x%016llx\n", vc4->emit_seqno); ++ seq_printf(m, "Finished seqno: 0x%016llx\n", vc4->finished_seqno); ++ ++ return 0; ++} ++#endif /* CONFIG_DEBUG_FS */ ++ + static void + vc4_queue_hangcheck(struct drm_device *dev) + { + +From 27166f5ae197a2c23959a7eff08adc65f64588ee Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 25 Jan 2016 13:03:33 -0800 +Subject: [PATCH 105/111] drm/vc4: Include vc4_drm.h in uapi in downstream + build. + +Signed-off-by: Eric Anholt +--- + include/uapi/drm/Kbuild | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild +index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 +--- a/include/uapi/drm/Kbuild ++++ b/include/uapi/drm/Kbuild +@@ -15,6 +15,7 @@ header-y += radeon_drm.h + header-y += savage_drm.h + header-y += sis_drm.h + header-y += tegra_drm.h ++header-y += vc4_drm.h + header-y += via_drm.h + header-y += vmwgfx_drm.h + header-y += msm_drm.h + +From 6546a741d421620b3f6ceaa3d205bc44f2664f31 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 30 Mar 2016 17:23:15 +0100 +Subject: [PATCH 106/111] cpufreq: Temporarily ignore io_is_busy=1 + +To speed testing of the new sdhost driver that adapts to changes in +core_freq, hack the on-demand governor to treat io_is_busy=1 as +io_is_busy=0. The io_is_busy feature can still be forced using +io_is_busy=2. + +Signed-off-by: Phil Elwell +--- + drivers/cpufreq/cpufreq_ondemand.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c +index 300163430516766d56b842d8d12dc33175eee66b..9ab7b40005cb7ddfafc3917dc874eea8bdd5ad04 100644 +--- a/drivers/cpufreq/cpufreq_ondemand.c ++++ b/drivers/cpufreq/cpufreq_ondemand.c +@@ -217,7 +217,12 @@ static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf, + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; +- dbs_data->io_is_busy = !!input; ++ // XXX temporary hack ++ if (input > 1) ++ input = 1; ++ else ++ input = 0; ++ dbs_data->io_is_busy = input; + + /* we need to re-evaluate prev_cpu_idle */ + gov_update_cpu_data(dbs_data); + +From b3b6562bdf13284b9a7d129bed5400853735dd0e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 14 Oct 2015 11:32:14 -0700 +Subject: [PATCH 107/111] drm/vc4: Force HDMI to connected. + +For some reason on the downstream tree, the HPD GPIO isn't working. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index fd2644d231ff867a4409840eba7f8234a4a1faba..ed9c5274d06a215331aee44da1f7214a0e1f6e28 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -166,6 +166,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + struct drm_device *dev = connector->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + ++ return connector_status_connected; ++ + if (vc4->hdmi->hpd_gpio) { + if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ + vc4->hdmi->hpd_active_low) + +From 2ab2541de11bd82a0f0a2e33c1da98cfba1cc268 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Tue, 19 Apr 2016 15:55:02 -0700 +Subject: [PATCH 108/111] ARM: bcm2708: Enable building power domain driver. + +Signed-off-by: Eric Anholt +--- + drivers/soc/bcm/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig +index 3066edea184d765a670ded0cead470597654abc1..e23518142ceac6651641cc30c327d60dded319d5 100644 +--- a/drivers/soc/bcm/Kconfig ++++ b/drivers/soc/bcm/Kconfig +@@ -1,6 +1,6 @@ + config RASPBERRYPI_POWER + bool "Raspberry Pi power domain driver" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on RASPBERRYPI_FIRMWARE=y + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM + +From 65dc3c63bb358171b0cff73177a563b2d5b22059 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 140/141] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 109/111] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -137031,42 +134677,75 @@ See: https://github.com/raspberrypi/linux/pull/1510 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c -index da27738b12428eaac52771cfc62261995d1aa58e..3164be24eba3c123ea8cc49f16d409ea1de9e605 100644 +index f22e060709e547528b29b747f796b45c445d23fa..76b7bd7d9d33a0dcefcdb5fe3e0df4ded087cb60 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c -@@ -475,3 +475,4 @@ MODULE_AUTHOR("Chris Verges "); +@@ -471,3 +471,4 @@ module_spi_driver(pcf2123_driver); + MODULE_AUTHOR("Chris Verges "); MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); MODULE_LICENSE("GPL"); - MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("spi:rtc-pcf2123"); -From 138aa92a761eb5d1c41460a167aef1b3c8282d97 Mon Sep 17 00:00:00 2001 +From fd34a5c7e7d87ead50d299aea015bd7483d88a7c Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Thu, 23 Jun 2016 16:37:46 +0100 -Subject: [PATCH 141/141] mmc: Apply ERASE_BROKEN quirks correctly +Date: Fri, 1 Jul 2016 22:09:24 +0100 +Subject: [PATCH 110/111] spi-bcm2835: Disable forced software CS + +Select software CS in bcm2708_common.dtsi, and disable the automatic +conversion in the driver to allow hardware CS to be re-enabled with an +overlay. + +See: https://github.com/raspberrypi/linux/issues/1547 Signed-off-by: Phil Elwell --- - drivers/mmc/card/block.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) + drivers/spi/spi-bcm2835.c | 2 ++ + 1 file changed, 2 insertions(+) -diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 9ce8676ff613f5e63503f8280afd6d73ce9dca60..e30060827dce0af390be65e4e170368652f27983 100644 ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -2543,12 +2543,9 @@ static const struct mmc_fixup blk_fixups[] = - * On some Kingston SD cards, multiple erases of less than 64 - * sectors can cause corruption. - */ -- MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -- MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -- MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2cef9121bf 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -707,6 +707,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) + return -EINVAL; + } - END_FIXUP - }; ++#if 0 + /* now translate native cs to GPIO */ + /* first look for chip select pins in the devices pin groups */ + for (pingroup_index = 0; +@@ -756,6 +757,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) + spi->chip_select, spi->cs_gpio, err); + return err; + } ++#endif + + return 0; + } + +From 3758f08ddbd97dd81fad915d20b11aa9e48bd769 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 25 Jul 2016 17:06:50 +0100 +Subject: [PATCH 111/111] iqaudio-dac: Compile fix - untested + +--- + sound/soc/bcm/iqaudio-dac.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +index 4e8e6dec14bcf4a1ff286c43742d4097249d6777..aa15bc4b49ca95edec905fddd8fd0a6d839ca627 100644 +--- a/sound/soc/bcm/iqaudio-dac.c ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -76,7 +76,11 @@ static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card) + static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) + { +- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ struct snd_soc_pcm_runtime *rtd; ++ struct snd_soc_dai *codec_dai; ++ ++ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name); ++ codec_dai = rtd->codec_dai; + + if (dapm->dev != codec_dai->dev) + return 0; diff --git a/projects/RPi2/patches/linux/linux-01-RPi_support.patch b/projects/RPi2/patches/linux/linux-01-RPi_support.patch index f14e5021b5..1320cee050 100644 --- a/projects/RPi2/patches/linux/linux-01-RPi_support.patch +++ b/projects/RPi2/patches/linux/linux-01-RPi_support.patch @@ -1,7 +1,7 @@ -From d7464704285e698d9fbe1d7fdd1aa8f0b0eb7421 Mon Sep 17 00:00:00 2001 +From 8e8a77fa775396b9d07c4c1706bafd847ac85015 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 27 Apr 2016 17:43:28 +0100 -Subject: [PATCH 001/141] Revert "SUNRPC: Make NFS swap work with multipath" +Subject: [PATCH 001/111] Revert "SUNRPC: Make NFS swap work with multipath" This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. --- @@ -9,10 +9,10 @@ This reverts commit 15001e5a7e1e207b6bd258cd8f187814cd15b6dc. 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c -index 7e0c9bf22df811475385496007cfac321e0422a5..06936855313fe14abac8af7929a7a35381886e9e 100644 +index 2808d550d2730ff8e36b6d8c072c65e1631064c4..b362c2f099941c1f3388507983ffbdd1b4cc1241 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c -@@ -2683,39 +2683,57 @@ void rpc_show_tasks(struct net *net) +@@ -2719,39 +2719,57 @@ void rpc_show_tasks(struct net *net) #endif #if IS_ENABLED(CONFIG_SUNRPC_SWAP) @@ -95,10 +95,10 @@ index 7e0c9bf22df811475385496007cfac321e0422a5..06936855313fe14abac8af7929a7a353 EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate); #endif /* CONFIG_SUNRPC_SWAP */ -From 6ef501bd1aea48c18efb9bb7675c483c21c37656 Mon Sep 17 00:00:00 2001 +From d826431779f00b7a0b267c720155e3fb70c9cd57 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 002/141] smsx95xx: fix crimes against truesize +Subject: [PATCH 002/111] smsx95xx: fix crimes against truesize smsc95xx is adjusting truesize when it shouldn't, and following a recent patch from Eric this is now triggering warnings. @@ -110,10 +110,10 @@ Signed-off-by: Steve Glendinning 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b233d7a0081 100644 +index dc989a8b5afbd62b07cd65a2fa5edde67d3cc5fb..116680e3089f16e1e3e9113a3b93e62cb78cc1bb 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -75,6 +75,10 @@ static bool turbo_mode = true; +@@ -80,6 +80,10 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -124,7 +124,7 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -1795,7 +1799,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1848,7 +1852,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(skb); skb_trim(skb, skb->len - 4); /* remove fcs */ @@ -134,7 +134,7 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 return 1; } -@@ -1813,7 +1818,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +@@ -1866,7 +1871,8 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (dev->net->features & NETIF_F_RXCSUM) smsc95xx_rx_csum_offload(ax_skb); skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */ @@ -145,21 +145,21 @@ index 2edc2bc6d1b9fb3201a5f4d564dffed93e30bddc..2ce8d2b7d35b6784b7d4faf85e765b23 usbnet_skb_return(dev, ax_skb); } -From 212ebeab1e1561b2b7964f04b55f0ca29fe925ea Mon Sep 17 00:00:00 2001 +From 46327b51faeab20854b57bc999cbdca10e5e1e56 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 17 Apr 2015 16:58:45 +0100 -Subject: [PATCH 003/141] smsc95xx: Disable turbo mode by default +Subject: [PATCH 003/111] smsc95xx: Disable turbo mode by default --- drivers/net/usb/smsc95xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 2ce8d2b7d35b6784b7d4faf85e765b233d7a0081..35ebf75d9949d945b7833ac8cb3c19083045fbd9 100644 +index 116680e3089f16e1e3e9113a3b93e62cb78cc1bb..aa4cb43dcd9ba83b042332bc15a4dce68affce28 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -71,7 +71,7 @@ struct smsc95xx_priv { - u8 suspend_flags; +@@ -76,7 +76,7 @@ struct smsc95xx_priv { + struct usbnet *dev; }; -static bool turbo_mode = true; @@ -168,10 +168,10 @@ index 2ce8d2b7d35b6784b7d4faf85e765b233d7a0081..35ebf75d9949d945b7833ac8cb3c1908 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); -From 580f083e3acc4172479b101a89e77e2ce2da4f58 Mon Sep 17 00:00:00 2001 +From acd55c74830d7bdaa13469b8363c6a607e1fc346 Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 004/141] add smsc95xx packetsize module_param +Subject: [PATCH 004/111] add smsc95xx packetsize module_param Signed-off-by: Sam Nazarko --- @@ -179,10 +179,10 @@ Signed-off-by: Sam Nazarko 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875769f7798 100644 +index aa4cb43dcd9ba83b042332bc15a4dce68affce28..889bdabd9dea6cebccc361aa4ac569d73681396b 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c -@@ -79,6 +79,10 @@ static bool truesize_mode = false; +@@ -84,6 +84,10 @@ static bool truesize_mode = false; module_param(truesize_mode, bool, 0644); MODULE_PARM_DESC(truesize_mode, "Report larger truesize value"); @@ -193,7 +193,7 @@ index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -960,13 +964,13 @@ static int smsc95xx_reset(struct usbnet *dev) +@@ -1005,13 +1009,13 @@ static int smsc95xx_reset(struct usbnet *dev) if (!turbo_mode) { burst_cap = 0; @@ -213,10 +213,10 @@ index 35ebf75d9949d945b7833ac8cb3c19083045fbd9..3cac3c9b276e4c76af92aa9b19451875 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 7dbc066e994a37e8eb495bf1e9aa857c2f1984e5 Mon Sep 17 00:00:00 2001 +From bd24d215fb9ec317bf643f453a3965560baf4ace Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 005/141] Allow mac address to be set in smsc95xx +Subject: [PATCH 005/111] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -224,7 +224,7 @@ Signed-off-by: popcornmix 1 file changed, 56 insertions(+) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c98fa635e6 100644 +index 889bdabd9dea6cebccc361aa4ac569d73681396b..d22a2324085fbf61fbd8920362bfc7b9f72bebe3 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -60,6 +60,7 @@ @@ -233,9 +233,9 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) +#define MAC_ADDR_LEN (6) - struct smsc95xx_priv { - u32 mac_cr; -@@ -83,6 +84,10 @@ static int packetsize = 0; + #define CARRIER_CHECK_DELAY (2 * HZ) + +@@ -88,6 +89,10 @@ static int packetsize = 0; module_param(packetsize, int, 0644); MODULE_PARM_DESC(packetsize, "Override the RX URB packet size"); @@ -246,7 +246,7 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { -@@ -772,6 +777,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +@@ -817,6 +822,53 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } @@ -300,7 +300,7 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 static void smsc95xx_init_mac_address(struct usbnet *dev) { const u8 *mac_addr; -@@ -793,6 +845,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) +@@ -838,6 +890,10 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } @@ -312,71 +312,10 @@ index 3cac3c9b276e4c76af92aa9b19451875769f7798..d9bdc74086f3d656a930375b6e0ea2c9 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From fe915d32402785e873d7eaed4d96a76016febefe Mon Sep 17 00:00:00 2001 -From: Nicolas Boullis -Date: Sun, 10 Apr 2016 13:23:05 +0200 -Subject: [PATCH 006/141] rtc: ds1307: ensure that any pending alarm is cleared - before a new alarm is enabled -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -If a previously-set alarm was disabled and then triggered, it may still -be pending when a new alarm is configured. - -Then, if the alarm is enabled before the pending alarm is cleared, then -an interrupt is immediately raised. - -Unfortunately, when the alarm is cleared and enabled during the same I²C -block write, the chip (at least the DS1339 I have) considers that the -alarm is enabled before it is cleared, and raises an interrupt. - -This patch ensures that the pending alarm is cleared before the alarm is -enabled. - -Signed-off-by: Nicolas Boullis -Signed-off-by: Alexandre Belloni ---- - drivers/rtc/rtc-ds1307.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index ecb7dbae9be9daa0ee96ede34a446a78e8e7debd..e94eb0952286300ec9847cddaf317476ddd05423 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -538,12 +538,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) - buf[5] = 0; - buf[6] = 0; - -- /* optionally enable ALARM1 */ -+ /* disable alarms */ - buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); -- if (t->enabled) { -- dev_dbg(dev, "alarm IRQ armed\n"); -- buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ -- } - buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); - - ret = ds1307->write_block_data(client, -@@ -553,6 +549,13 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) - return ret; - } - -+ /* optionally enable ALARM1 */ -+ if (t->enabled) { -+ dev_dbg(dev, "alarm IRQ armed\n"); -+ buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ -+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, buf[7]); -+ } -+ - return 0; - } - - -From 055f1b1bb388444df7b833fbfee65f916a7c563d Mon Sep 17 00:00:00 2001 +From e92d422ece30aa23fb14842d9debb6c2358002fc Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 9 Mar 2016 13:28:24 +0000 -Subject: [PATCH 007/141] serial: Take care starting a hung-up tty's port +Subject: [PATCH 006/111] serial: Take care starting a hung-up tty's port tty_port_hangup sets a port's tty field to NULL (holding the port lock), but uart_tx_stopped, called from __uart_start (with the port lock), @@ -391,10 +330,10 @@ Signed-off-by: Phil Elwell 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h -index cbfcf38e220def6070e3de57c56ce34f3536bd6c..96bc15aa5c2190287590dc32949d873289858e97 100644 +index a3d7c0d4a03e75016023184a5fea18c91d9d8dbc..d61b4167a03205f917448d0bd71a84d0e1891047 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h -@@ -403,7 +403,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); +@@ -406,7 +406,7 @@ int uart_resume_port(struct uart_driver *reg, struct uart_port *port); static inline int uart_tx_stopped(struct uart_port *port) { struct tty_struct *tty = port->state->port.tty; @@ -404,10 +343,10 @@ index cbfcf38e220def6070e3de57c56ce34f3536bd6c..96bc15aa5c2190287590dc32949d8732 return 0; } -From 03a2cc0edac61207b37b2bd89da0f3d60216aaf8 Mon Sep 17 00:00:00 2001 +From f3a47d492c05724f55956258fc0111a5917659b5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Jun 2014 13:42:01 +0100 -Subject: [PATCH 008/141] vmstat: Workaround for issue where dirty page count +Subject: [PATCH 007/111] vmstat: Workaround for issue where dirty page count goes negative See: @@ -418,10 +357,10 @@ http://www.spinics.net/lists/linux-mm/msg72236.html 1 file changed, 4 insertions(+) diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h -index 73fae8c4a5fb50d94b72f12bed28f98d170f5787..5dd127883ad1dee89dd72be4cccb2ffb069d3521 100644 +index d2da8e053210041bfcefb9e04b59d195880d2d0e..e3258dc35371ee6e528dc02ffc705570c2f555be 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h -@@ -220,7 +220,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) +@@ -222,7 +222,11 @@ static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) { atomic_long_dec(&zone->vm_stat[item]); @@ -434,10 +373,10 @@ index 73fae8c4a5fb50d94b72f12bed28f98d170f5787..5dd127883ad1dee89dd72be4cccb2ffb static inline void __inc_zone_page_state(struct page *page, -From 5c942d7f05053aa268bbdb55eae8a5ee6a5e99be Mon Sep 17 00:00:00 2001 +From e0a17406d94df8d5c79751f5e133120a7a59511f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 009/141] Protect __release_resource against resources without +Subject: [PATCH 008/111] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -465,10 +404,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From 5e8c5f982238dd72d4644df61f4f2140979e1fb4 Mon Sep 17 00:00:00 2001 +From f0cb6129d9a6fcb4bbc8ffddb25061635dda863d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 010/141] mm: Remove the PFN busy warning +Subject: [PATCH 009/111] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -480,10 +419,10 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 898fe3f909f91df712b34d52797e5aca384e418b..5a578b1e37f0e566f9ff930bdf13a4647085c514 100644 +index 8b3e1341b7544608cac4777a37bbd424432488e1..9dba743762508ea1cced150388afa38f7eb2878c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7101,8 +7101,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, +@@ -7452,8 +7452,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, /* Make sure the range is really isolated. */ if (test_pages_isolated(outer_start, end, false)) { @@ -493,10 +432,10 @@ index 898fe3f909f91df712b34d52797e5aca384e418b..5a578b1e37f0e566f9ff930bdf13a464 goto done; } -From f1498b3097cbe3783b462bd39f1b70d18400db87 Mon Sep 17 00:00:00 2001 +From 1d470f1c2c4269e41a6d00ac6ea1ecbed4691c46 Mon Sep 17 00:00:00 2001 From: Robert Tiemann Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 011/141] BCM2835_DT: Fix I2S register map +Subject: [PATCH 010/111] BCM2835_DT: Fix I2S register map --- Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- @@ -504,10 +443,10 @@ Subject: [PATCH 011/141] BCM2835_DT: Fix I2S register map 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -index 1396078d15ac625e737487bb242f79b330796951..2db8294474db47d8c199796d4d50a3a0a8a3cac5 100644 +index baf9b34d20bfb5b5493e0a69841362530c900a77..11c052acf65e74f032ae77bfd2749db860762b2d 100644 --- a/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt +++ b/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt -@@ -48,8 +48,8 @@ Example: +@@ -74,8 +74,8 @@ Example: bcm2835_i2s: i2s@7e203000 { compatible = "brcm,bcm2835-i2s"; @@ -534,10 +473,10 @@ index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554 dmas = <&dma 2>, <&dma 3>; -From 7a51654f93b5585198cc86ffd989975d8dc3779e Mon Sep 17 00:00:00 2001 +From bb8fde2aa103107b1a523b5dc06ac82157baeed3 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 012/141] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 011/111] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -552,7 +491,7 @@ though, so trap them early. 1 file changed, 1 insertion(+) diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c -index b6e950d4782a1e020acddb50705efb180fe758b3..bbb92c290448fcabcb468302dfa5762b44b60d4a 100644 +index 72ff1d5c5de67058f4ef22bb233c41b7c737d6e3..de3b3a37a63d00cc82ae4725b2fe8584c084c4dc 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c @@ -175,6 +175,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs) @@ -564,10 +503,10 @@ index b6e950d4782a1e020acddb50705efb180fe758b3..bbb92c290448fcabcb468302dfa5762b #endif } else if (stat) { -From af560bc2c4f7b65aa9b325422439e6daaa7b4789 Mon Sep 17 00:00:00 2001 +From bb1085ea18c518c017e8a2d816eb717901ca6a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 12 Jun 2015 19:01:05 +0200 -Subject: [PATCH 013/141] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 012/111] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -585,7 +524,7 @@ Acked-by: Stephen Warren 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig -index 7ef121472cdd4761d059ae9f3eaf26b04ac141a2..b1a5a7b68158c55317418ee87e1df0325f8e4482 100644 +index 68ab6412392a44b84f4519ff04d725a3505f9bcf..b2385da38949e08787b942e73ba287035b401986 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -143,6 +143,7 @@ config ARCH_BCM2835 @@ -696,10 +635,10 @@ index bf9cc5f2e839e845fe1ce65caa672b6212d3ffbc..3f601f98aa884b941fbb84edb349f6c4 } -From fcc8e585f59688079af11a79e8238670b4bb17d8 Mon Sep 17 00:00:00 2001 +From b63ae9dd6cb1f890f4e0b68ef441cb39f3dc6016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 23 Oct 2015 16:26:55 +0200 -Subject: [PATCH 014/141] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 013/111] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -795,10 +734,10 @@ index 3f601f98aa884b941fbb84edb349f6c469b940b1..20deb282286834b1f234a65e614b8584 for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From dab253783df6ebfb9d32eeac976f5a7493f1b968 Mon Sep 17 00:00:00 2001 +From d71ea2d5db8b7d9b36665cbe94b1e309353479f8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 015/141] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 014/111] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -819,17 +758,17 @@ index e3c19f30f591115a823467033702ff1b232c5ebc..f4963e3c1dbcd13edb9b97e9dad65438 }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From ecae09c78cf3e1fec1333cc482182044906889ce Mon Sep 17 00:00:00 2001 +From 141208db234695caa842b45a89581fa2e08c3f78 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 30 Jun 2015 14:12:42 +0100 -Subject: [PATCH 016/141] serial: 8250: Don't crash when nr_uarts is 0 +Subject: [PATCH 015/111] serial: 8250: Don't crash when nr_uarts is 0 --- drivers/tty/serial/8250/8250_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c -index 2f4f5ee651db63c040255347b56d0ac385e36415..edc1355f6381410fb79f48e17a2d2f47da66d841 100644 +index 0fbd7c033a251e7d0cb214ed2bbd1ad1f19f0a76..00fc96497968c826978465957454ad73c3fb6042 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -509,6 +509,8 @@ static void __init serial8250_isa_init_ports(void) @@ -842,10 +781,10 @@ index 2f4f5ee651db63c040255347b56d0ac385e36415..edc1355f6381410fb79f48e17a2d2f47 for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; -From 73f388363630c8b173556b874b54744a6afee2b6 Mon Sep 17 00:00:00 2001 +From e80e467e8d44ae69a48b29aa85ec0aecccad634b Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 017/141] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 016/111] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -854,10 +793,10 @@ Signed-off-by: Noralf Tronnes 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 08b1d93da9fedb36e1ae6ed3450221271f25998f..0a23c813397f14e503beb795b1f448124db74b9a 100644 +index fa77165fab2c1348163979da507df17e7168c49b..d11e2e4ea189466e686d762cb6c6fef9111ecf8e 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -373,7 +373,7 @@ static struct gpio_chip bcm2835_gpio_chip = { +@@ -386,7 +386,7 @@ static struct gpio_chip bcm2835_gpio_chip = { .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, .to_irq = bcm2835_gpio_to_irq, @@ -867,10 +806,10 @@ index 08b1d93da9fedb36e1ae6ed3450221271f25998f..0a23c813397f14e503beb795b1f44812 .can_sleep = false, }; -From 20c9618ebd27b09ea497f1232e22aee3b5ba7ec5 Mon Sep 17 00:00:00 2001 +From 26ec4fa6201b9cfceb3b99fefb9093df018f7400 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 018/141] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 017/111] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -891,7 +830,7 @@ the pins are often used for I2S instead. 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe238c7f09cf 100644 +index d11e2e4ea189466e686d762cb6c6fef9111ecf8e..107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ @@ -927,7 +866,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 spinlock_t irq_lock[BCM2835_NUM_BANKS]; }; -@@ -378,17 +379,16 @@ static struct gpio_chip bcm2835_gpio_chip = { +@@ -391,17 +392,16 @@ static struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; @@ -948,7 +887,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; -@@ -396,7 +396,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +@@ -409,7 +409,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } @@ -980,7 +919,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, -@@ -985,8 +1008,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -998,8 +1021,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; @@ -989,7 +928,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); -@@ -1001,10 +1022,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1014,10 +1035,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); @@ -1007,7 +946,7 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); -@@ -1062,6 +1088,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { +@@ -1074,6 +1100,7 @@ static struct platform_driver bcm2835_pinctrl_driver = { .remove = bcm2835_pinctrl_remove, .driver = { .name = MODULE_NAME, @@ -1016,10 +955,10 @@ index 0a23c813397f14e503beb795b1f448124db74b9a..b793bbdb12dca12722a7f0d07a29fe23 }, }; -From 1ba175b3d87e3a992c16a1dbdb4ea0ce5aa581ee Mon Sep 17 00:00:00 2001 +From c9eec3c71a1447f4fb118e7b1a1853fd5f38d2a6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 019/141] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 018/111] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -1033,10 +972,10 @@ interface, is unlikely to be a problem. 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index b793bbdb12dca12722a7f0d07a29fe238c7f09cf..8683a1be5ecc45e1e664d5e078f25e6ff0ebe282 100644 +index 107ad7d58de8f8a7f55e09c9cdcf7d66fa7ab66b..644bdecbcfcb79d3b84a33769265fca5d3d0c9e5 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -1029,6 +1029,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) +@@ -1042,6 +1042,8 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) int len; char *name; pc->irq[i] = irq_of_parse_and_map(np, i); @@ -1046,10 +985,10 @@ index b793bbdb12dca12722a7f0d07a29fe238c7f09cf..8683a1be5ecc45e1e664d5e078f25e6f pc->irq_data[i].irqgroup = i; -From 7025a28c0a51dab1cf83b4dde39ff2f29d8802a5 Mon Sep 17 00:00:00 2001 +From 61a07603237cf3093679b3c319fc6d0bc54e874b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 -Subject: [PATCH 020/141] pinctrl-bcm2835: Return pins to inputs when freed +Subject: [PATCH 019/111] pinctrl-bcm2835: Return pins to inputs when freed When dynamically unloading overlays, it is important that freed pins are restored to being inputs to prevent functions from being enabled in @@ -1061,10 +1000,10 @@ Signed-off-by: Phil Elwell 1 file changed, 11 insertions(+) diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54afdd2847 100644 +index 644bdecbcfcb79d3b84a33769265fca5d3d0c9e5..81a66cba2ab0f7e3ae179de7edd10122630e7abc 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c -@@ -831,6 +831,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = { +@@ -844,6 +844,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = { .dt_free_map = bcm2835_pctl_dt_free_map, }; @@ -1081,7 +1020,7 @@ index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54 static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev) { return BCM2835_FSEL_COUNT; -@@ -890,6 +900,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, +@@ -903,6 +913,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, } static const struct pinmux_ops bcm2835_pmx_ops = { @@ -1090,10 +1029,10 @@ index 8683a1be5ecc45e1e664d5e078f25e6ff0ebe282..6327122cb13b2a0229be4de7c3409b54 .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, -From 541fd5da6b0b4f90c60c026de2014ea9f20673dd Mon Sep 17 00:00:00 2001 +From bbf333328d9bca204d88968d9781a46450baddf5 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 021/141] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 020/111] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the @@ -1174,10 +1113,10 @@ index f35cc10772f6670397ea923ad30158270dd68578..5dfe20ffc2866fa6789825016c585175 /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n", -From 9826498a0561d5ad6adc0aef108c73b52c91232c Mon Sep 17 00:00:00 2001 +From a3538941a4ea2b1cce170ad969b43b66bbba8477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 3 Jun 2015 12:26:13 +0200 -Subject: [PATCH 022/141] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 021/111] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1235,365 +1174,10 @@ index 834d67684e205a185971c13ebc6620434eeac788..3b68a8d3501a5dcb1b4790c35d921cf5 static const char * const bcm2835_compat[] = { -From 4e99035ba81f037625f36a5e31b6b10ce582176d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Thu, 9 Apr 2015 12:34:11 +0200 -Subject: [PATCH 023/141] dmaengine: bcm2835: Add slave dma support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add slave transfer capability to BCM2835 dmaengine driver. -This patch is pulled from the bcm2708-dmaengine driver in the -Raspberry Pi repo. The work was done by Gellert Weisz. - -Tested using the bcm2835-mmc driver from the same repo. - -Signed-off-by: Noralf Trønnes ---- - drivers/dma/bcm2835-dma.c | 206 ++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 192 insertions(+), 14 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 996c4b00d323ed5c2dd6455f80eb36ed8e9a8b23..b278c663e3b31a7c906dd32d53db5e670f6bbc10 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -1,11 +1,10 @@ - /* - * BCM2835 DMA engine support - * -- * This driver only supports cyclic DMA transfers -- * as needed for the I2S module. -- * - * Author: Florian Meier - * Copyright 2013 -+ * Gellert Weisz -+ * Copyright 2013-2014 - * - * Based on - * OMAP DMAengine support by Russell King -@@ -95,6 +94,8 @@ struct bcm2835_desc { - size_t size; - }; - -+#define BCM2835_DMA_WAIT_CYCLES 0 /* Slow down DMA transfers: 0-31 */ -+ - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 - #define BCM2835_DMA_SOURCE_AD 0x0c -@@ -111,12 +112,16 @@ struct bcm2835_desc { - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - - #define BCM2835_DMA_INT_EN BIT(0) -+#define BCM2835_DMA_WAIT_RESP BIT(3) - #define BCM2835_DMA_D_INC BIT(4) -+#define BCM2835_DMA_D_WIDTH BIT(5) - #define BCM2835_DMA_D_DREQ BIT(6) - #define BCM2835_DMA_S_INC BIT(8) -+#define BCM2835_DMA_S_WIDTH BIT(9) - #define BCM2835_DMA_S_DREQ BIT(10) - - #define BCM2835_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2835_DMA_WAITS(x) (((x) & 0x1f) << 21) - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 -@@ -130,6 +135,14 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+#define MAX_NORMAL_TRANSFER SZ_1G -+/* -+ * Max length on a Lite channel is 65535 bytes. -+ * DMA handles byte-enables on SDRAM reads and writes even on 128-bit accesses, -+ * but byte-enables don't exist on peripheral addresses, so align to 32-bit. -+ */ -+#define MAX_LITE_TRANSFER (SZ_64K - 4) -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -226,12 +239,18 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- /* TODO Only works for cyclic DMA */ -- vchan_cyclic_callback(&d->vd); -- } -+ if (c->cyclic) { -+ vchan_cyclic_callback(&d->vd); - -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, -+ c->chan_base + BCM2835_DMA_CS); -+ -+ } else { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ } -+ } - - spin_unlock_irqrestore(&c->vc.lock, flags); - -@@ -339,8 +358,6 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -358,7 +375,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - struct bcm2835_desc *d; - dma_addr_t dev_addr; - unsigned int es, sync_type; -- unsigned int frame; -+ unsigned int frame, max_size; - int i; - - /* Grab configuration */ -@@ -393,7 +410,12 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - - d->c = c; - d->dir = direction; -- d->frames = buf_len / period_len; -+ if (c->ch >= 8) /* LITE channel */ -+ max_size = MAX_LITE_TRANSFER; -+ else -+ max_size = MAX_NORMAL_TRANSFER; -+ period_len = min(period_len, max_size); -+ d->frames = (buf_len - 1) / (period_len + 1); - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { -@@ -441,17 +463,171 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - BCM2835_DMA_PER_MAP(c->dreq); - - /* Length of a frame */ -- control_block->length = period_len; -+ if (frame != d->frames - 1) -+ control_block->length = period_len; -+ else -+ control_block->length = buf_len - (d->frames - 1) * -+ period_len; - d->size += control_block->length; - - /* - * Next block is the next frame. -- * This DMA engine driver currently only supports cyclic DMA. -+ * This function is called on cyclic DMA transfers. - * Therefore, wrap around at number of frames. - */ - control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr; - } - -+ c->cyclic = true; -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ -+static struct dma_async_tx_descriptor * -+bcm2835_dma_prep_slave_sg(struct dma_chan *chan, -+ struct scatterlist *sgl, -+ unsigned int sg_len, -+ enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ enum dma_slave_buswidth dev_width; -+ struct bcm2835_desc *d; -+ dma_addr_t dev_addr; -+ struct scatterlist *sgent; -+ unsigned int i, sync_type, split_cnt, max_size; -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(chan->device->dev, "direction not supported\n"); -+ return NULL; -+ } -+ -+ if (direction == DMA_DEV_TO_MEM) { -+ dev_addr = c->cfg.src_addr; -+ dev_width = c->cfg.src_addr_width; -+ sync_type = BCM2835_DMA_S_DREQ; -+ } else { -+ dev_addr = c->cfg.dst_addr; -+ dev_width = c->cfg.dst_addr_width; -+ sync_type = BCM2835_DMA_D_DREQ; -+ } -+ -+ /* Bus width translates to the element size (ES) */ -+ switch (dev_width) { -+ case DMA_SLAVE_BUSWIDTH_4_BYTES: -+ break; -+ default: -+ dev_err(chan->device->dev, "buswidth not supported: %i\n", -+ dev_width); -+ return NULL; -+ } -+ -+ /* Allocate and setup the descriptor. */ -+ d = kzalloc(sizeof(*d), GFP_NOWAIT); -+ if (!d) -+ return NULL; -+ -+ d->dir = direction; -+ -+ if (c->ch >= 8) /* LITE channel */ -+ max_size = MAX_LITE_TRANSFER; -+ else -+ max_size = MAX_NORMAL_TRANSFER; -+ -+ /* -+ * Store the length of the SG list in d->frames -+ * taking care to account for splitting up transfers -+ * too large for a LITE channel -+ */ -+ d->frames = 0; -+ for_each_sg(sgl, sgent, sg_len, i) { -+ unsigned int len = sg_dma_len(sgent); -+ -+ d->frames += len / max_size + 1; -+ } -+ -+ /* Allocate memory for control blocks */ -+ d->control_block_size = d->frames * sizeof(struct bcm2835_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 SG entries, create a control block -+ * for each frame and link them together. -+ * Count the number of times an SG entry had to be split -+ * as a result of using a LITE channel -+ */ -+ split_cnt = 0; -+ -+ for_each_sg(sgl, sgent, sg_len, i) { -+ unsigned int j; -+ dma_addr_t addr = sg_dma_address(sgent); -+ unsigned int len = sg_dma_len(sgent); -+ -+ for (j = 0; j < len; j += max_size) { -+ struct bcm2835_dma_cb *control_block = -+ &d->control_block_base[i + split_cnt]; -+ -+ /* Setup addresses */ -+ if (d->dir == DMA_DEV_TO_MEM) { -+ control_block->info = BCM2835_DMA_D_INC | -+ BCM2835_DMA_D_WIDTH | -+ BCM2835_DMA_S_DREQ; -+ control_block->src = dev_addr; -+ control_block->dst = addr + (dma_addr_t)j; -+ } else { -+ control_block->info = BCM2835_DMA_S_INC | -+ BCM2835_DMA_S_WIDTH | -+ BCM2835_DMA_D_DREQ; -+ control_block->src = addr + (dma_addr_t)j; -+ control_block->dst = dev_addr; -+ } -+ -+ /* Common part */ -+ control_block->info |= -+ BCM2835_DMA_WAITS(BCM2835_DMA_WAIT_CYCLES); -+ control_block->info |= BCM2835_DMA_WAIT_RESP; -+ -+ /* Enable */ -+ if (i == sg_len - 1 && len - j <= max_size) -+ control_block->info |= BCM2835_DMA_INT_EN; -+ -+ /* Setup synchronization */ -+ if (sync_type) -+ control_block->info |= sync_type; -+ -+ /* Setup DREQ channel */ -+ if (c->dreq) -+ control_block->info |= -+ BCM2835_DMA_PER_MAP(c->dreq); -+ -+ /* Length of a frame */ -+ control_block->length = min(len - j, max_size); -+ d->size += control_block->length; -+ -+ if (i < sg_len - 1 || len - j > max_size) { -+ /* Next block is the next frame. */ -+ control_block->next = -+ d->control_block_base_phys + -+ sizeof(struct bcm2835_dma_cb) * -+ (i + split_cnt + 1); -+ } else { -+ /* Next block is empty. */ -+ control_block->next = 0; -+ } -+ -+ if (len - j > max_size) -+ split_cnt++; -+ } -+ } -+ -+ c->cyclic = false; -+ - return vchan_tx_prep(&c->vc, &d->vd, flags); - error_cb: - i--; -@@ -620,6 +796,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -+ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -@@ -708,4 +885,5 @@ module_platform_driver(bcm2835_dma_driver); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); -+MODULE_AUTHOR("Gellert Weisz "); - MODULE_LICENSE("GPL v2"); - -From e3e040906062d7c43233c4b3a3572d21349f17d1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 3 Oct 2015 15:58:59 +0200 -Subject: [PATCH 024/141] dmaengine: bcm2835: set residue_granularity field -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -bcm2835-dma supports residue reporting at burst level but didn't report -this via the residue_granularity field. - -Without this field set properly we get playback issues with I2S cards. - -[by HiassofT, taken from bcm2708-dmaengine] -Signed-off-by: Noralf Trønnes ---- - drivers/dma/bcm2835-dma.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b278c663e3b31a7c906dd32d53db5e670f6bbc10..696fb30b4f5a01cda9b98038b8e548368cea05f4 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -802,6 +802,7 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - spin_lock_init(&od->lock); - -From b40ce4492e4b78af2c02256f1807ee2d9fc35920 Mon Sep 17 00:00:00 2001 +From 28e89502361a69361bb3c3132d9bfac45ed04719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 025/141] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 022/111] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1607,11 +1191,11 @@ Don't mask out channel 2. Signed-off-by: Noralf Trønnes --- drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 30 ++++++++++++++++++++++++------ - 2 files changed, 25 insertions(+), 7 deletions(-) + drivers/dma/bcm2835-dma.c | 26 +++++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index d96d87c56f2e13a6c85a815626f67b67c9940116..4d0425c820d476fc7e5d5acf12a32de074c91b1d 100644 +index 8c98779a12b134f3688e1076f1e11211c23e2623..ece64af02387ab867e21b7bc9178e0842bf1ecac 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -1624,10 +1208,10 @@ index d96d87c56f2e13a6c85a815626f67b67c9940116..4d0425c820d476fc7e5d5acf12a32de0 select DMA_VIRTUAL_CHANNELS diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f125511f67471 100644 +index 6149b27c33ad0962a19ed411055d9d05bfb252d3..43265b2847d37b3ee8f71b7528eebea1713f263c 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c -@@ -36,6 +36,7 @@ +@@ -37,6 +37,7 @@ #include #include #include @@ -1635,32 +1219,35 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 #include #include #include -@@ -786,6 +787,10 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -48,6 +49,7 @@ + + #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 + #define BCM2835_DMA_CHAN_NAME_SIZE 8 ++#define BCM2835_DMA_BULK_MASK BIT(0) + + struct bcm2835_dmadev { + struct dma_device ddev; +@@ -921,6 +923,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) + base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); - + rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK); + if (rc) + dev_err(&pdev->dev, "Failed to initialize the legacy API\n"); -+ + od->base = base; - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -@@ -818,11 +823,8 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -958,6 +963,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) goto err_no_dma; } -- /* -- * Do not use the FIQ and BULK channels, -- * because they are used by the GPU. -- */ -- chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); + /* Channel 0 is used by the legacy API */ + chans_available &= ~BCM2835_DMA_BULK_MASK; - - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); -@@ -866,6 +868,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) ++ + /* get irqs for each channel that we support */ + for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { + /* skip masked out channels */ +@@ -1032,6 +1040,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) { struct bcm2835_dmadev *od = platform_get_drvdata(pdev); @@ -1668,7 +1255,7 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 dma_async_device_unregister(&od->ddev); bcm2835_dma_free(od); -@@ -881,7 +884,22 @@ static struct platform_driver bcm2835_dma_driver = { +@@ -1047,7 +1056,22 @@ static struct platform_driver bcm2835_dma_driver = { }, }; @@ -1693,138 +1280,10 @@ index 696fb30b4f5a01cda9b98038b8e548368cea05f4..5db0a95985b20a2086c65762ea8f1255 MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From 17879c9ca6c35117102bf91e1cbebc9f4efe6100 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 12:28:30 +0200 -Subject: [PATCH 026/141] bcm2835-dma: Limit cyclic transfers on lite channels - to 32k - -Transfers larger than 32k cause repeated clicking with I2S soundcards. -The exact reason is yet unknown, so limit to 32k as bcm2708-dmaengine -did as an intermediate fix. ---- - drivers/dma/bcm2835-dma.c | 8 +++++++- - 1 file changed, 7 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 5db0a95985b20a2086c65762ea8f125511f67471..6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -144,6 +144,12 @@ struct bcm2835_desc { - */ - #define MAX_LITE_TRANSFER (SZ_64K - 4) - -+/* -+ * Transfers larger than 32k cause issues with the bcm2708-i2s driver, -+ * so limit transfer size to 32k as bcm2708-dmaengine did. -+ */ -+#define MAX_CYCLIC_LITE_TRANSFER SZ_32K -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -412,7 +418,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -+ max_size = MAX_CYCLIC_LITE_TRANSFER; - else - max_size = MAX_NORMAL_TRANSFER; - period_len = min(period_len, max_size); - -From b4c1abeefe17ac4871d90258edd3617137069432 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Mon, 16 Nov 2015 14:05:35 +0000 -Subject: [PATCH 027/141] bcm2835-dma: Fix up convert to DMA pool - ---- - drivers/dma/bcm2835-dma.c | 36 ++++++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 10 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9..d26b6bdbcf1ab33ab92937b889a37e505c925311 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -488,6 +488,17 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - c->cyclic = true; - - return vchan_tx_prep(&c->vc, &d->vd, flags); -+error_cb: -+ i--; -+ for (; i >= 0; i--) { -+ struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -+ -+ dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -+ } -+ -+ kfree(d->cb_list); -+ kfree(d); -+ return NULL; - } - - static struct dma_async_tx_descriptor * -@@ -534,6 +545,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (!d) - return NULL; - -+ d->c = c; - d->dir = direction; - - if (c->ch >= 8) /* LITE channel */ -@@ -553,15 +565,21 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - d->frames += len / max_size + 1; - } - -- /* Allocate memory for control blocks */ -- d->control_block_size = d->frames * sizeof(struct bcm2835_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) { -+ d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -+ if (!d->cb_list) { - kfree(d); - return NULL; - } -+ /* Allocate memory for control blocks */ -+ for (i = 0; i < d->frames; i++) { -+ struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -+ -+ cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -+ &cb_entry->paddr); -+ -+ if (!cb_entry->cb) -+ goto error_cb; -+ } - - /* - * Iterate over all SG entries, create a control block -@@ -578,7 +596,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - - for (j = 0; j < len; j += max_size) { - struct bcm2835_dma_cb *control_block = -- &d->control_block_base[i + split_cnt]; -+ d->cb_list[i + split_cnt].cb; - - /* Setup addresses */ - if (d->dir == DMA_DEV_TO_MEM) { -@@ -620,9 +638,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (i < sg_len - 1 || len - j > max_size) { - /* Next block is the next frame. */ - control_block->next = -- d->control_block_base_phys + -- sizeof(struct bcm2835_dma_cb) * -- (i + split_cnt + 1); -+ d->cb_list[i + split_cnt + 1].paddr; - } else { - /* Next block is empty. */ - control_block->next = 0; - -From 5a3d039eacc45898ee5a4f5b6fcbc97bcdbbe662 Mon Sep 17 00:00:00 2001 +From 0afec8b4eb4cb530d0c7f1dfd01592ce11768032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Sat, 15 Aug 2015 20:50:02 +0200 -Subject: [PATCH 028/141] bcm2835: Add support for uart1 +Subject: [PATCH 023/111] bcm2835: Add support for uart1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1881,10 +1340,10 @@ index 3b68a8d3501a5dcb1b4790c35d921cf5fa641ec7..e72e522fbc840c36a39cb6550850b3c6 static const char * const bcm2835_compat[] = { -From b4d7c36503083d12e86a7d4aade6f3addba8ad1c Mon Sep 17 00:00:00 2001 +From 185ef418f969b40b109156015b7fc4f85a36ca46 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 029/141] firmware: Updated mailbox header +Subject: [PATCH 024/111] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 11 +++++++++++ @@ -1947,10 +1406,10 @@ index 3fb357193f09914fe21f8555a4b8613f74f22bc3..227a107214a02deadcca3db202da265e RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, -From e725dd6d02f95b23299281de245e89c5f561cf78 Mon Sep 17 00:00:00 2001 +From 959d644104238b058ba73ce17324ec64c9feb912 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 030/141] Main bcm2708/bcm2709 linux port +Subject: [PATCH 025/111] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -2022,10 +1481,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 arch/arm/mach-bcm2709/vc_mem.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd742bfa6487 100644 +index 90542db1220dbcff5bc7f0d27ce233389a6d780d..437c4c3fd3cead08377098ae89de79c40d804df2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig -@@ -322,6 +322,52 @@ choice +@@ -324,6 +324,52 @@ choice default ARM_SINGLE_ARMV7M if !MMU default ARCH_MULTIPLATFORM if MMU @@ -2078,7 +1537,7 @@ index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd74 config ARCH_MULTIPLATFORM bool "Allow multiple platforms to be selected" depends on MMU -@@ -721,6 +767,9 @@ config ARCH_VIRT +@@ -725,6 +771,9 @@ config ARCH_VIRT # Kconfigs may be included either alphabetically (according to the # plat- suffix) or along side the corresponding mach-* source. # @@ -2089,10 +1548,10 @@ index cdfa6c2b7626f3a761364ac072fc359b5f02592a..aad71574d78fbf13ddb5616d5f9fdd74 source "arch/arm/mach-alpine/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 1098e91d6d3f34ff5ca9abd4784dd1793897115c..e11967517b52614b4babf9e8cbafd0f920aaf208 100644 +index 19a3dcf5eb2e5600563cbcd47599ba458a546260..a15dd5cde577cc014de4063b7881d2ce03198df8 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -1302,6 +1302,14 @@ choice +@@ -1294,6 +1294,14 @@ choice options; the platform specific options are deprecated and will be soon removed. @@ -2108,7 +1567,7 @@ index 1098e91d6d3f34ff5ca9abd4784dd1793897115c..e11967517b52614b4babf9e8cbafd0f9 config DEBUG_EXYNOS_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index 8c3ce2ac44c4a675e091e8b107f1dd04f5f0b299..c4d7d102840699013aca416a1e7b8d14110be166 100644 +index 274e8a6582f1cd671731d1acbdda6f0f49c358c8..36e8f1e6fc7f169a68aa9476e618b50c79b0b2e3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -153,6 +153,8 @@ textofs-$(CONFIG_ARCH_AXXIA) := 0x00308000 @@ -2140,7 +1599,7 @@ index 04286fd9e09ce7a27259c4d375a05a965e3be0ea..ed826280e744828ebb1c5ae6b7a62d70 ENDPROC(__fixup_a_pv_table) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c -index 4adfb46e3ee93276ea506b723eb11e33c57459f4..69aad0ebc902b82a83afd24938cafdfe1686136d 100644 +index 4a803c5a1ff7276859b823a7b9b02dc24ee6e564..c09505c5312860aade6f68f160f657349785d8cd 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -91,6 +91,16 @@ void arch_cpu_idle_exit(void) @@ -4400,7 +3859,7 @@ index 2ed1b8a922ed02b9e3545991873af77b4c1bf871..b52d949ee91d96eb7672fbbb4969bfa1 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile -index dc2b8997f6e637c0ae83f09b4b6bd4b92bffbf8d..c38fb1af8210f0a494ba58c3b6f1f99e54b88c1e 100644 +index 473974f9590a5cb19da5bf2bccf1e126f45bfb45..dc76b5e1b1f31fa2d802ee3da3dbfda1a88c6574 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o @@ -4413,7 +3872,7 @@ index dc2b8997f6e637c0ae83f09b4b6bd4b92bffbf8d..c38fb1af8210f0a494ba58c3b6f1f99e obj-$(CONFIG_ARCH_ATLAS7) += timer-atlas7.o obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile -index b03cfcbbac6b949b69c8b2f96ac7d307dd5b54e8..70cad6bd86fa78accb3bb39756442042aa4f2ee0 100644 +index 38853a187607591555c351bc2586b8ac73450b7f..382a22ab9ec6c02395a3be44d0787c15e2ddba8b 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -5,6 +5,9 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o @@ -4425,7 +3884,7 @@ index b03cfcbbac6b949b69c8b2f96ac7d307dd5b54e8..70cad6bd86fa78accb3bb39756442042 +obj-$(CONFIG_ARCH_BCM2709) += irq-bcm2836.o obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o - obj-$(CONFIG_ARCH_MMP) += irq-mmp.o + obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index 20deb282286834b1f234a65e614b8584688a25d7..c02bf8a9f9970401dc98c4f656c20c35d8070123 100644 --- a/drivers/irqchip/irq-bcm2835.c @@ -4448,10 +3907,10 @@ index 20deb282286834b1f234a65e614b8584688a25d7..c02bf8a9f9970401dc98c4f656c20c35 } init_FIQ(FIQ_START); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index 8dd4d290ab0d8608b9596c18da8db1096715badb..f7fe8bd8ac26e68b51359b868a1e1eff3e344bdf 100644 +index 45cde8cd39f2434f5f9ec02c702a91a7f6b971c9..6a01ffa629386bdecf85e5a4736f7c27133869ab 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -291,6 +291,7 @@ struct mmc_host { +@@ -302,6 +302,7 @@ struct mmc_host { #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) #define MMC_CAP2_NO_WRITE_PROTECT (1 << 18) /* No physical write protect pin, assume that card is always read-write */ #define MMC_CAP2_NO_SDIO (1 << 19) /* Do not send SDIO commands during initialization */ @@ -4460,38 +3919,36 @@ index 8dd4d290ab0d8608b9596c18da8db1096715badb..f7fe8bd8ac26e68b51359b868a1e1eff mmc_pm_flag_t pm_caps; /* supported pm features */ -From 98808be09a0e8a3b6781d7110c44a7dde78eb825 Mon Sep 17 00:00:00 2001 +From bc4a3b0949122d757a7bb93cf9bc2181af7777a9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 031/141] reboot: Use power off rather than busy spinning when +Subject: [PATCH 026/111] reboot: Use power off rather than busy spinning when halt is requested --- - arch/arm/kernel/reboot.c | 6 +----- - 1 file changed, 1 insertion(+), 5 deletions(-) + arch/arm/kernel/reboot.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c -index 71a2ff9ec4900c58677f12114c85c82e8cfaa575..812c15ee02742f4d1578895ac13e1e983a9ce3da 100644 +index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e00fb59a19 100644 --- a/arch/arm/kernel/reboot.c +++ b/arch/arm/kernel/reboot.c -@@ -102,11 +102,7 @@ void machine_shutdown(void) +@@ -102,9 +102,7 @@ void machine_shutdown(void) */ void machine_halt(void) { - local_irq_disable(); - smp_send_stop(); -- -- local_irq_disable(); - while (1); + machine_power_off(); } /* -From 00ccff1596aa4c356db53f7fa48816afa6eb874a Mon Sep 17 00:00:00 2001 +From 122b8acb7c8d60b790ef4665ae12b7f336316c68 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 11 Nov 2015 21:01:15 +0000 -Subject: [PATCH 032/141] squash: include ARCH_BCM2708 / ARCH_BCM2709 +Subject: [PATCH 027/111] squash: include ARCH_BCM2708 / ARCH_BCM2709 --- drivers/char/hw_random/Kconfig | 2 +- @@ -4506,7 +3963,7 @@ Subject: [PATCH 032/141] squash: include ARCH_BCM2708 / ARCH_BCM2709 9 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index 67ee8b08ab5318dca13054e6e1e65da9dcd1c000..b3ca2ee0a8f413151d70db1612ebb07e25416748 100644 +index ac51149e977758beb8db91e159175be9525fc13c..7fb001bb8e7609d3640b27cec5ec5180d8dbbcc2 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -90,7 +90,7 @@ config HW_RANDOM_BCM63XX @@ -4596,7 +4053,7 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile -index e4bc1151e04f3c2d7ed0eac8b659ae27244432ba..d996fe7f5b733864f26739aa0988b2466842dc19 100644 +index 42a5c1dddfefaf7414eca1809ef7d1bf75a11628..4c62b88401c5bee3015e74ce95a411d9c62c3dd6 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o @@ -4621,7 +4078,7 @@ index c182efc62c7bc3ffe31d81a539c88c35f55abac9..fe0f845fa21e1a2fa129814358f172ad PWM framework driver for BCM2835 controller (Raspberry Pi) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 9d8c84bb15446a75153d64f94a5900ab165193ac..2a27a37c54d8cf7c28620744147f7dc97771c3e5 100644 +index 4b931ec8d90b610f498a3e317e0523e9d1aa6900..82528961746f960e9851b4c252f42de5f1fbf298 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -94,7 +94,7 @@ config SPI_AXI_SPI_ENGINE @@ -4643,10 +4100,10 @@ index 9d8c84bb15446a75153d64f94a5900ab165193ac..2a27a37c54d8cf7c28620744147f7dc9 This selects a driver for the Broadcom BCM2835 SPI aux master. diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig -index fb947655badd02de231dd0777e88499c8a552044..8b2de7fb47f34888dd81262e793020afdc2dd44d 100644 +index b4b3e256491bfbe8c05fa0f7830c003541db8720..eaf2e847254e00b457ad37cb4a8c0b2baee8d1a9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -1401,7 +1401,7 @@ config BCM63XX_WDT +@@ -1409,7 +1409,7 @@ config BCM63XX_WDT config BCM2835_WDT tristate "Broadcom BCM2835 hardware watchdog" @@ -4668,10 +4125,10 @@ index 6a834e109f1de47e533d17e87cdc73d8ee86fc4d..c5070aec5996aafb2d9daaf75163e16a select REGMAP_MMIO help -From cd22cb8ce5c5e0d57cc587d3d6ea9e4d9c7b4cce Mon Sep 17 00:00:00 2001 +From 6f0fb5187200ef480efe629d0c758662df204f07 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 033/141] Add dwc_otg driver +Subject: [PATCH 028/111] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -5365,10 +4822,10 @@ index 358ca8dd784fe43700ae070764fa783500a792fe..abaac7c7142d8887c1516957fc52162c return i; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 1ab42bfbecaf6cf7780c87f2ae32a5948e48486e..292a26cefbbc2eee58433d792385f60f88c6a424 100644 +index bee13517676f9b2f00e3cd4e3fd4185f5aaa13c9..844ed26f2743b921e5a81cca1654badde94e05cd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -5044,7 +5044,7 @@ static void port_event(struct usb_hub *hub, int port1) +@@ -5046,7 +5046,7 @@ static void port_event(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0, unused; @@ -5378,10 +4835,10 @@ index 1ab42bfbecaf6cf7780c87f2ae32a5948e48486e..292a26cefbbc2eee58433d792385f60f USB_PORT_FEAT_C_OVER_CURRENT); msleep(100); /* Cool down */ diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 8e641b5893edb7a6195c34e43248540fbff39aa6..de3ed7d5d3dd3e9b2d20025e0c35a728248f4026 100644 +index ea681f157368f245772ab145073594bf4f6fb273..cb9b9c2df9b8fd7df50fa846b37c3f3d5fab6256 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1909,6 +1909,85 @@ free_interfaces: +@@ -1905,6 +1905,85 @@ free_interfaces: if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -9307,10 +8764,10 @@ index 0000000000000000000000000000000000000000..a896d73f7a9336f5a34015c44ea5a6b0 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index e9d4dde3e9b3dac1990d5dc58c8e6c2e196771a5..867dc98d83eb3cf38b50b52a922d5c543aa70a33 100644 +index d8f5674809e88e4f68d19411473ff752ce6230ef..50322813b65b6d7ddf273db46581c9b58be1c40b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -753,6 +753,19 @@ config USB_HWA_HCD +@@ -762,6 +762,19 @@ config USB_HWA_HCD To compile this driver a module, choose M here: the module will be called "hwa-hc". @@ -9331,10 +8788,10 @@ index e9d4dde3e9b3dac1990d5dc58c8e6c2e196771a5..867dc98d83eb3cf38b50b52a922d5c54 tristate "i.MX21 HCD support" depends on ARM && ARCH_MXC diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index a9ddd3c9ec9499b556789844eaaad5574a01d887..11d7761c61f59f08289a9b9ab78666cb069ba445 100644 +index 6ef785b0ea8ff0b5f4ee3bc40ba22d17c855478f..c28acc1b2877b6ac43604d1968351ce42e9470a5 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile -@@ -73,6 +73,8 @@ obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o +@@ -74,6 +74,8 @@ obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o @@ -65697,10 +65154,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From c195a8976feec61260f4ace36803130c41eebf65 Mon Sep 17 00:00:00 2001 +From c2cb17374b4e4c68ff926fe79c52d6338b93f74d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 034/141] bcm2708 framebuffer driver +Subject: [PATCH 029/111] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -65782,7 +65239,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/video/fbdev/bcm2708_fb.c diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 983280e8d93f3df4030c737978402ada4deaed10..ee72c3a2866f716cd68c646b7c501589a05b48f5 100644 +index 88b008fb8a4ec9f4f4458b8b65a5e7d4ccef57e5..78a9e6119fa13437862080d815e84d68f7010d1f 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -228,6 +228,20 @@ config FB_TILEBLITTING @@ -65807,7 +65264,7 @@ index 983280e8d93f3df4030c737978402ada4deaed10..ee72c3a2866f716cd68c646b7c501589 tristate "Aeroflex Gaisler framebuffer support" depends on FB && SPARC diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index 65fb15075c8f7f150febb09966766287c3aa0e07..df473d825c2e2481a871d794317e56b8d643370f 100644 +index f6731867dd26dfc4318799e5204cd583a5d27670..ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o @@ -69159,10 +68616,10 @@ index 3c14e43b82fefe1d32f591d1b2f61d2cd28d0fa8..7626beb6a5bb8df601ddf0f6e6909d1f +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -From 31bd889b7548e1ded4c0d9f8171541b2a1eba9ca Mon Sep 17 00:00:00 2001 +From b3848db30147e758d2d0f82c5dcfee8f567f0d82 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 035/141] dmaengine: Add support for BCM2708 +Subject: [PATCH 030/111] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69319,10 +68776,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 4d0425c820d476fc7e5d5acf12a32de074c91b1d..b7863f0cf95ca656859a355098aa334e20d121c3 100644 +index ece64af02387ab867e21b7bc9178e0842bf1ecac..ffc92425cbd7bafc23899b7680949e47943f9561 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig -@@ -474,6 +474,10 @@ config TIMB_DMA +@@ -488,6 +488,10 @@ config TIMB_DMA help Enable support for the Timberdale FPGA DMA engine. @@ -69334,7 +68791,7 @@ index 4d0425c820d476fc7e5d5acf12a32de074c91b1d..b7863f0cf95ca656859a355098aa334e tristate "AM33xx CPPI41 DMA support" depends on ARCH_OMAP diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile -index 6084127c14866ced0bef9865c8e5d9ffb13c16b6..8188c368a85f12950220942c28791bdc952c8848 100644 +index 614f28b0b739de875823b05a66a62186a1e9f45f..598e44dca3e4a9b33cc206e107226de8e0b34111 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_AT_HDMAC) += at_hdmac.o @@ -69782,10 +69239,10 @@ index 0000000000000000000000000000000000000000..99cc7fdbf543207208bf3638a0d4dbb6 + +#endif /* _PLAT_BCM2708_DMA_H */ -From daa0ba80c2355cafff1e77d3c0e5279fa39431ff Mon Sep 17 00:00:00 2001 +From a81ac3cfae61fc6b814594d419702a2808a731e6 Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 036/141] MMC: added alternative MMC driver +Subject: [PATCH 031/111] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -69903,7 +69360,7 @@ index fad660b95809224e3a06abde0709be3d50acf307..b79fe14c18f1fe521fadf8adfc136de6 } EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index e657af0e95fafce5bf65e0127540339dfbbb2ba5..04760616f94ce470a73d7ac99f27631db80849b5 100644 +index 0aa484c10c0a9b93a4aedc885235d95ffe6872e6..36d00eba1df06946fb2bb9bb9dd1f0d847ef8158 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -4,6 +4,35 @@ @@ -71532,10 +70989,10 @@ index 0000000000000000000000000000000000000000..ceb37930e167f47c9c848e8de757ad09 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 5c1dac87ebf26fc576b27b0a78d2bf2d277f413a Mon Sep 17 00:00:00 2001 +From ea4f732925a77e0c50915b345312cbce996201b8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 037/141] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 032/111] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -71682,12 +71139,12 @@ Signed-off-by: Phil Elwell --- drivers/mmc/host/Kconfig | 10 + drivers/mmc/host/Makefile | 1 + - drivers/mmc/host/bcm2835-sdhost.c | 2158 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 2169 insertions(+) + drivers/mmc/host/bcm2835-sdhost.c | 2189 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 2200 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-sdhost.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 04760616f94ce470a73d7ac99f27631db80849b5..259547484f859ae69c65af13bcbb1d06b53e29ac 100644 +index 36d00eba1df06946fb2bb9bb9dd1f0d847ef8158..97650d32a733251076726a0cecb4239906ff3814 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER @@ -71721,10 +71178,10 @@ index 3ba94f0af9b1793aa66d95d8fbd9bb661ca82778..8daaa94ab268495bbbf335ccad5a35e2 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 -index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e599026d43785 +index 0000000000000000000000000000000000000000..d7b6b5a4e31f7aaa76470d3a79ea78a643184855 --- /dev/null +++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -0,0 +1,2158 @@ +@@ -0,0 +1,2189 @@ +/* + * BCM2835 SD host driver. + * @@ -71765,6 +71222,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 +#include +#include +#include ++#include +#include +#include +#include @@ -71933,6 +71391,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + struct timeval stop_time; /* when the last stop was issued */ + u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ + u32 delay_after_this_stop; /* minimum time between this stop and subsequent data transfer */ ++ u32 user_overclock_50; /* User's preferred frequency to use when 50MHz is requested (in MHz) */ + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ + u32 overclock; /* Current frequency if overclocked, else zero */ + u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ @@ -72009,7 +71468,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + do { + entry = sdhost_log_buf + idx; + if (entry->event[0] != '\0') -+ pr_err("[%08x] %.4s %x %x\n", ++ pr_info("[%08x] %.4s %x %x\n", + entry->timestamp, + entry->event, + entry->param1, @@ -72051,7 +71510,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + const char *label) +{ + if (cmd) -+ pr_err("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", ++ pr_info("%s:%c%s op %d arg 0x%x flags 0x%x - resp %08x %08x %08x %08x, err %d\n", + mmc_hostname(host->mmc), + (cmd == host->cmd) ? '>' : ' ', + label, cmd->opcode, cmd->arg, cmd->flags, @@ -72066,7 +71525,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + bcm2835_sdhost_dumpcmd(host, host->mrq->sbc, "sbc"); + bcm2835_sdhost_dumpcmd(host, host->mrq->cmd, "cmd"); + if (host->mrq->data) -+ pr_err("%s: data blocks %x blksz %x - err %d\n", ++ pr_info("%s: data blocks %x blksz %x - err %d\n", + mmc_hostname(host->mmc), + host->mrq->data->blocks, + host->mrq->data->blksz, @@ -72074,53 +71533,53 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + bcm2835_sdhost_dumpcmd(host, host->mrq->stop, "stop"); + } + -+ pr_err("%s: =========== REGISTER DUMP ===========\n", ++ pr_info("%s: =========== REGISTER DUMP ===========\n", + mmc_hostname(host->mmc)); + -+ pr_err("%s: SDCMD 0x%08x\n", ++ pr_info("%s: SDCMD 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCMD)); -+ pr_err("%s: SDARG 0x%08x\n", ++ pr_info("%s: SDARG 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDARG)); -+ pr_err("%s: SDTOUT 0x%08x\n", ++ pr_info("%s: SDTOUT 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDTOUT)); -+ pr_err("%s: SDCDIV 0x%08x\n", ++ pr_info("%s: SDCDIV 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDCDIV)); -+ pr_err("%s: SDRSP0 0x%08x\n", ++ pr_info("%s: SDRSP0 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP0)); -+ pr_err("%s: SDRSP1 0x%08x\n", ++ pr_info("%s: SDRSP1 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP1)); -+ pr_err("%s: SDRSP2 0x%08x\n", ++ pr_info("%s: SDRSP2 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP2)); + pr_err("%s: SDRSP3 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDRSP3)); -+ pr_err("%s: SDHSTS 0x%08x\n", ++ pr_info("%s: SDHSTS 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHSTS)); -+ pr_err("%s: SDVDD 0x%08x\n", ++ pr_info("%s: SDVDD 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDVDD)); -+ pr_err("%s: SDEDM 0x%08x\n", ++ pr_info("%s: SDEDM 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDEDM)); -+ pr_err("%s: SDHCFG 0x%08x\n", ++ pr_info("%s: SDHCFG 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHCFG)); -+ pr_err("%s: SDHBCT 0x%08x\n", ++ pr_info("%s: SDHBCT 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBCT)); -+ pr_err("%s: SDHBLC 0x%08x\n", ++ pr_info("%s: SDHBLC 0x%08x\n", + mmc_hostname(host->mmc), + bcm2835_sdhost_read(host, SDHBLC)); + -+ pr_err("%s: ===========================================\n", ++ pr_info("%s: ===========================================\n", + mmc_hostname(host->mmc)); +} + @@ -72335,7 +71794,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + (fsm_state != SDEDM_FSM_READCRC)) { + hsts = bcm2835_sdhost_read(host, + SDHSTS); -+ pr_err("%s: fsm %x, hsts %x\n", ++ pr_info("%s: fsm %x, hsts %x\n", + mmc_hostname(host->mmc), + fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) @@ -72425,7 +71884,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + (fsm_state != SDEDM_FSM_WRITESTART2)) { + hsts = bcm2835_sdhost_read(host, + SDHSTS); -+ pr_err("%s: fsm %x, hsts %x\n", ++ pr_info("%s: fsm %x, hsts %x\n", + mmc_hostname(host->mmc), + fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) @@ -72680,9 +72139,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + + while (bcm2835_sdhost_read(host, SDCMD) & SDCMD_NEW_FLAG) { + if (timeout == 0) { -+ pr_err("%s: previous command never completed.\n", ++ pr_warn("%s: previous command never completed.\n", + mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) ++ bcm2835_sdhost_dumpregs(host); + cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + return false; @@ -72940,10 +72400,12 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + + /* Check for errors */ + if (sdcmd & SDCMD_NEW_FLAG) { -+ pr_err("%s: command never completed.\n", -+ mmc_hostname(host->mmc)); -+ bcm2835_sdhost_dumpregs(host); -+ host->cmd->error = -EIO; ++ if (host->debug) { ++ pr_err("%s: command %d never completed.\n", ++ mmc_hostname(host->mmc), host->cmd->opcode); ++ bcm2835_sdhost_dumpregs(host); ++ } ++ host->cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + return; + } else if (sdcmd & SDCMD_FAIL_FLAG) { @@ -72965,15 +72427,14 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + } else { + if (sdhsts & SDHSTS_CMD_TIME_OUT) { + if (host->debug) -+ pr_err("%s: command %d timeout\n", ++ pr_warn("%s: command %d timeout\n", + mmc_hostname(host->mmc), + host->cmd->opcode); + host->cmd->error = -ETIMEDOUT; + } else { -+ pr_err("%s: unexpected command %d error\n", ++ pr_warn("%s: unexpected command %d error\n", + mmc_hostname(host->mmc), + host->cmd->opcode); -+ bcm2835_sdhost_dumpregs(host); + host->cmd->error = -EILSEQ; + } + tasklet_schedule(&host->finish_tasklet); @@ -73097,8 +72558,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + } else if (intmask & SDHSTS_CMD_TIME_OUT) + host->cmd->error = -ETIMEDOUT; + -+ log_dump(); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) { ++ log_dump(); ++ bcm2835_sdhost_dumpregs(host); ++ } + } + else + bcm2835_sdhost_finish_command(host, NULL); @@ -73322,7 +72785,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + host->overclock_50 = (clock/MHZ); + + if (clock != host->overclock) { -+ pr_warn("%s: overclocking to %dHz\n", ++ pr_info("%s: overclocking to %dHz\n", + mmc_hostname(host->mmc), clock); + host->overclock = clock; + } @@ -73332,6 +72795,11 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + pr_warn("%s: cancelling overclock\n", + mmc_hostname(host->mmc)); + } ++ } else if (input_clock == 0) { ++ /* Reset the preferred overclock when the clock is stopped. ++ * This always happens during initialisation. */ ++ host->overclock_50 = host->user_overclock_50; ++ host->overclock = 0; + } + + /* Set the timeout to 500ms */ @@ -73405,13 +72873,15 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + log_event("REQ<", (u32)mrq, edm); + if ((fsm != SDEDM_FSM_IDENTMODE) && + (fsm != SDEDM_FSM_DATAMODE)) { -+ pr_err("%s: previous command (%d) not complete (EDM %x)\n", -+ mmc_hostname(host->mmc), -+ bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK, -+ edm); + log_event("REQ!", (u32)mrq, edm); -+ log_dump(); -+ bcm2835_sdhost_dumpregs(host); ++ if (host->debug) { ++ pr_warn("%s: previous command (%d) not complete (EDM %x)\n", ++ mmc_hostname(host->mmc), ++ bcm2835_sdhost_read(host, SDCMD) & SDCMD_CMD_MASK, ++ edm); ++ log_dump(); ++ bcm2835_sdhost_dumpregs(host); ++ } + mrq->cmd->error = -EILSEQ; + tasklet_schedule(&host->finish_tasklet); + mmiowb(); @@ -73541,16 +73011,19 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + mrq = host->mrq; + + /* Drop the overclock after any data corruption, or after any -+ error overclocked */ ++ * error while overclocked. Ignore errors for status commands, ++ * as they are likely when a card is ejected. */ + if (host->overclock) { -+ if ((mrq->cmd && mrq->cmd->error) || ++ if ((mrq->cmd && mrq->cmd->error && ++ (mrq->cmd->opcode != MMC_SEND_STATUS)) || + (mrq->data && mrq->data->error) || -+ (mrq->stop && mrq->stop->error)) { ++ (mrq->stop && mrq->stop->error) || ++ (mrq->sbc && mrq->sbc->error)) { + host->overclock_50--; + pr_warn("%s: reducing overclock due to errors\n", + mmc_hostname(host->mmc)); + host->reset_clock = 1; -+ mrq->cmd->error = -EILSEQ; ++ mrq->cmd->error = -ETIMEDOUT; + mrq->cmd->retries = 1; + } + } @@ -73575,6 +73048,21 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + mmc_hostname(host->mmc), err); + } + ++ /* The SDHOST block doesn't report any errors for a disconnected ++ interface. All cards and SDIO devices should report some supported ++ voltage range, so a zero response to SEND_OP_COND, IO_SEND_OP_COND ++ or APP_SEND_OP_COND can be treated as an error. */ ++ if (((mrq->cmd->opcode == MMC_SEND_OP_COND) || ++ (mrq->cmd->opcode == SD_IO_SEND_OP_COND) || ++ (mrq->cmd->opcode == SD_APP_OP_COND)) && ++ (mrq->cmd->error == 0) && ++ (mrq->cmd->resp[0] == 0)) { ++ mrq->cmd->error = -ETIMEDOUT; ++ if (host->debug) ++ pr_info("%s: faking timeout due to zero OCR\n", ++ mmc_hostname(host->mmc)); ++ } ++ + mmc_request_done(host->mmc, mrq); + log_event("TSK>", (u32)mrq, 0); +} @@ -73750,7 +73238,7 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 + &host->delay_after_stop); + of_property_read_u32(node, + "brcm,overclock-50", -+ &host->overclock_50); ++ &host->user_overclock_50); + of_property_read_u32(node, + "brcm,pio-limit", + &host->pio_limit); @@ -73884,10 +73372,10 @@ index 0000000000000000000000000000000000000000..a57faedd8ba71a38d057664f3b7e5990 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From 86d53b10b81d69a9dfe12830bd6237987e3a01b6 Mon Sep 17 00:00:00 2001 +From 324d21e6e89ecb598e332f431fffb01464462c6d Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 038/141] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards +Subject: [PATCH 033/111] mmc: Add MMC_QUIRK_ERASE_BROKEN for some cards Some SD cards have been found that corrupt data when small blocks are erased. Add a quirk to indicate that ERASE should not be used, @@ -73916,10 +73404,10 @@ Signed-off-by: Phil Elwell 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73ce9dca60 100644 +index c5472e3c923126097fd93f2abf31402a1717c228..c55094303b087eb944baf28d4023ab72a61206d5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c -@@ -132,6 +132,13 @@ enum { +@@ -133,6 +133,13 @@ enum { module_param(perdev_minors, int, 0444); MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); @@ -73933,7 +73421,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 static inline int mmc_blk_part_switch(struct mmc_card *card, struct mmc_blk_data *md); static int get_card_status(struct mmc_card *card, u32 *status, int retries); -@@ -2532,6 +2539,17 @@ static const struct mmc_fixup blk_fixups[] = +@@ -2576,6 +2583,17 @@ static const struct mmc_fixup blk_fixups[] = MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), @@ -73951,7 +73439,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 END_FIXUP }; -@@ -2539,6 +2557,7 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2583,6 +2601,7 @@ static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; char cap_str[10]; @@ -73959,7 +73447,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 /* * Check that the card supports the command class(es) we need. -@@ -2546,7 +2565,16 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2590,7 +2609,16 @@ static int mmc_blk_probe(struct mmc_card *card) if (!(card->csd.cmdclass & CCC_BLOCK_READ)) return -ENODEV; @@ -73977,7 +73465,7 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 md = mmc_blk_alloc(card); if (IS_ERR(md)) -@@ -2554,9 +2582,14 @@ static int mmc_blk_probe(struct mmc_card *card) +@@ -2598,9 +2626,14 @@ static int mmc_blk_probe(struct mmc_card *card) string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); @@ -73995,10 +73483,10 @@ index b0a27413cb1348052d68e783ce307d545f789e42..9ce8676ff613f5e63503f8280afd6d73 if (mmc_blk_alloc_parts(card, md)) goto out; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index 9eba56c68ca134f02a8328fe6bcd4ea0bcc7a45f..4b1ff84e016f6ba2a9387c54d999205696f056f7 100644 +index 8b4dfd45433b73c1ccf6fe4cd4f9ca3338546cff..376ca5e984f1d7e0a10bb6e90893cf81a331c8fa 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c -@@ -2253,7 +2253,8 @@ EXPORT_SYMBOL(mmc_erase); +@@ -2260,7 +2260,8 @@ EXPORT_SYMBOL(mmc_erase); int mmc_can_erase(struct mmc_card *card) { if ((card->host->caps & MMC_CAP_ERASE) && @@ -74023,10 +73511,10 @@ index eb0151bac50c1fd796f479d017bc3c3d7017c9e9..fa4e6454456747f02a10621f4f4da3ac unsigned int erase_shift; /* if erase unit is power 2 */ unsigned int pref_erase; /* in sectors */ -From 7ff65cec357efd357309ae92f0d605aa6c29419a Mon Sep 17 00:00:00 2001 +From b7a07a2134d0240e10a33263740f2b37e8ee1a92 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 039/141] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 034/111] cma: Add vc_cma driver to enable use of CMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -74058,7 +73546,7 @@ Signed-off-by: Noralf Trønnes create mode 100644 include/linux/broadcom/vc_cma.h diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 3ec0766ed5e97a80390f3e8dcbe009c4414c9cf2..aec9337379b730de016972fb523bebb7a7c6aff7 100644 +index 601f64fcc8908bad887a2f3fd70cd23fdf34ad1c..a23a93cfa57f01f37777f42fc241f62958fdf1c1 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -4,6 +4,8 @@ @@ -75369,10 +74857,10 @@ index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e + +#endif /* VC_CMA_H */ -From a32fde0621d166157b384b2c7ebecb3ef0b071be Mon Sep 17 00:00:00 2001 +From fd23e9dc16915a406af9bda180f64d882b92b160 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 040/141] bcm2708: alsa sound driver +Subject: [PATCH 035/111] bcm2708: alsa sound driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78109,10 +77597,10 @@ index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294 + +#endif // _VC_AUDIO_DEFS_H_ -From b2b5fec96343d4169965d38e32f0710d4ca58fc7 Mon Sep 17 00:00:00 2001 +From 11380abf87d0d53e0243f3178cdab81f4d4449a5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 041/141] bcm2708 vchiq driver +Subject: [PATCH 036/111] bcm2708 vchiq driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -78342,13 +77830,13 @@ Signed-off-by: Phil Elwell .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 40 + .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + .../interface/vchiq_arm/vchiq_2835_arm.c | 586 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2920 +++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2921 +++++++++++++++ .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 220 ++ .../interface/vchiq_arm/vchiq_build_info.h | 37 + .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 69 + .../interface/vchiq_arm/vchiq_connected.c | 120 + .../interface/vchiq_arm/vchiq_connected.h | 50 + - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3929 ++++++++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_core.c | 3933 ++++++++++++++++++++ .../vc04_services/interface/vchiq_arm/vchiq_core.h | 712 ++++ .../interface/vchiq_arm/vchiq_debugfs.c | 383 ++ .../interface/vchiq_arm/vchiq_debugfs.h | 52 + @@ -78363,7 +77851,7 @@ Signed-off-by: Phil Elwell .../vc04_services/interface/vchiq_arm/vchiq_util.c | 156 + .../vc04_services/interface/vchiq_arm/vchiq_util.h | 82 + .../interface/vchiq_arm/vchiq_version.c | 59 + - 37 files changed, 12831 insertions(+) + 37 files changed, 12836 insertions(+) create mode 100644 drivers/misc/vc04_services/Kconfig create mode 100644 drivers/misc/vc04_services/Makefile create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -80635,10 +80123,10 @@ index 0000000000000000000000000000000000000000..4cb5bff237288a4ee80d80ba53a2efe9 +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947dbd860cf90 +index 0000000000000000000000000000000000000000..2dfccafc765b2211bd7b8ead5e9e52bd8fe13913 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2920 @@ +@@ -0,0 +1,2921 @@ +/** + * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. + * Copyright (c) 2010-2012 Broadcom. All rights reserved. @@ -80705,10 +80193,10 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db +#define VCHIQ_MINOR 0 + +/* Some per-instance constants */ -+#define MAX_COMPLETIONS 16 ++#define MAX_COMPLETIONS 128 +#define MAX_SERVICES 64 +#define MAX_ELEMENTS 8 -+#define MSG_QUEUE_SIZE 64 ++#define MSG_QUEUE_SIZE 128 + +#define KEEPALIVE_VER 1 +#define KEEPALIVE_VER_MIN KEEPALIVE_VER @@ -80849,28 +80337,24 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + void *bulk_userdata) +{ + VCHIQ_COMPLETION_DATA_T *completion; ++ int insert; + DEBUG_INITIALISE(g_state.local) + -+ mutex_lock(&instance->completion_mutex); -+ -+ while (instance->completion_insert == -+ (instance->completion_remove + MAX_COMPLETIONS)) { ++ insert = instance->completion_insert; ++ while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { + /* Out of space - wait for the client */ + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + vchiq_log_trace(vchiq_arm_log_level, + "add_completion - completion queue full"); + DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); + -+ mutex_unlock(&instance->completion_mutex); + if (down_interruptible(&instance->remove_event) != 0) { + vchiq_log_info(vchiq_arm_log_level, + "service_callback interrupted"); + return VCHIQ_RETRY; + } + -+ mutex_lock(&instance->completion_mutex); + if (instance->closing) { -+ mutex_unlock(&instance->completion_mutex); + vchiq_log_info(vchiq_arm_log_level, + "service_callback closing"); + return VCHIQ_SUCCESS; @@ -80878,9 +80362,7 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + DEBUG_TRACE(SERVICE_CALLBACK_LINE); + } + -+ completion = -+ &instance->completions[instance->completion_insert & -+ (MAX_COMPLETIONS - 1)]; ++ completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; + + completion->header = header; + completion->reason = reason; @@ -80901,12 +80383,9 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + wmb(); + + if (reason == VCHIQ_MESSAGE_AVAILABLE) -+ user_service->message_available_pos = -+ instance->completion_insert; ++ user_service->message_available_pos = insert; + -+ instance->completion_insert++; -+ -+ mutex_unlock(&instance->completion_mutex); ++ instance->completion_insert = ++insert; + + up(&instance->insert_event); + @@ -81436,6 +80915,7 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + instance->completion_insert) + && !instance->closing) { + int rc; ++ + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + mutex_unlock(&instance->completion_mutex); + rc = down_interruptible(&instance->insert_event); @@ -81450,24 +80930,29 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + } + DEBUG_TRACE(AWAIT_COMPLETION_LINE); + -+ /* A read memory barrier is needed to stop prefetch of a stale -+ ** completion record -+ */ -+ rmb(); -+ + if (ret == 0) { + int msgbufcount = args.msgbufcount; ++ int remove; ++ ++ remove = instance->completion_remove; ++ + for (ret = 0; ret < args.count; ret++) { + VCHIQ_COMPLETION_DATA_T *completion; + VCHIQ_SERVICE_T *service; + USER_SERVICE_T *user_service; + VCHIQ_HEADER_T *header; -+ if (instance->completion_remove == -+ instance->completion_insert) ++ ++ if (remove == instance->completion_insert) + break; ++ + completion = &instance->completions[ -+ instance->completion_remove & -+ (MAX_COMPLETIONS - 1)]; ++ remove & (MAX_COMPLETIONS - 1)]; ++ ++ ++ /* A read memory barrier is needed to prevent ++ ** the prefetch of a stale completion record ++ */ ++ rmb(); + + service = completion->service_userdata; + user_service = service->base.userdata; @@ -81544,7 +81029,11 @@ index 0000000000000000000000000000000000000000..51e6018f413ca177146adfc4a2b947db + break; + } + -+ instance->completion_remove++; ++ /* Ensure that the above copy has completed ++ ** before advancing the remove pointer. */ ++ mb(); ++ ++ instance->completion_remove = ++remove; + } + + if (msgbufcount != args.msgbufcount) { @@ -84087,10 +83576,10 @@ index 0000000000000000000000000000000000000000..863b3e335c1aa4bbe7f8652e0e6c3713 +#endif /* VCHIQ_CONNECTED_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c new file mode 100644 -index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02bc41e599 +index 0000000000000000000000000000000000000000..71a3bedc55314f3b22dbff40c05dedf03b5e7169 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -0,0 +1,3929 @@ +@@ -0,0 +1,3933 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -84703,15 +84192,15 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + BITSET_T service_found[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; + int slot_queue_available; + -+ /* Use a read memory barrier to ensure that any state that may have -+ ** been modified by another thread is not masked by stale prefetched -+ ** values. */ -+ rmb(); -+ + /* Find slots which have been freed by the other side, and return them + ** to the available queue. */ + slot_queue_available = state->slot_queue_available; + ++ /* Use a memory barrier to ensure that any state that may have been ++ ** modified by another thread is not masked by stale prefetched ++ ** values. */ ++ mb(); ++ + while (slot_queue_available != local->slot_queue_recycle) { + unsigned int pos; + int slot_index = local->slot_queue[slot_queue_available++ & @@ -84719,6 +84208,8 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); + int data_found = 0; + ++ rmb(); ++ + vchiq_log_trace(vchiq_core_log_level, "%d: pfq %d=%x %x %x", + state->id, slot_index, (unsigned int)data, + local->slot_queue_recycle, slot_queue_available); @@ -84834,6 +84325,8 @@ index 0000000000000000000000000000000000000000..160db24aeea33a8296923501009c1f02 + up(&state->data_quota_event); + } + ++ mb(); ++ + state->slot_queue_available = slot_queue_available; + up(&state->slot_available_event); + } @@ -91472,10 +90965,10 @@ index 0000000000000000000000000000000000000000..b6bfa21155e431e93bfb2c149d324371 + return vchiq_build_time; +} -From 88c8fc95a876e0a12cad4e4ea94b904087942b5b Mon Sep 17 00:00:00 2001 +From 1a022d55ba03192671ab57aee87137e870501a88 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 16:07:06 +0100 -Subject: [PATCH 042/141] vc_mem: Add vc_mem driver +Subject: [PATCH 037/111] vc_mem: Add vc_mem driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -92480,10 +91973,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 8f6250cfb01812b76468450bd5b444cf9cb9f7a0 Mon Sep 17 00:00:00 2001 +From cceb483e245cc42f3bb2f96246080169084a8509 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 043/141] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 038/111] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -96901,10 +96394,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 7f32d45509743fd6e65691b064c8b1644f8a438c Mon Sep 17 00:00:00 2001 +From bd88b185bd5e789da9df304bceb13516d8fb68e3 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 044/141] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 039/111] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -97215,10 +96708,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From 18d5337bc159f0728bfced87cd74c1a80d5e9e85 Mon Sep 17 00:00:00 2001 +From e72622a4c692d9f85f4056d834804d738a6a3ce5 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 045/141] Add SMI driver +Subject: [PATCH 040/111] Add SMI driver Signed-off-by: Luke Wren --- @@ -99169,10 +98662,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From f758a1fea224d404f0e66b1f18310335971c7f64 Mon Sep 17 00:00:00 2001 +From 9d19676cd43462eeb3ff112f34566d179c5bc59a Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 046/141] Add SMI NAND driver +Subject: [PATCH 041/111] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -99537,10 +99030,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From 82bb93197112611f2a8b0c35f4a89db9ecb8f79e Mon Sep 17 00:00:00 2001 +From 883e2b3ab1545d31654c899b2175dba96718a477 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 047/141] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 042/111] lirc: added support for RaspberryPi GPIO lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others See: https://github.com/raspberrypi/linux/issues/525 @@ -100389,10 +99882,10 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From 1015e8e096b836dc67a178f535272a7255cb5821 Mon Sep 17 00:00:00 2001 +From 36561a4595f5e2fa6f0faedd5883be17dfc922d1 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 048/141] Add cpufreq driver +Subject: [PATCH 043/111] Add cpufreq driver Signed-off-by: popcornmix --- @@ -100403,10 +99896,10 @@ Signed-off-by: popcornmix create mode 100644 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 14b1f9393b057e106d7b068883ce486ea70239ec..c6e8bd553878a81d41cbe110930fb2791d787cc2 100644 +index d89b8afe23b6956b6c48e19c87cecc081e7725a1..465c727bb3ba70249409728d8f643a0002c6779c 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -229,6 +229,15 @@ config ARM_STI_CPUFREQ +@@ -220,6 +220,15 @@ config ARM_STI_CPUFREQ this config option if you wish to add CPUFreq support for STi based SoCs. @@ -100423,10 +99916,10 @@ index 14b1f9393b057e106d7b068883ce486ea70239ec..c6e8bd553878a81d41cbe110930fb279 bool "Tegra20 CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 9e63fb1b09f815fa70e1c4d908707ba39989f8fa..9e55083a9b247b86c2a29c9b268111918c10a7b9 100644 +index 0a9b6a093646bd1dd60ee092e362b24527f0ef1e..92a628a670c12c39c2be73fc91f65da5fdafd397 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -74,6 +74,7 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o +@@ -75,6 +75,7 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o @@ -100654,10 +100147,10 @@ index 0000000000000000000000000000000000000000..3eb9e9326231b08e6ee95ad486485245 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 3d10279adf0c0a1af20c8ec8427b3af1b8cb9868 Mon Sep 17 00:00:00 2001 +From 7540e4b3f77cb70cd77899f6cd80479e4f743599 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 049/141] Added hwmon/thermal driver for reporting core +Subject: [PATCH 044/111] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -100678,10 +100171,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/thermal/bcm2835-thermal.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index 3c3dc4a3d52cfb4685bdcbd2c62b55d33447804d..6789340aa1ce5d3711d23a87aafdd7e3c4793643 100644 +index 2d702ca6556f5b6185a95ec007ada7b124226272..32ab74bb842d658b6b937e38fa69b8abd31de94b 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -292,6 +292,13 @@ config INTEL_POWERCLAMP +@@ -282,6 +282,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -100696,10 +100189,10 @@ index 3c3dc4a3d52cfb4685bdcbd2c62b55d33447804d..6789340aa1ce5d3711d23a87aafdd7e3 tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index 8e9cbc3b5679ae221bcdd5d6bb82e91ebcfb3f1d..497014c0b271731daa831f7dbd5df0a6ca1ebe69 100644 +index 10b07c14f8a9f75363323d0c69542606d8dfed96..ac19930164fdcc773035a95af8136ec2f36fc8b7 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -38,6 +38,7 @@ obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o +@@ -39,6 +39,7 @@ obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o @@ -100823,10 +100316,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From bb69f1bafb8f1c4554094967a71bcc6565490294 Mon Sep 17 00:00:00 2001 +From cfbbb92f0c0496445cc97151580ea8b9a6d3e9d9 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 050/141] Add Chris Boot's i2c driver +Subject: [PATCH 045/111] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -100917,7 +100410,7 @@ Set the BSC_CLKT clock streching timeout to 35ms as per SMBus specs. create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 0967e1a5b3a25f1d351f83adb40f7bad0c52c659..c11fce150e1e371d17432af29ea96ab0a6c28d5d 100644 +index f167021b8c2178b8a9544bd7d750648c641f6c85..85e2de31c26cd03d5815fe397d47b461ad65359c 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" @@ -101483,10 +100976,10 @@ index 0000000000000000000000000000000000000000..c9b8e5cb1702e4b20e45214d81a7a40a +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From f2d4d11ef62907fa1baf51a856f9332350924ed9 Mon Sep 17 00:00:00 2001 +From 05cb723448582453691babf82541facfbb50defb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:27:06 +0200 -Subject: [PATCH 051/141] char: broadcom: Add vcio module +Subject: [PATCH 046/111] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101712,10 +101205,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From 89c0d29a525e784395e31862107e739ba787d0df Mon Sep 17 00:00:00 2001 +From ef21300b02abfc74b007a8bb4a66eda2bf3a88c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 26 Jun 2015 14:25:01 +0200 -Subject: [PATCH 052/141] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 047/111] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -101821,10 +101314,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..b980d531b35b9981a88356ef1c8a7b86 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 5a34e7fd4ff8b982785fda482d43ac50a476e3e5 Mon Sep 17 00:00:00 2001 +From 15948d937b12b2f04caf507d3ac39e044de22ed8 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 053/141] bcm2835: add v4l2 camera device +Subject: [PATCH 048/111] bcm2835: add v4l2 camera device - Supports raw YUV capture, preview, JPEG and H264. - Uses videobuf2 for data transfer, using dma_buf. @@ -102196,14 +101689,22 @@ Signed-off-by: Slawomir Stepien bcm2835-camera: Fix max/min error when looping over cameras/resolutions See: https://github.com/raspberrypi/linux/issues/1447#issuecomment-221303506 + +BCM2835-V4L2: Correct handling for BGR24 vs RGB24. + +There was a bug in the GPU firmware that had reversed these +two formats. +Detect the old firmware, and reverse the formats if necessary. + +Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> --- Documentation/video4linux/bcm2835-v4l2.txt | 60 + drivers/media/platform/Kconfig | 2 + drivers/media/platform/Makefile | 2 + drivers/media/platform/bcm2835/Kconfig | 25 + drivers/media/platform/bcm2835/Makefile | 5 + - drivers/media/platform/bcm2835/bcm2835-camera.c | 1982 ++++++++++++++++++++++ - drivers/media/platform/bcm2835/bcm2835-camera.h | 144 ++ + drivers/media/platform/bcm2835/bcm2835-camera.c | 2015 ++++++++++++++++++++++ + drivers/media/platform/bcm2835/bcm2835-camera.h | 145 ++ drivers/media/platform/bcm2835/controls.c | 1345 +++++++++++++++ drivers/media/platform/bcm2835/mmal-common.h | 53 + drivers/media/platform/bcm2835/mmal-encodings.h | 127 ++ @@ -102212,9 +101713,9 @@ See: https://github.com/raspberrypi/linux/issues/1447#issuecomment-221303506 drivers/media/platform/bcm2835/mmal-msg-port.h | 107 ++ drivers/media/platform/bcm2835/mmal-msg.h | 404 +++++ drivers/media/platform/bcm2835/mmal-parameters.h | 689 ++++++++ - drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 +++++++++++++++++++++ + drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++ drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++ - 17 files changed, 7170 insertions(+) + 17 files changed, 7204 insertions(+) create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt create mode 100644 drivers/media/platform/bcm2835/Kconfig create mode 100644 drivers/media/platform/bcm2835/Makefile @@ -102298,7 +101799,7 @@ index 0000000000000000000000000000000000000000..c585a8fadf91c5a04453e442fc29ed89 + +$ v4l2-ctl --list-formats diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index 201f5c296a951a24b35f5a0495af7b77b121acfd..b798ab852b51379b9e2b12aac158b86fff12315f 100644 +index 84e041c0a70e5b2634282f8605f7473efce3ac48..895c7182799dbccebb88e6545be8c5b281fe8518 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS @@ -102367,10 +101868,10 @@ index 0000000000000000000000000000000000000000..f17c79c33e4a07a2294907d3c748b4d6 +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c new file mode 100644 -index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd004c92cd3 +index 0000000000000000000000000000000000000000..70f4db2741037381e638d1dda5a95478809eb161 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -0,0 +1,1982 @@ +@@ -0,0 +1,2015 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -102488,7 +101989,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + .name = "RGB24 (LE)", + .fourcc = V4L2_PIX_FMT_RGB24, + .flags = 0, -+ .mmal = MMAL_ENCODING_BGR24, ++ .mmal = MMAL_ENCODING_RGB24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, @@ -102560,7 +102061,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + .name = "RGB24 (BE)", + .fourcc = V4L2_PIX_FMT_BGR24, + .flags = 0, -+ .mmal = MMAL_ENCODING_RGB24, ++ .mmal = MMAL_ENCODING_BGR24, + .depth = 24, + .mmal_component = MMAL_COMPONENT_CAMERA, + .ybbp = 3, @@ -103434,6 +102935,13 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + else + camera_port->format.encoding = mfmt->mmal; + ++ if (dev->rgb_bgr_swapped) { ++ if (camera_port->format.encoding == MMAL_ENCODING_RGB24) ++ camera_port->format.encoding = MMAL_ENCODING_BGR24; ++ else if (camera_port->format.encoding == MMAL_ENCODING_BGR24) ++ camera_port->format.encoding = MMAL_ENCODING_RGB24; ++ } ++ + camera_port->format.encoding_variant = 0; + camera_port->es.video.width = f->fmt.pix.width; + camera_port->es.video.height = f->fmt.pix.height; @@ -103944,12 +103452,17 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + return ret; +} + ++#define MAX_SUPPORTED_ENCODINGS 20 ++ +/* MMAL instance and component init */ +static int __init mmal_init(struct bm2835_mmal_dev *dev) +{ + int ret; + struct mmal_es_format *format; + u32 bool_true = 1; ++ u32 supported_encodings[MAX_SUPPORTED_ENCODINGS]; ++ int param_size; ++ struct vchiq_mmal_component *camera; + + ret = vchiq_mmal_init(&dev->instance); + if (ret < 0) @@ -103961,21 +103474,48 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + if (ret < 0) + goto unreg_mmal; + -+ if (dev->component[MMAL_COMPONENT_CAMERA]->outputs < -+ MMAL_CAMERA_PORT_COUNT) { ++ camera = dev->component[MMAL_COMPONENT_CAMERA]; ++ if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { + ret = -EINVAL; + goto unreg_camera; + } + + ret = set_camera_parameters(dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA], ++ camera, + dev); + if (ret < 0) + goto unreg_camera; + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW].format; ++ /* There was an error in the firmware that meant the camera component ++ * produced BGR instead of RGB. ++ * This is now fixed, but in order to support the old firmwares, we ++ * have to check. ++ */ ++ dev->rgb_bgr_swapped = true; ++ param_size = sizeof(supported_encodings); ++ ret = vchiq_mmal_port_parameter_get(dev->instance, ++ &camera->output[MMAL_CAMERA_PORT_CAPTURE], ++ MMAL_PARAMETER_SUPPORTED_ENCODINGS, ++ &supported_encodings, ++ ¶m_size); ++ if (ret == 0) { ++ int i; ++ ++ for (i = 0; i < param_size/sizeof(u32); i++) { ++ if (supported_encodings[i] == MMAL_ENCODING_BGR24) { ++ /* Found BGR24 first - old firmware. */ ++ break; ++ } ++ if (supported_encodings[i] == MMAL_ENCODING_RGB24) { ++ /* Found RGB24 first ++ * new firmware, so use RGB24. ++ */ ++ dev->rgb_bgr_swapped = false; ++ break; ++ } ++ } ++ } ++ format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; @@ -103989,9 +103529,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + format->es->video.frame_rate.num = 0; /* Rely on fps_range */ + format->es->video.frame_rate.den = 1; + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO].format; ++ format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + format->encoding_variant = MMAL_ENCODING_I420; @@ -104006,14 +103544,11 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + format->es->video.frame_rate.den = 1; + + vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO], ++ &camera->output[MMAL_CAMERA_PORT_VIDEO], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + -+ format = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE].format; ++ format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format; + + format->encoding = MMAL_ENCODING_OPAQUE; + @@ -104035,8 +103570,7 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 + dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; + + vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE], ++ &camera->output[MMAL_CAMERA_PORT_CAPTURE], + MMAL_PARAMETER_NO_IMAGE_PADDING, + &bool_true, sizeof(bool_true)); + @@ -104355,10 +103889,10 @@ index 0000000000000000000000000000000000000000..1b16c63315195c043c41d6676ecfedd0 +module_exit(bm2835_mmal_exit); diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h new file mode 100644 -index 0000000000000000000000000000000000000000..13f426f5ecdffeab714d658a6f8b76e63af5fcdb +index 0000000000000000000000000000000000000000..e6aeb7e7e381de65d6c6586205069a4c5cd33274 --- /dev/null +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -0,0 +1,144 @@ +@@ -0,0 +1,145 @@ +/* + * Broadcom BM2835 V4L2 driver + * @@ -104470,6 +104004,7 @@ index 0000000000000000000000000000000000000000..13f426f5ecdffeab714d658a6f8b76e6 + unsigned int camera_num; + unsigned int max_width; + unsigned int max_height; ++ unsigned int rgb_bgr_swapped; +}; + +int bm2835_mmal_init_controls( @@ -109514,10 +109049,10 @@ index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7d + +#endif /* MMAL_VCHIQ_H */ -From 9d7240665df60a5e171ae73b048b2744135f5ca5 Mon Sep 17 00:00:00 2001 +From 2be247eeb689931f548636200e5b64c51daa3248 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 054/141] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 049/111] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -110029,10 +109564,10 @@ index 0000000000000000000000000000000000000000..78c5845d2f01deb04b477327d83fa606 + return $trailer; +} -From 5237958e088b2951852b983ccaf0cc0d8fca3833 Mon Sep 17 00:00:00 2001 +From 4c81180311f93a3c6ed0f526f19d138a5c8c69cb Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 055/141] scripts/dtc: Update to upstream version 1.4.1 +Subject: [PATCH 050/111] scripts/dtc: Update to upstream version 1.4.1 Includes the new localfixups format. @@ -110065,10 +109600,10 @@ Signed-off-by: Phil Elwell 10 files changed, 1029 insertions(+), 654 deletions(-) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c -index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66aa0e632c3 100644 +index 386f9563313f713f896236814de35811d145d121..2164d8fe5f98f123bbf74aa25e69891b31bd8c64 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c -@@ -458,6 +458,8 @@ static void fixup_phandle_references(struct check *c, struct node *dt, +@@ -482,6 +482,8 @@ static void fixup_phandle_references(struct check *c, struct node *dt, struct node *node, struct property *prop) { struct marker *m = prop->val.markers; @@ -110077,7 +109612,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a struct node *refnode; cell_t phandle; -@@ -466,11 +468,70 @@ static void fixup_phandle_references(struct check *c, struct node *dt, +@@ -490,11 +492,70 @@ static void fixup_phandle_references(struct check *c, struct node *dt, refnode = get_node_by_ref(dt, m->ref); if (! refnode) { @@ -110150,7 +109685,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a phandle = get_node_phandle(dt, refnode); *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); } -@@ -652,6 +713,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, +@@ -676,6 +737,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, } TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); @@ -110196,7 +109731,7 @@ index 0c03ac9159c10a1e5eef0eca7136d246353aed16..88550b466b09a58ced505e1b1f73d66a static struct check *check_table[] = { &duplicate_node_names, &duplicate_property_names, &node_name_chars, &node_name_format, &property_name_chars, -@@ -670,6 +770,8 @@ static struct check *check_table[] = { +@@ -696,6 +796,8 @@ static struct check *check_table[] = { &avoid_default_addr_size, &obsolete_chosen_interrupt_controller, @@ -112656,7 +112191,7 @@ index 56212c8df660396b1d9bf6752e1121990e0789ab..f163b22b14b806b637c9fe996efd0276 void delete_labels(struct label **labels); diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c -index bd99fa2d33b85e873bd00178d6390d70f4afaa0d..238513780a5ba08c70d3995f45c35817fbabeb45 100644 +index ec14954f5810de3ad7262d5ee60e21b23565c155..f8f1e34b781f8c85d36a3d03f84ea5fe39f2e4b2 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -255,6 +255,204 @@ static int stringtable_insert(struct data *d, const char *str) @@ -112876,75 +112411,17 @@ index bd99fa2d33b85e873bd00178d6390d70f4afaa0d..238513780a5ba08c70d3995f45c35817 } diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h -index 11d93e6d8220c45d737175d22af4ab0ccaf871a1..2595dfda020fd9e03f0beff5006f229d5e393151 100644 +index ad9b05ae698b0495ecbda42ffcf4743555313a27..2595dfda020fd9e03f0beff5006f229d5e393151 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ --#define DTC_VERSION "DTC 1.4.1-gb06e55c8" +-#define DTC_VERSION "DTC 1.4.1-g53bf130b" +#define DTC_VERSION "DTC 1.4.1-g25efc119" -From b12e21f48fc616a5f49aa52e9cdf8a1bb9e4df1d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 5 Dec 2014 17:26:26 +0000 -Subject: [PATCH 056/141] fdt: Add support for the CONFIG_CMDLINE_EXTEND option - ---- - drivers/of/fdt.c | 29 ++++++++++++++++++++++++----- - 1 file changed, 24 insertions(+), 5 deletions(-) - -diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c -index 3349d2aa66346335fa3c84e485668bdbf77f6e52..1e2660514450f3f7a9d7e50c1d8cd94eb3381f48 100644 ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -960,19 +960,38 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, - - /* Retrieve command line */ - p = of_get_flat_dt_prop(node, "bootargs", &l); -- if (p != NULL && l > 0) -- strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else - * managed to set the command line, unless CONFIG_CMDLINE_FORCE - * is set in which case we override whatever was found earlier. -+ * -+ * However, it can be useful to be able to treat the default as -+ * a starting point to be extended using CONFIG_CMDLINE_EXTEND. - */ -+ ((char *)data)[0] = '\0'; -+ - #ifdef CONFIG_CMDLINE --#ifndef CONFIG_CMDLINE_FORCE -- if (!((char *)data)[0]) -+ strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ -+ if (p != NULL && l > 0) { -+#if defined(CONFIG_CMDLINE_EXTEND) -+ int len = strlen(data); -+ if (len > 0) { -+ strlcat(data, " ", COMMAND_LINE_SIZE); -+ len++; -+ } -+ strlcpy((char *)data + len, p, min((int)l, COMMAND_LINE_SIZE - len)); -+#elif defined(CONFIG_CMDLINE_FORCE) -+ pr_warning("Ignoring bootargs property (using the default kernel command line)\n"); -+#else -+ /* Neither extend nor force - just override */ -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif -- strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE); -+ } -+#else /* CONFIG_CMDLINE */ -+ if (p != NULL && l > 0) -+ strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); - #endif /* CONFIG_CMDLINE */ - - pr_debug("Command line is: %s\n", (char*)data); - -From 1bf8aae5799796f3db0674dabfdcca5fd7976d49 Mon Sep 17 00:00:00 2001 +From 9e47d686a2c50cd8e20ce11f4430494df04fab12 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 057/141] BCM2708: Add core Device Tree support +Subject: [PATCH 051/111] BCM2708: Add core Device Tree support Add the bare minimum needed to boot BCM2708 from a Device Tree. @@ -113011,32 +112488,34 @@ squash: Add cprman to dt BCM270X_DT: Use clk_core for I2C interfaces --- arch/arm/boot/dts/Makefile | 31 + - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 154 +++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 144 +++ + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 164 +++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 154 +++ arch/arm/boot/dts/bcm2708-rpi-cm.dts | 102 ++ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 52 + arch/arm/boot/dts/bcm2708.dtsi | 40 + - arch/arm/boot/dts/bcm2708_common.dtsi | 438 ++++++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 154 +++ + arch/arm/boot/dts/bcm2708_common.dtsi | 471 ++++++++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 164 +++ arch/arm/boot/dts/bcm2709.dtsi | 102 ++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 201 ++++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 211 ++++ arch/arm/boot/dts/bcm2710.dtsi | 102 ++ arch/arm/boot/dts/bcm2835-rpi-cm.dts | 93 ++ arch/arm/boot/dts/bcm2835-rpi-cm.dtsi | 30 + - arch/arm/boot/dts/overlays/Makefile | 99 ++ - arch/arm/boot/dts/overlays/README | 1161 ++++++++++++++++++++ + arch/arm/boot/dts/overlays/Makefile | 106 ++ + arch/arm/boot/dts/overlays/README | 1229 ++++++++++++++++++++ .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 53 + + arch/arm/boot/dts/overlays/ads1015-overlay.dts | 98 ++ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 89 ++ .../dts/overlays/akkordion-iqdacplus-overlay.dts | 46 + arch/arm/boot/dts/overlays/at86rf233-overlay.dts | 57 + .../audioinjector-wm8731-audio-overlay.dts | 39 + .../dts/overlays/bmp085_i2c-sensor-overlay.dts | 23 + arch/arm/boot/dts/overlays/dht11-overlay.dts | 39 + + .../boot/dts/overlays/dionaudio-loco-overlay.dts | 39 + arch/arm/boot/dts/overlays/dpi24-overlay.dts | 31 + arch/arm/boot/dts/overlays/dwc-otg-overlay.dts | 20 + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 29 + arch/arm/boot/dts/overlays/enc28j60-overlay.dts | 53 + - arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 45 + + arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 44 + .../boot/dts/overlays/gpio-poweroff-overlay.dts | 34 + .../boot/dts/overlays/hifiberry-amp-overlay.dts | 39 + .../boot/dts/overlays/hifiberry-dac-overlay.dts | 34 + @@ -113044,16 +112523,17 @@ BCM270X_DT: Use clk_core for I2C interfaces .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 93 ++ arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 +++ - arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 28 + + arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 43 + arch/arm/boot/dts/overlays/i2c-mux-overlay.dts | 139 +++ .../boot/dts/overlays/i2c-pwm-pca9685a-overlay.dts | 26 + - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 69 ++ + arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 73 ++ .../arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts | 61 + .../arm/boot/dts/overlays/i2c1-bcm2708-overlay.dts | 37 + .../boot/dts/overlays/i2s-gpio28-31-overlay.dts | 18 + arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts | 13 + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 43 + - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 43 + + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 46 + + .../overlays/iqaudio-digi-wm8804-audio-overlay.dts | 47 + .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 43 + .../boot/dts/overlays/justboom-digi-overlay.dts | 39 + arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 + @@ -113064,7 +112544,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/mz61581-overlay.dts | 117 ++ arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts | 27 + .../boot/dts/overlays/pi3-disable-bt-overlay.dts | 46 + - .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 ++ + .../boot/dts/overlays/pi3-miniuart-bt-overlay.dts | 64 + arch/arm/boot/dts/overlays/piscreen-overlay.dts | 102 ++ arch/arm/boot/dts/overlays/piscreen2r-overlay.dts | 106 ++ arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 ++ @@ -113082,6 +112562,7 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/rpi-proto-overlay.dts | 39 + arch/arm/boot/dts/overlays/rpi-sense-overlay.dts | 47 + .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 81 ++ + .../boot/dts/overlays/sc16is752-spi1-overlay.dts | 61 + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 32 + arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts | 36 + arch/arm/boot/dts/overlays/sdio-overlay.dts | 36 + @@ -113090,6 +112571,8 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/smi-nand-overlay.dts | 69 ++ arch/arm/boot/dts/overlays/smi-overlay.dts | 37 + .../boot/dts/overlays/spi-gpio35-39-overlay.dts | 31 + + arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 + + arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts | 26 + arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts | 57 + arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts | 69 ++ arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts | 81 ++ @@ -113098,12 +112581,12 @@ BCM270X_DT: Use clk_core for I2C interfaces arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 81 ++ arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 ++++ arch/arm/boot/dts/overlays/uart1-overlay.dts | 38 + - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 129 +++ + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 136 +++ arch/arm/boot/dts/overlays/vga666-overlay.dts | 30 + arch/arm/boot/dts/overlays/w1-gpio-overlay.dts | 39 + .../boot/dts/overlays/w1-gpio-pullup-overlay.dts | 41 + arch/arm/boot/dts/overlays/wittypi-overlay.dts | 44 + - 93 files changed, 7269 insertions(+) + 99 files changed, 7749 insertions(+) create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b-plus.dts create mode 100644 arch/arm/boot/dts/bcm2708-rpi-b.dts create mode 100755 arch/arm/boot/dts/bcm2708-rpi-cm.dts @@ -113119,12 +112602,14 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/Makefile create mode 100644 arch/arm/boot/dts/overlays/README create mode 100644 arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/ads1015-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/ads7846-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/at86rf233-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/bmp085_i2c-sensor-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dht11-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dpi24-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc-otg-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dwc2-overlay.dts @@ -113147,6 +112632,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/i2s-mmap-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/justboom-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/justboom-digi-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts @@ -113175,6 +112661,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/rpi-proto-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-sense-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdhost-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdio-1bit-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/sdio-overlay.dts @@ -113183,6 +112670,8 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/smi-nand-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/smi-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi-gpio35-39-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi-rtc-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-2cs-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/spi1-3cs-overlay.dts @@ -113198,7 +112687,7 @@ BCM270X_DT: Use clk_core for I2C interfaces create mode 100644 arch/arm/boot/dts/overlays/wittypi-overlay.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd0f7d812c 100644 +index 414b42710a366fc0f5708765d4ff0786e53a2b5b..93f2529ccbdfedb4b4e54898abf44911b47d2656 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -1,5 +1,26 @@ @@ -113228,10 +112717,10 @@ index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -839,10 +860,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - mt8127-moose.dtb \ - mt8135-evbp1.dtb +@@ -892,10 +913,20 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb + dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ + aspeed-ast2500-evb.dtb + +targets += dtbs dtbs_install +targets += $(dtb-y) @@ -113251,10 +112740,10 @@ index 95c1923ce6fa3d32bdeb2e3caedf0ad48eb4d679..1af92d7f71905fedfa7e19f72d1627bd +endif diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts new file mode 100644 -index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6e2eee966 +index 0000000000000000000000000000000000000000..db2705afa4e2229c961fe88bcae46233a4ce4542 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,154 @@ +@@ -0,0 +1,164 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -113294,6 +112783,11 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -113377,6 +112871,11 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -113411,10 +112910,10 @@ index 0000000000000000000000000000000000000000..0ac7725224aea4f490c670316f0ab8e6 +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf8023681478bcc +index 0000000000000000000000000000000000000000..beae0371477cc41f27006ef3f1ef7268839177df --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,144 @@ +@@ -0,0 +1,154 @@ +/dts-v1/; + +#include "bcm2708.dtsi" @@ -113454,6 +112953,11 @@ index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf80236 + brcm,pins = <28 29 30 31>; + brcm,function = <6>; /* alt2 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -113531,6 +113035,11 @@ index 0000000000000000000000000000000000000000..847483495a55f6e6567c81c10cf80236 + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -113773,10 +113282,10 @@ index 0000000000000000000000000000000000000000..f5a44cd4fef0ee221ed6ae1c43ca81da +}; diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f347098219d468 +index 0000000000000000000000000000000000000000..74434b986e3fbb257debfc79caef9fa68f750043 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -0,0 +1,438 @@ +@@ -0,0 +1,471 @@ +#include "dt-bindings/clock/bcm2835.h" +#include +#include "dt-bindings/power/raspberrypi-power.h" @@ -113835,10 +113344,32 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + <1 24>, + <1 25>, + <1 26>, -+ <1 27>; ++ /* dma channel 11-14 share one irq */ ++ <1 27>, ++ <1 27>, ++ <1 27>, ++ <1 27>, ++ /* unused shared irq for all channels */ ++ <1 28>; ++ interrupt-names = "dma0", ++ "dma1", ++ "dma2", ++ "dma3", ++ "dma4", ++ "dma5", ++ "dma6", ++ "dma7", ++ "dma8", ++ "dma9", ++ "dma10", ++ "dma11", ++ "dma12", ++ "dma13", ++ "dma14", ++ "dma-shared-all"; + + #dma-cells = <1>; -+ brcm,dma-channel-mask = <0x0f35>; ++ brcm,dma-channel-mask = <0x7f34>; + }; + + intc: interrupt-controller@7e00b200 { @@ -113940,7 +113471,7 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + * add more gpios if necessary as <&gpio 6 1> + * (but do not forget to make them output!) + */ -+ cs-gpios = <0>, <0>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; + }; + + i2c0: i2c@7e205000 { @@ -113959,6 +113490,17 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 + status = "disabled"; + }; + ++ dpi: dpi@7e208000 { ++ compatible = "brcm,bcm2835-dpi"; ++ reg = <0x7e208000 0x8c>; ++ clocks = <&cprman BCM2835_CLOCK_VPU>, ++ <&cprman BCM2835_CLOCK_DPI>; ++ clock-names = "core", "pixel"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ + pixelvalve1: pixelvalve@7e207000 { + compatible = "brcm,bcm2835-pixelvalve1"; + reg = <0x7e207000 0x100>; @@ -114217,10 +113759,10 @@ index 0000000000000000000000000000000000000000..6ea37c57f7b1f298c10a599982f34709 +}; diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff857a2603 +index 0000000000000000000000000000000000000000..eca72bd0d6e891b0096ac97b68c2da92199aa851 --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,154 @@ +@@ -0,0 +1,164 @@ +/dts-v1/; + +#include "bcm2709.dtsi" @@ -114260,6 +113802,11 @@ index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff + brcm,pins = <18 19 20 21>; + brcm,function = <4>; /* alt0 */ + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 45>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -114343,6 +113890,11 @@ index 0000000000000000000000000000000000000000..5e23c04f453ddadb97d244089100f3ff + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + __overrides__ { + uart0 = <&uart0>,"status"; @@ -114485,10 +114037,10 @@ index 0000000000000000000000000000000000000000..a8cfd7c4df5bcf7692d13882833c9785 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts new file mode 100644 -index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfaff14c151 +index 0000000000000000000000000000000000000000..a72e6e5a0ac0b2492db3d8034a5196b3e19ae008 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,201 @@ +@@ -0,0 +1,211 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -114552,6 +114104,11 @@ index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfa + brcm,function; + brcm,pull; + }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <40 41>; ++ brcm,function = <4>; ++ }; +}; + +&sdhost { @@ -114656,6 +114213,11 @@ index 0000000000000000000000000000000000000000..0979a27f05d97602ddbf550f7fe50cfa + hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +/ { + chosen { + bootargs = "8250.nr_uarts=1"; @@ -114935,10 +114497,10 @@ index 0000000000000000000000000000000000000000..9c4000fc686a9882b9ddde24fdcf937d +}; diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822924924cd +index 0000000000000000000000000000000000000000..7e740c894436e8fd9ed9b451e5b1f7888806922f --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,99 @@ +@@ -0,0 +1,106 @@ +ifeq ($(CONFIG_OF),y) + +# Overlays for the Raspberry Pi platform @@ -114954,15 +114516,17 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +endif + +dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo +dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo +dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo +dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo +dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo +dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dionaudio-loco.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo +dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo +dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo +dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo @@ -114972,19 +114536,21 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo +dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i2s-mmap.dtbo +dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dac.dtbo +dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo +dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo @@ -115009,20 +114575,23 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +dtbo-$(RPI_DT_OVERLAYS) += rpi-proto.dtbo +dtbo-$(RPI_DT_OVERLAYS) += rpi-sense.dtbo +dtbo-$(RPI_DT_OVERLAYS) += rra-digidac1-wm8741-audio.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += sc16is752-spi1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo +dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo +dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo ++dtbo-$(RPI_DT_OVERLAYS) += spi0-hw-cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo +dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo +dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo +dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo +dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo @@ -115040,10 +114609,10 @@ index 0000000000000000000000000000000000000000..0adb5b92c047cb7e12871cf75515f822 +clean-files := *.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README new file mode 100644 -index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776fe84e52a +index 0000000000000000000000000000000000000000..780bf6dda5a6694cb312140329120fda3b0c2f61 --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,1161 @@ +@@ -0,0 +1,1229 @@ +Introduction +============ + @@ -115214,6 +114783,28 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: ads1015 ++Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C ++Load: dtoverlay=ads1015,= ++Params: addr I2C bus address of device. Set based on how the ++ addr pin is wired. (default=0x48 assumes addr ++ is pulled to GND) ++ cha_enable Enable virtual channel a. (default=true) ++ cha_cfg Set the configuration for virtual channel a. ++ (default=4 configures this channel for the ++ voltage at A0 with respect to GND) ++ cha_datarate Set the datarate (samples/sec) for this channel. ++ (default=4 sets 1600 sps) ++ cha_gain Set the gain of the Programmable Gain ++ Amplifier for this channel. (default=2 sets the ++ full scale of the channel to 2.048 Volts) ++ ++ Channel (ch) parameters can be set for each enabled channel. ++ A maximum of 4 channels can be enabled (letters a thru d). ++ For more information refer to the device datasheet at: ++ http://www.ti.com/lit/ds/symlink/ads1015.pdf ++ ++ +Name: ads7846 +Info: ADS7846 Touch controller +Load: dtoverlay=ads7846,= @@ -115292,6 +114883,12 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + (default 4) + + ++Name: dionaudio-loco ++Info: Configures the Dion Audio LOCO DAC-AMP ++Load: dtoverlay=dionaudio-loco ++Params: ++ ++ +Name: dpi24 +Info: Overlay for a generic 24-bit DPI display + This uses GPIOs 0-27 (so no I2C, uart etc.), and activates the output @@ -115491,6 +115088,9 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + + trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) + ++ wakeup-source Specify that the RTC can be used as a wakeup ++ source ++ + +Name: i2c0-bcm2708 +Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations @@ -115561,6 +115161,19 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + responsibility of the user to ensure that + the Digital volume control is set to a value + that does not result in clipping/distortion!) ++ auto_mute_amp If specified, unmute/mute the IQaudIO amp when ++ starting/stopping audio playback. ++ unmute_amp If specified, unmute the IQaudIO amp once when ++ the DAC driver module loads. ++ ++ ++Name: iqaudio-digi-wm8804-audio ++Info: Configures the IQAudIO Digi WM8804 audio card ++Load: dtoverlay=iqaudio-digi-wm8804-audio,= ++Params: card_name Override the default, "IQAudIODigi", card name. ++ dai_name Override the default, "IQAudIO Digi", dai name. ++ dai_stream_name Override the default, "IQAudIO Digi HiFi", ++ dai stream name. + + +Name: justboom-dac @@ -115616,7 +115229,7 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + + +Name: mcp23017 -+Info: Configures the MCP23017 I2C port expander ++Info: Configures the MCP23017 I2C GPIO expander +Load: dtoverlay=mcp23017,= +Params: gpiopin Gpio pin connected to the INTA output of the + MCP23017 (default: 4) @@ -115708,7 +115321,9 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 + N.B. It is also necessary to edit /lib/systemd/system/hciuart.service + and replace ttyAMA0 with ttyS0, unless you have a system with udev rules + that create /dev/serial0 and /dev/serial1, in which case use -+ /dev/serial1 instead because it will always be correct. ++ /dev/serial1 instead because it will always be correct. Furthermore, ++ you must also set core_freq=250 in config.txt or the miniuart will not ++ work. +Load: dtoverlay=pi3-miniuart-bt +Params: + @@ -115894,6 +115509,16 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: sc16is752-spi1 ++Info: Overlay for the NXP SC16IS752 Dual UART with SPI Interface ++ Enables the chip on SPI1. ++ N.B.: spi1 is only accessible on devices with a 40pin header, eg: ++ A+, B+, Zero and PI2 B; as well as the Compute Module. ++ ++Load: dtoverlay=sc16is752-spi1,= ++Params: int_pin GPIO used for IRQ (default 24) ++ ++ +Name: sdhost +Info: Selects the bcm2835-sdhost SD/MMC driver, optionally with overclock. + N.B. This overlay is designed for situations where the mmc driver is @@ -115996,6 +115621,18 @@ index 0000000000000000000000000000000000000000..1516cc2e1616bb5e0cb519e05eee6776 +Params: + + ++Name: spi-rtc ++Info: Adds support for a number of SPI Real Time Clock devices ++Load: dtoverlay=spi-rtc,= ++Params: pcf2123 Select the PCF2123 device ++ ++ ++Name: spi0-hw-cs ++Info: Re-enables hardware CS/CE (chip selects) for SPI0 ++Load: dtoverlay=spi0-hw-cs ++Params: ++ ++ +Name: spi1-1cs +Info: Enables spi1 with a single chip select (CS) line and associated spidev + dev node. The gpio pin number for the CS line and spidev device node @@ -116264,6 +115901,110 @@ index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c6 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/ads1015-overlay.dts b/arch/arm/boot/dts/overlays/ads1015-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..02b9de46299bae8f22e1a665a482c0cb99cd30c9 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads1015-overlay.dts +@@ -0,0 +1,98 @@ ++/* ++ * 2016 - Erik Sejr ++ */ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ /* ----------- ADS1015 ------------ */ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ads1015: ads1015 { ++ compatible = "ti,ads1015"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "i2c_arm/ads1015"; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_a: channel_a { ++ reg = <4>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_b: channel_b { ++ reg = <5>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_c: channel_c { ++ reg = <6>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "i2c_arm/ads1015"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ channel_d: channel_d { ++ reg = <7>; ++ ti,gain = <2>; ++ ti,datarate = <4>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ addr = <&ads1015>,"reg:0"; ++ cha_enable = <0>,"=1"; ++ cha_cfg = <&channel_a>,"reg:0"; ++ cha_gain = <&channel_a>,"ti,gain:0"; ++ cha_datarate = <&channel_a>,"ti,datarate:0"; ++ chb_enable = <0>,"=2"; ++ chb_cfg = <&channel_b>,"reg:0"; ++ chb_gain = <&channel_b>,"ti,gain:0"; ++ chb_datarate = <&channel_b>,"ti,datarate:0"; ++ chc_enable = <0>,"=3"; ++ chc_cfg = <&channel_c>,"reg:0"; ++ chc_gain = <&channel_c>,"ti,gain:0"; ++ chc_datarate = <&channel_c>,"ti,datarate:0"; ++ chd_enable = <0>,"=4"; ++ chd_cfg = <&channel_d>,"reg:0"; ++ chd_gain = <&channel_d>,"ti,gain:0"; ++ chd_datarate = <&channel_d>,"ti,datarate:0"; ++ }; ++ ++}; diff --git a/arch/arm/boot/dts/overlays/ads7846-overlay.dts b/arch/arm/boot/dts/overlays/ads7846-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..edf2dc9d5d5f6830508edabf2d04c42d27ba9b41 @@ -116593,6 +116334,51 @@ index 0000000000000000000000000000000000000000..9bf67fd57bada3c3e06c09744fb18476 + <&dht11>,"gpios:4"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..3930f412bca4454c6673fb19859e607b360bc6c3 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-overlay.dts +@@ -0,0 +1,39 @@ ++// Definitions for Dion Audio LOCO DAC-AMP ++ ++/* ++ * PCM5242 DAC (in hardware mode) and TPA3118 AMP. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "dionaudio,loco-pcm5242-tpa3118"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/dpi24-overlay.dts b/arch/arm/boot/dts/overlays/dpi24-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..e4dbe40218a008ef4028c1214740c3d6bc574724 @@ -116752,10 +116538,10 @@ index 0000000000000000000000000000000000000000..db8a8feed94c010e368065fdd88b0286 +}; diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..a2d6bc79f4cd2604e6c65c000668cbb228327fe6 +index 0000000000000000000000000000000000000000..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 --- /dev/null +++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -@@ -0,0 +1,45 @@ +@@ -0,0 +1,44 @@ +// Definitions for ir-gpio module +/dts-v1/; +/plugin/; @@ -116794,8 +116580,7 @@ index 0000000000000000000000000000000000000000..a2d6bc79f4cd2604e6c65c000668cbb2 + __overrides__ { + // parameters + gpio_pin = <&gpio_ir>,"gpios:4", -+ <&gpio_ir_pins>,"brcm,pins:0", -+ <&gpio_ir_pins>,"brcm,pull:0"; // pin number ++ <&gpio_ir_pins>,"brcm,pins:0"; // pin number + gpio_pull = <&gpio_ir_pins>,"brcm,pull:0"; // pull-up/down state + + rc-map-name = <&gpio_ir>,"linux,rc-map-name"; // default rc map @@ -117288,10 +117073,10 @@ index 0000000000000000000000000000000000000000..8018aebde8e557f45ffd63eb86f6c7a1 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..2a2dc986770cfb036492ba8de19cbaff521c5fd5 +index 0000000000000000000000000000000000000000..b72b32e936774d901bc253b06e025c2dd48bdb1b --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -@@ -0,0 +1,28 @@ +@@ -0,0 +1,43 @@ +// Overlay for i2c_gpio bitbanging host bus. +/dts-v1/; +/plugin/; @@ -117313,6 +117098,21 @@ index 0000000000000000000000000000000000000000..2a2dc986770cfb036492ba8de19cbaff + }; + }; + }; ++ ++ fragment@1 { ++ target-path = "/aliases"; ++ __overlay__ { ++ i2c_gpio = "/i2c@0"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/__symbols__"; ++ __overlay__ { ++ i2c_gpio = "/i2c@0"; ++ }; ++ }; ++ + __overrides__ { + i2c_gpio_sda = <&i2c_gpio>,"gpios:4"; + i2c_gpio_scl = <&i2c_gpio>,"gpios:16"; @@ -117499,10 +117299,10 @@ index 0000000000000000000000000000000000000000..d1ffd2326669e46ad68939f94713cc99 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..40656474dfc16505433221a745c1d129c2737399 +index 0000000000000000000000000000000000000000..8b6f978155c02409eeb7c83353b8194fa3462435 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -0,0 +1,69 @@ +@@ -0,0 +1,73 @@ +// Definitions for several I2C based Real Time Clocks +/dts-v1/; +/plugin/; @@ -117570,6 +117370,10 @@ index 0000000000000000000000000000000000000000..40656474dfc16505433221a745c1d129 + pcf8523 = <&pcf8523>,"status"; + pcf8563 = <&pcf8563>,"status"; + trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; ++ wakeup-source = <&ds1339>,"wakeup-source?", ++ <&ds3231>,"wakeup-source?", ++ <&mcp7940x>,"wakeup-source?", ++ <&mcp7941x>,"wakeup-source?"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts @@ -117776,10 +117580,10 @@ index 0000000000000000000000000000000000000000..0d35c85382bb5766b3eeb9de1bd4a946 +}; diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..1d0663e19e7bf7395957ae49b501e5b15ecf3881 +index 0000000000000000000000000000000000000000..d4bad8742a985e2f15eed19ca52ef283a74fefb9 --- /dev/null +++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +// Definitions for IQaudIO DAC+ +/dts-v1/; +/plugin/; @@ -117812,15 +117616,71 @@ index 0000000000000000000000000000000000000000..1d0663e19e7bf7395957ae49b501e5b1 + + fragment@2 { + target = <&sound>; -+ frag2: __overlay__ { ++ iqaudio_dac: __overlay__ { + compatible = "iqaudio,iqaudio-dac"; + i2s-controller = <&i2s>; ++ mute-gpios = <&gpio 22 0>; ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ 24db_digital_gain = <&iqaudio_dac>,"iqaudio,24db_digital_gain?"; ++ auto_mute_amp = <&iqaudio_dac>,"iqaudio-dac,auto-mute-amp?"; ++ unmute_amp = <&iqaudio_dac>,"iqaudio-dac,unmute-amp?"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..da4fbfdfdbbbcf2505b9eb4789ddb779ec72cea8 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts +@@ -0,0 +1,47 @@ ++// Definitions for IQAudIO Digi WM8804 audio board ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ wm8804@3b { ++ #sound-dai-cells = <0>; ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ // DVDD-supply = <®_3v3>; ++ // PVDD-supply = <®_3v3>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ wm8804_digi: __overlay__ { ++ compatible = "iqaudio,wm8804-digi"; ++ i2s-controller = <&i2s>; + status = "okay"; + }; + }; + + __overrides__ { -+ 24db_digital_gain = <&frag2>,"iqaudio,24db_digital_gain?"; ++ card_name = <&wm8804_digi>,"wm8804-digi,card-name"; ++ dai_name = <&wm8804_digi>,"wm8804-digi,dai-name"; ++ dai_stream_name = <&wm8804_digi>,"wm8804-digi,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts @@ -119331,7 +119191,7 @@ index 0000000000000000000000000000000000000000..c021d02bb75ff5ceb5c5066d00e4bca9 +}; diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..1523eae9c39997aa68cfa583ada92a92395bb1e0 +index 0000000000000000000000000000000000000000..a442c8f0ec01b7503f32e070683a984e895f5668 --- /dev/null +++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts @@ -0,0 +1,34 @@ @@ -119350,7 +119210,7 @@ index 0000000000000000000000000000000000000000..1523eae9c39997aa68cfa583ada92a92 + }; + + fragment@1 { -+ target = <&soc>; ++ target-path = "/"; + __overlay__ { + pcm1794a-codec { + #sound-dai-cells = <0>; @@ -119672,6 +119532,73 @@ index 0000000000000000000000000000000000000000..16b1247bfa618ff85936ddf78c3aea58 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..d0a9e82dbea143e80249064873d8b9f0b56b2eaa +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/sc16is752-spi1-overlay.dts +@@ -0,0 +1,61 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&gpio>; ++ __overlay__ { ++ spi1_pins: spi1_pins { ++ brcm,pins = <19 20 21>; ++ brcm,function = <3>; /* alt4 */ ++ }; ++ ++ spi1_cs_pins: spi1_cs_pins { ++ brcm,pins = <18>; ++ brcm,function = <1>; /* output */ ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi1>; ++ frag1: __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi1_pins &spi1_cs_pins>; ++ cs-gpios = <&gpio 18 1>; ++ status = "okay"; ++ ++ sc16is752: sc16is752@0 { ++ compatible = "nxp,sc16is752"; ++ reg = <0>; /* CE0 */ ++ clocks = <&sc16is752_clk>; ++ interrupt-parent = <&gpio>; ++ interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */ ++ #gpio-controller; ++ #gpio-cells = <2>; ++ spi-max-frequency = <4000000>; ++ ++ sc16is752_clk: sc16is752_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <14745600>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&aux>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ int_pin = <&sc16is752>,"interrupts:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/sdhost-overlay.dts b/arch/arm/boot/dts/overlays/sdhost-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..a431177a1c9d320d5432ea448ad4d0f696c34525 @@ -120002,6 +119929,77 @@ index 0000000000000000000000000000000000000000..9648063d5963f2f6ec8f31038f3af582 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..88d1800d63c9f6727b46d4e590c8e96c671c3755 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts +@@ -0,0 +1,33 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&spidev0>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ rtc-pcf2123@0 { ++ compatible = "nxp,rtc-pcf2123"; ++ spi-max-frequency = <5000000>; ++ spi-cs-high = <1>; ++ reg = <0>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ pcf2123 = <0>, "=0=1"; ++ }; ++}; +diff --git a/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..ef9845f7184ee1ea90e8bdc23493b1cbbdc21896 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-hw-cs-overlay.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device tree overlay to re-enable hardware CS for SPI0 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ cs-gpios = <0>, <0>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0_cs_pins>; ++ __overlay__ { ++ brcm,pins = <8 7>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts b/arch/arm/boot/dts/overlays/spi1-1cs-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..71c243947004fa887998065df9c259b50edfa428 @@ -120728,10 +120726,10 @@ index 0000000000000000000000000000000000000000..fa73e1feaeb1bf53a6755e81a998e71c +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..a4ca2cabd4cd19d3a82ad1135604dfa52784fb3f +index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -0,0 +1,129 @@ +@@ -0,0 +1,136 @@ +/* + * vc4-kms-v3d-overlay.dts + */ @@ -120853,6 +120851,13 @@ index 0000000000000000000000000000000000000000..a4ca2cabd4cd19d3a82ad1135604dfa5 + }; + }; + ++ fragment@15 { ++ target-path = "/soc/dma"; ++ __overlay__ { ++ brcm,dma-channel-mask = <0x7f35>; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; @@ -121040,10 +121045,10 @@ index 0000000000000000000000000000000000000000..8498134fdbb3912e9ce18282b53084d8 + +}; -From 02be32ed3334f0edb4fcf4d61917c66c8442e0c0 Mon Sep 17 00:00:00 2001 +From 3e5b57715228496ea48c118917cb557d5c69ad74 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 20:00:21 +0000 -Subject: [PATCH 058/141] BCM270X_DT: Add a .dtbo target, use for overlays +Subject: [PATCH 052/111] BCM270X_DT: Add a .dtbo target, use for overlays Change the filenames and extensions to keep the pre-DDT style of overlay (-overlay.dtb) distinct from new ones that use a @@ -121105,10 +121110,10 @@ index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d24 .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index ddf83d0181e73d30fb86f68c0fa0a3f888335c0c..c819ddc5b7662eb03c158f9d8fcf8fe965bf577b 100644 +index e7df0f5db7ec273f45b755668815ce96ba1ffe46..8f50f48329b9460b7268322ea4fd99cf764134ec 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -306,6 +306,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ +@@ -311,6 +311,16 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ $(obj)/%.dtb: $(src)/%.dts FORCE $(call if_changed_dep,dtc) @@ -121126,10 +121131,10 @@ index ddf83d0181e73d30fb86f68c0fa0a3f888335c0c..c819ddc5b7662eb03c158f9d8fcf8fe9 # Bzip2 -From d19413c0965c18171ae81168fbc7b726496c7496 Mon Sep 17 00:00:00 2001 +From 6a36f694a362e7836a7ee1c0763920ff90ff8d1e Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 8 Apr 2016 17:43:27 +0100 -Subject: [PATCH 059/141] BCM270X_DT: Don't generate "linux,phandle" props +Subject: [PATCH 053/111] BCM270X_DT: Don't generate "linux,phandle" props The EPAPR standard says to use "phandle" properties to store phandles, rather than the deprecated "linux,phandle" version. By default, dtc @@ -121142,10 +121147,10 @@ Signed-off-by: Phil Elwell 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index c819ddc5b7662eb03c158f9d8fcf8fe965bf577b..b36099ab736a1373f61067a26c6e0d599d6c9a35 100644 +index 8f50f48329b9460b7268322ea4fd99cf764134ec..c1c3ceb265a3fd223b8a2a0a548ddad34f88ef4e 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib -@@ -308,7 +308,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE +@@ -313,7 +313,7 @@ $(obj)/%.dtb: $(src)/%.dts FORCE quiet_cmd_dtco = DTCO $@ cmd_dtco = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ @@ -121155,10 +121160,10 @@ index c819ddc5b7662eb03c158f9d8fcf8fe965bf577b..b36099ab736a1373f61067a26c6e0d59 -d $(depfile).dtc.tmp $(dtc-tmp) ; \ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) -From 1f046b8270b489dae7f2b58bff14930c274ea875 Mon Sep 17 00:00:00 2001 +From 2f0ee24bd8b41a4c6616319f888f805e65db0159 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 060/141] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 054/111] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -121188,7 +121193,7 @@ See: https://github.com/raspberrypi/linux/issues/1064 create mode 100644 drivers/leds/trigger/ledtrig-input.c diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 61143f55597e42f9b45fe4efe33a1c51614b22b4..e98df59ae47faf14b0cde1d6330a1d75b5ceb651 100644 +index 8229f063b483c77cf993891cb2bc2e7e9239ee6a..7a960e0bc2c7f918c880f724c22c773818f7df23 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -46,8 +46,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, @@ -121232,10 +121237,10 @@ index 61143f55597e42f9b45fe4efe33a1c51614b22b4..e98df59ae47faf14b0cde1d6330a1d75 state = !!gpiod_get_value_cansleep(led_dat->gpiod); else diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig -index 5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034..eb98cca4c239e5bb5c4abf7c731021ae56f3e91d 100644 +index 9893d911390daa4dd77986065ebde50b517d6b72..fbbe765e2fd2a593c2b1b40f71e4cb63d6339d80 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig -@@ -108,4 +108,11 @@ config LEDS_TRIGGER_CAMERA +@@ -116,6 +116,13 @@ config LEDS_TRIGGER_CAMERA This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. @@ -121246,16 +121251,19 @@ index 5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034..eb98cca4c239e5bb5c4abf7c731021ae + This allows the GPIOs assigned to be LEDs to be initialised to inputs. + If unsure, say Y. + - endif # LEDS_TRIGGERS + config LEDS_TRIGGER_PANIC + bool "LED Panic Trigger" + depends on LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile -index 1abf48dacf7ebfcfb8208f7ae7bdf29d7c11ba32..c03afdc34404a406a658326bcf28a2f22b4f4122 100644 +index 8cc64a4f4e255c1dd9fafde1ccd72d5a08ccbd5b..9452fe5640fec612f0e5e6a072d1af26d855847d 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile -@@ -8,3 +8,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o +@@ -9,4 +9,5 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_INPUT) += ledtrig-input.o + obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o diff --git a/drivers/leds/trigger/ledtrig-input.c b/drivers/leds/trigger/ledtrig-input.c new file mode 100644 index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05bae063e3b @@ -121317,13 +121325,13 @@ index 0000000000000000000000000000000000000000..27f8ebea43d86fc51c98db5c953da05b +MODULE_DESCRIPTION("Set LED GPIO to Input \"trigger\""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/leds.h b/include/linux/leds.h -index f203a8f89d30d0f3e214b43d2c72efea1bdad9f9..555cf15e87ee03c75d4bd836a3341645b020e857 100644 +index e5e7f2e80a54dd2f15737a3ef478287458641f6e..68086e559d963ed06a0ceb916f9b1555b213ddf8 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -50,6 +50,9 @@ struct led_classdev { - #define LED_SYSFS_DISABLE (1 << 22) - #define LED_DEV_CAP_FLASH (1 << 23) - #define LED_HW_PLUGGABLE (1 << 24) +@@ -52,6 +52,9 @@ struct led_classdev { + #define LED_DEV_CAP_FLASH (1 << 24) + #define LED_HW_PLUGGABLE (1 << 25) + #define LED_PANIC_INDICATOR (1 << 26) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT (1 << 30) +#define SET_GPIO_OUTPUT (1 << 31) @@ -121331,10 +121339,10 @@ index f203a8f89d30d0f3e214b43d2c72efea1bdad9f9..555cf15e87ee03c75d4bd836a3341645 /* Set LED brightness level * Must not sleep. Use brightness_set_blocking for drivers -From 9470cbd8875a8bdfd64b8dc63d7fd1a0174f14eb Mon Sep 17 00:00:00 2001 +From ea2507545d3bab2dcacab277a315e73e1d6e47de Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 061/141] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 055/111] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -121349,7 +121357,7 @@ Signed-off-by: Siarhei Siamashka 2 files changed, 35 insertions(+) diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index 4e73b6f6b1c0547877af572dfca953748d9eabc3..d3a8cc3f7dde67e904c695edac39a97b9beab678 100644 +index 76c1ad96fb37d4f07bbde6462f54825f566acbac..1d3b35ec8e393aac43dca0ec4566f7a7d0d8998a 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1084,6 +1084,25 @@ fb_blank(struct fb_info *info, int blank) @@ -121427,10 +121435,10 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..fa72af0c981710fe80bacf4cf6612f6d #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ #define FB_TYPE_PLANES 1 /* Non interleaved planes */ -From 572db909d29b86ecb3be3013d26a1238467dbde5 Mon Sep 17 00:00:00 2001 +From 87bd3668ff68813fed9de9d49038b3e46ecf771f Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 062/141] Speed up console framebuffer imageblit function +Subject: [PATCH 056/111] 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 @@ -121639,10 +121647,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From f8dff723eaf7d7a34d25c6ff717d03bb2fc7c0da Mon Sep 17 00:00:00 2001 +From 55a2f849b57c8ba767bdb979eab54a4072aeaa90 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 063/141] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 057/111] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) 1-wire: Add support for configuring pin for w1-gpio kernel module @@ -121808,10 +121816,10 @@ index a373ae69d9f6ef8a5925dbd5004cd5e9b8fc5c05..080e5976e2a6b75965ed753ddf29648c } diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 56a49ba41d83c0945203827946ba35dcb79897b0..881d72879b27fed8697ded8962e2f7c16796837d 100644 +index 129895f562b06630b464f2579dc9e5bdc105f35e..737a75b594c69716eae8d37479a40031b3045494 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h -@@ -171,6 +171,12 @@ struct w1_bus_master +@@ -173,6 +173,12 @@ struct w1_bus_master u8 (*set_pullup)(void *, int); @@ -121850,7 +121858,7 @@ index 20f766afa4c7d7b8116565687541f84184fe61f4..c4fbdb1f25e961f9f7bacbac7b52a6d7 mutex_lock(&w1_mlock); /* Search for the first available id (starting at 1). */ diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c -index 282092421cc9ee29d541e8722139387d0060c7db..fd0550f263f789b94038fd2fb2931022333029c2 100644 +index f4bc8c100a01b1f04a62ebca2528c51c05f40520..77527e37c7e749754cd3dc2241cdcb64f178166c 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -134,10 +134,22 @@ static void w1_pre_write(struct w1_master *dev) @@ -121892,10 +121900,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From c9fed34e3fbeb6d2573dc0a4caa6f68dc8d8a9cd Mon Sep 17 00:00:00 2001 +From 528bf1a9250bf36da5a68a23e567f159fe6b2d84 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 064/141] config: Enable CONFIG_MEMCG, but leave it disabled +Subject: [PATCH 058/111] config: Enable CONFIG_MEMCG, but leave it disabled (due to memory cost). Enable with cgroup_enable=memory. --- @@ -121903,10 +121911,10 @@ Subject: [PATCH 064/141] config: Enable CONFIG_MEMCG, but leave it disabled 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414c0df239b 100644 +index 75c0ff00aca60d298062755539e83cbfeaffaaf2..d3db7d24554254f8a33adb2ff9a0540262c78caa 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5587,7 +5587,7 @@ int __init cgroup_init_early(void) +@@ -5591,7 +5591,7 @@ int __init cgroup_init_early(void) return 0; } @@ -121915,7 +121923,7 @@ index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414 /** * cgroup_init - cgroup initialization -@@ -6117,6 +6117,28 @@ static int __init cgroup_no_v1(char *str) +@@ -6121,6 +6121,28 @@ static int __init cgroup_no_v1(char *str) } __setup("cgroup_no_v1=", cgroup_no_v1); @@ -121945,2970 +121953,24 @@ index 86cb5c6e89320f28e17691c6d69e58c9dfde81fb..0b5668a78c16322ac9f6b106c28cc414 * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -From e8b127ec4acfb3783529d0df323a2255bd647529 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 14:59:51 +0100 -Subject: [PATCH 065/141] 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 | 5 ++++ - sound/soc/codecs/Makefile | 2 ++ - sound/soc/codecs/pcm5102a.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 77 insertions(+) - create mode 100644 sound/soc/codecs/pcm5102a.c - -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 7ef3a0c16478d707b1ef843aecf0631a51813fb1..4308f90e688fce37f982ad4af0891a2411bcf420 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -100,6 +100,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_RT298 if I2C - select SND_SOC_RT5514 if I2C - select SND_SOC_RT5616 if I2C -+ select SND_SOC_PCM5102A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -631,6 +632,10 @@ config SND_SOC_RT5616 - tristate "Realtek RT5616 CODEC" - depends on I2C - -+config SND_SOC_PCM5102A -+ tristate -+ depends on I2C -+ - config SND_SOC_RT5631 - tristate "Realtek ALC5631/RT5631 CODEC" - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 185a712a7fe763bbba79fa1f4969cf5ba5424753..75220170be30c6144d503900e0f66ecd8de9ba6f 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -98,6 +98,7 @@ snd-soc-rt286-objs := rt286.o - snd-soc-rt298-objs := rt298.o - snd-soc-rt5514-objs := rt5514.o - snd-soc-rt5616-objs := rt5616.o -+snd-soc-pcm5102a-objs := pcm5102a.o - snd-soc-rt5631-objs := rt5631.o - snd-soc-rt5640-objs := rt5640.o - snd-soc-rt5645-objs := rt5645.o -@@ -307,6 +308,7 @@ obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o - obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o - obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o - obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.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_RT5645) += snd-soc-rt5645.o -diff --git a/sound/soc/codecs/pcm5102a.c b/sound/soc/codecs/pcm5102a.c -new file mode 100644 -index 0000000000000000000000000000000000000000..7c6598e717c523bc2e717861492a622ce66486c7 ---- /dev/null -+++ b/sound/soc/codecs/pcm5102a.c -@@ -0,0 +1,70 @@ -+/* -+ * 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 const struct of_device_id pcm5102a_of_match[] = { -+ { .compatible = "ti,pcm5102a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm5102a_of_match); -+ -+static struct platform_driver pcm5102a_codec_driver = { -+ .probe = pcm5102a_probe, -+ .remove = pcm5102a_remove, -+ .driver = { -+ .name = "pcm5102a-codec", -+ .owner = THIS_MODULE, -+ .of_match_table = pcm5102a_of_match, -+ }, -+}; -+ -+module_platform_driver(pcm5102a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM5102A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 977c8d769c949e7cf637af908b296870de72c356 Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 066/141] 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 | 4 ++ - sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 134 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index c5070aec5996aafb2d9daaf75163e16a29bc6892..ce81f14a88d08c90fb565cf3d60321a9b9a1fcee 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -7,3 +7,10 @@ config SND_BCM2835_SOC_I2S - Say Y or M if you want to add support for codecs attached to - the BCM2835 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 || SND_BCM2835_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 bc816b71e5a40958953bf7bf7e7bd08342e87738..b877d386363d935deefda3664089a4ae5b33b889 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o - - obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -0,0 +1,123 @@ -+/* -+ * 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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_dac_driver = { -+ .driver = { -+ .name = "snd-hifiberry-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dac_of_match, -+ }, -+ .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"); - -From bc7c4a474d3dc6280e3934bb217a6d8ca962465c Mon Sep 17 00:00:00 2001 -From: Florian Meier -Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 067/141] ASoC: Add support for Rpi-DAC - ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-dac.c | 119 ++++++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/Kconfig | 9 ++++ - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/pcm1794a.c | 69 +++++++++++++++++++++++++ - 6 files changed, 208 insertions(+) - create mode 100644 sound/soc/bcm/rpi-dac.c - create mode 100644 sound/soc/codecs/pcm1794a.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index ce81f14a88d08c90fb565cf3d60321a9b9a1fcee..900de22369a66758bbe49861238b647bd2ca037e 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -14,3 +14,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 || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM1794A -+ help -+ Say Y or M if you want to add support for RPi-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index b877d386363d935deefda3664089a4ae5b33b889..99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,5 +5,7 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1337a1c73 ---- /dev/null -+++ b/sound/soc/bcm/rpi-dac.c -@@ -0,0 +1,119 @@ -+/* -+ * 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 = "RPi-DAC", -+ .stream_name = "RPi-DAC 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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_rpi_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_rpi_dac_of_match[] = { -+ { .compatible = "rpi,rpi-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_rpi_dac_of_match); -+ -+static struct platform_driver snd_rpi_rpi_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_rpi_dac_of_match, -+ }, -+ .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 4308f90e688fce37f982ad4af0891a2411bcf420..513ab55fdc67af50f110f13ed6f6d6bb3740561e 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -101,6 +101,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_RT5514 if I2C - select SND_SOC_RT5616 if I2C - select SND_SOC_PCM5102A if I2C -+ select SND_SOC_PCM1794A if I2C - select SND_SOC_RT5631 if I2C - select SND_SOC_RT5640 if I2C - select SND_SOC_RT5645 if I2C -@@ -632,6 +633,14 @@ config SND_SOC_RT5616 - tristate "Realtek RT5616 CODEC" - depends on I2C - -+config SND_SOC_RT298 -+ tristate -+ depends on I2C -+ -+config SND_SOC_PCM1794A -+ tristate -+ depends on I2C -+ - config SND_SOC_PCM5102A - tristate - depends on I2C -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 75220170be30c6144d503900e0f66ecd8de9ba6f..b87e84543459776026be1b9a598fcc0c65abe987 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -98,6 +98,7 @@ snd-soc-rt286-objs := rt286.o - snd-soc-rt298-objs := rt298.o - snd-soc-rt5514-objs := rt5514.o - snd-soc-rt5616-objs := rt5616.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 -@@ -308,6 +309,7 @@ obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o - obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o - obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o - obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.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 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd843e17f4 ---- /dev/null -+++ b/sound/soc/codecs/pcm1794a.c -@@ -0,0 +1,69 @@ -+/* -+ * 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 const struct of_device_id pcm1794a_of_match[] = { -+ { .compatible = "ti,pcm1794a", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, pcm1794a_of_match); -+ -+static struct platform_driver pcm1794a_codec_driver = { -+ .probe = pcm1794a_probe, -+ .remove = pcm1794a_remove, -+ .driver = { -+ .name = "pcm1794a-codec", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(pcm1794a_of_match), -+ }, -+}; -+ -+module_platform_driver(pcm1794a_codec_driver); -+ -+MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); -+MODULE_AUTHOR("Florian Meier "); -+MODULE_LICENSE("GPL v2"); - -From 0f8e1f220bc0e4baf68c3e75884372e61cbde386 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 068/141] 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 | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c -index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 ---- a/sound/soc/codecs/wm8804.c -+++ b/sound/soc/codecs/wm8804.c -@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, - blen = 0x1; - break; - case 24: -+ case 32: - blen = 0x2; - break; - default: -@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { - }; - - #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 | \ -@@ -543,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { - }; - - static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { -- .idle_bias_off = true, -+ .idle_bias_off = false, - - .dapm_widgets = wm8804_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), - -From 5cb10ee9bb63758c8d125bb00222f3c543c647ad Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 069/141] ASoC: BCM:Add support for HiFiBerry Digi. Driver is - based on the patched WM8804 driver. - -Signed-off-by: Daniel Matuschek - -Add a parameter to turn off SPDIF output if no audio is playing - -This patch adds the paramater auto_shutdown_output to the kernel module. -Default behaviour of the module is the same, but when auto_shutdown_output -is set to 1, the SPDIF oputput will shutdown if no stream is playing. - -bugfix for 32kHz sample rate, was missing - -HiFiBerry Digi: set SPDIF status bits for sample rate - -The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. -While this is optional, some DACs and receivers do not accept this signal. This patch -adds the sample rate bits in the SPDIF status block. ---- - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 233 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_digi.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 900de22369a66758bbe49861238b647bd2ca037e..a34aff27bb3010f58773edb942adccc193ea0d26 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -15,6 +15,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 || SND_BCM2835_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 || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb..4d53c58dc6ba41116d1fa210b6ba08ee75526dd2 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,7 +5,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 - - 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 -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -0,0 +1,224 @@ -+/* -+ * 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 short int auto_shutdown_output = 0; -+module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); -+MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); -+ -+ -+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_startup(struct snd_pcm_substream *substream) { -+ /* turn on digital output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { -+ /* turn off output */ -+ if (auto_shutdown_output) { -+ /* turn off output */ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); -+ } -+} -+ -+ -+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 sampling_freq=1; -+ -+ int ret; -+ -+ samplerate = params_rate(params); -+ -+ if (samplerate<=96000) { -+ mclk_freq=samplerate*256; -+ mclk_div=WM8804_MCLKDIV_256FS; -+ } else { -+ mclk_freq=samplerate*128; -+ mclk_div=WM8804_MCLKDIV_128FS; -+ } -+ -+ switch (samplerate) { -+ case 32000: -+ sampling_freq=0x03; -+ break; -+ case 44100: -+ sampling_freq=0x00; -+ break; -+ case 48000: -+ sampling_freq=0x02; -+ break; -+ case 88200: -+ sampling_freq=0x08; -+ break; -+ case 96000: -+ sampling_freq=0x0a; -+ break; -+ case 176400: -+ sampling_freq=0x0c; -+ break; -+ case 192000: -+ sampling_freq=0x0e; -+ break; -+ default: -+ dev_err(codec->dev, -+ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", -+ samplerate); -+ } -+ -+ 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(codec->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); -+ -+ /* set sampling frequency status bits */ -+ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); -+ -+ 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, -+ .startup = snd_rpi_hifiberry_digi_startup, -+ .shutdown = snd_rpi_hifiberry_digi_shutdown, -+}; -+ -+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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-digi", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_digi_driver = { -+ .driver = { -+ .name = "snd-hifiberry-digi", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_digi_of_match, -+ }, -+ .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"); - -From f021cdc4838896508164acaa687458ecd4e95499 Mon Sep 17 00:00:00 2001 -From: Gordon Garrity -Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 070/141] Add IQaudIO Sound Card support for Raspberry Pi - -Set a limit of 0dB on Digital Volume Control - -The main volume control in the PCM512x DAC has a range up to -+24dB. This is dangerously loud and can potentially cause massive -clipping in the output stages. Therefore this sets a sensible -limit of 0dB for this control. - -Allow up to 24dB digital gain to be applied when using IQAudIO DAC+ - -24db_digital_gain DT param can be used to specify that PCM512x -codec "Digital" volume control should not be limited to 0dB gain, -and if specified will allow the full 24dB gain. - -Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt - -Add the ability to set the card name, dai name and dai stream name, from -dt config. - -Signed-off-by: DigitalDreamtime ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/iqaudio-dac.c | 148 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 157 insertions(+) - create mode 100644 sound/soc/bcm/iqaudio-dac.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index a34aff27bb3010f58773edb942adccc193ea0d26..38dcdd975b406b9308e151f5d3a80dbca5163be5 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -28,3 +28,10 @@ config SND_BCM2708_SOC_RPI_DAC - select SND_SOC_PCM1794A - help - Say Y or M if you want to add support for RPi-DAC. -+ -+config SND_BCM2708_SOC_IQAUDIO_DAC -+ tristate "Support for IQaudIO-DAC" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x_I2C -+ help -+ Say Y or M if you want to add support for IQaudIO-DAC. -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 4d53c58dc6ba41116d1fa210b6ba08ee75526dd2..08e4dc55757855fedec6845b82fc5f9f91f1584b 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,7 +7,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - 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-iqaudio-dac-objs := iqaudio-dac.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -new file mode 100644 -index 0000000000000000000000000000000000000000..b6b6dcf6e5a420d2c39d220b91928cd8ca832de7 ---- /dev/null -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,148 @@ -+/* -+ * ASoC Driver for IQaudIO 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 bool digital_gain_0db_limit = true; -+ -+static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ if (digital_gain_0db_limit) -+ { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai; -+// NOT USED struct snd_soc_codec *codec = rtd->codec; -+ 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_iqaudio_dac_ops = { -+ .hw_params = snd_rpi_iqaudio_dac_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { -+{ -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004c", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_iqaudio_dac_ops, -+ .init = snd_rpi_iqaudio_dac_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_iqaudio_dac = { -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_iqaudio_dac_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), -+}; -+ -+static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_iqaudio_dac.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_card *card = &snd_rpi_iqaudio_dac; -+ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool(pdev->dev.of_node, -+ "iqaudio,24db_digital_gain"); -+ if (of_property_read_string(pdev->dev.of_node, "card_name", -+ &card->name)) -+ card->name = "IQaudIODAC"; -+ if (of_property_read_string(pdev->dev.of_node, "dai_name", -+ &dai->name)) -+ dai->name = "IQaudIO DAC"; -+ if (of_property_read_string(pdev->dev.of_node, "dai_stream_name", -+ &dai->stream_name)) -+ dai->stream_name = "IQaudIO DAC HiFi"; -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); -+} -+ -+static const struct of_device_id iqaudio_of_match[] = { -+ { .compatible = "iqaudio,iqaudio-dac", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, iqaudio_of_match); -+ -+static struct platform_driver snd_rpi_iqaudio_dac_driver = { -+ .driver = { -+ .name = "snd-rpi-iqaudio-dac", -+ .owner = THIS_MODULE, -+ .of_match_table = iqaudio_of_match, -+ }, -+ .probe = snd_rpi_iqaudio_dac_probe, -+ .remove = snd_rpi_iqaudio_dac_remove, -+}; -+ -+module_platform_driver(snd_rpi_iqaudio_dac_driver); -+ -+MODULE_AUTHOR("Florian Meier "); -+MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); -+MODULE_LICENSE("GPL v2"); - -From 603759fab8f1f7fd294436cd617921e8ee310971 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 071/141] hid: Reduce default mouse polling interval to 60Hz - -Reduces overhead when using X ---- - drivers/hid/usbhid/hid-core.c | 10 +++++++--- - 1 file changed, 7 insertions(+), 3 deletions(-) - -diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400dfd5834f3 100644 ---- a/drivers/hid/usbhid/hid-core.c -+++ b/drivers/hid/usbhid/hid-core.c -@@ -49,7 +49,7 @@ - * Module parameters. - */ - --static unsigned int hid_mousepoll_interval; -+static unsigned int hid_mousepoll_interval = ~0; - module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); - MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - -@@ -1083,8 +1083,12 @@ static int usbhid_start(struct hid_device *hid) - } - - /* Change the polling interval of mice. */ -- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) -- interval = hid_mousepoll_interval; -+ if (hid->collection->usage == HID_GD_MOUSE) { -+ if (hid_mousepoll_interval == ~0 && interval < 16) -+ interval = 16; -+ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) -+ interval = hid_mousepoll_interval; -+ } - - ret = -ENOMEM; - if (usb_endpoint_dir_in(endpoint)) { - -From 80768052b3fdd23fd2cda99d1ee135f0680031b1 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 072/141] Added support for HiFiBerry DAC+ - -The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses -a different codec chip (PCM5122), therefore a new driver is necessary. - -Add support for the HiFiBerry DAC+ Pro. - -The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators. - -An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame. - -Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+ - -24db_digital_gain DT param can be used to specify that PCM512x -codec "Digital" volume control should not be limited to 0dB gain, -and if specified will allow the full 24dB gain. - -Add dt param to force HiFiBerry DAC+ Pro into slave mode - -"dtoverlay=hifiberry-dacplus,slave" - -Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode, -with Pi as master for bit and frame clock. - -Signed-off-by: DigitalDreamtime ---- - drivers/clk/Makefile | 1 + - drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/pcm512x.c | 3 +- - 6 files changed, 530 insertions(+), 1 deletion(-) - create mode 100644 drivers/clk/clk-hifiberry-dacpro.c - create mode 100644 sound/soc/bcm/hifiberry_dacplus.c - -diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 46869d696e4d7bba3962719fb9464684a2bb4c91..a202e6f0f294f5dd077871d6accf891f30c027ba 100644 ---- a/drivers/clk/Makefile -+++ b/drivers/clk/Makefile -@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o - obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o - obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o - obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o - obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o - obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o - obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o -diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c -new file mode 100644 -index 0000000000000000000000000000000000000000..3e35d455f4559bc0100a1e268eeb200f7c10df7e ---- /dev/null -+++ b/drivers/clk/clk-hifiberry-dacpro.c -@@ -0,0 +1,160 @@ -+/* -+ * Clock Driver for HiFiBerry DAC Pro -+ * -+ * Author: Stuart MacLean -+ * Copyright 2015 -+ * -+ * 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 -+ -+/* Clock rate of CLK44EN attached to GPIO6 pin */ -+#define CLK_44EN_RATE 22579200UL -+/* Clock rate of CLK48EN attached to GPIO3 pin */ -+#define CLK_48EN_RATE 24576000UL -+ -+/** -+ * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro -+ * @hw: clk_hw for the common clk framework -+ * @mode: 0 => CLK44EN, 1 => CLK48EN -+ */ -+struct clk_hifiberry_hw { -+ struct clk_hw hw; -+ uint8_t mode; -+}; -+ -+#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) -+ -+static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { -+ { .compatible = "hifiberry,dacpro-clk",}, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); -+ -+static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : -+ CLK_48EN_RATE; -+} -+ -+static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long *parent_rate) -+{ -+ long actual_rate; -+ -+ if (rate <= CLK_44EN_RATE) { -+ actual_rate = (long)CLK_44EN_RATE; -+ } else if (rate >= CLK_48EN_RATE) { -+ actual_rate = (long)CLK_48EN_RATE; -+ } else { -+ long diff44Rate = (long)(rate - CLK_44EN_RATE); -+ long diff48Rate = (long)(CLK_48EN_RATE - rate); -+ -+ if (diff44Rate < diff48Rate) -+ actual_rate = (long)CLK_44EN_RATE; -+ else -+ actual_rate = (long)CLK_48EN_RATE; -+ } -+ return actual_rate; -+} -+ -+ -+static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, -+ unsigned long rate, unsigned long parent_rate) -+{ -+ unsigned long actual_rate; -+ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); -+ -+ actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, -+ &parent_rate); -+ clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; -+ return 0; -+} -+ -+ -+const struct clk_ops clk_hifiberry_dacpro_rate_ops = { -+ .recalc_rate = clk_hifiberry_dacpro_recalc_rate, -+ .round_rate = clk_hifiberry_dacpro_round_rate, -+ .set_rate = clk_hifiberry_dacpro_set_rate, -+}; -+ -+static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) -+{ -+ int ret; -+ struct clk_hifiberry_hw *proclk; -+ struct clk *clk; -+ struct device *dev; -+ struct clk_init_data init; -+ -+ dev = &pdev->dev; -+ -+ proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); -+ if (!proclk) -+ return -ENOMEM; -+ -+ init.name = "clk-hifiberry-dacpro"; -+ init.ops = &clk_hifiberry_dacpro_rate_ops; -+ init.flags = CLK_IS_ROOT | CLK_IS_BASIC; -+ init.parent_names = NULL; -+ init.num_parents = 0; -+ -+ proclk->mode = 0; -+ proclk->hw.init = &init; -+ -+ clk = devm_clk_register(dev, &proclk->hw); -+ if (!IS_ERR(clk)) { -+ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, -+ clk); -+ } else { -+ dev_err(dev, "Fail to register clock driver\n"); -+ kfree(proclk); -+ ret = PTR_ERR(clk); -+ } -+ return ret; -+} -+ -+static int clk_hifiberry_dacpro_remove(struct platform_device *pdev) -+{ -+ of_clk_del_provider(pdev->dev.of_node); -+ return 0; -+} -+ -+static struct platform_driver clk_hifiberry_dacpro_driver = { -+ .probe = clk_hifiberry_dacpro_probe, -+ .remove = clk_hifiberry_dacpro_remove, -+ .driver = { -+ .name = "clk-hifiberry-dacpro", -+ .of_match_table = clk_hifiberry_dacpro_dt_ids, -+ }, -+}; -+ -+static int __init clk_hifiberry_dacpro_init(void) -+{ -+ return platform_driver_register(&clk_hifiberry_dacpro_driver); -+} -+core_initcall(clk_hifiberry_dacpro_init); -+ -+static void __exit clk_hifiberry_dacpro_exit(void) -+{ -+ platform_driver_unregister(&clk_hifiberry_dacpro_driver); -+} -+module_exit(clk_hifiberry_dacpro_exit); -+ -+MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:clk-hifiberry-dacpro"); -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 38dcdd975b406b9308e151f5d3a80dbca5163be5..8c338b5803042ad3834ee46a8dc93f53c53953f6 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -15,6 +15,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_DACPLUS -+ tristate "Support for HifiBerry DAC+" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM512x -+ 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 || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 08e4dc55757855fedec6845b82fc5f9f91f1584b..a29538e56b62ef6e7098b81b81e1389a22beeafa 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -5,11 +5,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - - # BCM2708 Machine Support - snd-soc-hifiberry-dac-objs := hifiberry_dac.o -+snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -new file mode 100644 -index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -0,0 +1,358 @@ -+/* -+ * ASoC Driver for HiFiBerry DAC+ / DAC Pro -+ * -+ * Author: Daniel Matuschek, Stuart MacLean -+ * Copyright 2014-2015 -+ * based on code by Florian Meier -+ * -+ * 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 -+#include -+ -+#include "../codecs/pcm512x.h" -+ -+#define HIFIBERRY_DACPRO_NOCLOCK 0 -+#define HIFIBERRY_DACPRO_CLK44EN 1 -+#define HIFIBERRY_DACPRO_CLK48EN 2 -+ -+struct pcm512x_priv { -+ struct regmap *regmap; -+ struct clk *sclk; -+}; -+ -+/* Clock rate of CLK44EN attached to GPIO6 pin */ -+#define CLK_44EN_RATE 22579200UL -+/* Clock rate of CLK48EN attached to GPIO3 pin */ -+#define CLK_48EN_RATE 24576000UL -+ -+static bool slave; -+static bool snd_rpi_hifiberry_is_dacpro; -+static bool digital_gain_0db_limit = true; -+ -+static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_codec *codec, -+ int clk_id) -+{ -+ switch (clk_id) { -+ case HIFIBERRY_DACPRO_NOCLOCK: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x00); -+ break; -+ case HIFIBERRY_DACPRO_CLK44EN: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x20); -+ break; -+ case HIFIBERRY_DACPRO_CLK48EN: -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x04); -+ break; -+ } -+} -+ -+static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_codec *codec) -+{ -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x24, 0x24); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_codec *codec) -+{ -+ int sck; -+ -+ sck = snd_soc_read(codec, PCM512x_RATE_DET_4); -+ return (!(sck & 0x40)); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep( -+ struct snd_soc_codec *codec) -+{ -+ msleep(2); -+ return snd_rpi_hifiberry_dacplus_is_sclk(codec); -+} -+ -+static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_codec *codec) -+{ -+ bool isClk44EN, isClk48En, isNoClk; -+ -+ snd_rpi_hifiberry_dacplus_clk_gpio(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK44EN); -+ isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_NOCLOCK); -+ isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK48EN); -+ isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); -+ -+ return (isClk44EN && isClk48En && !isNoClk); -+} -+ -+static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate) -+{ -+ int type; -+ -+ switch (sample_rate) { -+ case 11025: -+ case 22050: -+ case 44100: -+ case 88200: -+ case 176400: -+ type = HIFIBERRY_DACPRO_CLK44EN; -+ break; -+ default: -+ type = HIFIBERRY_DACPRO_CLK48EN; -+ break; -+ } -+ return type; -+} -+ -+static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_codec *codec, -+ int sample_rate) -+{ -+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); -+ -+ if (!IS_ERR(pcm512x->sclk)) { -+ int ctype; -+ -+ ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate); -+ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN) -+ ? CLK_44EN_RATE : CLK_48EN_RATE); -+ snd_rpi_hifiberry_dacplus_select_clk(codec, ctype); -+ } -+} -+ -+static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ struct pcm512x_priv *priv; -+ -+ if (slave) -+ snd_rpi_hifiberry_is_dacpro = false; -+ else -+ snd_rpi_hifiberry_is_dacpro = -+ snd_rpi_hifiberry_dacplus_is_pro_card(codec); -+ -+ if (snd_rpi_hifiberry_is_dacpro) { -+ struct snd_soc_dai_link *dai = rtd->dai_link; -+ -+ dai->name = "HiFiBerry DAC+ Pro"; -+ dai->stream_name = "HiFiBerry DAC+ Pro HiFi"; -+ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM; -+ -+ snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11); -+ snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03); -+ snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63); -+ } else { -+ priv = snd_soc_codec_get_drvdata(codec); -+ priv->sclk = ERR_PTR(-ENOENT); -+ } -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); -+ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); -+ -+ if (digital_gain_0db_limit) -+ { -+ int ret; -+ struct snd_soc_card *card = rtd->card; -+ -+ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); -+ if (ret < 0) -+ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); -+ } -+ -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_update_rate_den( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); -+ struct snd_ratnum *rats_no_pll; -+ unsigned int num = 0, den = 0; -+ int err; -+ -+ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL); -+ if (!rats_no_pll) -+ return -ENOMEM; -+ -+ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; -+ rats_no_pll->den_min = 1; -+ rats_no_pll->den_max = 128; -+ rats_no_pll->den_step = 1; -+ -+ err = snd_interval_ratnum(hw_param_interval(params, -+ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den); -+ if (err >= 0 && den) { -+ params->rate_num = num; -+ params->rate_den = den; -+ } -+ -+ devm_kfree(rtd->dev, rats_no_pll); -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro( -+ struct snd_soc_dai *cpu_dai, struct snd_pcm_hw_params *params) -+{ -+ int bratio = snd_pcm_format_physical_width(params_format(params)) -+ * params_channels(params); -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio); -+} -+ -+static int snd_rpi_hifiberry_dacplus_hw_params( -+ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) -+{ -+ int ret; -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ if (snd_rpi_hifiberry_is_dacpro) { -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_rpi_hifiberry_dacplus_set_sclk(codec, -+ params_rate(params)); -+ -+ ret = snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro(cpu_dai, -+ params); -+ if (!ret) -+ ret = snd_rpi_hifiberry_dacplus_update_rate_den( -+ substream, params); -+ } else { -+ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64); -+ } -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_startup( -+ struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); -+ return 0; -+} -+ -+static void snd_rpi_hifiberry_dacplus_shutdown( -+ struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00); -+} -+ -+/* machine stream operations */ -+static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { -+ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, -+ .startup = snd_rpi_hifiberry_dacplus_startup, -+ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { -+{ -+ .name = "HiFiBerry DAC+", -+ .stream_name = "HiFiBerry DAC+ HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "pcm512x-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "pcm512x.1-004d", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_dacplus_ops, -+ .init = snd_rpi_hifiberry_dacplus_init, -+}, -+}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_hifiberry_dacplus = { -+ .name = "snd_rpi_hifiberry_dacplus", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_hifiberry_dacplus_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), -+}; -+ -+static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai; -+ -+ dai = &snd_rpi_hifiberry_dacplus_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ -+ digital_gain_0db_limit = !of_property_read_bool( -+ pdev->dev.of_node, "hifiberry,24db_digital_gain"); -+ slave = of_property_read_bool(pdev->dev.of_node, -+ "hifiberry-dacplus,slave"); -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -+ if (ret) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); -+} -+ -+static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-dacplus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); -+ -+static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { -+ .driver = { -+ .name = "snd-rpi-hifiberry-dacplus", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, -+ }, -+ .probe = snd_rpi_hifiberry_dacplus_probe, -+ .remove = snd_rpi_hifiberry_dacplus_remove, -+}; -+ -+module_platform_driver(snd_rpi_hifiberry_dacplus_driver); -+ -+MODULE_AUTHOR("Daniel Matuschek "); -+MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c -index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 ---- a/sound/soc/codecs/pcm512x.c -+++ b/sound/soc/codecs/pcm512x.c -@@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, - int fssp; - int gpio; - -- lrclk_div = snd_soc_params_to_frame_size(params); -+ lrclk_div = snd_pcm_format_physical_width(params_format(params)) -+ * params_channels(params); - if (lrclk_div == 0) { - dev_err(dev, "No LRCLK?\n"); - return -EINVAL; - -From 4c27bbc1e655e55b28889b902af5c5a5be6172e4 Mon Sep 17 00:00:00 2001 -From: Daniel Matuschek -Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 073/141] Added driver for HiFiBerry Amp amplifier add-on board - -The driver contains a low-level hardware driver for the TAS5713 and the -drivers for the Raspberry Pi I2S subsystem. - -TAS5713: return error if initialisation fails - -Existing TAS5713 driver logs errors during initialisation, but does not return -an error code. Therefore even if initialisation fails, the driver will still be -loaded, but won't work. This patch fixes this. I2C communication error will now -reported correctly by a non-zero return code. - -HiFiBerry Amp: fix device-tree problems - -Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. ---- - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ - sound/soc/codecs/Kconfig | 4 + - sound/soc/codecs/Makefile | 2 + - sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ - sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 722 insertions(+) - create mode 100644 sound/soc/bcm/hifiberry_amp.c - create mode 100644 sound/soc/codecs/tas5713.c - create mode 100644 sound/soc/codecs/tas5713.h - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 8c338b5803042ad3834ee46a8dc93f53c53953f6..7677c898773e6dd87c3ef385e380aa42c85e66d8 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -29,6 +29,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI - help - Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. - -+config SND_BCM2708_SOC_HIFIBERRY_AMP -+ tristate "Support for the HifiBerry Amp" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_TAS5713 -+ help -+ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. -+ - config SND_BCM2708_SOC_RPI_DAC - tristate "Support for RPi-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index a29538e56b62ef6e7098b81b81e1389a22beeafa..30db4951129c2d853c5cf631f4cd1263926692d0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -7,11 +7,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o - snd-soc-hifiberry-dac-objs := hifiberry_dac.o - snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -new file mode 100644 -index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 ---- /dev/null -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,128 @@ -+/* -+ * ASoC Driver for HifiBerry AMP -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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_amp_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ // ToDo: init of the dsp-registers. -+ return 0; -+} -+ -+static int snd_rpi_hifiberry_amp_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, 64); -+} -+ -+static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { -+ .hw_params = snd_rpi_hifiberry_amp_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { -+ { -+ .name = "HifiBerry AMP", -+ .stream_name = "HifiBerry AMP HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "tas5713-hifi", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "tas5713.1-001b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | -+ SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBS_CFS, -+ .ops = &snd_rpi_hifiberry_amp_ops, -+ .init = snd_rpi_hifiberry_amp_init, -+ }, -+}; -+ -+ -+static struct snd_soc_card snd_rpi_hifiberry_amp = { -+ .name = "snd_rpi_hifiberry_amp", -+ .owner = THIS_MODULE, -+ .dai_link = snd_rpi_hifiberry_amp_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), -+}; -+ -+static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { -+ { .compatible = "hifiberry,hifiberry-amp", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); -+ -+ -+static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_hifiberry_amp.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); -+ -+ if (ret != 0) { -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+ -+static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); -+} -+ -+ -+static struct platform_driver snd_rpi_hifiberry_amp_driver = { -+ .driver = { -+ .name = "snd-hifiberry-amp", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_hifiberry_amp_of_match, -+ }, -+ .probe = snd_rpi_hifiberry_amp_probe, -+ .remove = snd_rpi_hifiberry_amp_remove, -+}; -+ -+ -+module_platform_driver(snd_rpi_hifiberry_amp_driver); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 513ab55fdc67af50f110f13ed6f6d6bb3740561e..ebcfbfd843db89e8ca86b318d2783c850079c15a 100644 ---- a/sound/soc/codecs/Kconfig -+++ b/sound/soc/codecs/Kconfig -@@ -129,6 +129,7 @@ config SND_SOC_ALL_CODECS - select SND_SOC_TFA9879 if I2C - select SND_SOC_TLV320AIC23_I2C if I2C - select SND_SOC_TLV320AIC23_SPI if SPI_MASTER -+ select SND_SOC_TAS5713 if I2C - select SND_SOC_TLV320AIC26 if SPI_MASTER - select SND_SOC_TLV320AIC31XX if I2C - select SND_SOC_TLV320AIC32X4 if I2C -@@ -759,6 +760,9 @@ config SND_SOC_TFA9879 - tristate "NXP Semiconductors TFA9879 amplifier" - depends on I2C - -+config SND_SOC_TAS5713 -+ tristate -+ - config SND_SOC_TLV320AIC23 - tristate - -diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index b87e84543459776026be1b9a598fcc0c65abe987..9974a13a2c7ef4a9c476c34faa133ecc7e687272 100644 ---- a/sound/soc/codecs/Makefile -+++ b/sound/soc/codecs/Makefile -@@ -132,6 +132,7 @@ snd-soc-sti-sas-objs := sti-sas.o - snd-soc-tas5086-objs := tas5086.o - snd-soc-tas571x-objs := tas571x.o - snd-soc-tfa9879-objs := tfa9879.o -+snd-soc-tas5713-objs := tas5713.o - snd-soc-tlv320aic23-objs := tlv320aic23.o - snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o - snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -340,6 +341,7 @@ obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o - obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o - obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o - obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o -+obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o - obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o - obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o -diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9b2713861dcbed751842ca29c88eb1eae5867411 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.c -@@ -0,0 +1,369 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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 -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "tas5713.h" -+ -+ -+static struct i2c_client *i2c; -+ -+struct tas5713_priv { -+ struct regmap *regmap; -+ int mclk_div; -+ struct snd_soc_codec *codec; -+}; -+ -+static struct tas5713_priv *priv_data; -+ -+ -+ -+ -+/* -+ * _ _ ___ _ ___ _ _ -+ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ -+ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< -+ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ -+ * -+ */ -+ -+static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); -+ -+ -+static const struct snd_kcontrol_new tas5713_snd_controls[] = { -+ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), -+ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) -+}; -+ -+ -+ -+ -+/* -+ * __ __ _ _ ___ _ -+ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ -+ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| -+ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params, -+ struct snd_soc_dai *dai) -+{ -+ u16 blen = 0x00; -+ -+ struct snd_soc_codec *codec; -+ codec = dai->codec; -+ priv_data->codec = dai->codec; -+ -+ switch (params_format(params)) { -+ case SNDRV_PCM_FORMAT_S16_LE: -+ blen = 0x03; -+ break; -+ case SNDRV_PCM_FORMAT_S20_3LE: -+ blen = 0x1; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ blen = 0x04; -+ break; -+ case SNDRV_PCM_FORMAT_S32_LE: -+ blen = 0x05; -+ break; -+ default: -+ dev_err(dai->dev, "Unsupported word length: %u\n", -+ params_format(params)); -+ return -EINVAL; -+ } -+ -+ // set word length -+ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); -+ -+ return 0; -+} -+ -+ -+static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) -+{ -+ unsigned int val = 0; -+ -+ struct tas5713_priv *tas5713; -+ struct snd_soc_codec *codec = dai->codec; -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ if (mute) { -+ val = TAS5713_SOFT_MUTE_ALL; -+ } -+ -+ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); -+} -+ -+ -+static const struct snd_soc_dai_ops tas5713_dai_ops = { -+ .hw_params = tas5713_hw_params, -+ .mute_stream = tas5713_mute_stream, -+}; -+ -+ -+static struct snd_soc_dai_driver tas5713_dai = { -+ .name = "tas5713-hifi", -+ .playback = { -+ .stream_name = "Playback", -+ .channels_min = 2, -+ .channels_max = 2, -+ .rates = SNDRV_PCM_RATE_8000_48000, -+ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), -+ }, -+ .ops = &tas5713_dai_ops, -+}; -+ -+ -+ -+ -+/* -+ * ___ _ ___ _ -+ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ -+ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| -+ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static int tas5713_remove(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ return 0; -+} -+ -+ -+static int tas5713_probe(struct snd_soc_codec *codec) -+{ -+ struct tas5713_priv *tas5713; -+ int i, ret; -+ -+ i2c = container_of(codec->dev, struct i2c_client, dev); -+ -+ tas5713 = snd_soc_codec_get_drvdata(codec); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Trim oscillator -+ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); -+ if (ret < 0) return ret; -+ msleep(1000); -+ -+ // Reset error -+ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); -+ if (ret < 0) return ret; -+ -+ // Clock mode: 44/48kHz, MCLK=64xfs -+ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); -+ if (ret < 0) return ret; -+ -+ // I2S 24bit -+ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); -+ if (ret < 0) return ret; -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); -+ if (ret < 0) return ret; -+ -+ // Set volume to 0db -+ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); -+ if (ret < 0) return ret; -+ -+ // Now start programming the default initialization sequence -+ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { -+ ret = i2c_master_send(i2c, -+ tas5713_init_sequence[i].data, -+ tas5713_init_sequence[i].size); -+ if (ret < 0) { -+ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); -+ } -+ } -+ -+ // Unmute -+ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); -+ if (ret < 0) return ret; -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { -+ .probe = tas5713_probe, -+ .remove = tas5713_remove, -+ .controls = tas5713_snd_controls, -+ .num_controls = ARRAY_SIZE(tas5713_snd_controls), -+}; -+ -+ -+ -+ -+/* -+ * ___ ___ ___ ___ _ -+ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ -+ * | | / / (__ | |) | '_| \ V / -_) '_| -+ * |___/___\___| |___/|_| |_|\_/\___|_| -+ * -+ */ -+ -+static const struct reg_default tas5713_reg_defaults[] = { -+ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB -+ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB -+ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB -+ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB -+}; -+ -+ -+static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case TAS5713_DEVICE_ID: -+ case TAS5713_ERROR_STATUS: -+ return true; -+ default: -+ return false; -+ } -+} -+ -+ -+static const struct of_device_id tas5713_of_match[] = { -+ { .compatible = "ti,tas5713", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, tas5713_of_match); -+ -+ -+static struct regmap_config tas5713_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ -+ .max_register = TAS5713_MAX_REGISTER, -+ .volatile_reg = tas5713_reg_volatile, -+ -+ .cache_type = REGCACHE_RBTREE, -+ .reg_defaults = tas5713_reg_defaults, -+ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), -+}; -+ -+ -+static int tas5713_i2c_probe(struct i2c_client *i2c, -+ const struct i2c_device_id *id) -+{ -+ int ret; -+ -+ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); -+ if (!priv_data) -+ return -ENOMEM; -+ -+ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); -+ if (IS_ERR(priv_data->regmap)) { -+ ret = PTR_ERR(priv_data->regmap); -+ return ret; -+ } -+ -+ i2c_set_clientdata(i2c, priv_data); -+ -+ ret = snd_soc_register_codec(&i2c->dev, -+ &soc_codec_dev_tas5713, &tas5713_dai, 1); -+ -+ return ret; -+} -+ -+ -+static int tas5713_i2c_remove(struct i2c_client *i2c) -+{ -+ snd_soc_unregister_codec(&i2c->dev); -+ i2c_set_clientdata(i2c, NULL); -+ -+ kfree(priv_data); -+ -+ return 0; -+} -+ -+ -+static const struct i2c_device_id tas5713_i2c_id[] = { -+ { "tas5713", 0 }, -+ { } -+}; -+ -+MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); -+ -+ -+static struct i2c_driver tas5713_i2c_driver = { -+ .driver = { -+ .name = "tas5713", -+ .owner = THIS_MODULE, -+ .of_match_table = tas5713_of_match, -+ }, -+ .probe = tas5713_i2c_probe, -+ .remove = tas5713_i2c_remove, -+ .id_table = tas5713_i2c_id -+}; -+ -+ -+static int __init tas5713_modinit(void) -+{ -+ int ret = 0; -+ -+ ret = i2c_add_driver(&tas5713_i2c_driver); -+ if (ret) { -+ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", -+ ret); -+ } -+ -+ return ret; -+} -+module_init(tas5713_modinit); -+ -+ -+static void __exit tas5713_exit(void) -+{ -+ i2c_del_driver(&tas5713_i2c_driver); -+} -+module_exit(tas5713_exit); -+ -+ -+MODULE_AUTHOR("Sebastian Eickhoff "); -+MODULE_DESCRIPTION("ASoC driver for TAS5713"); -+MODULE_LICENSE("GPL v2"); -diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h -new file mode 100644 -index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8f612a342 ---- /dev/null -+++ b/sound/soc/codecs/tas5713.h -@@ -0,0 +1,210 @@ -+/* -+ * ASoC Driver for TAS5713 -+ * -+ * Author: Sebastian Eickhoff -+ * Copyright 2014 -+ * -+ * 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. -+ */ -+ -+#ifndef _TAS5713_H -+#define _TAS5713_H -+ -+ -+// TAS5713 I2C-bus register addresses -+ -+#define TAS5713_CLOCK_CTRL 0x00 -+#define TAS5713_DEVICE_ID 0x01 -+#define TAS5713_ERROR_STATUS 0x02 -+#define TAS5713_SYSTEM_CTRL1 0x03 -+#define TAS5713_SERIAL_DATA_INTERFACE 0x04 -+#define TAS5713_SYSTEM_CTRL2 0x05 -+#define TAS5713_SOFT_MUTE 0x06 -+#define TAS5713_VOL_MASTER 0x07 -+#define TAS5713_VOL_CH1 0x08 -+#define TAS5713_VOL_CH2 0x09 -+#define TAS5713_VOL_HEADPHONE 0x0A -+#define TAS5713_VOL_CONFIG 0x0E -+#define TAS5713_MODULATION_LIMIT 0x10 -+#define TAS5713_IC_DLY_CH1 0x11 -+#define TAS5713_IC_DLY_CH2 0x12 -+#define TAS5713_IC_DLY_CH3 0x13 -+#define TAS5713_IC_DLY_CH4 0x14 -+ -+#define TAS5713_START_STOP_PERIOD 0x1A -+#define TAS5713_OSC_TRIM 0x1B -+#define TAS5713_BKND_ERR 0x1C -+ -+#define TAS5713_INPUT_MUX 0x20 -+#define TAS5713_SRC_SELECT_CH4 0x21 -+#define TAS5713_PWM_MUX 0x25 -+ -+#define TAS5713_CH1_BQ0 0x29 -+#define TAS5713_CH1_BQ1 0x2A -+#define TAS5713_CH1_BQ2 0x2B -+#define TAS5713_CH1_BQ3 0x2C -+#define TAS5713_CH1_BQ4 0x2D -+#define TAS5713_CH1_BQ5 0x2E -+#define TAS5713_CH1_BQ6 0x2F -+#define TAS5713_CH1_BQ7 0x58 -+#define TAS5713_CH1_BQ8 0x59 -+ -+#define TAS5713_CH2_BQ0 0x30 -+#define TAS5713_CH2_BQ1 0x31 -+#define TAS5713_CH2_BQ2 0x32 -+#define TAS5713_CH2_BQ3 0x33 -+#define TAS5713_CH2_BQ4 0x34 -+#define TAS5713_CH2_BQ5 0x35 -+#define TAS5713_CH2_BQ6 0x36 -+#define TAS5713_CH2_BQ7 0x5C -+#define TAS5713_CH2_BQ8 0x5D -+ -+#define TAS5713_CH4_BQ0 0x5A -+#define TAS5713_CH4_BQ1 0x5B -+#define TAS5713_CH3_BQ0 0x5E -+#define TAS5713_CH3_BQ1 0x5F -+ -+#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B -+#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C -+#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E -+#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F -+#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 -+#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 -+#define TAS5713_DRC_CTRL 0x46 -+ -+#define TAS5713_BANK_SW_CTRL 0x50 -+#define TAS5713_CH1_OUTPUT_MIXER 0x51 -+#define TAS5713_CH2_OUTPUT_MIXER 0x52 -+#define TAS5713_CH1_INPUT_MIXER 0x53 -+#define TAS5713_CH2_INPUT_MIXER 0x54 -+#define TAS5713_OUTPUT_POST_SCALE 0x56 -+#define TAS5713_OUTPUT_PRESCALE 0x57 -+ -+#define TAS5713_IDF_POST_SCALE 0x62 -+ -+#define TAS5713_CH1_INLINE_MIXER 0x70 -+#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 -+#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 -+#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 -+#define TAS5713_CH2_INLINE_MIXER 0x74 -+#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 -+#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 -+#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 -+ -+#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 -+#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 -+ -+#define TAS5713_REGISTER_COUNT 0x46 -+#define TAS5713_MAX_REGISTER 0xF9 -+ -+ -+// Bitmasks for registers -+#define TAS5713_SOFT_MUTE_ALL 0x07 -+ -+ -+ -+struct tas5713_init_command { -+ const int size; -+ const char *const data; -+}; -+ -+static const struct tas5713_init_command tas5713_init_sequence[] = { -+ -+ // Trim oscillator -+ { .size = 2, .data = "\x1B\x00" }, -+ // System control register 1 (0x03): block DC -+ { .size = 2, .data = "\x03\x80" }, -+ // Mute everything -+ { .size = 2, .data = "\x05\x40" }, -+ // Modulation limit register (0x10): 97.7% -+ { .size = 2, .data = "\x10\x02" }, -+ // Interchannel delay registers -+ // (0x11, 0x12, 0x13, and 0x14): BD mode -+ { .size = 2, .data = "\x11\xB8" }, -+ { .size = 2, .data = "\x12\x60" }, -+ { .size = 2, .data = "\x13\xA0" }, -+ { .size = 2, .data = "\x14\x48" }, -+ // PWM shutdown group register (0x19): no shutdown -+ { .size = 2, .data = "\x19\x00" }, -+ // Input multiplexer register (0x20): BD mode -+ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, -+ // PWM output mux register (0x25) -+ // Channel 1 --> OUTA, channel 1 neg --> OUTB -+ // Channel 2 --> OUTC, channel 2 neg --> OUTD -+ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, -+ // DRC control (0x46): DRC off -+ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, -+ // BKND_ERR register (0x1C): 299ms reset period -+ { .size = 2, .data = "\x1C\x07" }, -+ // Mute channel 3 -+ { .size = 2, .data = "\x0A\xFF" }, -+ // Volume configuration register (0x0E): volume slew 512 steps -+ { .size = 2, .data = "\x0E\x90" }, -+ // Clock control register (0x00): 44/48kHz, MCLK=64xfs -+ { .size = 2, .data = "\x00\x60" }, -+ // Bank switch and eq control (0x50): no bank switching -+ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, -+ // Volume registers (0x07, 0x08, 0x09, 0x0A) -+ { .size = 2, .data = "\x07\x20" }, -+ { .size = 2, .data = "\x08\x30" }, -+ { .size = 2, .data = "\x09\x30" }, -+ { .size = 2, .data = "\x0A\xFF" }, -+ // 0x72, 0x73, 0x76, 0x77 input mixer: -+ // no intermix between channels -+ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, -+ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: -+ // no inline DRC inmix -+ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, -+ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, -+ // 0x56, 0x57 Output scale -+ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, -+ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, -+ // 0x3B, 0x3c -+ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, -+ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, -+ // 0x51, 0x52: output mixer -+ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, -+ // PEQ defaults -+ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, -+}; -+ -+ -+#endif /* _TAS5713_H */ - -From 419495c7b6f7f29a8977453e02116b12fd0419f4 Mon Sep 17 00:00:00 2001 -From: Ryan Coe -Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 074/141] Update ds1307 driver for device-tree support - -Signed-off-by: Ryan Coe ---- - drivers/rtc/rtc-ds1307.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c -index e94eb0952286300ec9847cddaf317476ddd05423..f5d93be977142d306c787547736e8722bfe51b3c 100644 ---- a/drivers/rtc/rtc-ds1307.c -+++ b/drivers/rtc/rtc-ds1307.c -@@ -1608,6 +1608,14 @@ static int ds1307_remove(struct i2c_client *client) - return 0; - } - -+#ifdef CONFIG_OF -+static const struct of_device_id ds1307_of_match[] = { -+ { .compatible = "maxim,ds1307" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, ds1307_of_match); -+#endif -+ - static struct i2c_driver ds1307_driver = { - .driver = { - .name = "rtc-ds1307", - -From 1345cf9552dd55512240e16e076c3f67b018363c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 27 Feb 2015 15:10:24 +0000 -Subject: [PATCH 075/141] enc28j60: Add device tree compatible string and an - overlay - ---- - drivers/net/ethernet/microchip/enc28j60.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c -index 86ea17e7ba7bff17f40755663e1b10b7d7b4cbcc..a1b20c146eb8f3d9af757b79c19be96ed43adfba 100644 ---- a/drivers/net/ethernet/microchip/enc28j60.c -+++ b/drivers/net/ethernet/microchip/enc28j60.c -@@ -1630,9 +1630,16 @@ static int enc28j60_remove(struct spi_device *spi) - return 0; - } - -+static const struct of_device_id enc28j60_of_match[] = { -+ { .compatible = "microchip,enc28j60", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, enc28j60_of_match); -+ - static struct spi_driver enc28j60_driver = { - .driver = { - .name = DRV_NAME, -+ .of_match_table = enc28j60_of_match, - }, - .probe = enc28j60_probe, - .remove = enc28j60_remove, - -From 52b97cb78e02a4f2d606d47fd7b350f518f9dfca Mon Sep 17 00:00:00 2001 -From: Waldemar Brodkorb -Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 076/141] Add driver for rpi-proto - -Forward port of 3.10.x driver from https://github.com/koalo -We are using a custom board and would like to use rpi 3.18.x -kernel. Patch works fine for our embedded system. - -URL to the audio chip: -http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ - -Playback tested with devicetree enabled. - -Signed-off-by: Waldemar Brodkorb ---- - sound/soc/bcm/Kconfig | 7 +++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 163 insertions(+) - create mode 100644 sound/soc/bcm/rpi-proto.c - -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7677c898773e6dd87c3ef385e380aa42c85e66d8..8669a9ac9734c465c7dc3f40c864f71b68a6de75 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -43,6 +43,13 @@ config SND_BCM2708_SOC_RPI_DAC - help - Say Y or M if you want to add support for RPi-DAC. - -+config SND_BCM2708_SOC_RPI_PROTO -+ tristate "Support for Rpi-PROTO" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM8731 -+ help -+ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). -+ - config SND_BCM2708_SOC_IQAUDIO_DAC - tristate "Support for IQaudIO-DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 30db4951129c2d853c5cf631f4cd1263926692d0..4f5ab1fa4414e64a164eaa4575ffaa06d1cbf332 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -9,6 +9,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-hifiberry-amp-objs := hifiberry_amp.o - snd-soc-rpi-dac-objs := rpi-dac.o -+snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o - - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -16,4 +17,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o - obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o -diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed6772b19a2d ---- /dev/null -+++ b/sound/soc/bcm/rpi-proto.c -@@ -0,0 +1,154 @@ -+/* -+ * 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_codec *codec = rtd->codec; -+ 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); -+ if (ret < 0){ -+ dev_err(codec->dev, -+ "Failed to set BCLK ratio %d\n", ret); -+ return ret; -+ } -+ -+ /* Set proto sysclk */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, -+ sysclk, SND_SOC_CLOCK_IN); -+ if (ret < 0) { -+ dev_err(codec->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", -+ .owner = THIS_MODULE, -+ .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; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; -+ i2s_node = of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ -+ if (i2s_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ } -+ } -+ -+ 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 const struct of_device_id snd_rpi_proto_of_match[] = { -+ { .compatible = "rpi,rpi-proto", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); -+ -+static struct platform_driver snd_rpi_proto_driver = { -+ .driver = { -+ .name = "snd-rpi-proto", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_rpi_proto_of_match, -+ }, -+ .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"); - -From 8b79a80ed03b0aa97088181f1d3d599be28ced1d Mon Sep 17 00:00:00 2001 +From f909136a4636faf8d7fd30fce66104b487b2ecff Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 077/141] config: Add default configs +Subject: [PATCH 059/111] config: Add default configs --- - arch/arm/configs/bcm2709_defconfig | 1279 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1289 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2568 insertions(+) + arch/arm/configs/bcm2709_defconfig | 1288 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1296 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2584 insertions(+) create mode 100644 arch/arm/configs/bcm2709_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483e32c7fd8 +index 0000000000000000000000000000000000000000..af34386096ebc5b3c7d7cf60120e5ad48ba635b8 --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1279 @@ +@@ -0,0 +1,1288 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +CONFIG_LOCALVERSION="-v7" @@ -124925,6 +121987,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_FREEZER=y @@ -124944,6 +122007,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y @@ -124976,6 +122040,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y @@ -125309,7 +122374,6 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m -+CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y @@ -125466,6 +122530,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m @@ -125525,6 +122590,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_GPIO_BCM_VIRT=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m @@ -125767,12 +122833,15 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -125949,6 +123018,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m @@ -125970,9 +123040,9 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_R9701=m @@ -125982,6 +123052,7 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_BCM2708=y @@ -126190,10 +123261,10 @@ index 0000000000000000000000000000000000000000..f42c5ebcbff904746a282a3d6fb13483 +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44a922c0ea +index 0000000000000000000000000000000000000000..da2df3d30e15a55a34b45d3ebbf98e906da6379c --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1289 @@ +@@ -0,0 +1,1296 @@ +# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_PHYS_OFFSET=0 +# CONFIG_LOCALVERSION_AUTO is not set @@ -126209,6 +123280,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y ++CONFIG_NMI_LOG_BUF_SHIFT=12 +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_FREEZER=y @@ -126228,6 +123300,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y ++CONFIG_TRIM_UNUSED_KSYMS=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y @@ -126587,7 +123660,6 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NFC=m -+CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_CMA=y @@ -126744,6 +123816,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_RPISENSE=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m @@ -126772,7 +123845,6 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y -+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y @@ -126802,6 +123874,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_MCP23S08=m +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m @@ -127044,12 +124117,15 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m -+CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m ++CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m +CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m ++CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI=m +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_DIGIDAC1_SOUNDCARD=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m +CONFIG_SND_SOC_ADAU1701=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -127241,6 +124317,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_LEDS_TRIGGER_TRANSIENT=m +CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_INPUT=y ++CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +CONFIG_RTC_DRV_DS1307=m @@ -127262,9 +124339,9 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m ++CONFIG_RTC_DRV_DS1302=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_R9701=m @@ -127274,6 +124351,7 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_PCF2127=m ++CONFIG_RTC_DRV_RV3029C2=m +CONFIG_DMADEVICES=y +CONFIG_DMA_BCM2835=y +CONFIG_DMA_BCM2708=y @@ -127484,10 +124562,49 @@ index 0000000000000000000000000000000000000000..8bd02073ab8f35ef28db5fcd628e3e44 +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From 7e74308c1c5da500e6e745656092196ba3c683f0 Mon Sep 17 00:00:00 2001 +From aa15290cdeac3133072d8ea98a4197d32f13cbf0 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 14 Jul 2014 22:02:09 +0100 +Subject: [PATCH 060/111] hid: Reduce default mouse polling interval to 60Hz + +Reduces overhead when using X +--- + drivers/hid/usbhid/hid-core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c +index ae83af649a607f67239f1a64bf45dd4b5770cc7d..4a7af9d0b910f59d17421ce14138400dfd5834f3 100644 +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -49,7 +49,7 @@ + * Module parameters. + */ + +-static unsigned int hid_mousepoll_interval; ++static unsigned int hid_mousepoll_interval = ~0; + module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); + MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); + +@@ -1083,8 +1083,12 @@ static int usbhid_start(struct hid_device *hid) + } + + /* Change the polling interval of mice. */ +- if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) +- interval = hid_mousepoll_interval; ++ if (hid->collection->usage == HID_GD_MOUSE) { ++ if (hid_mousepoll_interval == ~0 && interval < 16) ++ interval = 16; ++ else if (hid_mousepoll_interval != ~0 && hid_mousepoll_interval != 0) ++ interval = hid_mousepoll_interval; ++ } + + ret = -ENOMEM; + if (usb_endpoint_dir_in(endpoint)) { + +From 8d8a8564c00e70c5606af68c4acdb8c5e2ac8cf8 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 078/141] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 061/111] rpi-ft5406: Add touchscreen driver for pi LCD display Fix driver detection failure Check that the buffer response is non-zero meaning the touchscreen was detected @@ -127782,10 +124899,10 @@ index 0000000000000000000000000000000000000000..b27dbee8f56773dbd2a5503dc864747d +MODULE_DESCRIPTION("Touchscreen driver for memory based FT5406"); +MODULE_LICENSE("GPL"); -From 9f1c48411136e52a5ee06ceb154ebc20a4636df8 Mon Sep 17 00:00:00 2001 +From caa5f748c7c34919061a800d3b9600aeef93ae3f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 13 Oct 2014 11:47:53 +0100 -Subject: [PATCH 079/141] Improve __copy_to_user and __copy_from_user +Subject: [PATCH 062/111] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -129341,10 +126458,10 @@ index 6bd1089b07e0960830ed6bd6a8345202b7efd8b0..cd17dd11ebe7bbe00089e70cd2ccea74 static unsigned long noinline __clear_user_memset(void __user *addr, unsigned long n) -From 7c1b0f68ed1f587b0bf3755ec32f8045695d9507 Mon Sep 17 00:00:00 2001 +From 626055cab99e810168105994b1368f783545728f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 080/141] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 063/111] gpio-poweroff: Allow it to work on Raspberry Pi The Raspberry Pi firmware manages the power-down and reboot process. To do this it installs a pm_power_off handler, causing @@ -129379,10 +126496,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From 7899a439b21e546e9d0999fcc25f0c6ef3c05c4c Mon Sep 17 00:00:00 2001 +From f62be97894117c25b4f8bbad415770b21f09a919 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 081/141] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 064/111] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -129592,7 +126709,7 @@ index 0000000000000000000000000000000000000000..6a416769065d2198344792eb02d8e38d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index eea61e349e26afe4b0f9d52a3f036877f0e2403a..d2c3b724604a6ce660bbeffc754288c9168c447e 100644 +index 1bcf601de5bcea35c6844362811213bfd9b406c7..c264e883b54f4538a64db1536e9583193b322014 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -10,6 +10,14 @@ config MFD_CORE @@ -129611,10 +126728,10 @@ index eea61e349e26afe4b0f9d52a3f036877f0e2403a..d2c3b724604a6ce660bbeffc754288c9 tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 5eaa6465d0a6e2bf20df77951b573b4c0ccc477f..8dc2dde11a22226ef4ed91b0eb69dfc9b4b84298 100644 +index 42a66e19e191da93b5036cd9fd8bb9e1cb1340bd..8806f37c52ec1a378804acdf4184ef6729aa815a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -203,3 +203,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o +@@ -205,3 +205,5 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o @@ -129784,10 +126901,10 @@ index 0000000000000000000000000000000000000000..eea9312dc96a496ce846b0c5a83e6e4f +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index ee72c3a2866f716cd68c646b7c501589a05b48f5..5be1a31a836a0528975f259fabb793bef4d2aa71 100644 +index 78a9e6119fa13437862080d815e84d68f7010d1f..ec1a5c27ead7dce18608eb6314f0ae8072fdf9bc 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -2502,3 +2502,16 @@ config FB_SM712 +@@ -2501,3 +2501,16 @@ config FB_SM712 This driver is also available as a module. The module will be called sm712fb. If you want to compile it as a module, say M here and read . @@ -129805,10 +126922,10 @@ index ee72c3a2866f716cd68c646b7c501589a05b48f5..5be1a31a836a0528975f259fabb793be + help + This is the framebuffer driver for the Raspberry Pi Sense HAT diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile -index df473d825c2e2481a871d794317e56b8d643370f..474c5673b275a82d60ad08ddf3bdc13879d3722a 100644 +index ee3b3496cee43899cd6b0037f6f22ec1b55bcbb2..459f9d1d4a37bb386c207df0f3aab581b9eb5e9e 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile -@@ -149,6 +149,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o +@@ -148,6 +148,7 @@ obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_MXS) += mxsfb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o @@ -130248,10 +127365,2863 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 20ba6b1d6362b32aac1fa3dc6f073d1046b7b27a Mon Sep 17 00:00:00 2001 +From f8f8a656cd3bf3fbeeeaa821ac7f11dd7071979e Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Fri, 22 Nov 2013 19:19:08 +0100 +Subject: [PATCH 065/111] 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 | 4 ++ + sound/soc/bcm/hifiberry_dac.c | 123 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 134 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index c5070aec5996aafb2d9daaf75163e16a29bc6892..ce81f14a88d08c90fb565cf3d60321a9b9a1fcee 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -7,3 +7,10 @@ config SND_BCM2835_SOC_I2S + Say Y or M if you want to add support for codecs attached to + the BCM2835 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 || SND_BCM2835_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 bc816b71e5a40958953bf7bf7e7bd08342e87738..b877d386363d935deefda3664089a4ae5b33b889 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -3,3 +3,7 @@ snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o + + obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..29ecc08a227cdd4b3c6141935d0c5d21c2c6b4d8 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dac.c +@@ -0,0 +1,123 @@ ++/* ++ * 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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_hifiberry_dac_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dac_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_dac_driver = { ++ .driver = { ++ .name = "snd-hifiberry-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dac_of_match, ++ }, ++ .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"); + +From 6f6c153a71efcace4d50c009ff7103c6a872004c Mon Sep 17 00:00:00 2001 +From: Florian Meier +Date: Mon, 25 Jan 2016 15:48:59 +0000 +Subject: [PATCH 066/111] ASoC: Add support for Rpi-DAC + +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-dac.c | 119 ++++++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/Kconfig | 5 ++ + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/pcm1794a.c | 69 +++++++++++++++++++++++++ + 6 files changed, 204 insertions(+) + create mode 100644 sound/soc/bcm/rpi-dac.c + create mode 100644 sound/soc/codecs/pcm1794a.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index ce81f14a88d08c90fb565cf3d60321a9b9a1fcee..900de22369a66758bbe49861238b647bd2ca037e 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -14,3 +14,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 || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM1794A ++ help ++ Say Y or M if you want to add support for RPi-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index b877d386363d935deefda3664089a4ae5b33b889..99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,5 +5,7 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1337a1c73 +--- /dev/null ++++ b/sound/soc/bcm/rpi-dac.c +@@ -0,0 +1,119 @@ ++/* ++ * 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 = "RPi-DAC", ++ .stream_name = "RPi-DAC 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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_rpi_dac_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_rpi_dac_of_match[] = { ++ { .compatible = "rpi,rpi-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_rpi_dac_of_match); ++ ++static struct platform_driver snd_rpi_rpi_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_rpi_dac_of_match, ++ }, ++ .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 f3fb98f0a995bb41dd473ccc4443164e404c9883..4a53fa058a6837b93d2e66b15fda7183cf355058 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -93,6 +93,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_PCM1681 if I2C + select SND_SOC_PCM179X_I2C if I2C + select SND_SOC_PCM179X_SPI if SPI_MASTER ++ select SND_SOC_PCM1794A if I2C + select SND_SOC_PCM3008 + select SND_SOC_PCM3168A_I2C if I2C + select SND_SOC_PCM3168A_SPI if SPI_MASTER +@@ -648,6 +649,10 @@ config SND_SOC_RT5616 + tristate "Realtek RT5616 CODEC" + depends on I2C + ++config SND_SOC_PCM1794A ++ tristate ++ depends on I2C ++ + config SND_SOC_RT5631 + tristate "Realtek ALC5631/RT5631 CODEC" + depends on I2C +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 0f548fd34ca3fd9e8a1b080cd2d38a480c3c5212..96b312249d197b2083b157d1c07eb106bc34ba7f 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -87,6 +87,7 @@ snd-soc-pcm1681-objs := pcm1681.o + snd-soc-pcm179x-codec-objs := pcm179x.o + snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o + snd-soc-pcm179x-spi-objs := pcm179x-spi.o ++snd-soc-pcm1794a-objs := pcm1794a.o + snd-soc-pcm3008-objs := pcm3008.o + snd-soc-pcm3168a-objs := pcm3168a.o + snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o +@@ -309,6 +310,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o + obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o + obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o + obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o ++obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o + obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o + obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o + obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o +diff --git a/sound/soc/codecs/pcm1794a.c b/sound/soc/codecs/pcm1794a.c +new file mode 100644 +index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd843e17f4 +--- /dev/null ++++ b/sound/soc/codecs/pcm1794a.c +@@ -0,0 +1,69 @@ ++/* ++ * 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 const struct of_device_id pcm1794a_of_match[] = { ++ { .compatible = "ti,pcm1794a", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, pcm1794a_of_match); ++ ++static struct platform_driver pcm1794a_codec_driver = { ++ .probe = pcm1794a_probe, ++ .remove = pcm1794a_remove, ++ .driver = { ++ .name = "pcm1794a-codec", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(pcm1794a_of_match), ++ }, ++}; ++ ++module_platform_driver(pcm1794a_codec_driver); ++ ++MODULE_DESCRIPTION("ASoC PCM1794A codec driver"); ++MODULE_AUTHOR("Florian Meier "); ++MODULE_LICENSE("GPL v2"); + +From b3591796ac8c05287e949d01fad785b9d2311e9c Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:41:23 +0100 +Subject: [PATCH 067/111] 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 | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c +index 8d914702cae4a3fe2c0ca0599cd1ec79f7322c83..c846716b4ed1027ade5512e8be90801dc0fa1c7b 100644 +--- a/sound/soc/codecs/wm8804.c ++++ b/sound/soc/codecs/wm8804.c +@@ -304,6 +304,7 @@ static int wm8804_hw_params(struct snd_pcm_substream *substream, + blen = 0x1; + break; + case 24: ++ case 32: + blen = 0x2; + break; + default: +@@ -515,7 +516,7 @@ static const struct snd_soc_dai_ops wm8804_dai_ops = { + }; + + #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 | \ +@@ -543,7 +544,7 @@ static struct snd_soc_dai_driver wm8804_dai = { + }; + + static const struct snd_soc_codec_driver soc_codec_dev_wm8804 = { +- .idle_bias_off = true, ++ .idle_bias_off = false, + + .dapm_widgets = wm8804_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets), + +From 8e7395e59afaa7f683db84c4737c9235917e0144 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Wed, 15 Jan 2014 21:42:08 +0100 +Subject: [PATCH 068/111] ASoC: BCM:Add support for HiFiBerry Digi. Driver is + based on the patched WM8804 driver. + +Signed-off-by: Daniel Matuschek + +Add a parameter to turn off SPDIF output if no audio is playing + +This patch adds the paramater auto_shutdown_output to the kernel module. +Default behaviour of the module is the same, but when auto_shutdown_output +is set to 1, the SPDIF oputput will shutdown if no stream is playing. + +bugfix for 32kHz sample rate, was missing + +HiFiBerry Digi: set SPDIF status bits for sample rate + +The HiFiBerry Digi driver did not signal the sample rate in the SPDIF status bits. +While this is optional, some DACs and receivers do not accept this signal. This patch +adds the sample rate bits in the SPDIF status block. +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_digi.c | 224 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 233 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_digi.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 900de22369a66758bbe49861238b647bd2ca037e..a34aff27bb3010f58773edb942adccc193ea0d26 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -15,6 +15,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 || SND_BCM2835_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 || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 99c96b4c41e46c17c38c8691e7a8a33b1bc7b3bb..4d53c58dc6ba41116d1fa210b6ba08ee75526dd2 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,7 +5,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-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 + + 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 +diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9840e15d3e2be6396bc3ce6e74749408cc28c333 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_digi.c +@@ -0,0 +1,224 @@ ++/* ++ * 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 short int auto_shutdown_output = 0; ++module_param(auto_shutdown_output, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++ ++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_startup(struct snd_pcm_substream *substream) { ++ /* turn on digital output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_digi_shutdown(struct snd_pcm_substream *substream) { ++ /* turn off output */ ++ if (auto_shutdown_output) { ++ /* turn off output */ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++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 sampling_freq=1; ++ ++ int ret; ++ ++ samplerate = params_rate(params); ++ ++ if (samplerate<=96000) { ++ mclk_freq=samplerate*256; ++ mclk_div=WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq=samplerate*128; ++ mclk_div=WM8804_MCLKDIV_128FS; ++ } ++ ++ switch (samplerate) { ++ case 32000: ++ sampling_freq=0x03; ++ break; ++ case 44100: ++ sampling_freq=0x00; ++ break; ++ case 48000: ++ sampling_freq=0x02; ++ break; ++ case 88200: ++ sampling_freq=0x08; ++ break; ++ case 96000: ++ sampling_freq=0x0a; ++ break; ++ case 176400: ++ sampling_freq=0x0c; ++ break; ++ case 192000: ++ sampling_freq=0x0e; ++ break; ++ default: ++ dev_err(codec->dev, ++ "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } ++ ++ 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(codec->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); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ 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, ++ .startup = snd_rpi_hifiberry_digi_startup, ++ .shutdown = snd_rpi_hifiberry_digi_shutdown, ++}; ++ ++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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_digi_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_hifiberry_digi_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_digi_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_digi_driver = { ++ .driver = { ++ .name = "snd-hifiberry-digi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_digi_of_match, ++ }, ++ .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"); + +From d8399bf3bd675104993779d1862d57fbbd31128a Mon Sep 17 00:00:00 2001 +From: Gordon Garrity +Date: Sat, 8 Mar 2014 16:56:57 +0000 +Subject: [PATCH 069/111] Add IQaudIO Sound Card support for Raspberry Pi + +Set a limit of 0dB on Digital Volume Control + +The main volume control in the PCM512x DAC has a range up to ++24dB. This is dangerously loud and can potentially cause massive +clipping in the output stages. Therefore this sets a sensible +limit of 0dB for this control. + +Allow up to 24dB digital gain to be applied when using IQAudIO DAC+ + +24db_digital_gain DT param can be used to specify that PCM512x +codec "Digital" volume control should not be limited to 0dB gain, +and if specified will allow the full 24dB gain. + +Modify IQAudIO DAC+ ASoC driver to set card/dai config from dt + +Add the ability to set the card name, dai name and dai stream name, from +dt config. + +Signed-off-by: DigitalDreamtime + +IQaudIO: auto-mute for AMP+ and DigiAMP+ + +IQAudIO amplifier mute via GPIO22. Add dt params for "one-shot" unmute +and auto mute. + +Revision 2, auto mute implementing HiassofT suggestion to mute/unmute +using set_bias_level, rather than startup/shutdown.... +"By default DAPM waits 5 seconds (pmdown_time) before shutting down +playback streams so a close/stop immediately followed by open/start +doesn't trigger an amp mute+unmute." + +Tested on both AMP+ (via DAC+) and DigiAMP+, with both options... + +dtoverlay=iqaudio-dacplus,unmute_amp + "one-shot" unmute when kernel module loads. + +dtoverlay=iqaudio-dacplus,auto_mute_amp + Unmute amp when ALSA device opened by a client. Mute, with 5 second delay + when ALSA device closed. (Re-opening the device within the 5 second close + window, will cancel mute.) + +Revision 4, using gpiod. + +Revision 5, clean-up formatting before adding mute code. + - Convert tab plus 4 space formatting to 2x tab + - Remove '// NOT USED' commented code + +Revision 6, don't attempt to "one-shot" unmute amp, unless card is +successfully registered. + +Signed-off-by: DigitalDreamtime +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio-dac.c | 234 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 243 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio-dac.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a34aff27bb3010f58773edb942adccc193ea0d26..38dcdd975b406b9308e151f5d3a80dbca5163be5 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -28,3 +28,10 @@ config SND_BCM2708_SOC_RPI_DAC + select SND_SOC_PCM1794A + help + Say Y or M if you want to add support for RPi-DAC. ++ ++config SND_BCM2708_SOC_IQAUDIO_DAC ++ tristate "Support for IQaudIO-DAC" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x_I2C ++ help ++ Say Y or M if you want to add support for IQaudIO-DAC. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 4d53c58dc6ba41116d1fa210b6ba08ee75526dd2..08e4dc55757855fedec6845b82fc5f9f91f1584b 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,7 +7,9 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + 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-iqaudio-dac-objs := iqaudio-dac.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +new file mode 100644 +index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097249d6777 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -0,0 +1,234 @@ ++/* ++ * ASoC Driver for IQaudIO 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 ++#include ++ ++static bool digital_gain_0db_limit = true; ++ ++static struct gpio_desc *mute_gpio; ++ ++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ if (digital_gain_0db_limit) ++ { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_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); ++} ++ ++static void snd_rpi_iqaudio_gpio_mute(struct snd_soc_card *card) ++{ ++ if (mute_gpio) { ++ dev_info(card->dev, "%s: muting amp using GPIO22\n", ++ __func__); ++ gpiod_set_value_cansleep(mute_gpio, 0); ++ } ++} ++ ++static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card) ++{ ++ if (mute_gpio) { ++ dev_info(card->dev, "%s: un-muting amp using GPIO22\n", ++ __func__); ++ gpiod_set_value_cansleep(mute_gpio, 1); ++ } ++} ++ ++static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) ++{ ++ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ ++ if (dapm->dev != codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_PREPARE: ++ if (dapm->bias_level != SND_SOC_BIAS_STANDBY) ++ break; ++ ++ /* UNMUTE AMP */ ++ snd_rpi_iqaudio_gpio_unmute(card); ++ ++ break; ++ case SND_SOC_BIAS_STANDBY: ++ if (dapm->bias_level != SND_SOC_BIAS_PREPARE) ++ break; ++ ++ /* MUTE AMP */ ++ snd_rpi_iqaudio_gpio_mute(card); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = { ++ .hw_params = snd_rpi_iqaudio_dac_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = { ++{ ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004c", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_iqaudio_dac_ops, ++ .init = snd_rpi_iqaudio_dac_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_dac = { ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_iqaudio_dac_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai), ++}; ++ ++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ bool gpio_unmute = false; ++ ++ snd_rpi_iqaudio_dac.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_card *card = &snd_rpi_iqaudio_dac; ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_dac_dai[0]; ++ bool auto_gpio_mute = false; ++ ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "iqaudio,24db_digital_gain"); ++ ++ if (of_property_read_string(pdev->dev.of_node, "card_name", ++ &card->name)) ++ card->name = "IQaudIODAC"; ++ ++ if (of_property_read_string(pdev->dev.of_node, "dai_name", ++ &dai->name)) ++ dai->name = "IQaudIO DAC"; ++ ++ if (of_property_read_string(pdev->dev.of_node, ++ "dai_stream_name", &dai->stream_name)) ++ dai->stream_name = "IQaudIO DAC HiFi"; ++ ++ /* gpio_unmute - one time unmute amp using GPIO */ ++ gpio_unmute = of_property_read_bool(pdev->dev.of_node, ++ "iqaudio-dac,unmute-amp"); ++ ++ /* auto_gpio_mute - mute/unmute amp using GPIO */ ++ auto_gpio_mute = of_property_read_bool(pdev->dev.of_node, ++ "iqaudio-dac,auto-mute-amp"); ++ ++ if (auto_gpio_mute || gpio_unmute) { ++ mute_gpio = devm_gpiod_get_optional(&pdev->dev, "mute", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(mute_gpio)) { ++ ret = PTR_ERR(mute_gpio); ++ dev_err(&pdev->dev, ++ "Failed to get mute gpio: %d\n", ret); ++ return ret; ++ } ++ ++ if (auto_gpio_mute && mute_gpio) ++ snd_rpi_iqaudio_dac.set_bias_level = ++ snd_rpi_iqaudio_set_bias_level; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); ++ if (ret) { ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ return ret; ++ } ++ ++ if (gpio_unmute && mute_gpio) ++ snd_rpi_iqaudio_gpio_unmute(&snd_rpi_iqaudio_dac); ++ ++ return 0; ++} ++ ++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev) ++{ ++ snd_rpi_iqaudio_gpio_mute(&snd_rpi_iqaudio_dac); ++ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac); ++} ++ ++static const struct of_device_id iqaudio_of_match[] = { ++ { .compatible = "iqaudio,iqaudio-dac", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, iqaudio_of_match); ++ ++static struct platform_driver snd_rpi_iqaudio_dac_driver = { ++ .driver = { ++ .name = "snd-rpi-iqaudio-dac", ++ .owner = THIS_MODULE, ++ .of_match_table = iqaudio_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_dac_probe, ++ .remove = snd_rpi_iqaudio_dac_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_dac_driver); ++ ++MODULE_AUTHOR("Florian Meier "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); ++MODULE_LICENSE("GPL v2"); + +From e3b89bd7a255c275dd778e5f871304feb30986c1 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 10:06:56 +0200 +Subject: [PATCH 070/111] Added support for HiFiBerry DAC+ + +The driver is based on the HiFiBerry DAC driver. However HiFiBerry DAC+ uses +a different codec chip (PCM5122), therefore a new driver is necessary. + +Add support for the HiFiBerry DAC+ Pro. + +The HiFiBerry DAC+ and DAC+ Pro products both use the existing bcm sound driver with the DAC+ Pro having a special clock device driver representing the two high precision oscillators. + +An addition bug fix is included for the PCM512x codec where by the physical size of the sample frame is used in the calculation of the LRCK divisor as it was found to be wrong when using 24-bit depth sample contained in a little endian 4-byte sample frame. + +Limit PCM512x "Digital" gain to 0dB by default with HiFiBerry DAC+ + +24db_digital_gain DT param can be used to specify that PCM512x +codec "Digital" volume control should not be limited to 0dB gain, +and if specified will allow the full 24dB gain. + +Add dt param to force HiFiBerry DAC+ Pro into slave mode + +"dtoverlay=hifiberry-dacplus,slave" + +Add 'slave' param to use HiFiBerry DAC+ Pro in slave mode, +with Pi as master for bit and frame clock. + +Signed-off-by: DigitalDreamtime +--- + drivers/clk/Makefile | 1 + + drivers/clk/clk-hifiberry-dacpro.c | 160 +++++++++++++++++ + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_dacplus.c | 358 +++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/pcm512x.c | 3 +- + 6 files changed, 530 insertions(+), 1 deletion(-) + create mode 100644 drivers/clk/clk-hifiberry-dacpro.c + create mode 100644 sound/soc/bcm/hifiberry_dacplus.c + +diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile +index dcc5e698ff6dd4d61255dd274dafadb1af239161..1f7a766d4edb9c6115486b8ec4d9017b5f87b074 100644 +--- a/drivers/clk/Makefile ++++ b/drivers/clk/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o + obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o + obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o + obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += clk-hifiberry-dacpro.o + obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o + obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o + obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o +diff --git a/drivers/clk/clk-hifiberry-dacpro.c b/drivers/clk/clk-hifiberry-dacpro.c +new file mode 100644 +index 0000000000000000000000000000000000000000..99cee2b1706c43170b4fc35c0023349b9019606c +--- /dev/null ++++ b/drivers/clk/clk-hifiberry-dacpro.c +@@ -0,0 +1,160 @@ ++/* ++ * Clock Driver for HiFiBerry DAC Pro ++ * ++ * Author: Stuart MacLean ++ * Copyright 2015 ++ * ++ * 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 ++ ++/* Clock rate of CLK44EN attached to GPIO6 pin */ ++#define CLK_44EN_RATE 22579200UL ++/* Clock rate of CLK48EN attached to GPIO3 pin */ ++#define CLK_48EN_RATE 24576000UL ++ ++/** ++ * struct hifiberry_dacpro_clk - Common struct to the HiFiBerry DAC Pro ++ * @hw: clk_hw for the common clk framework ++ * @mode: 0 => CLK44EN, 1 => CLK48EN ++ */ ++struct clk_hifiberry_hw { ++ struct clk_hw hw; ++ uint8_t mode; ++}; ++ ++#define to_hifiberry_clk(_hw) container_of(_hw, struct clk_hifiberry_hw, hw) ++ ++static const struct of_device_id clk_hifiberry_dacpro_dt_ids[] = { ++ { .compatible = "hifiberry,dacpro-clk",}, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, clk_hifiberry_dacpro_dt_ids); ++ ++static unsigned long clk_hifiberry_dacpro_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ return (to_hifiberry_clk(hw)->mode == 0) ? CLK_44EN_RATE : ++ CLK_48EN_RATE; ++} ++ ++static long clk_hifiberry_dacpro_round_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long *parent_rate) ++{ ++ long actual_rate; ++ ++ if (rate <= CLK_44EN_RATE) { ++ actual_rate = (long)CLK_44EN_RATE; ++ } else if (rate >= CLK_48EN_RATE) { ++ actual_rate = (long)CLK_48EN_RATE; ++ } else { ++ long diff44Rate = (long)(rate - CLK_44EN_RATE); ++ long diff48Rate = (long)(CLK_48EN_RATE - rate); ++ ++ if (diff44Rate < diff48Rate) ++ actual_rate = (long)CLK_44EN_RATE; ++ else ++ actual_rate = (long)CLK_48EN_RATE; ++ } ++ return actual_rate; ++} ++ ++ ++static int clk_hifiberry_dacpro_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ unsigned long actual_rate; ++ struct clk_hifiberry_hw *clk = to_hifiberry_clk(hw); ++ ++ actual_rate = (unsigned long)clk_hifiberry_dacpro_round_rate(hw, rate, ++ &parent_rate); ++ clk->mode = (actual_rate == CLK_44EN_RATE) ? 0 : 1; ++ return 0; ++} ++ ++ ++const struct clk_ops clk_hifiberry_dacpro_rate_ops = { ++ .recalc_rate = clk_hifiberry_dacpro_recalc_rate, ++ .round_rate = clk_hifiberry_dacpro_round_rate, ++ .set_rate = clk_hifiberry_dacpro_set_rate, ++}; ++ ++static int clk_hifiberry_dacpro_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct clk_hifiberry_hw *proclk; ++ struct clk *clk; ++ struct device *dev; ++ struct clk_init_data init; ++ ++ dev = &pdev->dev; ++ ++ proclk = kzalloc(sizeof(struct clk_hifiberry_hw), GFP_KERNEL); ++ if (!proclk) ++ return -ENOMEM; ++ ++ init.name = "clk-hifiberry-dacpro"; ++ init.ops = &clk_hifiberry_dacpro_rate_ops; ++ init.flags = CLK_IS_BASIC; ++ init.parent_names = NULL; ++ init.num_parents = 0; ++ ++ proclk->mode = 0; ++ proclk->hw.init = &init; ++ ++ clk = devm_clk_register(dev, &proclk->hw); ++ if (!IS_ERR(clk)) { ++ ret = of_clk_add_provider(dev->of_node, of_clk_src_simple_get, ++ clk); ++ } else { ++ dev_err(dev, "Fail to register clock driver\n"); ++ kfree(proclk); ++ ret = PTR_ERR(clk); ++ } ++ return ret; ++} ++ ++static int clk_hifiberry_dacpro_remove(struct platform_device *pdev) ++{ ++ of_clk_del_provider(pdev->dev.of_node); ++ return 0; ++} ++ ++static struct platform_driver clk_hifiberry_dacpro_driver = { ++ .probe = clk_hifiberry_dacpro_probe, ++ .remove = clk_hifiberry_dacpro_remove, ++ .driver = { ++ .name = "clk-hifiberry-dacpro", ++ .of_match_table = clk_hifiberry_dacpro_dt_ids, ++ }, ++}; ++ ++static int __init clk_hifiberry_dacpro_init(void) ++{ ++ return platform_driver_register(&clk_hifiberry_dacpro_driver); ++} ++core_initcall(clk_hifiberry_dacpro_init); ++ ++static void __exit clk_hifiberry_dacpro_exit(void) ++{ ++ platform_driver_unregister(&clk_hifiberry_dacpro_driver); ++} ++module_exit(clk_hifiberry_dacpro_exit); ++ ++MODULE_DESCRIPTION("HiFiBerry DAC Pro clock driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:clk-hifiberry-dacpro"); +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 38dcdd975b406b9308e151f5d3a80dbca5163be5..8c338b5803042ad3834ee46a8dc93f53c53953f6 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -15,6 +15,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_DACPLUS ++ tristate "Support for HifiBerry DAC+" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM512x ++ 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 || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 08e4dc55757855fedec6845b82fc5f9f91f1584b..a29538e56b62ef6e7098b81b81e1389a22beeafa 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -5,11 +5,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + + # BCM2708 Machine Support + snd-soc-hifiberry-dac-objs := hifiberry_dac.o ++snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.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_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c +new file mode 100644 +index 0000000000000000000000000000000000000000..65600674c286e8a7be8efd352d5a80889221a1d6 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_dacplus.c +@@ -0,0 +1,358 @@ ++/* ++ * ASoC Driver for HiFiBerry DAC+ / DAC Pro ++ * ++ * Author: Daniel Matuschek, Stuart MacLean ++ * Copyright 2014-2015 ++ * based on code by Florian Meier ++ * ++ * 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 ++#include ++ ++#include "../codecs/pcm512x.h" ++ ++#define HIFIBERRY_DACPRO_NOCLOCK 0 ++#define HIFIBERRY_DACPRO_CLK44EN 1 ++#define HIFIBERRY_DACPRO_CLK48EN 2 ++ ++struct pcm512x_priv { ++ struct regmap *regmap; ++ struct clk *sclk; ++}; ++ ++/* Clock rate of CLK44EN attached to GPIO6 pin */ ++#define CLK_44EN_RATE 22579200UL ++/* Clock rate of CLK48EN attached to GPIO3 pin */ ++#define CLK_48EN_RATE 24576000UL ++ ++static bool slave; ++static bool snd_rpi_hifiberry_is_dacpro; ++static bool digital_gain_0db_limit = true; ++ ++static void snd_rpi_hifiberry_dacplus_select_clk(struct snd_soc_codec *codec, ++ int clk_id) ++{ ++ switch (clk_id) { ++ case HIFIBERRY_DACPRO_NOCLOCK: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x00); ++ break; ++ case HIFIBERRY_DACPRO_CLK44EN: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x20); ++ break; ++ case HIFIBERRY_DACPRO_CLK48EN: ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x24, 0x04); ++ break; ++ } ++} ++ ++static void snd_rpi_hifiberry_dacplus_clk_gpio(struct snd_soc_codec *codec) ++{ ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x24, 0x24); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_3, 0x0f, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_6, 0x0f, 0x02); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_sclk(struct snd_soc_codec *codec) ++{ ++ int sck; ++ ++ sck = snd_soc_read(codec, PCM512x_RATE_DET_4); ++ return (!(sck & 0x40)); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_sclk_sleep( ++ struct snd_soc_codec *codec) ++{ ++ msleep(2); ++ return snd_rpi_hifiberry_dacplus_is_sclk(codec); ++} ++ ++static bool snd_rpi_hifiberry_dacplus_is_pro_card(struct snd_soc_codec *codec) ++{ ++ bool isClk44EN, isClk48En, isNoClk; ++ ++ snd_rpi_hifiberry_dacplus_clk_gpio(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK44EN); ++ isClk44EN = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_NOCLOCK); ++ isNoClk = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ snd_rpi_hifiberry_dacplus_select_clk(codec, HIFIBERRY_DACPRO_CLK48EN); ++ isClk48En = snd_rpi_hifiberry_dacplus_is_sclk_sleep(codec); ++ ++ return (isClk44EN && isClk48En && !isNoClk); ++} ++ ++static int snd_rpi_hifiberry_dacplus_clk_for_rate(int sample_rate) ++{ ++ int type; ++ ++ switch (sample_rate) { ++ case 11025: ++ case 22050: ++ case 44100: ++ case 88200: ++ case 176400: ++ type = HIFIBERRY_DACPRO_CLK44EN; ++ break; ++ default: ++ type = HIFIBERRY_DACPRO_CLK48EN; ++ break; ++ } ++ return type; ++} ++ ++static void snd_rpi_hifiberry_dacplus_set_sclk(struct snd_soc_codec *codec, ++ int sample_rate) ++{ ++ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); ++ ++ if (!IS_ERR(pcm512x->sclk)) { ++ int ctype; ++ ++ ctype = snd_rpi_hifiberry_dacplus_clk_for_rate(sample_rate); ++ clk_set_rate(pcm512x->sclk, (ctype == HIFIBERRY_DACPRO_CLK44EN) ++ ? CLK_44EN_RATE : CLK_48EN_RATE); ++ snd_rpi_hifiberry_dacplus_select_clk(codec, ctype); ++ } ++} ++ ++static int snd_rpi_hifiberry_dacplus_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct pcm512x_priv *priv; ++ ++ if (slave) ++ snd_rpi_hifiberry_is_dacpro = false; ++ else ++ snd_rpi_hifiberry_is_dacpro = ++ snd_rpi_hifiberry_dacplus_is_pro_card(codec); ++ ++ if (snd_rpi_hifiberry_is_dacpro) { ++ struct snd_soc_dai_link *dai = rtd->dai_link; ++ ++ dai->name = "HiFiBerry DAC+ Pro"; ++ dai->stream_name = "HiFiBerry DAC+ Pro HiFi"; ++ dai->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM; ++ ++ snd_soc_update_bits(codec, PCM512x_BCLK_LRCLK_CFG, 0x31, 0x11); ++ snd_soc_update_bits(codec, PCM512x_MASTER_MODE, 0x03, 0x03); ++ snd_soc_update_bits(codec, PCM512x_MASTER_CLKDIV_2, 0x7f, 63); ++ } else { ++ priv = snd_soc_codec_get_drvdata(codec); ++ priv->sclk = ERR_PTR(-ENOENT); ++ } ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_EN, 0x08, 0x08); ++ snd_soc_update_bits(codec, PCM512x_GPIO_OUTPUT_4, 0x0f, 0x02); ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); ++ ++ if (digital_gain_0db_limit) ++ { ++ int ret; ++ struct snd_soc_card *card = rtd->card; ++ ++ ret = snd_soc_limit_volume(card, "Digital Playback Volume", 207); ++ if (ret < 0) ++ dev_warn(card->dev, "Failed to set volume limit: %d\n", ret); ++ } ++ ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_update_rate_den( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ struct pcm512x_priv *pcm512x = snd_soc_codec_get_drvdata(codec); ++ struct snd_ratnum *rats_no_pll; ++ unsigned int num = 0, den = 0; ++ int err; ++ ++ rats_no_pll = devm_kzalloc(rtd->dev, sizeof(*rats_no_pll), GFP_KERNEL); ++ if (!rats_no_pll) ++ return -ENOMEM; ++ ++ rats_no_pll->num = clk_get_rate(pcm512x->sclk) / 64; ++ rats_no_pll->den_min = 1; ++ rats_no_pll->den_max = 128; ++ rats_no_pll->den_step = 1; ++ ++ err = snd_interval_ratnum(hw_param_interval(params, ++ SNDRV_PCM_HW_PARAM_RATE), 1, rats_no_pll, &num, &den); ++ if (err >= 0 && den) { ++ params->rate_num = num; ++ params->rate_den = den; ++ } ++ ++ devm_kfree(rtd->dev, rats_no_pll); ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro( ++ struct snd_soc_dai *cpu_dai, struct snd_pcm_hw_params *params) ++{ ++ int bratio = snd_pcm_format_physical_width(params_format(params)) ++ * params_channels(params); ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, bratio); ++} ++ ++static int snd_rpi_hifiberry_dacplus_hw_params( ++ struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) ++{ ++ int ret; ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ if (snd_rpi_hifiberry_is_dacpro) { ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_rpi_hifiberry_dacplus_set_sclk(codec, ++ params_rate(params)); ++ ++ ret = snd_rpi_hifiberry_dacplus_set_bclk_ratio_pro(cpu_dai, ++ params); ++ if (!ret) ++ ret = snd_rpi_hifiberry_dacplus_update_rate_den( ++ substream, params); ++ } else { ++ ret = snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++ } ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_startup( ++ struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x08); ++ return 0; ++} ++ ++static void snd_rpi_hifiberry_dacplus_shutdown( ++ struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_update_bits(codec, PCM512x_GPIO_CONTROL_1, 0x08, 0x00); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_hifiberry_dacplus_ops = { ++ .hw_params = snd_rpi_hifiberry_dacplus_hw_params, ++ .startup = snd_rpi_hifiberry_dacplus_startup, ++ .shutdown = snd_rpi_hifiberry_dacplus_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_dacplus_dai[] = { ++{ ++ .name = "HiFiBerry DAC+", ++ .stream_name = "HiFiBerry DAC+ HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "pcm512x-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "pcm512x.1-004d", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_dacplus_ops, ++ .init = snd_rpi_hifiberry_dacplus_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_hifiberry_dacplus = { ++ .name = "snd_rpi_hifiberry_dacplus", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_hifiberry_dacplus_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_dacplus_dai), ++}; ++ ++static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_dacplus.dev = &pdev->dev; ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai; ++ ++ dai = &snd_rpi_hifiberry_dacplus_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ ++ digital_gain_0db_limit = !of_property_read_bool( ++ pdev->dev.of_node, "hifiberry,24db_digital_gain"); ++ slave = of_property_read_bool(pdev->dev.of_node, ++ "hifiberry-dacplus,slave"); ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); ++ if (ret) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_hifiberry_dacplus_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_dacplus); ++} ++ ++static const struct of_device_id snd_rpi_hifiberry_dacplus_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-dacplus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_dacplus_of_match); ++ ++static struct platform_driver snd_rpi_hifiberry_dacplus_driver = { ++ .driver = { ++ .name = "snd-rpi-hifiberry-dacplus", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_dacplus_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_dacplus_probe, ++ .remove = snd_rpi_hifiberry_dacplus_remove, ++}; ++ ++module_platform_driver(snd_rpi_hifiberry_dacplus_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for HiFiBerry DAC+"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c +index 047c48953a20cd4075000ac294a17fe59baedcde..090fe0ee08e8765f9edbb62777413bb69f87d693 100644 +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -854,7 +854,8 @@ static int pcm512x_set_dividers(struct snd_soc_dai *dai, + int fssp; + int gpio; + +- lrclk_div = snd_soc_params_to_frame_size(params); ++ lrclk_div = snd_pcm_format_physical_width(params_format(params)) ++ * params_channels(params); + if (lrclk_div == 0) { + dev_err(dev, "No LRCLK?\n"); + return -EINVAL; + +From 5d2e827ef45aeb4bad9c5881b213b093b4c35cd9 Mon Sep 17 00:00:00 2001 +From: Daniel Matuschek +Date: Mon, 4 Aug 2014 11:09:58 +0200 +Subject: [PATCH 071/111] Added driver for HiFiBerry Amp amplifier add-on board + +The driver contains a low-level hardware driver for the TAS5713 and the +drivers for the Raspberry Pi I2S subsystem. + +TAS5713: return error if initialisation fails + +Existing TAS5713 driver logs errors during initialisation, but does not return +an error code. Therefore even if initialisation fails, the driver will still be +loaded, but won't work. This patch fixes this. I2C communication error will now +reported correctly by a non-zero return code. + +HiFiBerry Amp: fix device-tree problems + +Some code to load the driver based on device-tree-overlays was missing. This is added by this patch. +--- + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ + sound/soc/codecs/Kconfig | 4 + + sound/soc/codecs/Makefile | 2 + + sound/soc/codecs/tas5713.c | 369 ++++++++++++++++++++++++++++++++++++++++++ + sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ + 7 files changed, 722 insertions(+) + create mode 100644 sound/soc/bcm/hifiberry_amp.c + create mode 100644 sound/soc/codecs/tas5713.c + create mode 100644 sound/soc/codecs/tas5713.h + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 8c338b5803042ad3834ee46a8dc93f53c53953f6..7677c898773e6dd87c3ef385e380aa42c85e66d8 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -29,6 +29,13 @@ config SND_BCM2708_SOC_HIFIBERRY_DIGI + help + Say Y or M if you want to add support for HifiBerry Digi S/PDIF output board. + ++config SND_BCM2708_SOC_HIFIBERRY_AMP ++ tristate "Support for the HifiBerry Amp" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_TAS5713 ++ help ++ Say Y or M if you want to add support for the HifiBerry Amp amplifier board. ++ + config SND_BCM2708_SOC_RPI_DAC + tristate "Support for RPi-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index a29538e56b62ef6e7098b81b81e1389a22beeafa..30db4951129c2d853c5cf631f4cd1263926692d0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -7,11 +7,13 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o + snd-soc-hifiberry-dac-objs := hifiberry_dac.o + snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o ++snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0bb12e4761ce60d3364c66b2bd0f8f7dbdcecfb1 +--- /dev/null ++++ b/sound/soc/bcm/hifiberry_amp.c +@@ -0,0 +1,128 @@ ++/* ++ * ASoC Driver for HifiBerry AMP ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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_amp_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ // ToDo: init of the dsp-registers. ++ return 0; ++} ++ ++static int snd_rpi_hifiberry_amp_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, 64); ++} ++ ++static struct snd_soc_ops snd_rpi_hifiberry_amp_ops = { ++ .hw_params = snd_rpi_hifiberry_amp_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_hifiberry_amp_dai[] = { ++ { ++ .name = "HifiBerry AMP", ++ .stream_name = "HifiBerry AMP HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "tas5713-hifi", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "tas5713.1-001b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | ++ SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &snd_rpi_hifiberry_amp_ops, ++ .init = snd_rpi_hifiberry_amp_init, ++ }, ++}; ++ ++ ++static struct snd_soc_card snd_rpi_hifiberry_amp = { ++ .name = "snd_rpi_hifiberry_amp", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_hifiberry_amp_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_hifiberry_amp_dai), ++}; ++ ++static const struct of_device_id snd_rpi_hifiberry_amp_of_match[] = { ++ { .compatible = "hifiberry,hifiberry-amp", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_hifiberry_amp_of_match); ++ ++ ++static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_hifiberry_amp.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_hifiberry_amp_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); ++ ++ if (ret != 0) { ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++ ++static int snd_rpi_hifiberry_amp_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_hifiberry_amp); ++} ++ ++ ++static struct platform_driver snd_rpi_hifiberry_amp_driver = { ++ .driver = { ++ .name = "snd-hifiberry-amp", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_hifiberry_amp_of_match, ++ }, ++ .probe = snd_rpi_hifiberry_amp_probe, ++ .remove = snd_rpi_hifiberry_amp_remove, ++}; ++ ++ ++module_platform_driver(snd_rpi_hifiberry_amp_driver); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig +index 4a53fa058a6837b93d2e66b15fda7183cf355058..010fd5f0338988fd58095cf7d2bfbad82aa62b2c 100644 +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -132,6 +132,7 @@ config SND_SOC_ALL_CODECS + select SND_SOC_TFA9879 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER ++ select SND_SOC_TAS5713 if I2C + select SND_SOC_TLV320AIC26 if SPI_MASTER + select SND_SOC_TLV320AIC31XX if I2C + select SND_SOC_TLV320AIC32X4_I2C if I2C +@@ -774,6 +775,9 @@ config SND_SOC_TFA9879 + tristate "NXP Semiconductors TFA9879 amplifier" + depends on I2C + ++config SND_SOC_TAS5713 ++ tristate ++ + config SND_SOC_TLV320AIC23 + tristate + +diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile +index 96b312249d197b2083b157d1c07eb106bc34ba7f..2f39e6b9d488ea5341ba40282eef12dac899e6af 100644 +--- a/sound/soc/codecs/Makefile ++++ b/sound/soc/codecs/Makefile +@@ -135,6 +135,7 @@ snd-soc-tas5086-objs := tas5086.o + snd-soc-tas571x-objs := tas571x.o + snd-soc-tas5720-objs := tas5720.o + snd-soc-tfa9879-objs := tfa9879.o ++snd-soc-tas5713-objs := tas5713.o + snd-soc-tlv320aic23-objs := tlv320aic23.o + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o +@@ -347,6 +348,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o + obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o + obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o + obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o ++obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o + obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o +diff --git a/sound/soc/codecs/tas5713.c b/sound/soc/codecs/tas5713.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9b2713861dcbed751842ca29c88eb1eae5867411 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.c +@@ -0,0 +1,369 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "tas5713.h" ++ ++ ++static struct i2c_client *i2c; ++ ++struct tas5713_priv { ++ struct regmap *regmap; ++ int mclk_div; ++ struct snd_soc_codec *codec; ++}; ++ ++static struct tas5713_priv *priv_data; ++ ++ ++ ++ ++/* ++ * _ _ ___ _ ___ _ _ ++ * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___ ++ * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-< ++ * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/ ++ * ++ */ ++ ++static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1); ++ ++ ++static const struct snd_kcontrol_new tas5713_snd_controls[] = { ++ SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv), ++ SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv) ++}; ++ ++ ++ ++ ++/* ++ * __ __ _ _ ___ _ ++ * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _ ++ * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_| ++ * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ u16 blen = 0x00; ++ ++ struct snd_soc_codec *codec; ++ codec = dai->codec; ++ priv_data->codec = dai->codec; ++ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ blen = 0x03; ++ break; ++ case SNDRV_PCM_FORMAT_S20_3LE: ++ blen = 0x1; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ blen = 0x04; ++ break; ++ case SNDRV_PCM_FORMAT_S32_LE: ++ blen = 0x05; ++ break; ++ default: ++ dev_err(dai->dev, "Unsupported word length: %u\n", ++ params_format(params)); ++ return -EINVAL; ++ } ++ ++ // set word length ++ snd_soc_update_bits(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen); ++ ++ return 0; ++} ++ ++ ++static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream) ++{ ++ unsigned int val = 0; ++ ++ struct tas5713_priv *tas5713; ++ struct snd_soc_codec *codec = dai->codec; ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ if (mute) { ++ val = TAS5713_SOFT_MUTE_ALL; ++ } ++ ++ return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val); ++} ++ ++ ++static const struct snd_soc_dai_ops tas5713_dai_ops = { ++ .hw_params = tas5713_hw_params, ++ .mute_stream = tas5713_mute_stream, ++}; ++ ++ ++static struct snd_soc_dai_driver tas5713_dai = { ++ .name = "tas5713-hifi", ++ .playback = { ++ .stream_name = "Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ), ++ }, ++ .ops = &tas5713_dai_ops, ++}; ++ ++ ++ ++ ++/* ++ * ___ _ ___ _ ++ * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _ ++ * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_| ++ * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static int tas5713_remove(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ return 0; ++} ++ ++ ++static int tas5713_probe(struct snd_soc_codec *codec) ++{ ++ struct tas5713_priv *tas5713; ++ int i, ret; ++ ++ i2c = container_of(codec->dev, struct i2c_client, dev); ++ ++ tas5713 = snd_soc_codec_get_drvdata(codec); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Trim oscillator ++ ret = snd_soc_write(codec, TAS5713_OSC_TRIM, 0x00); ++ if (ret < 0) return ret; ++ msleep(1000); ++ ++ // Reset error ++ ret = snd_soc_write(codec, TAS5713_ERROR_STATUS, 0x00); ++ if (ret < 0) return ret; ++ ++ // Clock mode: 44/48kHz, MCLK=64xfs ++ ret = snd_soc_write(codec, TAS5713_CLOCK_CTRL, 0x60); ++ if (ret < 0) return ret; ++ ++ // I2S 24bit ++ ret = snd_soc_write(codec, TAS5713_SERIAL_DATA_INTERFACE, 0x05); ++ if (ret < 0) return ret; ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ret = snd_soc_write(codec, TAS5713_SOFT_MUTE, 0x00); ++ if (ret < 0) return ret; ++ ++ // Set volume to 0db ++ ret = snd_soc_write(codec, TAS5713_VOL_MASTER, 0x00); ++ if (ret < 0) return ret; ++ ++ // Now start programming the default initialization sequence ++ for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) { ++ ret = i2c_master_send(i2c, ++ tas5713_init_sequence[i].data, ++ tas5713_init_sequence[i].size); ++ if (ret < 0) { ++ printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret); ++ } ++ } ++ ++ // Unmute ++ ret = snd_soc_write(codec, TAS5713_SYSTEM_CTRL2, 0x00); ++ if (ret < 0) return ret; ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_codec_driver soc_codec_dev_tas5713 = { ++ .probe = tas5713_probe, ++ .remove = tas5713_remove, ++ .controls = tas5713_snd_controls, ++ .num_controls = ARRAY_SIZE(tas5713_snd_controls), ++}; ++ ++ ++ ++ ++/* ++ * ___ ___ ___ ___ _ ++ * |_ _|_ ) __| | \ _ _(_)_ _____ _ _ ++ * | | / / (__ | |) | '_| \ V / -_) '_| ++ * |___/___\___| |___/|_| |_|\_/\___|_| ++ * ++ */ ++ ++static const struct reg_default tas5713_reg_defaults[] = { ++ { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB ++ { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB ++ { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB ++ { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB ++}; ++ ++ ++static bool tas5713_reg_volatile(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case TAS5713_DEVICE_ID: ++ case TAS5713_ERROR_STATUS: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++ ++static const struct of_device_id tas5713_of_match[] = { ++ { .compatible = "ti,tas5713", }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, tas5713_of_match); ++ ++ ++static struct regmap_config tas5713_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ ++ .max_register = TAS5713_MAX_REGISTER, ++ .volatile_reg = tas5713_reg_volatile, ++ ++ .cache_type = REGCACHE_RBTREE, ++ .reg_defaults = tas5713_reg_defaults, ++ .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults), ++}; ++ ++ ++static int tas5713_i2c_probe(struct i2c_client *i2c, ++ const struct i2c_device_id *id) ++{ ++ int ret; ++ ++ priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL); ++ if (!priv_data) ++ return -ENOMEM; ++ ++ priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config); ++ if (IS_ERR(priv_data->regmap)) { ++ ret = PTR_ERR(priv_data->regmap); ++ return ret; ++ } ++ ++ i2c_set_clientdata(i2c, priv_data); ++ ++ ret = snd_soc_register_codec(&i2c->dev, ++ &soc_codec_dev_tas5713, &tas5713_dai, 1); ++ ++ return ret; ++} ++ ++ ++static int tas5713_i2c_remove(struct i2c_client *i2c) ++{ ++ snd_soc_unregister_codec(&i2c->dev); ++ i2c_set_clientdata(i2c, NULL); ++ ++ kfree(priv_data); ++ ++ return 0; ++} ++ ++ ++static const struct i2c_device_id tas5713_i2c_id[] = { ++ { "tas5713", 0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id); ++ ++ ++static struct i2c_driver tas5713_i2c_driver = { ++ .driver = { ++ .name = "tas5713", ++ .owner = THIS_MODULE, ++ .of_match_table = tas5713_of_match, ++ }, ++ .probe = tas5713_i2c_probe, ++ .remove = tas5713_i2c_remove, ++ .id_table = tas5713_i2c_id ++}; ++ ++ ++static int __init tas5713_modinit(void) ++{ ++ int ret = 0; ++ ++ ret = i2c_add_driver(&tas5713_i2c_driver); ++ if (ret) { ++ printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n", ++ ret); ++ } ++ ++ return ret; ++} ++module_init(tas5713_modinit); ++ ++ ++static void __exit tas5713_exit(void) ++{ ++ i2c_del_driver(&tas5713_i2c_driver); ++} ++module_exit(tas5713_exit); ++ ++ ++MODULE_AUTHOR("Sebastian Eickhoff "); ++MODULE_DESCRIPTION("ASoC driver for TAS5713"); ++MODULE_LICENSE("GPL v2"); +diff --git a/sound/soc/codecs/tas5713.h b/sound/soc/codecs/tas5713.h +new file mode 100644 +index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8f612a342 +--- /dev/null ++++ b/sound/soc/codecs/tas5713.h +@@ -0,0 +1,210 @@ ++/* ++ * ASoC Driver for TAS5713 ++ * ++ * Author: Sebastian Eickhoff ++ * Copyright 2014 ++ * ++ * 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. ++ */ ++ ++#ifndef _TAS5713_H ++#define _TAS5713_H ++ ++ ++// TAS5713 I2C-bus register addresses ++ ++#define TAS5713_CLOCK_CTRL 0x00 ++#define TAS5713_DEVICE_ID 0x01 ++#define TAS5713_ERROR_STATUS 0x02 ++#define TAS5713_SYSTEM_CTRL1 0x03 ++#define TAS5713_SERIAL_DATA_INTERFACE 0x04 ++#define TAS5713_SYSTEM_CTRL2 0x05 ++#define TAS5713_SOFT_MUTE 0x06 ++#define TAS5713_VOL_MASTER 0x07 ++#define TAS5713_VOL_CH1 0x08 ++#define TAS5713_VOL_CH2 0x09 ++#define TAS5713_VOL_HEADPHONE 0x0A ++#define TAS5713_VOL_CONFIG 0x0E ++#define TAS5713_MODULATION_LIMIT 0x10 ++#define TAS5713_IC_DLY_CH1 0x11 ++#define TAS5713_IC_DLY_CH2 0x12 ++#define TAS5713_IC_DLY_CH3 0x13 ++#define TAS5713_IC_DLY_CH4 0x14 ++ ++#define TAS5713_START_STOP_PERIOD 0x1A ++#define TAS5713_OSC_TRIM 0x1B ++#define TAS5713_BKND_ERR 0x1C ++ ++#define TAS5713_INPUT_MUX 0x20 ++#define TAS5713_SRC_SELECT_CH4 0x21 ++#define TAS5713_PWM_MUX 0x25 ++ ++#define TAS5713_CH1_BQ0 0x29 ++#define TAS5713_CH1_BQ1 0x2A ++#define TAS5713_CH1_BQ2 0x2B ++#define TAS5713_CH1_BQ3 0x2C ++#define TAS5713_CH1_BQ4 0x2D ++#define TAS5713_CH1_BQ5 0x2E ++#define TAS5713_CH1_BQ6 0x2F ++#define TAS5713_CH1_BQ7 0x58 ++#define TAS5713_CH1_BQ8 0x59 ++ ++#define TAS5713_CH2_BQ0 0x30 ++#define TAS5713_CH2_BQ1 0x31 ++#define TAS5713_CH2_BQ2 0x32 ++#define TAS5713_CH2_BQ3 0x33 ++#define TAS5713_CH2_BQ4 0x34 ++#define TAS5713_CH2_BQ5 0x35 ++#define TAS5713_CH2_BQ6 0x36 ++#define TAS5713_CH2_BQ7 0x5C ++#define TAS5713_CH2_BQ8 0x5D ++ ++#define TAS5713_CH4_BQ0 0x5A ++#define TAS5713_CH4_BQ1 0x5B ++#define TAS5713_CH3_BQ0 0x5E ++#define TAS5713_CH3_BQ1 0x5F ++ ++#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B ++#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C ++#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E ++#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F ++#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40 ++#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43 ++#define TAS5713_DRC_CTRL 0x46 ++ ++#define TAS5713_BANK_SW_CTRL 0x50 ++#define TAS5713_CH1_OUTPUT_MIXER 0x51 ++#define TAS5713_CH2_OUTPUT_MIXER 0x52 ++#define TAS5713_CH1_INPUT_MIXER 0x53 ++#define TAS5713_CH2_INPUT_MIXER 0x54 ++#define TAS5713_OUTPUT_POST_SCALE 0x56 ++#define TAS5713_OUTPUT_PRESCALE 0x57 ++ ++#define TAS5713_IDF_POST_SCALE 0x62 ++ ++#define TAS5713_CH1_INLINE_MIXER 0x70 ++#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71 ++#define TAS5713_CH1_R_CHANNEL_MIXER 0x72 ++#define TAS5713_CH1_L_CHANNEL_MIXER 0x73 ++#define TAS5713_CH2_INLINE_MIXER 0x74 ++#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75 ++#define TAS5713_CH2_L_CHANNEL_MIXER 0x76 ++#define TAS5713_CH2_R_CHANNEL_MIXER 0x77 ++ ++#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8 ++#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9 ++ ++#define TAS5713_REGISTER_COUNT 0x46 ++#define TAS5713_MAX_REGISTER 0xF9 ++ ++ ++// Bitmasks for registers ++#define TAS5713_SOFT_MUTE_ALL 0x07 ++ ++ ++ ++struct tas5713_init_command { ++ const int size; ++ const char *const data; ++}; ++ ++static const struct tas5713_init_command tas5713_init_sequence[] = { ++ ++ // Trim oscillator ++ { .size = 2, .data = "\x1B\x00" }, ++ // System control register 1 (0x03): block DC ++ { .size = 2, .data = "\x03\x80" }, ++ // Mute everything ++ { .size = 2, .data = "\x05\x40" }, ++ // Modulation limit register (0x10): 97.7% ++ { .size = 2, .data = "\x10\x02" }, ++ // Interchannel delay registers ++ // (0x11, 0x12, 0x13, and 0x14): BD mode ++ { .size = 2, .data = "\x11\xB8" }, ++ { .size = 2, .data = "\x12\x60" }, ++ { .size = 2, .data = "\x13\xA0" }, ++ { .size = 2, .data = "\x14\x48" }, ++ // PWM shutdown group register (0x19): no shutdown ++ { .size = 2, .data = "\x19\x00" }, ++ // Input multiplexer register (0x20): BD mode ++ { .size = 2, .data = "\x20\x00\x89\x77\x72" }, ++ // PWM output mux register (0x25) ++ // Channel 1 --> OUTA, channel 1 neg --> OUTB ++ // Channel 2 --> OUTC, channel 2 neg --> OUTD ++ { .size = 5, .data = "\x25\x01\x02\x13\x45" }, ++ // DRC control (0x46): DRC off ++ { .size = 5, .data = "\x46\x00\x00\x00\x00" }, ++ // BKND_ERR register (0x1C): 299ms reset period ++ { .size = 2, .data = "\x1C\x07" }, ++ // Mute channel 3 ++ { .size = 2, .data = "\x0A\xFF" }, ++ // Volume configuration register (0x0E): volume slew 512 steps ++ { .size = 2, .data = "\x0E\x90" }, ++ // Clock control register (0x00): 44/48kHz, MCLK=64xfs ++ { .size = 2, .data = "\x00\x60" }, ++ // Bank switch and eq control (0x50): no bank switching ++ { .size = 5, .data = "\x50\x00\x00\x00\x00" }, ++ // Volume registers (0x07, 0x08, 0x09, 0x0A) ++ { .size = 2, .data = "\x07\x20" }, ++ { .size = 2, .data = "\x08\x30" }, ++ { .size = 2, .data = "\x09\x30" }, ++ { .size = 2, .data = "\x0A\xFF" }, ++ // 0x72, 0x73, 0x76, 0x77 input mixer: ++ // no intermix between channels ++ { .size = 5, .data = "\x72\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x73\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x76\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x77\x00\x80\x00\x00" }, ++ // 0x70, 0x71, 0x74, 0x75 inline DRC mixer: ++ // no inline DRC inmix ++ { .size = 5, .data = "\x70\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x71\x00\x00\x00\x00" }, ++ { .size = 5, .data = "\x74\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x75\x00\x00\x00\x00" }, ++ // 0x56, 0x57 Output scale ++ { .size = 5, .data = "\x56\x00\x80\x00\x00" }, ++ { .size = 5, .data = "\x57\x00\x02\x00\x00" }, ++ // 0x3B, 0x3c ++ { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" }, ++ { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" }, ++ // 0x51, 0x52: output mixer ++ { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" }, ++ // PEQ defaults ++ { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++ { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, ++}; ++ ++ ++#endif /* _TAS5713_H */ + +From a071d287ae26904607ae671615e7d54e20eee74c Mon Sep 17 00:00:00 2001 +From: Ryan Coe +Date: Sat, 31 Jan 2015 18:25:49 -0700 +Subject: [PATCH 072/111] Update ds1307 driver for device-tree support + +Signed-off-by: Ryan Coe +--- + drivers/rtc/rtc-ds1307.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c +index 821d9c089cdb48a40a244d1c18ab912d6f0b9432..409ed8e449e54ea6751185b1c0760cfc8aaaf59e 100644 +--- a/drivers/rtc/rtc-ds1307.c ++++ b/drivers/rtc/rtc-ds1307.c +@@ -1610,6 +1610,14 @@ static int ds1307_remove(struct i2c_client *client) + return 0; + } + ++#ifdef CONFIG_OF ++static const struct of_device_id ds1307_of_match[] = { ++ { .compatible = "maxim,ds1307" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, ds1307_of_match); ++#endif ++ + static struct i2c_driver ds1307_driver = { + .driver = { + .name = "rtc-ds1307", + +From c1c82394785fd988a7b800782009558c4464a316 Mon Sep 17 00:00:00 2001 +From: Waldemar Brodkorb +Date: Wed, 25 Mar 2015 09:26:17 +0100 +Subject: [PATCH 073/111] Add driver for rpi-proto + +Forward port of 3.10.x driver from https://github.com/koalo +We are using a custom board and would like to use rpi 3.18.x +kernel. Patch works fine for our embedded system. + +URL to the audio chip: +http://www.mikroe.com/add-on-boards/audio-voice/audio-codec-proto/ + +Playback tested with devicetree enabled. + +Signed-off-by: Waldemar Brodkorb +--- + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-proto.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 163 insertions(+) + create mode 100644 sound/soc/bcm/rpi-proto.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 7677c898773e6dd87c3ef385e380aa42c85e66d8..8669a9ac9734c465c7dc3f40c864f71b68a6de75 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -43,6 +43,13 @@ config SND_BCM2708_SOC_RPI_DAC + help + Say Y or M if you want to add support for RPi-DAC. + ++config SND_BCM2708_SOC_RPI_PROTO ++ tristate "Support for Rpi-PROTO" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8731 ++ help ++ Say Y or M if you want to add support for Audio Codec Board PROTO (WM8731). ++ + config SND_BCM2708_SOC_IQAUDIO_DAC + tristate "Support for IQaudIO-DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 30db4951129c2d853c5cf631f4cd1263926692d0..4f5ab1fa4414e64a164eaa4575ffaa06d1cbf332 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -9,6 +9,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-hifiberry-amp-objs := hifiberry_amp.o + snd-soc-rpi-dac-objs := rpi-dac.o ++snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o + + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -16,4 +17,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed6772b19a2d +--- /dev/null ++++ b/sound/soc/bcm/rpi-proto.c +@@ -0,0 +1,154 @@ ++/* ++ * 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_codec *codec = rtd->codec; ++ 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); ++ if (ret < 0){ ++ dev_err(codec->dev, ++ "Failed to set BCLK ratio %d\n", ret); ++ return ret; ++ } ++ ++ /* Set proto sysclk */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, ++ sysclk, SND_SOC_CLOCK_IN); ++ if (ret < 0) { ++ dev_err(codec->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", ++ .owner = THIS_MODULE, ++ .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; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_rpi_proto_dai[0]; ++ i2s_node = of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ } ++ } ++ ++ 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 const struct of_device_id snd_rpi_proto_of_match[] = { ++ { .compatible = "rpi,rpi-proto", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_proto_of_match); ++ ++static struct platform_driver snd_rpi_proto_driver = { ++ .driver = { ++ .name = "snd-rpi-proto", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_proto_of_match, ++ }, ++ .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"); + +From e7dd0527b17927b2e94d04e13edf24506f812e2e Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 082/141] RaspiDAC3 support +Subject: [PATCH 074/111] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -130500,10 +130470,10 @@ index 0000000000000000000000000000000000000000..e7422e2dd3d70622a48ab3b2e1929869 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 562cf8a575b110278e6caeab401b0fd2460c6bfe Mon Sep 17 00:00:00 2001 +From 3573e75f6f331207b9bd31a2ba536b7e109bc0c1 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:02:34 +0100 -Subject: [PATCH 083/141] tpa6130a2: Add headphone switch control +Subject: [PATCH 075/111] tpa6130a2: Add headphone switch control Signed-off-by: Jan Grulich --- @@ -130594,2079 +130564,10 @@ index 11d85c5c787addb8d8add7fc2b52ab91cc49b63d..3caaa17e28e91e995d6781ca7f88b747 /* -From 71796389ee6b2fd23b047bc51d7f525228a5cfa2 Mon Sep 17 00:00:00 2001 -From: P33M -Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 084/141] rpi_display: add backlight driver and overlay - -Add a mailbox-driven backlight controller for the Raspberry Pi DSI -touchscreen display. Requires updated GPU firmware to recognise the -mailbox request. - -Signed-off-by: Gordon Hollingworth ---- - drivers/video/backlight/Kconfig | 6 ++ - drivers/video/backlight/Makefile | 1 + - drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 drivers/video/backlight/rpi_backlight.c - -diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig -index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 ---- a/drivers/video/backlight/Kconfig -+++ b/drivers/video/backlight/Kconfig -@@ -265,6 +265,12 @@ config BACKLIGHT_PWM - If you have a LCD backlight adjustable by PWM, say Y to enable - this driver. - -+config BACKLIGHT_RPI -+ tristate "Raspberry Pi display firmware driven backlight" -+ help -+ If you have the Raspberry Pi DSI touchscreen display, say Y to -+ enable the mailbox-controlled backlight driver. -+ - config BACKLIGHT_DA903X - tristate "Backlight Driver for DA9030/DA9034 using WLED" - depends on PMIC_DA903X -diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile -index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 ---- a/drivers/video/backlight/Makefile -+++ b/drivers/video/backlight/Makefile -@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o - obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o - obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o - obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o -+obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o - obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o - obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o - obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o -diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c -new file mode 100644 -index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad ---- /dev/null -+++ b/drivers/video/backlight/rpi_backlight.c -@@ -0,0 +1,119 @@ -+/* -+ * rpi_bl.c - Backlight controller through VPU -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct rpi_backlight { -+ struct device *dev; -+ struct device *fbdev; -+ struct rpi_firmware *fw; -+}; -+ -+static int rpi_backlight_update_status(struct backlight_device *bl) -+{ -+ struct rpi_backlight *gbl = bl_get_data(bl); -+ int brightness = bl->props.brightness; -+ int ret; -+ -+ if (bl->props.power != FB_BLANK_UNBLANK || -+ bl->props.fb_blank != FB_BLANK_UNBLANK || -+ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) -+ brightness = 0; -+ -+ ret = rpi_firmware_property(gbl->fw, -+ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, -+ &brightness, sizeof(brightness)); -+ if (ret) { -+ dev_err(gbl->dev, "Failed to set brightness\n"); -+ return ret; -+ } -+ -+ if (brightness < 0) { -+ dev_err(gbl->dev, "Backlight change failed\n"); -+ return -EAGAIN; -+ } -+ -+ return 0; -+} -+ -+static const struct backlight_ops rpi_backlight_ops = { -+ .options = BL_CORE_SUSPENDRESUME, -+ .update_status = rpi_backlight_update_status, -+}; -+ -+static int rpi_backlight_probe(struct platform_device *pdev) -+{ -+ struct backlight_properties props; -+ struct backlight_device *bl; -+ struct rpi_backlight *gbl; -+ struct device_node *fw_node; -+ -+ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); -+ if (gbl == NULL) -+ return -ENOMEM; -+ -+ gbl->dev = &pdev->dev; -+ -+ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); -+ if (!fw_node) { -+ dev_err(&pdev->dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ gbl->fw = rpi_firmware_get(fw_node); -+ if (!gbl->fw) -+ return -EPROBE_DEFER; -+ -+ memset(&props, 0, sizeof(props)); -+ props.type = BACKLIGHT_RAW; -+ props.max_brightness = 255; -+ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), -+ &pdev->dev, gbl, &rpi_backlight_ops, -+ &props); -+ if (IS_ERR(bl)) { -+ dev_err(&pdev->dev, "failed to register backlight\n"); -+ return PTR_ERR(bl); -+ } -+ -+ bl->props.brightness = 255; -+ backlight_update_status(bl); -+ -+ platform_set_drvdata(pdev, bl); -+ return 0; -+} -+ -+static const struct of_device_id rpi_backlight_of_match[] = { -+ { .compatible = "raspberrypi,rpi-backlight" }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); -+ -+static struct platform_driver rpi_backlight_driver = { -+ .driver = { -+ .name = "rpi-backlight", -+ .of_match_table = of_match_ptr(rpi_backlight_of_match), -+ }, -+ .probe = rpi_backlight_probe, -+}; -+ -+module_platform_driver(rpi_backlight_driver); -+ -+MODULE_AUTHOR("Gordon Hollingworth "); -+MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); -+MODULE_LICENSE("GPL"); - -From 824452ae388cddf8cfa2aff4c7cf3978dff74165 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 085/141] bcm2835-virtgpio: Virtual GPIO driver - -Add a virtual GPIO driver that uses the firmware mailbox interface to -request that the VPU toggles LEDs. ---- - drivers/gpio/Kconfig | 6 ++ - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+) - create mode 100644 drivers/gpio/gpio-bcm-virt.c - -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index 5f3429f0bf46970fcf376c79dca6633cd7469d5a..86cb971105296fea399bc3c51b69ba0a8834f9e6 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -142,6 +142,12 @@ config GPIO_BCM_KONA - help - Turn on GPIO support for Broadcom "Kona" chips. - -+config GPIO_BCM_VIRT -+ bool "Broadcom Virt GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) -+ help -+ Turn on virtual GPIO support for Broadcom BCM283X chips. -+ - config GPIO_BRCMSTB - tristate "BRCMSTB GPIO support" - default y if (ARCH_BRCMSTB || BMIPS_GENERIC) -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index 1e0b74f3b1ed98021f3d05b067b749b7cb1c652d..908596d99ce7b0390bfdec32a27de996efdeccd3 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -26,6 +26,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o - obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o -+obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o - obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o - obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o - obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o -diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c -new file mode 100644 -index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-virt.c -@@ -0,0 +1,179 @@ -+/* -+ * brcmvirt GPIO driver -+ * -+ * Copyright (C) 2012,2013 Dom Cobley -+ * Based on gpio-clps711x.c by Alexander Shiyan -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define MODULE_NAME "brcmvirt-gpio" -+#define NUM_GPIO 2 -+ -+struct brcmvirt_gpio { -+ struct gpio_chip gc; -+ u32 __iomem *ts_base; -+ /* two packed 16-bit counts of enabled and disables -+ Allows host to detect a brief enable that was missed */ -+ u32 enables_disables[NUM_GPIO]; -+}; -+ -+static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return -EINVAL; -+} -+ -+static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ return 0; -+} -+ -+static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) -+{ -+ struct brcmvirt_gpio *gpio; -+ unsigned v; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ v = readl(gpio->ts_base + off); -+ return (v >> off) & 1; -+} -+ -+static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) -+{ -+ struct brcmvirt_gpio *gpio; -+ u16 enables, disables; -+ s16 diff; -+ bool lit; -+ gpio = container_of(gc, struct brcmvirt_gpio, gc); -+ enables = gpio->enables_disables[off] >> 16; -+ disables = gpio->enables_disables[off] >> 0; -+ diff = (s16)(enables - disables); -+ lit = diff > 0; -+ if ((val && lit) || (!val && !lit)) -+ return; -+ if (val) -+ enables++; -+ else -+ disables++; -+ diff = (s16)(enables - disables); -+ BUG_ON(diff != 0 && diff != 1); -+ gpio->enables_disables[off] = (enables << 16) | (disables << 0); -+ writel(gpio->enables_disables[off], gpio->ts_base + off); -+} -+ -+static int brcmvirt_gpio_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmvirt_gpio *ucb; -+ u32 gpiovirtbuf; -+ int err = 0; -+ -+ fw_node = of_parse_phandle(np, "firmware", 0); -+ if (!fw_node) { -+ dev_err(dev, "Missing firmware node\n"); -+ return -ENOENT; -+ } -+ -+ fw = rpi_firmware_get(fw_node); -+ if (!fw) -+ return -EPROBE_DEFER; -+ -+ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, -+ &gpiovirtbuf, sizeof(gpiovirtbuf)); -+ -+ if (err) { -+ dev_err(dev, "Failed to get gpiovirtbuf\n"); -+ goto err; -+ } -+ -+ if (!gpiovirtbuf) { -+ dev_err(dev, "No virtgpio buffer\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); -+ if (!ucb) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ // mmap the physical memory -+ gpiovirtbuf &= ~0xc0000000; -+ ucb->ts_base = ioremap(gpiovirtbuf, 4096); -+ if (ucb->ts_base == NULL) { -+ dev_err(dev, "Failed to map physical address\n"); -+ err = -ENOENT; -+ goto err; -+ } -+ -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ //ucb->gc.dev = dev; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 100; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmvirt_gpio_dir_in; -+ ucb->gc.direction_output = brcmvirt_gpio_dir_out; -+ ucb->gc.get = brcmvirt_gpio_get; -+ ucb->gc.set = brcmvirt_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto err; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+err: -+ return err; -+ -+} -+ -+static int brcmvirt_gpio_remove(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ iounmap(ucb->ts_base); -+ return err; -+} -+ -+static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-virtgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); -+ -+static struct platform_driver brcmvirt_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), -+ }, -+ .probe = brcmvirt_gpio_probe, -+ .remove = brcmvirt_gpio_remove, -+}; -+module_platform_driver(brcmvirt_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dom Cobley "); -+MODULE_DESCRIPTION("brcmvirt GPIO driver"); -+MODULE_ALIAS("platform:brcmvirt-gpio"); - -From 2e0d36e08a5adcb7987977e75105354a5757cc81 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 4 Mar 2016 12:49:09 +0000 -Subject: [PATCH 086/141] DRM_VC4: Allow to be built for ARCH_BCM270x - ---- - drivers/gpu/drm/vc4/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index 584810474e5b84b211a5cbda681ea04c41bc0055..870fea56438d718c3887f1192afdab176e72e38f 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -1,6 +1,6 @@ - config DRM_VC4 - tristate "Broadcom VC4 Graphics" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on DRM - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - -From 974384491624ce3930e1883e12c2fa3064fed752 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 087/141] amba_pl011: Don't use DT aliases for numbering - -The pl011 driver looks for DT aliases of the form "serial", -and if found uses as the device ID. This can cause -/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the -other serial port is provided by the 8250 driver which doesn't -use the same logic. ---- - drivers/tty/serial/amba-pl011.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 7c198e0a3178ae2ab9805c9f317c722d18b2dadf..4f9e97b8a8eeaf0a728a419e3d6614533cb67f4b 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2413,7 +2413,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, - if (IS_ERR(base)) - return PTR_ERR(base); - -+ /* Don't use DT serial aliases - it causes the device to -+ be renumbered to ttyAMA1 if it is the second serial port in the -+ system, even though the other one is ttyS0. The 8250 driver -+ doesn't use this logic, so always remains ttyS0. - index = pl011_probe_dt_alias(index, dev); -+ */ - - uap->old_cr = 0; - uap->port.dev = dev; - -From 37beef929ac285a1f38408254579cca1bb0021b3 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 088/141] OF: DT-Overlay configfs interface - -This is a port of Pantelis Antoniou's v3 port that makes use of the -new upstreamed configfs support for binary attributes. - -Original commit message: - -Add a runtime interface to using configfs for generic device tree overlay -usage. With it its possible to use device tree overlays without having -to use a per-platform overlay manager. - -Please see Documentation/devicetree/configfs-overlays.txt for more info. - -Changes since v2: -- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) -- Created a documentation entry -- Slight rewording in Kconfig - -Changes since v1: -- of_resolve() -> of_resolve_phandles(). - -Originally-signed-off-by: Pantelis Antoniou -Signed-off-by: Phil Elwell - -DT configfs: Fix build errors on other platforms - -Signed-off-by: Phil Elwell - -DT configfs: fix build error - -There is an error when compiling rpi-4.6.y branch: - CC drivers/of/configfs.o -drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .default_groups = of_cfs_def_groups, - ^ -drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') - -The .default_groups is linked list since commit -1ae1602de028acaa42a0f6ff18d19756f8e825c6. -This commit uses configfs_add_default_group to fix this problem. - -Signed-off-by: Slawomir Stepien ---- - Documentation/devicetree/configfs-overlays.txt | 31 +++ - drivers/of/Kconfig | 7 + - drivers/of/Makefile | 1 + - drivers/of/configfs.c | 311 +++++++++++++++++++++++++ - 4 files changed, 350 insertions(+) - create mode 100644 Documentation/devicetree/configfs-overlays.txt - create mode 100644 drivers/of/configfs.c - -diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt -new file mode 100644 -index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad ---- /dev/null -+++ b/Documentation/devicetree/configfs-overlays.txt -@@ -0,0 +1,31 @@ -+Howto use the configfs overlay interface. -+ -+A device-tree configfs entry is created in /config/device-tree/overlays -+and and it is manipulated using standard file system I/O. -+Note that this is a debug level interface, for use by developers and -+not necessarily something accessed by normal users due to the -+security implications of having direct access to the kernel's device tree. -+ -+* To create an overlay you mkdir the directory: -+ -+ # mkdir /config/device-tree/overlays/foo -+ -+* Either you echo the overlay firmware file to the path property file. -+ -+ # echo foo.dtbo >/config/device-tree/overlays/foo/path -+ -+* Or you cat the contents of the overlay to the dtbo file -+ -+ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo -+ -+The overlay file will be applied, and devices will be created/destroyed -+as required. -+ -+To remove it simply rmdir the directory. -+ -+ # rmdir /config/device-tree/overlays/foo -+ -+The rationalle of the dual interface (firmware & direct copy) is that each is -+better suited to different use patterns. The firmware interface is what's -+intended to be used by hardware managers in the kernel, while the copy interface -+make sense for developers (since it avoids problems with namespaces). -diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig -index e2a48415d9691059f1beb2afee7f134019d65ecf..7e5e6c4e77e070692cab0ed2e4b827c08c0a1c29 100644 ---- a/drivers/of/Kconfig -+++ b/drivers/of/Kconfig -@@ -112,4 +112,11 @@ config OF_OVERLAY - While this option is selected automatically when needed, you can - enable it manually to improve device tree unit test coverage. - -+config OF_CONFIGFS -+ bool "Device Tree Overlay ConfigFS interface" -+ select CONFIGFS_FS -+ select OF_OVERLAY -+ help -+ Enable a simple user-space driven DT overlay interface. -+ - endif # OF -diff --git a/drivers/of/Makefile b/drivers/of/Makefile -index 156c072b31177eab081de4e54ab28b7815e32c95..46c8f5754ed84410d7dea83bfedcbdebf3f85453 100644 ---- a/drivers/of/Makefile -+++ b/drivers/of/Makefile -@@ -1,4 +1,5 @@ - obj-y = base.o device.o platform.o -+obj-$(CONFIG_OF_CONFIGFS) += configfs.o - obj-$(CONFIG_OF_DYNAMIC) += dynamic.o - obj-$(CONFIG_OF_FLATTREE) += fdt.o - obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o -diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c -new file mode 100644 -index 0000000000000000000000000000000000000000..68f889d9fa1dc19d18964aa9fd208137ed51f013 ---- /dev/null -+++ b/drivers/of/configfs.c -@@ -0,0 +1,311 @@ -+/* -+ * Configfs entries for device-tree -+ * -+ * Copyright (C) 2013 - Pantelis Antoniou -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "of_private.h" -+ -+struct cfs_overlay_item { -+ struct config_item item; -+ -+ char path[PATH_MAX]; -+ -+ const struct firmware *fw; -+ struct device_node *overlay; -+ int ov_id; -+ -+ void *dtbo; -+ int dtbo_size; -+}; -+ -+static int create_overlay(struct cfs_overlay_item *overlay, void *blob) -+{ -+ int err; -+ -+ /* unflatten the tree */ -+ of_fdt_unflatten_tree(blob, &overlay->overlay); -+ if (overlay->overlay == NULL) { -+ pr_err("%s: failed to unflatten tree\n", __func__); -+ err = -EINVAL; -+ goto out_err; -+ } -+ pr_debug("%s: unflattened OK\n", __func__); -+ -+ /* mark it as detached */ -+ of_node_set_flag(overlay->overlay, OF_DETACHED); -+ -+ /* perform resolution */ -+ err = of_resolve_phandles(overlay->overlay); -+ if (err != 0) { -+ pr_err("%s: Failed to resolve tree\n", __func__); -+ goto out_err; -+ } -+ pr_debug("%s: resolved OK\n", __func__); -+ -+ err = of_overlay_create(overlay->overlay); -+ if (err < 0) { -+ pr_err("%s: Failed to create overlay (err=%d)\n", -+ __func__, err); -+ goto out_err; -+ } -+ overlay->ov_id = err; -+ -+out_err: -+ return err; -+} -+ -+static inline struct cfs_overlay_item *to_cfs_overlay_item( -+ struct config_item *item) -+{ -+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; -+} -+ -+static ssize_t cfs_overlay_item_path_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ return sprintf(page, "%s\n", overlay->path); -+} -+ -+static ssize_t cfs_overlay_item_path_store(struct config_item *item, -+ const char *page, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ const char *p = page; -+ char *s; -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy to path buffer (and make sure it's always zero terminated */ -+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); -+ overlay->path[sizeof(overlay->path) - 1] = '\0'; -+ -+ /* strip trailing newlines */ -+ s = overlay->path + strlen(overlay->path); -+ while (s > overlay->path && *--s == '\n') -+ *s = '\0'; -+ -+ pr_debug("%s: path is '%s'\n", __func__, overlay->path); -+ -+ err = request_firmware(&overlay->fw, overlay->path, NULL); -+ if (err != 0) -+ goto out_err; -+ -+ err = create_overlay(overlay, (void *)overlay->fw->data); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ -+ release_firmware(overlay->fw); -+ overlay->fw = NULL; -+ -+ overlay->path[0] = '\0'; -+ return err; -+} -+ -+static ssize_t cfs_overlay_item_status_show(struct config_item *item, -+ char *page) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ return sprintf(page, "%s\n", -+ overlay->ov_id >= 0 ? "applied" : "unapplied"); -+} -+ -+CONFIGFS_ATTR(cfs_overlay_item_, path); -+CONFIGFS_ATTR_RO(cfs_overlay_item_, status); -+ -+static struct configfs_attribute *cfs_overlay_attrs[] = { -+ &cfs_overlay_item_attr_path, -+ &cfs_overlay_item_attr_status, -+ NULL, -+}; -+ -+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, -+ void *buf, size_t max_count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ pr_debug("%s: buf=%p max_count=%zu\n", __func__, -+ buf, max_count); -+ -+ if (overlay->dtbo == NULL) -+ return 0; -+ -+ /* copy if buffer provided */ -+ if (buf != NULL) { -+ /* the buffer must be large enough */ -+ if (overlay->dtbo_size > max_count) -+ return -ENOSPC; -+ -+ memcpy(buf, overlay->dtbo, overlay->dtbo_size); -+ } -+ -+ return overlay->dtbo_size; -+} -+ -+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, -+ const void *buf, size_t count) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ int err; -+ -+ /* if it's set do not allow changes */ -+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) -+ return -EPERM; -+ -+ /* copy the contents */ -+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); -+ if (overlay->dtbo == NULL) -+ return -ENOMEM; -+ -+ overlay->dtbo_size = count; -+ -+ err = create_overlay(overlay, overlay->dtbo); -+ if (err != 0) -+ goto out_err; -+ -+ return count; -+ -+out_err: -+ kfree(overlay->dtbo); -+ overlay->dtbo = NULL; -+ overlay->dtbo_size = 0; -+ -+ return err; -+} -+ -+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); -+ -+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { -+ &cfs_overlay_item_attr_dtbo, -+ NULL, -+}; -+ -+static void cfs_overlay_release(struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ if (overlay->ov_id >= 0) -+ of_overlay_destroy(overlay->ov_id); -+ if (overlay->fw) -+ release_firmware(overlay->fw); -+ /* kfree with NULL is safe */ -+ kfree(overlay->dtbo); -+ kfree(overlay); -+} -+ -+static struct configfs_item_operations cfs_overlay_item_ops = { -+ .release = cfs_overlay_release, -+}; -+ -+static struct config_item_type cfs_overlay_type = { -+ .ct_item_ops = &cfs_overlay_item_ops, -+ .ct_attrs = cfs_overlay_attrs, -+ .ct_bin_attrs = cfs_overlay_bin_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *cfs_overlay_group_make_item( -+ struct config_group *group, const char *name) -+{ -+ struct cfs_overlay_item *overlay; -+ -+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); -+ if (!overlay) -+ return ERR_PTR(-ENOMEM); -+ overlay->ov_id = -1; -+ -+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); -+ return &overlay->item; -+} -+ -+static void cfs_overlay_group_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); -+ -+ config_item_put(&overlay->item); -+} -+ -+static struct configfs_group_operations overlays_ops = { -+ .make_item = cfs_overlay_group_make_item, -+ .drop_item = cfs_overlay_group_drop_item, -+}; -+ -+static struct config_item_type overlays_type = { -+ .ct_group_ops = &overlays_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_group_operations of_cfs_ops = { -+ /* empty - we don't allow anything to be created */ -+}; -+ -+static struct config_item_type of_cfs_type = { -+ .ct_group_ops = &of_cfs_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+struct config_group of_cfs_overlay_group; -+ -+static struct configfs_subsystem of_cfs_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = "device-tree", -+ .ci_type = &of_cfs_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), -+}; -+ -+static int __init of_cfs_init(void) -+{ -+ int ret; -+ -+ pr_info("%s\n", __func__); -+ -+ config_group_init(&of_cfs_subsys.su_group); -+ config_group_init_type_name(&of_cfs_overlay_group, "overlays", -+ &overlays_type); -+ configfs_add_default_group(&of_cfs_overlay_group, -+ &of_cfs_subsys.su_group); -+ -+ ret = configfs_register_subsystem(&of_cfs_subsys); -+ if (ret != 0) { -+ pr_err("%s: failed to register subsys\n", __func__); -+ goto out; -+ } -+ pr_info("%s: OK\n", __func__); -+out: -+ return ret; -+} -+late_initcall(of_cfs_init); - -From dd2cbdf281925d7bf1d6b8417b6c231f082d30ea Mon Sep 17 00:00:00 2001 -From: Cheong2K -Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 089/141] brcm: adds support for BCM43341 wifi - ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + - 2 files changed, 3 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index 43fd3f402ebad89f89f7d5f8afdce9613d87b5de..c3c7c799c62014cada37bed43dfa32ac4df5757e 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -@@ -606,6 +606,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); -+BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); - BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); - BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); -@@ -622,6 +623,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), -+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -index 699f2c2782ee9d898a25c95e0c5d45744d0777ff..15598b3687a213d8c00d45965a6b9351759f47fc 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h -@@ -35,6 +35,7 @@ - #define BRCM_CC_4330_CHIP_ID 0x4330 - #define BRCM_CC_4334_CHIP_ID 0x4334 - #define BRCM_CC_43340_CHIP_ID 43340 -+#define BRCM_CC_43341_CHIP_ID 43341 - #define BRCM_CC_43362_CHIP_ID 43362 - #define BRCM_CC_4335_CHIP_ID 0x4335 - #define BRCM_CC_4339_CHIP_ID 0x4339 - -From 369253d684cda53c5e59a6bba7e1dbae18be0c45 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 9 Mar 2016 17:25:59 +0000 -Subject: [PATCH 090/141] brcmfmac: Disable power management - -Disable wireless power saving in the brcmfmac WLAN driver. This is a -temporary measure until the connectivity loss resulting from power -saving is resolved. - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index d5c2a27573b45cdfcbb72bf32dedc1dcd0af82da..5a08f59fdfdaa9bd9fef3cd2344c0772b75371cc 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2623,6 +2623,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, - * preference in cfg struct to apply this to - * FW later while initializing the dongle - */ -+ pr_info("power management disabled\n"); -+ enabled = false; - cfg->pwr_save = enabled; - if (!check_vif_up(ifp->vif)) { - - -From 06b146ccc00624225d4dabd803369dcc4a9781b0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 28 Apr 2016 17:13:47 +0100 -Subject: [PATCH 091/141] brcmfmac: Use original country code as a fallback - -Commit 73345fd212980d2e28a5c6d83801c903bd773680: - - brcmfmac: Configure country code using device specific settings - -prevents region codes from working on devices that lack a region code -translation table. In the event of an absent table, preserve the old -behaviour of using the provided code as-is. - -Signed-off-by: Phil Elwell ---- - .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 5a08f59fdfdaa9bd9fef3cd2344c0772b75371cc..ceba7b6909b2b2bf4045c5f7640d531f497b505f 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6516,12 +6516,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - struct brcmfmac_pd_cc *country_codes; - struct brcmfmac_pd_cc_entry *cc; - s32 found_index; -+ char ccode[BRCMF_COUNTRY_BUF_SZ]; -+ int rev; - int i; - -+ memcpy(ccode, alpha2, sizeof(ccode)); -+ rev = -1; -+ - country_codes = drvr->settings->country_codes; - if (!country_codes) { -- brcmf_dbg(TRACE, "No country codes configured for device\n"); -- return -EINVAL; -+ brcmf_dbg(TRACE, "No country codes configured for device" -+ " - use requested value\n"); -+ goto use_input_value; - } - - if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -6545,10 +6551,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], - brcmf_dbg(TRACE, "No country code match found\n"); - return -EINVAL; - } -- memset(ccreq, 0, sizeof(*ccreq)); -- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); -- memcpy(ccreq->ccode, country_codes->table[found_index].cc, -+ rev = country_codes->table[found_index].rev; -+ memcpy(ccode, country_codes->table[found_index].cc, - BRCMF_COUNTRY_BUF_SZ); -+ -+use_input_value: -+ memset(ccreq, 0, sizeof(*ccreq)); -+ ccreq->rev = cpu_to_le32(rev); -+ memcpy(ccreq->ccode, ccode, sizeof(ccode)); - ccreq->country_abbrev[0] = alpha2[0]; - ccreq->country_abbrev[1] = alpha2[1]; - ccreq->country_abbrev[2] = 0; - -From 007bfc89dd5acef6db652e14fa1b3c99bad17c94 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 19 May 2016 15:36:09 +0100 -Subject: [PATCH 092/141] brcmfmac: Plug memory leak in brcmf_fill_bss_param - -See: https://github.com/raspberrypi/linux/issues/1471 - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index ceba7b6909b2b2bf4045c5f7640d531f497b505f..afb01540261e99c87209aaa53aef439eb297f7c2 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2413,7 +2413,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) - WL_BSS_INFO_MAX); - if (err) { - brcmf_err("Failed to get bss info (%d)\n", err); -- return; -+ goto out_err; - } - si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); - si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); -@@ -2425,6 +2425,9 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) - si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; - if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; -+ -+out_err: -+ kfree(buf); - } - - static s32 - -From f2f7ef4bb245c425305c0edb901357c3cf84b8e8 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 093/141] hci_h5: Don't send conf_req when ACTIVE - -Without this patch, a modem and kernel can continuously bombard each -other with conf_req and conf_rsp messages, in a demented game of tag. ---- - drivers/bluetooth/hci_h5.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c -index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 ---- a/drivers/bluetooth/hci_h5.c -+++ b/drivers/bluetooth/hci_h5.c -@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) - h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_req, 2) == 0) { - h5_link_control(hu, conf_rsp, 2); -- h5_link_control(hu, conf_req, 3); -+ if (h5->state != H5_ACTIVE) -+ h5_link_control(hu, conf_req, 3); - } else if (memcmp(data, conf_rsp, 2) == 0) { - if (H5_HDR_LEN(hdr) > 2) - h5->tx_win = (data[2] & 0x07); - -From 74f2b9d0a28818a144d4b2a5480c33f948dc19c6 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 22 Jan 2016 13:06:39 -0800 -Subject: [PATCH 094/141] drm/vc4: Add a debugfs node for tracking execution - state. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 1 + - drivers/gpu/drm/vc4/vc4_gem.c | 14 ++++++++++++++ - 3 files changed, 16 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c -index d76ad10b07fda3bb674f45c2151e621c60633364..a99aa8676af774977778edfa2604b6b9df31a4dc 100644 ---- a/drivers/gpu/drm/vc4/vc4_debugfs.c -+++ b/drivers/gpu/drm/vc4/vc4_debugfs.c -@@ -17,6 +17,7 @@ - - static const struct drm_info_list vc4_debugfs_list[] = { - {"bo_stats", vc4_bo_stats_debugfs, 0}, -+ {"gem_exec", vc4_gem_exec_debugfs, 0}, - {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, - {"hvs_regs", vc4_hvs_debugfs_regs, 0}, - {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index fa2ad15d4f62b8baea68e09b52f4edf1c70bb6b6..f0929867b2337eaf781d64860c70cafd006c41b7 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -440,6 +440,7 @@ void vc4_job_handle_completed(struct vc4_dev *vc4); - int vc4_queue_seqno_cb(struct drm_device *dev, - struct vc4_seqno_cb *cb, uint64_t seqno, - void (*func)(struct vc4_seqno_cb *cb)); -+int vc4_gem_exec_debugfs(struct seq_file *m, void *arg); - - /* vc4_hdmi.c */ - extern struct platform_driver vc4_hdmi_driver; -diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c -index 8d4384f8b78d2dbe88df720db6df67c0e1a31e53..aa4517c294540ac7ebc5c8c1da6b9d147409fcb4 100644 ---- a/drivers/gpu/drm/vc4/vc4_gem.c -+++ b/drivers/gpu/drm/vc4/vc4_gem.c -@@ -32,6 +32,20 @@ - #include "vc4_regs.h" - #include "vc4_trace.h" - -+#ifdef CONFIG_DEBUG_FS -+int vc4_gem_exec_debugfs(struct seq_file *m, void *unused) -+{ -+ struct drm_info_node *node = (struct drm_info_node *)m->private; -+ struct drm_device *dev = node->minor->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ -+ seq_printf(m, "Emitted seqno: 0x%016llx\n", vc4->emit_seqno); -+ seq_printf(m, "Finished seqno: 0x%016llx\n", vc4->finished_seqno); -+ -+ return 0; -+} -+#endif /* CONFIG_DEBUG_FS */ -+ - static void - vc4_queue_hangcheck(struct drm_device *dev) - { - -From a6b2cb6f6413cb7800a8d7bdcf73084f768f6848 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 25 Jan 2016 13:03:33 -0800 -Subject: [PATCH 095/141] drm/vc4: Include vc4_drm.h in uapi in downstream - build. - -Signed-off-by: Eric Anholt ---- - include/uapi/drm/Kbuild | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild -index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 ---- a/include/uapi/drm/Kbuild -+++ b/include/uapi/drm/Kbuild -@@ -15,6 +15,7 @@ header-y += radeon_drm.h - header-y += savage_drm.h - header-y += sis_drm.h - header-y += tegra_drm.h -+header-y += vc4_drm.h - header-y += via_drm.h - header-y += vmwgfx_drm.h - header-y += msm_drm.h - -From 6283aa9ef68d0c97b0b9623ff53f8461c62e2c8d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 30 Mar 2016 17:23:15 +0100 -Subject: [PATCH 096/141] cpufreq: Temporarily ignore io_is_busy=1 - -To speed testing of the new sdhost driver that adapts to changes in -core_freq, hack the on-demand governor to treat io_is_busy=1 as -io_is_busy=0. The io_is_busy feature can still be forced using -io_is_busy=2. - -Signed-off-by: Phil Elwell ---- - drivers/cpufreq/cpufreq_ondemand.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c -index acd80272ded67b46ad651cb0eceb92bdf71e26d7..72c5a4c7d6e40bd7407c769c0f6c418fb15df665 100644 ---- a/drivers/cpufreq/cpufreq_ondemand.c -+++ b/drivers/cpufreq/cpufreq_ondemand.c -@@ -216,7 +216,12 @@ static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf, - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; -- dbs_data->io_is_busy = !!input; -+ // XXX temporary hack -+ if (input > 1) -+ input = 1; -+ else -+ input = 0; -+ dbs_data->io_is_busy = input; - - /* we need to re-evaluate prev_cpu_idle */ - gov_update_cpu_data(dbs_data); - -From 5e9758439d0e513703384a808b1e09f0896e9359 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Apr 2016 16:59:24 +0100 -Subject: [PATCH 097/141] Revert "ASoC: bcm2835: move to use the clock - framework" - -This reverts commit 517e7a1537ae4663268be5d0c0ec62c563b9fc99. ---- - sound/soc/bcm/bcm2835-i2s.c | 284 ++++++++++++++++++++++++++++++++++---------- - 1 file changed, 220 insertions(+), 64 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 1c1f2210387b26e9551959378f6792f18648652e..3303d5f58082f68b68b535b2bdf7ce8d14cafcc4 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - - #include -@@ -47,6 +46,55 @@ - #include - #include - -+/* Clock registers */ -+#define BCM2835_CLK_PCMCTL_REG 0x00 -+#define BCM2835_CLK_PCMDIV_REG 0x04 -+ -+/* Clock register settings */ -+#define BCM2835_CLK_PASSWD (0x5a000000) -+#define BCM2835_CLK_PASSWD_MASK (0xff000000) -+#define BCM2835_CLK_MASH(v) ((v) << 9) -+#define BCM2835_CLK_FLIP BIT(8) -+#define BCM2835_CLK_BUSY BIT(7) -+#define BCM2835_CLK_KILL BIT(5) -+#define BCM2835_CLK_ENAB BIT(4) -+#define BCM2835_CLK_SRC(v) (v) -+ -+#define BCM2835_CLK_SHIFT (12) -+#define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) -+#define BCM2835_CLK_DIVF(v) (v) -+#define BCM2835_CLK_DIVF_MASK (0xFFF) -+ -+enum { -+ BCM2835_CLK_MASH_0 = 0, -+ BCM2835_CLK_MASH_1, -+ BCM2835_CLK_MASH_2, -+ BCM2835_CLK_MASH_3, -+}; -+ -+enum { -+ BCM2835_CLK_SRC_GND = 0, -+ BCM2835_CLK_SRC_OSC, -+ BCM2835_CLK_SRC_DBG0, -+ BCM2835_CLK_SRC_DBG1, -+ BCM2835_CLK_SRC_PLLA, -+ BCM2835_CLK_SRC_PLLC, -+ BCM2835_CLK_SRC_PLLD, -+ BCM2835_CLK_SRC_HDMI, -+}; -+ -+/* Most clocks are not useable (freq = 0) */ -+static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { -+ [BCM2835_CLK_SRC_GND] = 0, -+ [BCM2835_CLK_SRC_OSC] = 19200000, -+ [BCM2835_CLK_SRC_DBG0] = 0, -+ [BCM2835_CLK_SRC_DBG1] = 0, -+ [BCM2835_CLK_SRC_PLLA] = 0, -+ [BCM2835_CLK_SRC_PLLC] = 0, -+ [BCM2835_CLK_SRC_PLLD] = 500000000, -+ [BCM2835_CLK_SRC_HDMI] = 0, -+}; -+ - /* I2S registers */ - #define BCM2835_I2S_CS_A_REG 0x00 - #define BCM2835_I2S_FIFO_A_REG 0x04 -@@ -110,6 +158,10 @@ - #define BCM2835_I2S_INT_RXR BIT(1) - #define BCM2835_I2S_INT_TXW BIT(0) - -+/* I2S DMA interface */ -+/* FIXME: Needs IOMMU support */ -+#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) -+ - /* General device struct */ - struct bcm2835_i2s_dev { - struct device *dev; -@@ -117,23 +169,21 @@ struct bcm2835_i2s_dev { - unsigned int fmt; - unsigned int bclk_ratio; - -- struct regmap *i2s_regmap; -- struct clk *clk; -- bool clk_prepared; -+ struct regmap *i2s_regmap; -+ struct regmap *clk_regmap; - }; - - static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) - { -+ /* Start the clock if in master mode */ - unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; - -- if (dev->clk_prepared) -- return; -- - switch (master) { - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBS_CFM: -- clk_prepare_enable(dev->clk); -- dev->clk_prepared = true; -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); - break; - default: - break; -@@ -142,9 +192,28 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) - - static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) - { -- if (dev->clk_prepared) -- clk_disable_unprepare(dev->clk); -- dev->clk_prepared = false; -+ uint32_t clkreg; -+ int timeout = 1000; -+ -+ /* Stop clock */ -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD); -+ -+ /* Wait for the BUSY flag going down */ -+ while (--timeout) { -+ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); -+ if (!(clkreg & BCM2835_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, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, -+ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); -+ } - } - - static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, -@@ -154,7 +223,8 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - uint32_t syncval; - uint32_t csreg; - uint32_t i2s_active_state; -- bool clk_was_prepared; -+ uint32_t clkreg; -+ uint32_t clk_active_state; - uint32_t off; - uint32_t clr; - -@@ -168,10 +238,15 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); - i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); - -+ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); -+ clk_active_state = clkreg & BCM2835_CLK_ENAB; -+ - /* Start clock if not running */ -- clk_was_prepared = dev->clk_prepared; -- if (!clk_was_prepared) -- bcm2835_i2s_start_clock(dev); -+ if (!clk_active_state) { -+ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, -+ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); -+ } - - /* Stop I2S module */ - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); -@@ -205,7 +280,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, - dev_err(dev->dev, "I2S SYNC error!\n"); - - /* Stop clock if it was not running before */ -- if (!clk_was_prepared) -+ if (!clk_active_state) - bcm2835_i2s_stop_clock(dev); - - /* Restore I2S state */ -@@ -234,9 +309,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { - struct bcm2835_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 = BCM2835_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; - - /* -@@ -258,9 +343,11 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - 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; -@@ -269,12 +356,69 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - /* If bclk_ratio already set, use that one. */ - if (dev->bclk_ratio) - bclk_ratio = dev->bclk_ratio; -- else -- /* otherwise calculate a fitting block ratio */ -- bclk_ratio = 2 * data_length; - -- /* set target clock rate*/ -- clk_set_rate(dev->clk, sampling_rate * 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 = BCM2835_CLK_SRC_OSC; -+ mash = BCM2835_CLK_MASH_0; -+ -+ if (bcm2835_clk_freq[clk_src] % target_frequency == 0 -+ && bit_master && frame_master) { -+ divi = bcm2835_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 = BCM2835_CLK_SRC_PLLD; -+ mash = BCM2835_CLK_MASH_1; -+ -+ dividend = bcm2835_clk_freq[clk_src]; -+ dividend <<= BCM2835_CLK_SHIFT; -+ do_div(dividend, target_frequency); -+ divi = dividend >> BCM2835_CLK_SHIFT; -+ divf = dividend & BCM2835_CLK_DIVF_MASK; -+ } -+ -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD -+ | BCM2835_CLK_DIVI(divi) -+ | BCM2835_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD -+ | BCM2835_CLK_MASH(mash) -+ | BCM2835_CLK_SRC(clk_src)); - - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; -@@ -548,7 +692,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { - .trigger = bcm2835_i2s_trigger, - .hw_params = bcm2835_i2s_hw_params, - .set_fmt = bcm2835_i2s_set_dai_fmt, -- .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, -+ .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio - }; - - static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) -@@ -606,14 +750,34 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) - }; - } - --static const struct regmap_config bcm2835_regmap_config = { -- .reg_bits = 32, -- .reg_stride = 4, -- .val_bits = 32, -- .max_register = BCM2835_I2S_GRAY_REG, -- .precious_reg = bcm2835_i2s_precious_reg, -- .volatile_reg = bcm2835_i2s_volatile_reg, -- .cache_type = REGCACHE_RBTREE, -+static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) -+{ -+ switch (reg) { -+ case BCM2835_CLK_PCMCTL_REG: -+ return true; -+ default: -+ return false; -+ }; -+} -+ -+static const struct regmap_config bcm2835_regmap_config[] = { -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2835_I2S_GRAY_REG, -+ .precious_reg = bcm2835_i2s_precious_reg, -+ .volatile_reg = bcm2835_i2s_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, -+ { -+ .reg_bits = 32, -+ .reg_stride = 4, -+ .val_bits = 32, -+ .max_register = BCM2835_CLK_PCMDIV_REG, -+ .volatile_reg = bcm2835_clk_volatile_reg, -+ .cache_type = REGCACHE_RBTREE, -+ }, - }; - - static const struct snd_soc_component_driver bcm2835_i2s_component = { -@@ -623,50 +787,42 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - static int bcm2835_i2s_probe(struct platform_device *pdev) - { - struct bcm2835_i2s_dev *dev; -+ int i; - int ret; -- struct resource *mem; -- void __iomem *base; -- const __be32 *addr; -- dma_addr_t dma_base; -+ 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, -+ &bcm2835_regmap_config[i]); -+ if (IS_ERR(regmap[i])) -+ return PTR_ERR(regmap[i]); -+ } - - dev = devm_kzalloc(&pdev->dev, sizeof(*dev), - GFP_KERNEL); - if (!dev) - return -ENOMEM; - -- /* get the clock */ -- dev->clk_prepared = false; -- dev->clk = devm_clk_get(&pdev->dev, NULL); -- if (IS_ERR(dev->clk)) { -- dev_err(&pdev->dev, "could not get clk: %ld\n", -- PTR_ERR(dev->clk)); -- return PTR_ERR(dev->clk); -- } -- -- /* Request ioarea */ -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- base = devm_ioremap_resource(&pdev->dev, mem); -- if (IS_ERR(base)) -- return PTR_ERR(base); -- -- dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base, -- &bcm2835_regmap_config); -- if (IS_ERR(dev->i2s_regmap)) -- return PTR_ERR(dev->i2s_regmap); -- -- /* Set the DMA address - we have to parse DT ourselves */ -- addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); -- if (!addr) { -- dev_err(&pdev->dev, "could not get DMA-register address\n"); -- return -EINVAL; -- } -- dma_base = be32_to_cpup(addr); -+ dev->i2s_regmap = regmap[0]; -+ dev->clk_regmap = regmap[1]; - -+ /* Set the DMA address */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -- dma_base + BCM2835_I2S_FIFO_A_REG; -+ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -+ + BCM2835_VCMMU_SHIFT; - - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -- dma_base + BCM2835_I2S_FIFO_A_REG; -+ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -+ + BCM2835_VCMMU_SHIFT; - - /* Set the bus width */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = - -From 4ced68a9916e83d80a0a17cae13fe1ab890b8c4b Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 16:44:05 +0200 -Subject: [PATCH 098/141] bcm2835-i2s: get base address for DMA from devicetree - -Code copied from spi-bcm2835. Get physical address from devicetree -instead of using hardcoded constant. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++-------- - 1 file changed, 12 insertions(+), 8 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 3303d5f58082f68b68b535b2bdf7ce8d14cafcc4..0f25db4cd198c0a511e8a205b0cb2be62ba94adf 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { - #define BCM2835_I2S_INT_RXR BIT(1) - #define BCM2835_I2S_INT_TXW BIT(0) - --/* I2S DMA interface */ --/* FIXME: Needs IOMMU support */ --#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) -- - /* General device struct */ - struct bcm2835_i2s_dev { - struct device *dev; -@@ -791,6 +788,15 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - int ret; - struct regmap *regmap[2]; - struct resource *mem[2]; -+ const __be32 *addr; -+ dma_addr_t dma_reg_base; -+ -+ addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); -+ if (!addr) { -+ dev_err(&pdev->dev, "could not get DMA-register address\n"); -+ return -ENODEV; -+ } -+ dma_reg_base = be32_to_cpup(addr); - - /* Request both ioareas */ - for (i = 0; i <= 1; i++) { -@@ -817,12 +823,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - - /* Set the DMA address */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = -- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -- + BCM2835_VCMMU_SHIFT; -+ dma_reg_base + BCM2835_I2S_FIFO_A_REG; - - dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = -- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG -- + BCM2835_VCMMU_SHIFT; -+ dma_reg_base + BCM2835_I2S_FIFO_A_REG; - - /* Set the bus width */ - dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = - -From 56e0cbbd52af08a2064dd94403957bd3a6775f2a Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:21:16 +0200 -Subject: [PATCH 099/141] bcm2835-i2s: add 24bit support, update bclk_ratio to - more correct values - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit 62c05a0b5328d9376d39c9e74da10b8a2465c234 ("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 - -RPi commit 3e8c672bc4e92d457aa4654bbb4cfd79a18a2327 ("bcm2708-i2s: -Update bclk_ratio to more correct values") - -Discussion about blck_ratio affecting sound quality: -https://github.com/raspberrypi/linux/issues/681 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 0f25db4cd198c0a511e8a205b0cb2be62ba94adf..0f35d7c0f4026bb50a7223461b907b9797bd9a05 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -340,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - data_length = 16; -- bclk_ratio = 40; -+ bclk_ratio = 50; -+ break; -+ case SNDRV_PCM_FORMAT_S24_LE: -+ data_length = 24; -+ bclk_ratio = 50; - break; - case SNDRV_PCM_FORMAT_S32_LE: - data_length = 32; -- bclk_ratio = 80; -+ bclk_ratio = 100; - break; - default: - return -EINVAL; -@@ -420,7 +424,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; - -- if (data_length > 24) -+ if (data_length >= 24) - format |= BCM2835_I2S_CHWEX; - - format |= BCM2835_I2S_CHWID((data_length-8)&0xf); -@@ -711,6 +715,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { -@@ -718,6 +723,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, - -From 23d9e41cac43d6ce057b9b15ae3db92b1cd67200 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:25:51 +0200 -Subject: [PATCH 100/141] bcm2835-i2s: setup clock only if CPU is clock master - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit c14827ecdaa36607f6110f9ce8df96e698672191 ("bcm2708: Allow -option card devices to be configured via DT") - -Original work by Zoltan Szenczi, committed to RPi tree by -Phil Elwell. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 28 +++++++++++++++++++--------- - 1 file changed, 19 insertions(+), 9 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 0f35d7c0f4026bb50a7223461b907b9797bd9a05..d5e412302811ed8b007fc53f0aa2b5ddd12774b6 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -411,15 +411,25 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - divf = dividend & BCM2835_CLK_DIVF_MASK; - } - -- /* Set clock divider */ -- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD -- | BCM2835_CLK_DIVI(divi) -- | BCM2835_CLK_DIVF(divf)); -- -- /* Setup clock, but don't start it yet */ -- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD -- | BCM2835_CLK_MASH(mash) -- | BCM2835_CLK_SRC(clk_src)); -+ /* Clock should only be set up here if CPU is clock master */ -+ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { -+ case SND_SOC_DAIFMT_CBS_CFS: -+ case SND_SOC_DAIFMT_CBS_CFM: -+ /* Set clock divider */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, -+ BCM2835_CLK_PASSWD -+ | BCM2835_CLK_DIVI(divi) -+ | BCM2835_CLK_DIVF(divf)); -+ -+ /* Setup clock, but don't start it yet */ -+ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, -+ BCM2835_CLK_PASSWD -+ | BCM2835_CLK_MASH(mash) -+ | BCM2835_CLK_SRC(clk_src)); -+ break; -+ default: -+ break; -+ } - - /* Setup the frame format */ - format = BCM2835_I2S_CHEN; - -From c3e9993c137b57996503171e72763ef7df1ce43b Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:49:51 +0200 -Subject: [PATCH 101/141] bcm2835-i2s: Eliminate debugfs directory error - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit fd7d7a3dbe9262d16971ef81c234ed28c6499dd7 ("bcm2708: -Eliminate i2s debugfs directory error") - -Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') -to avoid the name clash when registering debugfs entries. - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index d5e412302811ed8b007fc53f0aa2b5ddd12774b6..2d29050e739b0af02d0f5122d18178b61c024bea 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -782,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { - .precious_reg = bcm2835_i2s_precious_reg, - .volatile_reg = bcm2835_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, -+ .name = "i2s", - }, - { - .reg_bits = 32, -@@ -790,6 +791,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { - .max_register = BCM2835_CLK_PCMDIV_REG, - .volatile_reg = bcm2835_clk_volatile_reg, - .cache_type = REGCACHE_RBTREE, -+ .name = "clk", - }, - }; - - -From f88b870ca6cb55cc9be59b4d3c3d3ba35b0305e1 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:35:20 +0200 -Subject: [PATCH 102/141] bcm2835-i2s: Register PCM device - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit ba46b4935a23aa2caac1855ead52a035d4776680 ("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 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 23 ++++++++++++++++++++++- - 1 file changed, 22 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 2d29050e739b0af02d0f5122d18178b61c024bea..ce93ef0579ab142c788736f0d309c92636b8983d 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -799,6 +799,25 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - .name = "bcm2835-i2s-comp", - }; - -+static const struct snd_pcm_hardware bcm2835_pcm_hardware = { -+ .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, -+ .periods_min = 2, -+ .periods_max = 255, -+ .buffer_bytes_max = 128 * PAGE_SIZE, -+}; -+ -+static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = { -+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, -+ .pcm_hardware = &bcm2835_pcm_hardware, -+ .prealloc_buffer_size = 256 * PAGE_SIZE, -+}; -+ - static int bcm2835_i2s_probe(struct platform_device *pdev) - { - struct bcm2835_i2s_dev *dev; -@@ -870,7 +889,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - return ret; - } - -- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); -+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, -+ &bcm2835_dmaengine_pcm_config, -+ SND_DMAENGINE_PCM_FLAG_COMPAT); - if (ret) { - dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); - return ret; - -From 0e8d7503a489cb6bd5980bb2bbf10b7560bad8c9 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 11 Oct 2015 15:55:21 +0200 -Subject: [PATCH 103/141] bcm2835-i2s: Enable MMAP support via a DT property - -Code ported from bcm2708-i2s driver in Raspberry Pi tree. - -RPi commit 7ee829fd77a30127db5d0b3c7d79b8718166e568 ("bcm2708-i2s: -Enable MMAP support via a DT property and overlay") - -The i2s driver used to claim to support MMAP, but that feature was disabled -when some problems were found. Add the ability to enable this feature -through Device Tree, using the i2s-mmap overlay. - -See: #1004 - -Signed-off-by: Matthias Reichl ---- - sound/soc/bcm/bcm2835-i2s.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index ce93ef0579ab142c788736f0d309c92636b8983d..6f60c2cebb412524bb0e30d0339fe556680e8637 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -799,7 +799,7 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { - .name = "bcm2835-i2s-comp", - }; - --static const struct snd_pcm_hardware bcm2835_pcm_hardware = { -+static struct snd_pcm_hardware bcm2835_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX, - .formats = SNDRV_PCM_FMTBIT_S16_LE | -@@ -835,6 +835,11 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) - } - dma_reg_base = be32_to_cpup(addr); - -+ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) -+ bcm2835_pcm_hardware.info |= -+ SNDRV_PCM_INFO_MMAP | -+ SNDRV_PCM_INFO_MMAP_VALID; -+ - /* Request both ioareas */ - for (i = 0; i <= 1; i++) { - void __iomem *base; - -From 5862cb36220cb6b57b8553ed54d2764ff89a083a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 Apr 2016 15:44:14 +0100 -Subject: [PATCH 104/141] bcm2835-i2s: Reduce the TX DREQ threshold - -TX FIFO overrun is thought to be the cause of channel swapping, so -reducing the DREQ threshold seems reasonable and appears to be -effective. - -See: https://github.com/raspberrypi/linux/issues/1417 - -Signed-off-by: Phil Elwell ---- - sound/soc/bcm/bcm2835-i2s.c | 21 ++++++++++++++------- - 1 file changed, 14 insertions(+), 7 deletions(-) - -diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c -index 6f60c2cebb412524bb0e30d0339fe556680e8637..b26f9587dec01d62606df3f47b3ef00c908fa05b 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -555,15 +555,22 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - - /* Setup the DMA parameters */ - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, -- BCM2835_I2S_RXTHR(1) -- | BCM2835_I2S_TXTHR(1) -- | BCM2835_I2S_DMAEN, 0xffffffff); -+ BCM2835_I2S_RXTHR(3) -+ | BCM2835_I2S_TXTHR(3) -+ | BCM2835_I2S_DMAEN, -+ BCM2835_I2S_RXTHR(1) -+ | BCM2835_I2S_TXTHR(1) -+ | BCM2835_I2S_DMAEN); - - regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, -- BCM2835_I2S_TX_PANIC(0x10) -- | BCM2835_I2S_RX_PANIC(0x30) -- | BCM2835_I2S_TX(0x30) -- | BCM2835_I2S_RX(0x20), 0xffffffff); -+ BCM2835_I2S_TX_PANIC(0x7f) -+ | BCM2835_I2S_RX_PANIC(0x7f) -+ | BCM2835_I2S_TX(0x7f) -+ | BCM2835_I2S_RX(0x7f), -+ BCM2835_I2S_TX_PANIC(0x10) -+ | BCM2835_I2S_RX_PANIC(0x30) -+ | BCM2835_I2S_TX(0x20) -+ | BCM2835_I2S_RX(0x20)); - - /* Clear FIFOs */ - bcm2835_i2s_clear_fifos(dev, true, true); - -From afc742b15306af6aca77683b0737a013a9d48488 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Oct 2015 11:32:14 -0700 -Subject: [PATCH 105/141] drm/vc4: Force HDMI to connected. - -For some reason on the downstream tree, the HPD GPIO isn't working. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c -index d8b864925fd38757cdc12e72d5ea102f32d2af09..136847ea795c58b8f0b2363a36242de512a01f83 100644 ---- a/drivers/gpu/drm/vc4/vc4_hdmi.c -+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c -@@ -166,6 +166,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) - struct drm_device *dev = connector->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); - -+ return connector_status_connected; -+ - if (vc4->hdmi->hpd_gpio) { - if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ - vc4->hdmi->hpd_active_low) - -From 0c089d1889103454a70b10a1adfc6a1095d273e5 Mon Sep 17 00:00:00 2001 +From 46c3097c1776e1fe84731643d691527a1cc856fa Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 106/141] Add Support for JustBoom Audio boards +Subject: [PATCH 076/111] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -132675,46 +130576,14 @@ rather than a struct snd_soc_codec *. Signed-off-by: Phil Elwell --- - arch/arm/configs/bcm2709_defconfig | 4 +- - arch/arm/configs/bcmrpi_defconfig | 4 +- - sound/soc/bcm/Kconfig | 14 +++ - sound/soc/bcm/Makefile | 4 + - sound/soc/bcm/justboom-dac.c | 162 ++++++++++++++++++++++++++++ - sound/soc/bcm/justboom-digi.c | 215 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 399 insertions(+), 4 deletions(-) + sound/soc/bcm/Kconfig | 14 +++ + sound/soc/bcm/Makefile | 4 + + sound/soc/bcm/justboom-dac.c | 162 +++++++++++++++++++++++++++++++ + sound/soc/bcm/justboom-digi.c | 215 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 395 insertions(+) create mode 100644 sound/soc/bcm/justboom-dac.c create mode 100644 sound/soc/bcm/justboom-digi.c -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index f42c5ebcbff904746a282a3d6fb13483e32c7fd8..055ecfcfea6df119dda49a1ffdb1e5a34ccef0c0 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -856,8 +856,8 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m - CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 8bd02073ab8f35ef28db5fcd628e3e44a922c0ea..8e0b51f853c055beb9fc6e8bf18f3ee2e54d6010 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -848,8 +848,8 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DAC=m --CONFIG_SND_BCM2708_SOC_BOOMBERRY_DIGI=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -+CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI=m - CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig index 1a3f8264403d64690fef60d41df38d21d3eb6030..e2e2782a2f8af27c1782993bd63747b620f26e1e 100644 --- a/sound/soc/bcm/Kconfig @@ -133152,33 +131021,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 699848abef604bd891a88c4c85825f699b9e9eea Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 19 Apr 2016 15:55:02 -0700 -Subject: [PATCH 107/141] ARM: bcm2708: Enable building power domain driver. - -Signed-off-by: Eric Anholt ---- - drivers/soc/bcm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig -index 3066edea184d765a670ded0cead470597654abc1..e23518142ceac6651641cc30c327d60dded319d5 100644 ---- a/drivers/soc/bcm/Kconfig -+++ b/drivers/soc/bcm/Kconfig -@@ -1,6 +1,6 @@ - config RASPBERRYPI_POWER - bool "Raspberry Pi power domain driver" -- depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST - depends on RASPBERRYPI_FIRMWARE=y - select PM_GENERIC_DOMAINS if PM - select PM_GENERIC_DOMAINS_OF if PM - -From ce8f9a782faff6c9d9af11ca0ecd8ea9927c87eb Mon Sep 17 00:00:00 2001 +From a774bf62b65352d425d75c064ade27e67e4d51b0 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 108/141] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 077/111] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -133360,21 +131206,25 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From 2612db33ceeb9fe17f9581ddcf4e90dc534bd3d5 Mon Sep 17 00:00:00 2001 +From 50e698a0f5934beb1044d987d0fde684fc57583b Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 109/141] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 078/111] New AudioInjector.net Pi soundcard with low jitter audio in and out. Contains the sound/soc/bcm ALSA machine driver and necessary alterations to the Kconfig and Makefile. Adds the dts overlay and updates the Makefile and README. Updates the relevant defconfig files to enable building for the Raspberry Pi. Thanks to Phil Elwell (pelwell) for the review, simple-card concepts and discussion. Thanks to Clive Messer for overlay naming suggestions. + +Added support for headphones, microphone and bclk_ratio settings. + +This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. --- sound/soc/bcm/Kconfig | 7 ++ sound/soc/bcm/Makefile | 3 + - sound/soc/bcm/audioinjector-pi-soundcard.c | 142 +++++++++++++++++++++++++++++ - 3 files changed, 152 insertions(+) + sound/soc/bcm/audioinjector-pi-soundcard.c | 191 +++++++++++++++++++++++++++++ + 3 files changed, 201 insertions(+) create mode 100644 sound/soc/bcm/audioinjector-pi-soundcard.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig @@ -133412,10 +131262,10 @@ index d3124f579475524a739ced533f6dff69394eee1c..3353192be30394bd595423dccec17838 + diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c new file mode 100644 -index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc160a485281 +index 0000000000000000000000000000000000000000..5ff0985e07efb96b95634a65995f09f7c68d9e99 --- /dev/null +++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -0,0 +1,142 @@ +@@ -0,0 +1,191 @@ +/* + * ASoC Driver for AudioInjector Pi add on soundcard + * @@ -133447,16 +131297,56 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 + +#include "../codecs/wm8731.h" + ++static const unsigned int bcm2835_rates_12000000[] = { ++ 32000, 44100, 48000, 96000, 88200, ++}; ++ ++static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { ++ .list = bcm2835_rates_12000000, ++ .count = ARRAY_SIZE(bcm2835_rates_12000000), ++}; ++ ++static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) ++{ ++ /* Setup constraints, because there is a 12 MHz XTAL on the board */ ++ snd_pcm_hw_constraint_list(substream->runtime, 0, ++ SNDRV_PCM_HW_PARAM_RATE, ++ &bcm2835_constraints_12000000); ++ return 0; ++} ++ ++static int snd_audioinjector_pi_soundcard_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; ++ ++ switch (params_rate(params)){ ++ case 8000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); ++ case 32000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); ++ case 44100: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); ++ case 48000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); ++ case 88200: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); ++ case 96000: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ default: ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); ++ } ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_audioinjector_pi_soundcard_ops = { ++ .startup = snd_audioinjector_pi_soundcard_startup, ++ .hw_params = snd_audioinjector_pi_soundcard_hw_params, ++}; ++ +static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) +{ -+ struct snd_soc_dapm_context *dapm = &rtd->card->dapm; -+ -+ // not connected -+ snd_soc_dapm_nc_pin(dapm, "Mic Bias"); -+ snd_soc_dapm_nc_pin(dapm, "MICIN"); -+ snd_soc_dapm_nc_pin(dapm, "RHPOUT"); -+ snd_soc_dapm_nc_pin(dapm, "LHPOUT"); -+ + return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); +} + @@ -133468,30 +131358,39 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 + .codec_dai_name = "wm8731-hifi", + .platform_name = "bcm2835-i2s.0", + .codec_name = "wm8731.1-001a", ++ .ops = &snd_audioinjector_pi_soundcard_ops, + .init = audioinjector_pi_soundcard_dai_init, + .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, + }, +}; + +static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_LINE("Line In Jacks", NULL), ++ SND_SOC_DAPM_MIC("Microphone", NULL), +}; + -+/* Corgi machine connections to the codec pins */ +static const struct snd_soc_dapm_route audioinjector_audio_map[] = { ++ /* headphone connected to LHPOUT, RHPOUT */ ++ {"Headphone Jack", NULL, "LHPOUT"}, ++ {"Headphone Jack", NULL, "RHPOUT"}, ++ + /* speaker connected to LOUT, ROUT */ + {"Ext Spk", NULL, "ROUT"}, + {"Ext Spk", NULL, "LOUT"}, + + /* line inputs */ + {"Line In Jacks", NULL, "Line Input"}, ++ ++ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ ++ {"Microphone", NULL, "Mic Bias"}, +}; + +static struct snd_soc_card snd_soc_audioinjector = { + .name = "audioinjector-pi-soundcard", + .dai_link = audioinjector_pi_soundcard_dai, -+ .num_links = 1, ++ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), + + .dapm_widgets = wm8731_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), @@ -133559,225 +131458,327 @@ index 0000000000000000000000000000000000000000..39f29e26897226a413b4fa0a11a9bc16 +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From c7b2ab47d4bfb5efecae620fc045435228f877bf Mon Sep 17 00:00:00 2001 -From: Dave Stevenson <6by9@users.noreply.github.com> -Date: Wed, 25 May 2016 23:25:36 +0100 -Subject: [PATCH 110/141] BCM2835-V4L2: Correct handling for BGR24 vs RGB24. +From 1f2eac04eced09d8ac3697b73155cc3db05c1a26 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Thu, 30 Jun 2016 18:38:42 +0100 +Subject: [PATCH 079/111] Add IQAudIO Digi WM8804 board support -There was a bug in the GPU firmware that had reversed these -two formats. -Detect the old firmware, and reverse the formats if necessary. +Support IQAudIO Digi board with iqaudio_digi machine driver and + iqaudio-digi-wm8804-audio overlay. -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> +NB. Machine driver is a cut and paste of hifiberry_digi code, with format + and general cleanup to comply with kernel coding standards. + +Signed-off-by: DigitalDreamtime --- - drivers/media/platform/bcm2835/bcm2835-camera.c | 69 ++++++++++++++++++------- - drivers/media/platform/bcm2835/bcm2835-camera.h | 1 + - 2 files changed, 52 insertions(+), 18 deletions(-) + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/iqaudio_digi.c | 239 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 248 insertions(+) + create mode 100644 sound/soc/bcm/iqaudio_digi.c -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index 1b16c63315195c043c41d6676ecfedd004c92cd3..70f4db2741037381e638d1dda5a95478809eb161 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -115,7 +115,7 @@ static struct mmal_fmt formats[] = { - .name = "RGB24 (LE)", - .fourcc = V4L2_PIX_FMT_RGB24, - .flags = 0, -- .mmal = MMAL_ENCODING_BGR24, -+ .mmal = MMAL_ENCODING_RGB24, - .depth = 24, - .mmal_component = MMAL_COMPONENT_CAMERA, - .ybbp = 3, -@@ -187,7 +187,7 @@ static struct mmal_fmt formats[] = { - .name = "RGB24 (BE)", - .fourcc = V4L2_PIX_FMT_BGR24, - .flags = 0, -- .mmal = MMAL_ENCODING_RGB24, -+ .mmal = MMAL_ENCODING_BGR24, - .depth = 24, - .mmal_component = MMAL_COMPONENT_CAMERA, - .ybbp = 3, -@@ -1061,6 +1061,13 @@ static int mmal_setup_components(struct bm2835_mmal_dev *dev, - else - camera_port->format.encoding = mfmt->mmal; +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index e2e40eda90f447a4700767071715e263bfa9a6e7..616f47e72a2300df0ed79f082c67ba0af13067ee 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -71,6 +71,13 @@ config SND_BCM2708_SOC_IQAUDIO_DAC + help + Say Y or M if you want to add support for IQaudIO-DAC. -+ if (dev->rgb_bgr_swapped) { -+ if (camera_port->format.encoding == MMAL_ENCODING_RGB24) -+ camera_port->format.encoding = MMAL_ENCODING_BGR24; -+ else if (camera_port->format.encoding == MMAL_ENCODING_BGR24) -+ camera_port->format.encoding = MMAL_ENCODING_RGB24; ++config SND_BCM2708_SOC_IQAUDIO_DIGI ++ tristate "Support for IQAudIO Digi" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for IQAudIO Digital IO board. ++ + config SND_BCM2708_SOC_RASPIDAC3 + tristate "Support for RaspiDAC Rev.3x" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 3353192be30394bd595423dccec17838e3054a1d..fb3e44d2668bda0494751d4e6c925f34a5ce2bc3 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -14,6 +14,7 @@ snd-soc-justboom-digi-objs := justboom-digi.o + snd-soc-rpi-dac-objs := rpi-dac.o + snd-soc-rpi-proto-objs := rpi-proto.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o ++snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + +@@ -27,6 +28,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o ++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + +diff --git a/sound/soc/bcm/iqaudio_digi.c b/sound/soc/bcm/iqaudio_digi.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e7816319639e39d65 +--- /dev/null ++++ b/sound/soc/bcm/iqaudio_digi.c +@@ -0,0 +1,239 @@ ++/* ++ * ASoC Driver for IQAudIO WM8804 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 short int auto_shutdown_output; ++module_param(auto_shutdown_output, short, ++ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); ++MODULE_PARM_DESC(auto_shutdown_output, "Shutdown SP/DIF output if playback is stopped"); ++ ++static int snd_rpi_iqaudio_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_iqaudio_digi_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn on digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x00); ++ ++ return 0; ++} ++ ++static void snd_rpi_iqaudio_digi_shutdown(struct snd_pcm_substream *substream) ++{ ++ if (auto_shutdown_output) { ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ /* turn off digital output */ ++ snd_soc_update_bits(codec, WM8804_PWRDN, 0x3c, 0x3c); ++ } ++} ++ ++ ++static int snd_rpi_iqaudio_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 sampling_freq = 1; ++ ++ int ret; ++ ++ int samplerate = params_rate(params); ++ ++ if (samplerate <= 96000) { ++ mclk_freq = samplerate * 256; ++ mclk_div = WM8804_MCLKDIV_256FS; ++ } else { ++ mclk_freq = samplerate * 128; ++ mclk_div = WM8804_MCLKDIV_128FS; + } + - camera_port->format.encoding_variant = 0; - camera_port->es.video.width = f->fmt.pix.width; - camera_port->es.video.height = f->fmt.pix.height; -@@ -1571,12 +1578,17 @@ static int set_camera_parameters(struct vchiq_mmal_instance *instance, - return ret; - } - -+#define MAX_SUPPORTED_ENCODINGS 20 ++ switch (samplerate) { ++ case 32000: ++ sampling_freq = 0x03; ++ break; ++ case 44100: ++ sampling_freq = 0x00; ++ break; ++ case 48000: ++ sampling_freq = 0x02; ++ break; ++ case 88200: ++ sampling_freq = 0x08; ++ break; ++ case 96000: ++ sampling_freq = 0x0a; ++ break; ++ case 176400: ++ sampling_freq = 0x0c; ++ break; ++ case 192000: ++ sampling_freq = 0x0e; ++ break; ++ default: ++ dev_err(codec->dev, "Failed to set WM8804 SYSCLK, unsupported samplerate %d\n", ++ samplerate); ++ } + - /* MMAL instance and component init */ - static int __init mmal_init(struct bm2835_mmal_dev *dev) - { - int ret; - struct mmal_es_format *format; - u32 bool_true = 1; -+ u32 supported_encodings[MAX_SUPPORTED_ENCODINGS]; -+ int param_size; -+ struct vchiq_mmal_component *camera; - - ret = vchiq_mmal_init(&dev->instance); - if (ret < 0) -@@ -1588,21 +1600,48 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - if (ret < 0) - goto unreg_mmal; - -- if (dev->component[MMAL_COMPONENT_CAMERA]->outputs < -- MMAL_CAMERA_PORT_COUNT) { -+ camera = dev->component[MMAL_COMPONENT_CAMERA]; -+ if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { - ret = -EINVAL; - goto unreg_camera; - } - - ret = set_camera_parameters(dev->instance, -- dev->component[MMAL_COMPONENT_CAMERA], -+ camera, - dev); - if (ret < 0) - goto unreg_camera; - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_PREVIEW].format; -+ /* There was an error in the firmware that meant the camera component -+ * produced BGR instead of RGB. -+ * This is now fixed, but in order to support the old firmwares, we -+ * have to check. -+ */ -+ dev->rgb_bgr_swapped = true; -+ param_size = sizeof(supported_encodings); -+ ret = vchiq_mmal_port_parameter_get(dev->instance, -+ &camera->output[MMAL_CAMERA_PORT_CAPTURE], -+ MMAL_PARAMETER_SUPPORTED_ENCODINGS, -+ &supported_encodings, -+ ¶m_size); -+ if (ret == 0) { -+ int i; ++ snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); ++ snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); + -+ for (i = 0; i < param_size/sizeof(u32); i++) { -+ if (supported_encodings[i] == MMAL_ENCODING_BGR24) { -+ /* Found BGR24 first - old firmware. */ -+ break; -+ } -+ if (supported_encodings[i] == MMAL_ENCODING_RGB24) { -+ /* Found RGB24 first -+ * new firmware, so use RGB24. -+ */ -+ dev->rgb_bgr_swapped = false; -+ break; -+ } ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, ++ sysclk, SND_SOC_CLOCK_OUT); ++ if (ret < 0) { ++ dev_err(codec->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); ++ ++ /* set sampling frequency status bits */ ++ snd_soc_update_bits(codec, WM8804_SPDTX4, 0x0f, sampling_freq); ++ ++ return snd_soc_dai_set_bclk_ratio(cpu_dai, 64); ++} ++ ++/* machine stream operations */ ++static struct snd_soc_ops snd_rpi_iqaudio_digi_ops = { ++ .hw_params = snd_rpi_iqaudio_digi_hw_params, ++ .startup = snd_rpi_iqaudio_digi_startup, ++ .shutdown = snd_rpi_iqaudio_digi_shutdown, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_iqaudio_digi_dai[] = { ++{ ++ .name = "IQAudIO Digi", ++ .stream_name = "IQAudIO 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_iqaudio_digi_ops, ++ .init = snd_rpi_iqaudio_digi_init, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_iqaudio_digi = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .dai_link = snd_rpi_iqaudio_digi_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_digi_dai), ++}; ++ ++static int snd_rpi_iqaudio_digi_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &snd_rpi_iqaudio_digi; ++ char *prefix = "wm8804-digi,"; ++ char prop[128]; ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_iqaudio_digi.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_iqaudio_digi_dai[0]; ++ struct device_node *i2s_node; ++ ++ i2s_node = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; + } ++ ++ snprintf(prop, sizeof(prop), "%scard-name", prefix); ++ of_property_read_string(np, prop, &card->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-name", prefix); ++ of_property_read_string(np, prop, &dai->name); ++ ++ snprintf(prop, sizeof(prop), "%sdai-stream-name", prefix); ++ of_property_read_string(np, prop, &dai->stream_name); + } -+ format = &camera->output[MMAL_CAMERA_PORT_PREVIEW].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; -@@ -1616,9 +1655,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - format->es->video.frame_rate.num = 0; /* Rely on fps_range */ - format->es->video.frame_rate.den = 1; - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_VIDEO].format; -+ format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; -@@ -1633,14 +1670,11 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - format->es->video.frame_rate.den = 1; - - vchiq_mmal_port_parameter_set(dev->instance, -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_VIDEO], -+ &camera->output[MMAL_CAMERA_PORT_VIDEO], - MMAL_PARAMETER_NO_IMAGE_PADDING, - &bool_true, sizeof(bool_true)); - -- format = -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_CAPTURE].format; -+ format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - -@@ -1662,8 +1696,7 @@ static int __init mmal_init(struct bm2835_mmal_dev *dev) - dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; - - vchiq_mmal_port_parameter_set(dev->instance, -- &dev->component[MMAL_COMPONENT_CAMERA]-> -- output[MMAL_CAMERA_PORT_CAPTURE], -+ &camera->output[MMAL_CAMERA_PORT_CAPTURE], - MMAL_PARAMETER_NO_IMAGE_PADDING, - &bool_true, sizeof(bool_true)); - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h -index 13f426f5ecdffeab714d658a6f8b76e63af5fcdb..e6aeb7e7e381de65d6c6586205069a4c5cd33274 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.h -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -109,6 +109,7 @@ struct bm2835_mmal_dev { - unsigned int camera_num; - unsigned int max_width; - unsigned int max_height; -+ unsigned int rgb_bgr_swapped; - }; - - int bm2835_mmal_init_controls( ++ ++ ret = snd_soc_register_card(card); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_iqaudio_digi_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_iqaudio_digi); ++} ++ ++static const struct of_device_id snd_rpi_iqaudio_digi_of_match[] = { ++ { .compatible = "iqaudio,wm8804-digi", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_iqaudio_digi_of_match); ++ ++static struct platform_driver snd_rpi_iqaudio_digi_driver = { ++ .driver = { ++ .name = "IQAudIODigi", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_iqaudio_digi_of_match, ++ }, ++ .probe = snd_rpi_iqaudio_digi_probe, ++ .remove = snd_rpi_iqaudio_digi_remove, ++}; ++ ++module_platform_driver(snd_rpi_iqaudio_digi_driver); ++ ++MODULE_AUTHOR("Daniel Matuschek "); ++MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); ++MODULE_LICENSE("GPL v2"); -From 4630382072020373bf103fca3e5fbb0d59111e52 Mon Sep 17 00:00:00 2001 +From 3163272227b6e87a808cbc2834b93bfa3ad03674 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 111/141] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 080/111] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + sound/soc/bcm/Kconfig | 8 + sound/soc/bcm/Makefile | 2 + sound/soc/bcm/digidac1-soundcard.c | 422 +++++++++++++++++++++++++++++++++++++ - 5 files changed, 434 insertions(+) + 3 files changed, 432 insertions(+) create mode 100644 sound/soc/bcm/digidac1-soundcard.c -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 055ecfcfea6df119dda49a1ffdb1e5a34ccef0c0..1643dab1f04fdca37c71eb66cfc3c2a81bff9094 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -862,6 +862,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 8e0b51f853c055beb9fc6e8bf18f3ee2e54d6010..d936b43acaf2f28331e75b42b9f2bb7ff3fdbdf8 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -854,6 +854,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m - CONFIG_SND_BCM2708_SOC_RASPIDAC3=m - CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m - CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m -+CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index e2e40eda90f447a4700767071715e263bfa9a6e7..fa11cd792824f21424a3b798336b676d33181a43 100644 +index 616f47e72a2300df0ed79f082c67ba0af13067ee..a7e4e25ccf2de23f7a3793af66f795825e69fbb8 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig -@@ -92,3 +92,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD +@@ -99,3 +99,11 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD select SND_SOC_WM8731 help Say Y or M if you want to add support for audioinjector.net Pi Hat @@ -133790,19 +131791,19 @@ index e2e40eda90f447a4700767071715e263bfa9a6e7..fa11cd792824f21424a3b798336b676d + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 3353192be30394bd595423dccec17838e3054a1d..a9448fdcd6bcc4e4cb96e985fbe758aea002ddd8 100644 +index fb3e44d2668bda0494751d4e6c925f34a5ce2bc3..781037a9e323834ba62ec55c6cf28a95c769c2cb 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o - snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -17,6 +17,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o + snd-soc-iqaudio-digi-objs := iqaudio_digi.o snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o +snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o -@@ -29,4 +30,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o - obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +@@ -31,4 +32,5 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o +obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o @@ -134236,2791 +132237,2436 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From 86c24bce60588df5dc50e7a7e44913500f20e913 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 21:56:40 +0100 -Subject: [PATCH 112/141] BCM270X_DT: Fix rpi-dac overlay +From 9dc99dadefde0b3bb0140831fdda208c72f776c7 Mon Sep 17 00:00:00 2001 +From: DigitalDreamtime +Date: Sat, 2 Jul 2016 16:26:19 +0100 +Subject: [PATCH 081/111] Add support for Dion Audio LOCO DAC-AMP HAT -The rpi-dac overlay is almost identical to the hifiberry-dac overlay - -the codec used is different but it also doesn't sit on the I2C bus. As -a result, when the overlays were modified for dynamic loading and it -was discovered that the hifiberry-dac overlay didn't work any more, the -the rpi-dac overlay was also broken. +Using dedicated machine driver and pcm5102a codec driver. -The failure was caused by the fact that outside a bus, device names are -constructed from the concatenation of the path elements leading to it, -so moving the codec instantiation inside /soc caused the device name -to get a "soc" added, breaking ALSA's naming. - -See: http://forum.kodi.tv/showthread.php?tid=269814&pid=2349776#pid2349776 - -Signed-off-by: Phil Elwell +Signed-off-by: DigitalDreamtime --- - arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + sound/soc/bcm/Kconfig | 7 +++ + sound/soc/bcm/Makefile | 3 +- + sound/soc/bcm/dionaudio_loco.c | 121 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 130 insertions(+), 1 deletion(-) + create mode 100644 sound/soc/bcm/dionaudio_loco.c -diff --git a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -index 1523eae9c39997aa68cfa583ada92a92395bb1e0..a442c8f0ec01b7503f32e070683a984e895f5668 100644 ---- a/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/rpi-dac-overlay.dts -@@ -13,7 +13,7 @@ - }; - - fragment@1 { -- target = <&soc>; -+ target-path = "/"; - __overlay__ { - pcm1794a-codec { - #sound-dai-cells = <0>; - -From 0a0d01b64325a8ca5a165e1b35c2dac59540aecc Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 22:21:47 +0100 -Subject: [PATCH 113/141] BCM270X_DT: Add mcp23017 to the overlay Makefile - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 0adb5b92c047cb7e12871cf75515f822924924cd..c514bbfe7384f58d5db4e861d842bd772cc4e51a 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -44,6 +44,7 @@ dtbo-$(RPI_DT_OVERLAYS) += iqaudio-dacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo - dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo - dtbo-$(RPI_DT_OVERLAYS) += mmc.dtbo - -From 71097672c9df575ce85171b6e94f6e403cda43fb Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 3 Jun 2016 23:01:01 +0100 -Subject: [PATCH 114/141] BCM270X_DT: Sort entries to placate check script - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c514bbfe7384f58d5db4e861d842bd772cc4e51a..ed62846e18e4d3098169f05a1a8ba16caf1619aa 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -18,10 +18,10 @@ dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo - dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += bmp085_i2c-sensor.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo - dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo - dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo --dtbo-$(RPI_DT_OVERLAYS) += dht11.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo - dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo - dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo - dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo -@@ -31,10 +31,10 @@ dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo - dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo --dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += i2c-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c0-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2c1-bcm2708.dtbo - dtbo-$(RPI_DT_OVERLAYS) += i2s-gpio28-31.dtbo -@@ -73,16 +73,16 @@ dtbo-$(RPI_DT_OVERLAYS) += sdhost.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdio.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdio-1bit.dtbo - dtbo-$(RPI_DT_OVERLAYS) += sdtweak.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo --dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi2-3cs.dtbo --dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo - dtbo-$(RPI_DT_OVERLAYS) += tinylcd35.dtbo - dtbo-$(RPI_DT_OVERLAYS) += uart1.dtbo - dtbo-$(RPI_DT_OVERLAYS) += vc4-kms-v3d.dtbo - -From 789888ba7c35e13bde91ca45d714002118f574d4 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sat, 4 Jun 2016 11:30:48 +0200 -Subject: [PATCH 115/141] gpio-ir overlay: gpio_pin shouldn't change pull - setting - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/overlays/gpio-ir-overlay.dts | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -index a2d6bc79f4cd2604e6c65c000668cbb228327fe6..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 100644 ---- a/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -+++ b/arch/arm/boot/dts/overlays/gpio-ir-overlay.dts -@@ -36,8 +36,7 @@ - __overrides__ { - // parameters - gpio_pin = <&gpio_ir>,"gpios:4", -- <&gpio_ir_pins>,"brcm,pins:0", -- <&gpio_ir_pins>,"brcm,pull:0"; // pin number -+ <&gpio_ir_pins>,"brcm,pins:0"; // pin number - gpio_pull = <&gpio_ir_pins>,"brcm,pull:0"; // pull-up/down state - - rc-map-name = <&gpio_ir>,"linux,rc-map-name"; // default rc map - -From 5a5bfc2ef28f207f1b73666d392fe375241facbb Mon Sep 17 00:00:00 2001 -From: Nicolas Boullis -Date: Sat, 4 Jun 2016 00:57:06 +0200 -Subject: [PATCH 116/141] Implement a "wakeup-source" option for the i2c-rtc - DeviceTree overlay. - -See: https://github.com/raspberrypi/linux/pull/1511 ---- - arch/arm/boot/dts/overlays/README | 3 +++ - arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts | 4 ++++ - 2 files changed, 7 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 1516cc2e1616bb5e0cb519e05eee6776fe84e52a..628cff3fc60a13b26b3f2f572573884df480c7bf 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -445,6 +445,9 @@ Params: ds1307 Select the DS1307 device - - trickle-resistor-ohms Resistor value for trickle charge (DS1339-only) - -+ wakeup-source Specify that the RTC can be used as a wakeup -+ source +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index a7e4e25ccf2de23f7a3793af66f795825e69fbb8..8873fd8adce1d17cb543251f5cdc6ac8f4bf523d 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -107,3 +107,10 @@ config SND_DIGIDAC1_SOUNDCARD + select SND_SOC_WM8741 + help + Say Y or M if you want to add support for Red Rocks Audio DigiDAC1 board. + ++config SND_BCM2708_SOC_DIONAUDIO_LOCO ++ tristate "Support for Dion Audio LOCO DAC-AMP" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5102a ++ help ++ Say Y or M if you want to add support for Dion Audio LOCO. +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 781037a9e323834ba62ec55c6cf28a95c769c2cb..17f70f951322239696623c2347e5d846bbef2369 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -18,6 +18,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o + snd-soc-raspidac3-objs := raspidac3.o + snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o ++snd-soc-dionaudio-loco-objs := dionaudio_loco.o - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations -diff --git a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -index 40656474dfc16505433221a745c1d129c2737399..8b6f978155c02409eeb7c83353b8194fa3462435 100644 ---- a/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-rtc-overlay.dts -@@ -65,5 +65,9 @@ - pcf8523 = <&pcf8523>,"status"; - pcf8563 = <&pcf8563>,"status"; - trickle-resistor-ohms = <&ds1339>,"trickle-resistor-ohms:0"; -+ wakeup-source = <&ds1339>,"wakeup-source?", -+ <&ds3231>,"wakeup-source?", -+ <&mcp7940x>,"wakeup-source?", -+ <&mcp7941x>,"wakeup-source?"; - }; - }; - -From 4cd5ee7be97df04ab1877b1640ec905d7c474f0f Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 6 Jun 2016 09:23:37 +0100 -Subject: [PATCH 117/141] BCM270X_DT: Make i2c-gpio usable by other overlays - -Modify the i2c-gpio overlay to export symbol i2c-gpio for use by other -overlays. Export the alias as well for good measure. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -index 2a2dc986770cfb036492ba8de19cbaff521c5fd5..b72b32e936774d901bc253b06e025c2dd48bdb1b 100644 ---- a/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-gpio-overlay.dts -@@ -19,6 +19,21 @@ - }; - }; - }; -+ -+ fragment@1 { -+ target-path = "/aliases"; -+ __overlay__ { -+ i2c_gpio = "/i2c@0"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/__symbols__"; -+ __overlay__ { -+ i2c_gpio = "/i2c@0"; -+ }; -+ }; -+ - __overrides__ { - i2c_gpio_sda = <&i2c_gpio>,"gpios:4"; - i2c_gpio_scl = <&i2c_gpio>,"gpios:16"; - -From 500f0fe6429f3f12379db02d70a41aa98c319e4f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:13 +0000 -Subject: [PATCH 118/141] Revert "bcm2835-dma: Fix up convert to DMA pool" - -This reverts commit ec2e48fda22c57cab56a4332d1a095f91c919493. ---- - drivers/dma/bcm2835-dma.c | 36 ++++++++++-------------------------- - 1 file changed, 10 insertions(+), 26 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index d26b6bdbcf1ab33ab92937b889a37e505c925311..6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -488,17 +488,6 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - c->cyclic = true; - - return vchan_tx_prep(&c->vc, &d->vd, flags); --error_cb: -- i--; -- for (; i >= 0; i--) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o +@@ -33,4 +34,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DIGI) += snd-soc-iqaudio-digi.o + obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o + obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - -- dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -- } -- -- kfree(d->cb_list); -- kfree(d); -- return NULL; - } - - static struct dma_async_tx_descriptor * -@@ -545,7 +534,6 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (!d) - return NULL; - -- d->c = c; - d->dir = direction; - - if (c->ch >= 8) /* LITE channel */ -@@ -565,21 +553,15 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - d->frames += len / max_size + 1; - } - -- d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -- if (!d->cb_list) { -+ /* Allocate memory for control blocks */ -+ d->control_block_size = d->frames * sizeof(struct bcm2835_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; - } -- /* Allocate memory for control blocks */ -- for (i = 0; i < d->frames; i++) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -- -- cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -- &cb_entry->paddr); -- -- if (!cb_entry->cb) -- goto error_cb; -- } - - /* - * Iterate over all SG entries, create a control block -@@ -596,7 +578,7 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - - for (j = 0; j < len; j += max_size) { - struct bcm2835_dma_cb *control_block = -- d->cb_list[i + split_cnt].cb; -+ &d->control_block_base[i + split_cnt]; - - /* Setup addresses */ - if (d->dir == DMA_DEV_TO_MEM) { -@@ -638,7 +620,9 @@ bcm2835_dma_prep_slave_sg(struct dma_chan *chan, - if (i < sg_len - 1 || len - j > max_size) { - /* Next block is the next frame. */ - control_block->next = -- d->cb_list[i + split_cnt + 1].paddr; -+ d->control_block_base_phys + -+ sizeof(struct bcm2835_dma_cb) * -+ (i + split_cnt + 1); - } else { - /* Next block is empty. */ - control_block->next = 0; - -From 0e0bf40b1ed256811118c2f1a09364c397622506 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:22 +0000 -Subject: [PATCH 119/141] Revert "bcm2835-dma: Limit cyclic transfers on lite - channels to 32k" - -This reverts commit 052c2005b6ecedc5abad86632f5781adda310aa7. ---- - drivers/dma/bcm2835-dma.c | 8 +------- - 1 file changed, 1 insertion(+), 7 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 6b87ce2bb3c9d30e54e0da4f76586d3f077f6aa9..5db0a95985b20a2086c65762ea8f125511f67471 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -144,12 +144,6 @@ struct bcm2835_desc { - */ - #define MAX_LITE_TRANSFER (SZ_64K - 4) - --/* -- * Transfers larger than 32k cause issues with the bcm2708-i2s driver, -- * so limit transfer size to 32k as bcm2708-dmaengine did. -- */ --#define MAX_CYCLIC_LITE_TRANSFER SZ_32K -- - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -418,7 +412,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_CYCLIC_LITE_TRANSFER; -+ max_size = MAX_LITE_TRANSFER; - else - max_size = MAX_NORMAL_TRANSFER; - period_len = min(period_len, max_size); - -From d78219d3a8c093856a13c745f74f0015dcca48c5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:30 +0000 -Subject: [PATCH 120/141] Revert "dmaengine: bcm2835: Load driver early and - support legacy API" - -This reverts commit 6f56fff39c811953809b011f59c49a2122c4d173. ---- - drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 30 ++++++------------------------ - 2 files changed, 7 insertions(+), 25 deletions(-) - -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index b7863f0cf95ca656859a355098aa334e20d121c3..1acfa84be0d1f74f5a830b04cab05ba7fa0841ab 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 -+ depends on ARCH_BCM2835 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 5db0a95985b20a2086c65762ea8f125511f67471..696fb30b4f5a01cda9b98038b8e548368cea05f4 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -787,10 +786,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - if (IS_ERR(base)) - return PTR_ERR(base); - -- rc = bcm_dmaman_probe(pdev, base, BCM2835_DMA_BULK_MASK); -- if (rc) -- dev_err(&pdev->dev, "Failed to initialize the legacy API\n"); -- - od->base = base; - - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -@@ -823,8 +818,11 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- /* Channel 0 is used by the legacy API */ -- chans_available &= ~BCM2835_DMA_BULK_MASK; -+ /* -+ * Do not use the FIQ and BULK channels, -+ * because they are used by the GPU. -+ */ -+ chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); - - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); -@@ -868,7 +866,6 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - { - struct bcm2835_dmadev *od = platform_get_drvdata(pdev); - -- bcm_dmaman_remove(pdev); - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); - -@@ -884,22 +881,7 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --static int bcm2835_dma_init(void) --{ -- return platform_driver_register(&bcm2835_dma_driver); --} -- --static void bcm2835_dma_exit(void) --{ -- platform_driver_unregister(&bcm2835_dma_driver); --} -- --/* -- * Load after serial driver (arch_initcall) so we see the messages if it fails, -- * but before drivers (module_init) that need a DMA channel. -- */ --subsys_initcall(bcm2835_dma_init); --module_exit(bcm2835_dma_exit); -+module_platform_driver(bcm2835_dma_driver); - - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - -From e7fbd84691eb79a03d7bd28d4713ad72213750a7 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 17:17:37 +0000 -Subject: [PATCH 121/141] Revert "dmaengine: bcm2835: Add slave dma support" - -This reverts commit 8a349301238aabb40c9da5ca8c8492b6b8d146f6. ---- - drivers/dma/bcm2835-dma.c | 206 ++++------------------------------------------ - 1 file changed, 14 insertions(+), 192 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 696fb30b4f5a01cda9b98038b8e548368cea05f4..2d72fe81243fbbcc92f52e1935ed48b6cbc23665 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -1,10 +1,11 @@ - /* - * BCM2835 DMA engine support - * -+ * This driver only supports cyclic DMA transfers -+ * as needed for the I2S module. -+ * - * Author: Florian Meier - * Copyright 2013 -- * Gellert Weisz -- * Copyright 2013-2014 - * - * Based on - * OMAP DMAengine support by Russell King -@@ -94,8 +95,6 @@ struct bcm2835_desc { - size_t size; - }; - --#define BCM2835_DMA_WAIT_CYCLES 0 /* Slow down DMA transfers: 0-31 */ -- - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 - #define BCM2835_DMA_SOURCE_AD 0x0c -@@ -112,16 +111,12 @@ struct bcm2835_desc { - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - - #define BCM2835_DMA_INT_EN BIT(0) --#define BCM2835_DMA_WAIT_RESP BIT(3) - #define BCM2835_DMA_D_INC BIT(4) --#define BCM2835_DMA_D_WIDTH BIT(5) - #define BCM2835_DMA_D_DREQ BIT(6) - #define BCM2835_DMA_S_INC BIT(8) --#define BCM2835_DMA_S_WIDTH BIT(9) - #define BCM2835_DMA_S_DREQ BIT(10) - - #define BCM2835_DMA_PER_MAP(x) ((x) << 16) --#define BCM2835_DMA_WAITS(x) (((x) & 0x1f) << 21) - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 -@@ -135,14 +130,6 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - --#define MAX_NORMAL_TRANSFER SZ_1G --/* -- * Max length on a Lite channel is 65535 bytes. -- * DMA handles byte-enables on SDRAM reads and writes even on 128-bit accesses, -- * but byte-enables don't exist on peripheral addresses, so align to 32-bit. -- */ --#define MAX_LITE_TRANSFER (SZ_64K - 4) -- - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -239,19 +226,13 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- if (c->cyclic) { -- vchan_cyclic_callback(&d->vd); -- -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, -- c->chan_base + BCM2835_DMA_CS); -- -- } else { -- vchan_cookie_complete(&c->desc->vd); -- bcm2835_dma_start_desc(c); -- } -+ /* TODO Only works for cyclic DMA */ -+ vchan_cyclic_callback(&d->vd); - } - -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -+ - spin_unlock_irqrestore(&c->vc.lock, flags); - - return IRQ_HANDLED; -@@ -358,6 +339,8 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -375,7 +358,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - struct bcm2835_desc *d; - dma_addr_t dev_addr; - unsigned int es, sync_type; -- unsigned int frame, max_size; -+ unsigned int frame; - int i; - - /* Grab configuration */ -@@ -410,12 +393,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - - d->c = c; - d->dir = direction; -- if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -- else -- max_size = MAX_NORMAL_TRANSFER; -- period_len = min(period_len, max_size); -- d->frames = (buf_len - 1) / (period_len + 1); -+ d->frames = buf_len / period_len; - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { -@@ -463,171 +441,17 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - BCM2835_DMA_PER_MAP(c->dreq); - - /* Length of a frame */ -- if (frame != d->frames - 1) -- control_block->length = period_len; -- else -- control_block->length = buf_len - (d->frames - 1) * -- period_len; -+ control_block->length = period_len; - d->size += control_block->length; - - /* - * Next block is the next frame. -- * This function is called on cyclic DMA transfers. -+ * This DMA engine driver currently only supports cyclic DMA. - * Therefore, wrap around at number of frames. - */ - control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr; - } - -- c->cyclic = true; -- -- return vchan_tx_prep(&c->vc, &d->vd, flags); --} -- --static struct dma_async_tx_descriptor * --bcm2835_dma_prep_slave_sg(struct dma_chan *chan, -- struct scatterlist *sgl, -- unsigned int sg_len, -- enum dma_transfer_direction direction, -- unsigned long flags, void *context) --{ -- struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -- enum dma_slave_buswidth dev_width; -- struct bcm2835_desc *d; -- dma_addr_t dev_addr; -- struct scatterlist *sgent; -- unsigned int i, sync_type, split_cnt, max_size; -- -- if (!is_slave_direction(direction)) { -- dev_err(chan->device->dev, "direction not supported\n"); -- return NULL; -- } -- -- if (direction == DMA_DEV_TO_MEM) { -- dev_addr = c->cfg.src_addr; -- dev_width = c->cfg.src_addr_width; -- sync_type = BCM2835_DMA_S_DREQ; -- } else { -- dev_addr = c->cfg.dst_addr; -- dev_width = c->cfg.dst_addr_width; -- sync_type = BCM2835_DMA_D_DREQ; -- } -- -- /* Bus width translates to the element size (ES) */ -- switch (dev_width) { -- case DMA_SLAVE_BUSWIDTH_4_BYTES: -- break; -- default: -- dev_err(chan->device->dev, "buswidth not supported: %i\n", -- dev_width); -- return NULL; -- } -- -- /* Allocate and setup the descriptor. */ -- d = kzalloc(sizeof(*d), GFP_NOWAIT); -- if (!d) -- return NULL; -- -- d->dir = direction; -- -- if (c->ch >= 8) /* LITE channel */ -- max_size = MAX_LITE_TRANSFER; -- else -- max_size = MAX_NORMAL_TRANSFER; -- -- /* -- * Store the length of the SG list in d->frames -- * taking care to account for splitting up transfers -- * too large for a LITE channel -- */ -- d->frames = 0; -- for_each_sg(sgl, sgent, sg_len, i) { -- unsigned int len = sg_dma_len(sgent); -- -- d->frames += len / max_size + 1; -- } -- -- /* Allocate memory for control blocks */ -- d->control_block_size = d->frames * sizeof(struct bcm2835_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 SG entries, create a control block -- * for each frame and link them together. -- * Count the number of times an SG entry had to be split -- * as a result of using a LITE channel -- */ -- split_cnt = 0; -- -- for_each_sg(sgl, sgent, sg_len, i) { -- unsigned int j; -- dma_addr_t addr = sg_dma_address(sgent); -- unsigned int len = sg_dma_len(sgent); -- -- for (j = 0; j < len; j += max_size) { -- struct bcm2835_dma_cb *control_block = -- &d->control_block_base[i + split_cnt]; -- -- /* Setup addresses */ -- if (d->dir == DMA_DEV_TO_MEM) { -- control_block->info = BCM2835_DMA_D_INC | -- BCM2835_DMA_D_WIDTH | -- BCM2835_DMA_S_DREQ; -- control_block->src = dev_addr; -- control_block->dst = addr + (dma_addr_t)j; -- } else { -- control_block->info = BCM2835_DMA_S_INC | -- BCM2835_DMA_S_WIDTH | -- BCM2835_DMA_D_DREQ; -- control_block->src = addr + (dma_addr_t)j; -- control_block->dst = dev_addr; -- } -- -- /* Common part */ -- control_block->info |= -- BCM2835_DMA_WAITS(BCM2835_DMA_WAIT_CYCLES); -- control_block->info |= BCM2835_DMA_WAIT_RESP; -- -- /* Enable */ -- if (i == sg_len - 1 && len - j <= max_size) -- control_block->info |= BCM2835_DMA_INT_EN; -- -- /* Setup synchronization */ -- if (sync_type) -- control_block->info |= sync_type; -- -- /* Setup DREQ channel */ -- if (c->dreq) -- control_block->info |= -- BCM2835_DMA_PER_MAP(c->dreq); -- -- /* Length of a frame */ -- control_block->length = min(len - j, max_size); -- d->size += control_block->length; -- -- if (i < sg_len - 1 || len - j > max_size) { -- /* Next block is the next frame. */ -- control_block->next = -- d->control_block_base_phys + -- sizeof(struct bcm2835_dma_cb) * -- (i + split_cnt + 1); -- } else { -- /* Next block is empty. */ -- control_block->next = 0; -- } -- -- if (len - j > max_size) -- split_cnt++; -- } -- } -- -- c->cyclic = false; -- - return vchan_tx_prep(&c->vc, &d->vd, flags); - error_cb: - i--; -@@ -796,7 +620,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -- od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -@@ -886,5 +709,4 @@ module_platform_driver(bcm2835_dma_driver); - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - MODULE_AUTHOR("Florian Meier "); --MODULE_AUTHOR("Gellert Weisz "); - MODULE_LICENSE("GPL v2"); - -From 6f4cc15d3c4cb1787fa599075a8d55df3d3136c8 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:56 -0700 -Subject: [PATCH 122/141] dmaengine: bcm2835: remove unnecessary masking of dma - channels - -The original patch contained 3 dma channels that were masked out. - -These - as far as research and discussions show - are a -artefacts remaining from the downstream legacy dma-api. - -Right now down-stream still includes a legacy api used only -in a single (downstream only) driver (bcm2708_fb) that requires -2D DMA for speedup (DMA-channel 0). -Formerly the sd-card support driver also was using this legacy -api (DMA-channel 2), but since has been moved over to use -dmaengine directly. - -The DMA-channel 3 is already masked out in the devicetree in -the default property "brcm,dma-channel-mask = <0x7f35>;" - -So we can remove the whole masking of DMA channels. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 9 --------- - 1 file changed, 9 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 2d72fe81243fbbcc92f52e1935ed48b6cbc23665..e4ca980049bab83ddbb58435c662e4a30321d4f8 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -123,9 +123,6 @@ struct bcm2835_desc { - #define BCM2835_DMA_DATA_TYPE_S32 4 - #define BCM2835_DMA_DATA_TYPE_S128 16 - --#define BCM2835_DMA_BULK_MASK BIT(0) --#define BCM2835_DMA_FIQ_MASK (BIT(2) | BIT(3)) -- - /* Valid only for channels 0 - 14, 15 has its own base address */ - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) -@@ -641,12 +638,6 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- /* -- * Do not use the FIQ and BULK channels, -- * because they are used by the GPU. -- */ -- chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK); -- - for (i = 0; i < pdev->num_resources; i++) { - irq = platform_get_irq(pdev, i); - if (irq < 0) - -From 595eb44ddbba0e43280f2993be27f8b49f2f3f5f Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:57 -0700 -Subject: [PATCH 123/141] dmaengine: bcm2835: add additional defines for - DMA-registers - -Add additional defines describing the DMA registers -as well as adding some more documentation to those registers. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 57 ++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 49 insertions(+), 8 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index e4ca980049bab83ddbb58435c662e4a30321d4f8..a1d851aa5b182f9b0f4d6c2ab719b1ade2167c11 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -97,26 +97,67 @@ struct bcm2835_desc { - - #define BCM2835_DMA_CS 0x00 - #define BCM2835_DMA_ADDR 0x04 -+#define BCM2835_DMA_TI 0x08 - #define BCM2835_DMA_SOURCE_AD 0x0c - #define BCM2835_DMA_DEST_AD 0x10 --#define BCM2835_DMA_NEXTCB 0x1C -+#define BCM2835_DMA_LEN 0x14 -+#define BCM2835_DMA_STRIDE 0x18 -+#define BCM2835_DMA_NEXTCB 0x1c -+#define BCM2835_DMA_DEBUG 0x20 - - /* DMA CS Control and Status bits */ --#define BCM2835_DMA_ACTIVE BIT(0) --#define BCM2835_DMA_INT BIT(2) -+#define BCM2835_DMA_ACTIVE BIT(0) /* activate the DMA */ -+#define BCM2835_DMA_END BIT(1) /* current CB has ended */ -+#define BCM2835_DMA_INT BIT(2) /* interrupt status */ -+#define BCM2835_DMA_DREQ BIT(3) /* DREQ state */ - #define BCM2835_DMA_ISPAUSED BIT(4) /* Pause requested or not active */ - #define BCM2835_DMA_ISHELD BIT(5) /* Is held by DREQ flow control */ --#define BCM2835_DMA_ERR BIT(8) -+#define BCM2835_DMA_WAITING_FOR_WRITES BIT(6) /* waiting for last -+ * AXI-write to ack -+ */ -+#define BCM2835_DMA_ERR BIT(8) -+#define BCM2835_DMA_PRIORITY(x) ((x & 15) << 16) /* AXI priority */ -+#define BCM2835_DMA_PANIC_PRIORITY(x) ((x & 15) << 20) /* panic priority */ -+/* current value of TI.BCM2835_DMA_WAIT_RESP */ -+#define BCM2835_DMA_WAIT_FOR_WRITES BIT(28) -+#define BCM2835_DMA_DIS_DEBUG BIT(29) /* disable debug pause signal */ - #define BCM2835_DMA_ABORT BIT(30) /* Stop current CB, go to next, WO */ - #define BCM2835_DMA_RESET BIT(31) /* WO, self clearing */ - -+/* Transfer information bits - also bcm2835_cb.info field */ - #define BCM2835_DMA_INT_EN BIT(0) -+#define BCM2835_DMA_TDMODE BIT(1) /* 2D-Mode */ -+#define BCM2835_DMA_WAIT_RESP BIT(3) /* wait for AXI-write to be acked */ - #define BCM2835_DMA_D_INC BIT(4) --#define BCM2835_DMA_D_DREQ BIT(6) -+#define BCM2835_DMA_D_WIDTH BIT(5) /* 128bit writes if set */ -+#define BCM2835_DMA_D_DREQ BIT(6) /* enable DREQ for destination */ -+#define BCM2835_DMA_D_IGNORE BIT(7) /* ignore destination writes */ - #define BCM2835_DMA_S_INC BIT(8) --#define BCM2835_DMA_S_DREQ BIT(10) -- --#define BCM2835_DMA_PER_MAP(x) ((x) << 16) -+#define BCM2835_DMA_S_WIDTH BIT(9) /* 128bit writes if set */ -+#define BCM2835_DMA_S_DREQ BIT(10) /* enable SREQ for source */ -+#define BCM2835_DMA_S_IGNORE BIT(11) /* ignore source reads - read 0 */ -+#define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12) -+#define BCM2835_DMA_PER_MAP(x) ((x & 31) << 16) /* REQ source */ -+#define BCM2835_DMA_WAIT(x) ((x & 31) << 21) /* add DMA-wait cycles */ -+#define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */ -+ -+/* debug register bits */ -+#define BCM2835_DMA_DEBUG_LAST_NOT_SET_ERR BIT(0) -+#define BCM2835_DMA_DEBUG_FIFO_ERR BIT(1) -+#define BCM2835_DMA_DEBUG_READ_ERR BIT(2) -+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_SHIFT 4 -+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_BITS 4 -+#define BCM2835_DMA_DEBUG_ID_SHIFT 16 -+#define BCM2835_DMA_DEBUG_ID_BITS 9 -+#define BCM2835_DMA_DEBUG_STATE_SHIFT 16 -+#define BCM2835_DMA_DEBUG_STATE_BITS 9 -+#define BCM2835_DMA_DEBUG_VERSION_SHIFT 25 -+#define BCM2835_DMA_DEBUG_VERSION_BITS 3 -+#define BCM2835_DMA_DEBUG_LITE BIT(28) -+ -+/* shared registers for all dma channels */ -+#define BCM2835_DMA_INT_STATUS 0xfe0 -+#define BCM2835_DMA_ENABLE 0xff0 - - #define BCM2835_DMA_DATA_TYPE_S8 1 - #define BCM2835_DMA_DATA_TYPE_S16 2 - -From 55d60dc6c0c2571736495f5bc7beac5e3c76d1da Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:58 -0700 -Subject: [PATCH 124/141] dmaengine: bcm2835: move cyclic member from - bcm2835_chan into bcm2835_desc - -In preparation to consolidating code we move the cyclic member -into the bcm_2835_desc structure. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index a1d851aa5b182f9b0f4d6c2ab719b1ade2167c11..b3bc382fd1998324d6034e203afdd77a4d7ad168 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -73,7 +73,6 @@ struct bcm2835_chan { - struct list_head node; - - struct dma_slave_config cfg; -- bool cyclic; - unsigned int dreq; - - int ch; -@@ -93,6 +92,8 @@ struct bcm2835_desc { - - unsigned int frames; - size_t size; -+ -+ bool cyclic; - }; - - #define BCM2835_DMA_CS 0x00 -@@ -377,8 +378,6 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - struct bcm2835_chan *c = to_bcm2835_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) - bcm2835_dma_start_desc(c); -@@ -432,6 +431,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - d->c = c; - d->dir = direction; - d->frames = buf_len / period_len; -+ d->cyclic = true; - - d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); - if (!d->cb_list) { - -From 17068219bf274d789d6a25faf73cb20a653f23f6 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:24:59 -0700 -Subject: [PATCH 125/141] dmaengine: bcm2835: move controlblock chain - generation into separate method - -In preparation of adding slave_sg functionality this patch moves the -generation/allocation of bcm2835_desc and the building of -the corresponding DMA-control-block chain from bcm2835_dma_prep_dma_cyclic -into the newly created method bcm2835_dma_create_cb_chain. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 294 +++++++++++++++++++++++++++++++--------------- - 1 file changed, 198 insertions(+), 96 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b3bc382fd1998324d6034e203afdd77a4d7ad168..4db0e232fab8e3422d4c28a164ed67f0676981f2 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -88,12 +88,12 @@ struct bcm2835_desc { - struct virt_dma_desc vd; - enum dma_transfer_direction dir; - -- struct bcm2835_cb_entry *cb_list; -- - unsigned int frames; - size_t size; - - bool cyclic; -+ -+ struct bcm2835_cb_entry cb_list[]; - }; - - #define BCM2835_DMA_CS 0x00 -@@ -169,6 +169,13 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+/* how many frames of max_len size do we need to transfer len bytes */ -+static inline size_t bcm2835_dma_frames_for_length(size_t len, -+ size_t max_len) -+{ -+ return DIV_ROUND_UP(len, max_len); -+} -+ - static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d) - { - return container_of(d, struct bcm2835_dmadev, ddev); -@@ -185,19 +192,161 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc( - return container_of(t, struct bcm2835_desc, vd.tx); - } - --static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) -+static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) - { -- struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd); -- int i; -+ size_t i; - - for (i = 0; i < desc->frames; i++) - dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb, - desc->cb_list[i].paddr); - -- kfree(desc->cb_list); - kfree(desc); - } - -+static void bcm2835_dma_desc_free(struct virt_dma_desc *vd) -+{ -+ bcm2835_dma_free_cb_chain( -+ container_of(vd, struct bcm2835_desc, vd)); -+} -+ -+static void bcm2835_dma_create_cb_set_length( -+ struct bcm2835_chan *chan, -+ struct bcm2835_dma_cb *control_block, -+ size_t len, -+ size_t period_len, -+ size_t *total_len, -+ u32 finalextrainfo) -+{ -+ /* set the length */ -+ control_block->length = len; -+ -+ /* finished if we have no period_length */ -+ if (!period_len) -+ return; -+ -+ /* -+ * period_len means: that we need to generate -+ * transfers that are terminating at every -+ * multiple of period_len - this is typically -+ * used to set the interrupt flag in info -+ * which is required during cyclic transfers -+ */ -+ -+ /* have we filled in period_length yet? */ -+ if (*total_len + control_block->length < period_len) -+ return; -+ -+ /* calculate the length that remains to reach period_length */ -+ control_block->length = period_len - *total_len; -+ -+ /* reset total_length for next period */ -+ *total_len = 0; -+ -+ /* add extrainfo bits in info */ -+ control_block->info |= finalextrainfo; -+} -+ -+/** -+ * bcm2835_dma_create_cb_chain - create a control block and fills data in -+ * -+ * @chan: the @dma_chan for which we run this -+ * @direction: the direction in which we transfer -+ * @cyclic: it is a cyclic transfer -+ * @info: the default info bits to apply per controlblock -+ * @frames: number of controlblocks to allocate -+ * @src: the src address to assign (if the S_INC bit is set -+ * in @info, then it gets incremented) -+ * @dst: the dst address to assign (if the D_INC bit is set -+ * in @info, then it gets incremented) -+ * @buf_len: the full buffer length (may also be 0) -+ * @period_len: the period length when to apply @finalextrainfo -+ * in addition to the last transfer -+ * this will also break some control-blocks early -+ * @finalextrainfo: additional bits in last controlblock -+ * (or when period_len is reached in case of cyclic) -+ * @gfp: the GFP flag to use for allocation -+ */ -+static struct bcm2835_desc *bcm2835_dma_create_cb_chain( -+ struct dma_chan *chan, enum dma_transfer_direction direction, -+ bool cyclic, u32 info, u32 finalextrainfo, size_t frames, -+ dma_addr_t src, dma_addr_t dst, size_t buf_len, -+ size_t period_len, gfp_t gfp) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ size_t len = buf_len, total_len; -+ size_t frame; -+ struct bcm2835_desc *d; -+ struct bcm2835_cb_entry *cb_entry; -+ struct bcm2835_dma_cb *control_block; -+ -+ /* allocate and setup the descriptor. */ -+ d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), -+ gfp); -+ if (!d) -+ return NULL; -+ -+ d->c = c; -+ d->dir = direction; -+ d->cyclic = cyclic; -+ -+ /* -+ * Iterate over all frames, create a control block -+ * for each frame and link them together. -+ */ -+ for (frame = 0, total_len = 0; frame < frames; d->frames++, frame++) { -+ cb_entry = &d->cb_list[frame]; -+ cb_entry->cb = dma_pool_alloc(c->cb_pool, gfp, -+ &cb_entry->paddr); -+ if (!cb_entry->cb) -+ goto error_cb; -+ -+ /* fill in the control block */ -+ control_block = cb_entry->cb; -+ control_block->info = info; -+ control_block->src = src; -+ control_block->dst = dst; -+ control_block->stride = 0; -+ control_block->next = 0; -+ /* set up length in control_block if requested */ -+ if (buf_len) { -+ /* calculate length honoring period_length */ -+ bcm2835_dma_create_cb_set_length( -+ c, control_block, -+ len, period_len, &total_len, -+ cyclic ? finalextrainfo : 0); -+ -+ /* calculate new remaining length */ -+ len -= control_block->length; -+ } -+ -+ /* link this the last controlblock */ -+ if (frame) -+ d->cb_list[frame - 1].cb->next = cb_entry->paddr; -+ -+ /* update src and dst and length */ -+ if (src && (info & BCM2835_DMA_S_INC)) -+ src += control_block->length; -+ if (dst && (info & BCM2835_DMA_D_INC)) -+ dst += control_block->length; -+ -+ /* Length of total transfer */ -+ d->size += control_block->length; -+ } -+ -+ /* the last frame requires extra flags */ -+ d->cb_list[d->frames - 1].cb->info |= finalextrainfo; -+ -+ /* detect a size missmatch */ -+ if (buf_len && (d->size != buf_len)) -+ goto error_cb; -+ -+ return d; -+error_cb: -+ bcm2835_dma_free_cb_chain(d); -+ -+ return NULL; -+} -+ - static int bcm2835_dma_abort(void __iomem *chan_base) - { - unsigned long cs; -@@ -391,12 +540,11 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - unsigned long flags) - { - struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -- enum dma_slave_buswidth dev_width; - struct bcm2835_desc *d; -- dma_addr_t dev_addr; -- unsigned int es, sync_type; -- unsigned int frame; -- int i; -+ dma_addr_t src, dst; -+ u32 info = BCM2835_DMA_WAIT_RESP; -+ u32 extra = BCM2835_DMA_INT_EN; -+ size_t frames; - - /* Grab configuration */ - if (!is_slave_direction(direction)) { -@@ -404,104 +552,58 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - return NULL; - } - -- if (direction == DMA_DEV_TO_MEM) { -- dev_addr = c->cfg.src_addr; -- dev_width = c->cfg.src_addr_width; -- sync_type = BCM2835_DMA_S_DREQ; -- } else { -- dev_addr = c->cfg.dst_addr; -- dev_width = c->cfg.dst_addr_width; -- sync_type = BCM2835_DMA_D_DREQ; -- } -- -- /* Bus width translates to the element size (ES) */ -- switch (dev_width) { -- case DMA_SLAVE_BUSWIDTH_4_BYTES: -- es = BCM2835_DMA_DATA_TYPE_S32; -- break; -- default: -+ if (!buf_len) { -+ dev_err(chan->device->dev, -+ "%s: bad buffer length (= 0)\n", __func__); - return NULL; - } - -- /* Now allocate and setup the descriptor. */ -- d = kzalloc(sizeof(*d), GFP_NOWAIT); -- if (!d) -- return NULL; -+ /* -+ * warn if buf_len is not a multiple of period_len - this may leed -+ * to unexpected latencies for interrupts and thus audiable clicks -+ */ -+ if (buf_len % period_len) -+ dev_warn_once(chan->device->dev, -+ "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n", -+ __func__, buf_len, period_len); - -- d->c = c; -- d->dir = direction; -- d->frames = buf_len / period_len; -- d->cyclic = true; -+ /* Setup DREQ channel */ -+ if (c->dreq != 0) -+ info |= BCM2835_DMA_PER_MAP(c->dreq); - -- d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL); -- if (!d->cb_list) { -- kfree(d); -- return NULL; -+ if (direction == DMA_DEV_TO_MEM) { -+ if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ src = c->cfg.src_addr; -+ dst = buf_addr; -+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; -+ } else { -+ if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ dst = c->cfg.dst_addr; -+ src = buf_addr; -+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; - } -- /* Allocate memory for control blocks */ -- for (i = 0; i < d->frames; i++) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; - -- cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC, -- &cb_entry->paddr); -- if (!cb_entry->cb) -- goto error_cb; -- } -+ /* calculate number of frames */ -+ frames = DIV_ROUND_UP(buf_len, period_len); - - /* -- * Iterate over all frames, create a control block -- * for each frame and link them together. -+ * allocate the CB chain -+ * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine -+ * implementation calls prep_dma_cyclic with interrupts disabled. - */ -- for (frame = 0; frame < d->frames; frame++) { -- struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb; -- -- /* Setup adresses */ -- if (d->dir == DMA_DEV_TO_MEM) { -- control_block->info = BCM2835_DMA_D_INC; -- control_block->src = dev_addr; -- control_block->dst = buf_addr + frame * period_len; -- } else { -- control_block->info = BCM2835_DMA_S_INC; -- control_block->src = buf_addr + frame * period_len; -- control_block->dst = dev_addr; -- } -- -- /* Enable interrupt */ -- control_block->info |= BCM2835_DMA_INT_EN; -- -- /* Setup synchronization */ -- if (sync_type != 0) -- control_block->info |= sync_type; -- -- /* Setup DREQ channel */ -- if (c->dreq != 0) -- control_block->info |= -- BCM2835_DMA_PER_MAP(c->dreq); -- -- /* Length of a frame */ -- control_block->length = period_len; -- d->size += control_block->length; -+ d = bcm2835_dma_create_cb_chain(chan, direction, true, -+ info, extra, -+ frames, src, dst, buf_len, -+ period_len, GFP_NOWAIT); -+ if (!d) -+ return NULL; - -- /* -- * 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->cb_list[((frame + 1) % d->frames)].paddr; -- } -+ /* wrap around into a loop */ -+ d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr; - - return vchan_tx_prep(&c->vc, &d->vd, flags); --error_cb: -- i--; -- for (; i >= 0; i--) { -- struct bcm2835_cb_entry *cb_entry = &d->cb_list[i]; -- -- dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr); -- } -- -- kfree(d->cb_list); -- kfree(d); -- return NULL; - } - - static int bcm2835_dma_slave_config(struct dma_chan *chan, - -From 4d44a8902ae85fe42de9d30c52e757acc9425012 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:00 -0700 -Subject: [PATCH 126/141] dmaengine: bcm2835: limit max length based on channel - type - -The bcm2835 dma system has 2 basic types of dma-channels: -* "normal" channels -* "light" channels - -Lite channels are limited in several aspects: -* internal data-structure is 128 bit (not 256) -* does not support BCM2835_DMA_TDMODE (2D) -* DMA length register is limited to 16 bit. - so 0-65535 (not 0-65536 as mentioned in the official datasheet) -* BCM2835_DMA_S/D_IGNORE are not supported - -The detection of the type of mode is implemented by looking at -the LITE bit in the DEBUG register for each channel. -This allows automatic detection. - -Based on this the maximum block size is set to (64K - 4) or to 1G -and this limit is honored during generation of control block -chains. The effect is that when a LITE channel is used more -control blocks are used to do the same transfer (compared -to a normal channel). - -As there are several sources/target DREQS that are 32 bit wide -we need to have the transfer to be a multiple of 4 as this would -break the transfer otherwise. - -This is why the limit of (64K - 4) was chosen over the -alternative of (64K - 4K). - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 29 ++++++++++++++++++++++++++--- - 1 file changed, 26 insertions(+), 3 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 4db0e232fab8e3422d4c28a164ed67f0676981f2..59c5ef36d97059a4f988f083a64f084da02093cd 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -81,6 +81,8 @@ struct bcm2835_chan { - - void __iomem *chan_base; - int irq_number; -+ -+ bool is_lite_channel; - }; - - struct bcm2835_desc { -@@ -169,6 +171,16 @@ struct bcm2835_desc { - #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */ - #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n)) - -+/* the max dma length for different channels */ -+#define MAX_DMA_LEN SZ_1G -+#define MAX_LITE_DMA_LEN (SZ_64K - 4) -+ -+static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c) -+{ -+ /* lite and normal channels have different max frame length */ -+ return c->is_lite_channel ? MAX_LITE_DMA_LEN : MAX_DMA_LEN; -+} -+ - /* how many frames of max_len size do we need to transfer len bytes */ - static inline size_t bcm2835_dma_frames_for_length(size_t len, - size_t max_len) -@@ -217,8 +229,10 @@ static void bcm2835_dma_create_cb_set_length( - size_t *total_len, - u32 finalextrainfo) - { -- /* set the length */ -- control_block->length = len; -+ size_t max_len = bcm2835_dma_max_frame_length(chan); -+ -+ /* set the length taking lite-channel limitations into account */ -+ control_block->length = min_t(u32, len, max_len); - - /* finished if we have no period_length */ - if (!period_len) -@@ -544,6 +558,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - dma_addr_t src, dst; - u32 info = BCM2835_DMA_WAIT_RESP; - u32 extra = BCM2835_DMA_INT_EN; -+ size_t max_len = bcm2835_dma_max_frame_length(c); - size_t frames; - - /* Grab configuration */ -@@ -586,7 +601,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic( - } - - /* calculate number of frames */ -- frames = DIV_ROUND_UP(buf_len, period_len); -+ frames = /* number of periods */ -+ DIV_ROUND_UP(buf_len, period_len) * -+ /* number of frames per period */ -+ bcm2835_dma_frames_for_length(period_len, max_len); - - /* - * allocate the CB chain -@@ -685,6 +703,11 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - c->ch = chan_id; - c->irq_number = irq; - -+ /* check in DEBUG register if this is a LITE channel */ -+ if (readl(c->chan_base + BCM2835_DMA_DEBUG) & -+ BCM2835_DMA_DEBUG_LITE) -+ c->is_lite_channel = true; -+ - return 0; - } - - -From d773b94b0b340a9087bc636283e28dd46a53428b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:01 -0700 -Subject: [PATCH 127/141] dmaengine: bcm2835: add slave_sg support to - bcm2835-dma - -Add slave_sg support to bcm2835-dma using shared allocation -code for bcm2835_desc and DMA-control blocks already used by -dma_cyclic. - -Note that bcm2835_dma_callback had to get modified to support -both modes of operation (cyclic and non-cyclic). - -Tested using: -* Hifiberry I2S card (using cyclic DMA) -* fb_st7735r SPI-framebuffer (using slave_sg DMA via spi-bcm2835) -playing BigBuckBunny for audio and video. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 113 ++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 108 insertions(+), 5 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 59c5ef36d97059a4f988f083a64f084da02093cd..b46b12f66f387e0b87aa6d09192071b58da9e953 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -260,6 +260,23 @@ static void bcm2835_dma_create_cb_set_length( - control_block->info |= finalextrainfo; - } - -+static inline size_t bcm2835_dma_count_frames_for_sg( -+ struct bcm2835_chan *c, -+ struct scatterlist *sgl, -+ unsigned int sg_len) -+{ -+ size_t frames = 0; -+ struct scatterlist *sgent; -+ unsigned int i; -+ size_t plength = bcm2835_dma_max_frame_length(c); -+ -+ for_each_sg(sgl, sgent, sg_len, i) -+ frames += bcm2835_dma_frames_for_length( -+ sg_dma_len(sgent), plength); -+ -+ return frames; -+} -+ - /** - * bcm2835_dma_create_cb_chain - create a control block and fills data in - * -@@ -361,6 +378,32 @@ error_cb: - return NULL; - } - -+static void bcm2835_dma_fill_cb_chain_with_sg( -+ struct dma_chan *chan, -+ enum dma_transfer_direction direction, -+ struct bcm2835_cb_entry *cb, -+ struct scatterlist *sgl, -+ unsigned int sg_len) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ size_t max_len = bcm2835_dma_max_frame_length(c); -+ unsigned int i, len; -+ dma_addr_t addr; -+ struct scatterlist *sgent; -+ -+ for_each_sg(sgl, sgent, sg_len, i) { -+ for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent); -+ len > 0; -+ addr += cb->cb->length, len -= cb->cb->length, cb++) { -+ if (direction == DMA_DEV_TO_MEM) -+ cb->cb->dst = addr; -+ else -+ cb->cb->src = addr; -+ cb->cb->length = min(len, max_len); -+ } -+ } -+} -+ - static int bcm2835_dma_abort(void __iomem *chan_base) - { - unsigned long cs; -@@ -428,13 +471,19 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - d = c->desc; - - if (d) { -- /* TODO Only works for cyclic DMA */ -- vchan_cyclic_callback(&d->vd); -+ if (d->cyclic) { -+ /* call the cyclic callback */ -+ vchan_cyclic_callback(&d->vd); -+ -+ /* Keep the DMA engine running */ -+ writel(BCM2835_DMA_ACTIVE, -+ c->chan_base + BCM2835_DMA_CS); -+ } else { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ } - } - -- /* Keep the DMA engine running */ -- writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS); -- - spin_unlock_irqrestore(&c->vc.lock, flags); - - return IRQ_HANDLED; -@@ -548,6 +597,58 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - spin_unlock_irqrestore(&c->vc.lock, flags); - } - -+static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( -+ struct dma_chan *chan, -+ struct scatterlist *sgl, unsigned int sg_len, -+ enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ struct bcm2835_desc *d; -+ dma_addr_t src = 0, dst = 0; -+ u32 info = BCM2835_DMA_WAIT_RESP; -+ u32 extra = BCM2835_DMA_INT_EN; -+ size_t frames; -+ -+ if (!is_slave_direction(direction)) { -+ dev_err(chan->device->dev, -+ "%s: bad direction?\n", __func__); -+ return NULL; -+ } -+ -+ if (c->dreq != 0) -+ info |= BCM2835_DMA_PER_MAP(c->dreq); -+ -+ if (direction == DMA_DEV_TO_MEM) { -+ if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ src = c->cfg.src_addr; -+ info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC; -+ } else { -+ if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) -+ return NULL; -+ dst = c->cfg.dst_addr; -+ info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC; -+ } -+ -+ /* count frames in sg list */ -+ frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len); -+ -+ /* allocate the CB chain */ -+ d = bcm2835_dma_create_cb_chain(chan, direction, false, -+ info, extra, -+ frames, src, dst, 0, 0, -+ GFP_KERNEL); -+ if (!d) -+ return NULL; -+ -+ /* fill in frames with scatterlist pointers */ -+ bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list, -+ sgl, sg_len); -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ - static struct dma_async_tx_descriptor *bcm2835_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, -@@ -778,11 +879,13 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); - dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); - dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); -+ dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); - od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; - od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; -+ od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - -From 0a01d07fac2c8e641d9a33241040637ee91faf10 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Wed, 16 Mar 2016 12:25:02 -0700 -Subject: [PATCH 128/141] dmaengine: bcm2835: add dma_memcopy support to - bcm2835-dma - -Also added check for an error condition in bcm2835_dma_create_cb_chain -that showed up during development of this patch. - -Tested using dmatest for all enabled channels. - -Signed-off-by: Martin Sperl -Reviewed-by: Eric Anholt -Signed-off-by: Eric Anholt -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 36 +++++++++++++++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index b46b12f66f387e0b87aa6d09192071b58da9e953..cc771cd35dd0c28829b6500421af686be865000b 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -310,6 +310,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( - struct bcm2835_cb_entry *cb_entry; - struct bcm2835_dma_cb *control_block; - -+ if (!frames) -+ return NULL; -+ - /* allocate and setup the descriptor. */ - d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), - gfp); -@@ -597,6 +600,34 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) - spin_unlock_irqrestore(&c->vc.lock, flags); - } - -+struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( -+ struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, -+ size_t len, unsigned long flags) -+{ -+ struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); -+ struct bcm2835_desc *d; -+ u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; -+ u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; -+ size_t max_len = bcm2835_dma_max_frame_length(c); -+ size_t frames; -+ -+ /* if src, dst or len is not given return with an error */ -+ if (!src || !dst || !len) -+ return NULL; -+ -+ /* calculate number of frames */ -+ frames = bcm2835_dma_frames_for_length(len, max_len); -+ -+ /* allocate the CB chain - this also fills in the pointers */ -+ d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, -+ info, extra, frames, -+ src, dst, len, 0, GFP_KERNEL); -+ if (!d) -+ return NULL; -+ -+ return vchan_tx_prep(&c->vc, &d->vd, flags); -+} -+ - static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( - struct dma_chan *chan, - struct scatterlist *sgl, unsigned int sg_len, -@@ -880,17 +911,20 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); - dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); - dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); -+ dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask); - od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; - od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; - od->ddev.device_tx_status = bcm2835_dma_tx_status; - od->ddev.device_issue_pending = bcm2835_dma_issue_pending; - od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; - od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; -+ od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy; - od->ddev.device_config = bcm2835_dma_slave_config; - od->ddev.device_terminate_all = bcm2835_dma_terminate_all; - od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); - od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -- od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | -+ BIT(DMA_MEM_TO_MEM); - od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - od->ddev.dev = &pdev->dev; - INIT_LIST_HEAD(&od->ddev.channels); - -From 535e5d3ace534cdf359604c184e9f187ead13095 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Mon, 11 Apr 2016 13:29:08 +0000 -Subject: [PATCH 129/141] dmaengine: bcm2835: use platform_get_irq_byname - -Use platform_get_irq_byname to allow for correct mapping of -interrupts to dma channels. - -The currently implemented device tree is unfortunately -implemented with the wrong assumption, that each dma-channel -has its own dma channel, but dma-irq 11 is handling -dma-channel 11-14 and dma-irq 12 is actually a "catch all" -interrupt. - -So here we use the byname variant and require that interrupts -are explicitly named via the interrupts-name property in the -device tree. - -The use of shared interrupts is also implemented. - -As a side-effect this means we can now use dma channels 12, 13 and 14 -in a correct manner - also testing shows that onl using -channels 11 to 14 for spi and i2s works perfectly (when playing -some video) - -Signed-off-by: Martin Sperl -Acked-by: Eric Anholt -Acked-by: Mark Rutland -Signed-off-by: Vinod Koul ---- - drivers/dma/bcm2835-dma.c | 77 ++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 63 insertions(+), 14 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index cc771cd35dd0c28829b6500421af686be865000b..974015193b93cdb398f1157b89b6e2cf5234354e 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -46,6 +46,9 @@ - - #include "virt-dma.h" - -+#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14 -+#define BCM2835_DMA_CHAN_NAME_SIZE 8 -+ - struct bcm2835_dmadev { - struct dma_device ddev; - spinlock_t lock; -@@ -81,6 +84,7 @@ struct bcm2835_chan { - - void __iomem *chan_base; - int irq_number; -+ unsigned int irq_flags; - - bool is_lite_channel; - }; -@@ -466,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data) - struct bcm2835_desc *d; - unsigned long flags; - -+ /* check the shared interrupt */ -+ if (c->irq_flags & IRQF_SHARED) { -+ /* check if the interrupt is enabled */ -+ flags = readl(c->chan_base + BCM2835_DMA_CS); -+ /* if not set then we are not the reason for the irq */ -+ if (!(flags & BCM2835_DMA_INT)) -+ return IRQ_NONE; -+ } -+ - spin_lock_irqsave(&c->vc.lock, flags); - - /* Acknowledge interrupt */ -@@ -506,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan) - return -ENOMEM; - } - -- return request_irq(c->irq_number, -- bcm2835_dma_callback, 0, "DMA IRQ", c); -+ return request_irq(c->irq_number, bcm2835_dma_callback, -+ c->irq_flags, "DMA IRQ", c); - } - - static void bcm2835_dma_free_chan_resources(struct dma_chan *chan) -@@ -819,7 +832,8 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan) - return 0; - } - --static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) -+static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, -+ int irq, unsigned int irq_flags) - { - struct bcm2835_chan *c; - -@@ -834,6 +848,7 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq) - c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id); - c->ch = chan_id; - c->irq_number = irq; -+ c->irq_flags = irq_flags; - - /* check in DEBUG register if this is a LITE channel */ - if (readl(c->chan_base + BCM2835_DMA_DEBUG) & -@@ -882,9 +897,11 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - struct resource *res; - void __iomem *base; - int rc; -- int i; -- int irq; -+ int i, j; -+ int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1]; -+ int irq_flags; - uint32_t chans_available; -+ char chan_name[BCM2835_DMA_CHAN_NAME_SIZE]; - - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; -@@ -941,16 +958,48 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - goto err_no_dma; - } - -- for (i = 0; i < pdev->num_resources; i++) { -- irq = platform_get_irq(pdev, i); -- if (irq < 0) -- break; -- -- if (chans_available & (1 << i)) { -- rc = bcm2835_dma_chan_init(od, i, irq); -- if (rc) -- goto err_no_dma; -+ /* get irqs for each channel that we support */ -+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { -+ /* skip masked out channels */ -+ if (!(chans_available & (1 << i))) { -+ irq[i] = -1; -+ continue; - } -+ -+ /* get the named irq */ -+ snprintf(chan_name, sizeof(chan_name), "dma%i", i); -+ irq[i] = platform_get_irq_byname(pdev, chan_name); -+ if (irq[i] >= 0) -+ continue; -+ -+ /* legacy device tree case handling */ -+ dev_warn_once(&pdev->dev, -+ "missing interrupts-names property in device tree - legacy interpretation is used"); -+ /* -+ * in case of channel >= 11 -+ * use the 11th interrupt and that is shared -+ */ -+ irq[i] = platform_get_irq(pdev, i < 11 ? i : 11); -+ } -+ -+ /* get irqs for each channel */ -+ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { -+ /* skip channels without irq */ -+ if (irq[i] < 0) -+ continue; -+ -+ /* check if there are other channels that also use this irq */ -+ irq_flags = 0; -+ for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++) -+ if ((i != j) && (irq[j] == irq[i])) { -+ irq_flags = IRQF_SHARED; -+ break; -+ } -+ -+ /* initialize the channel */ -+ rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags); -+ if (rc) -+ goto err_no_dma; - } - - dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i); - -From df774079ce9acc952350f182ef76d627b82968f8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Sat, 3 Oct 2015 22:22:55 +0200 -Subject: [PATCH 130/141] dmaengine: bcm2835: Load driver early and support - legacy API -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Load driver early since at least bcm2708_fb doesn't support deferred -probing and even if it did, we don't want the video driver deferred. - -Support the legacy DMA API which is needed by bcm2708_fb -(but only using the dedicated dma channel 0). - -Signed-off-by: Noralf Trønnes -Signed-off-by: Martin Sperl ---- - drivers/dma/Kconfig | 2 +- - drivers/dma/bcm2835-dma.c | 27 ++++++++++++++++++++++++++- - 2 files changed, 27 insertions(+), 2 deletions(-) - -diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 1acfa84be0d1f74f5a830b04cab05ba7fa0841ab..b7863f0cf95ca656859a355098aa334e20d121c3 100644 ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -108,7 +108,7 @@ config COH901318 - - config DMA_BCM2835 - tristate "BCM2835 DMA engine support" -- depends on ARCH_BCM2835 -+ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 - select DMA_ENGINE - select DMA_VIRTUAL_CHANNELS - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 974015193b93cdb398f1157b89b6e2cf5234354e..2d7aba118640447854732384351601137b502839 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1021,6 +1022,14 @@ static int bcm2835_dma_probe(struct platform_device *pdev) - - dev_dbg(&pdev->dev, "Load BCM2835 DMA engine driver\n"); - -+ /* load the legacy api if bit 0 in the mask is cleared */ -+ if ((chans_available & BIT(0)) == 0) { -+ rc = bcm_dmaman_probe(pdev, base, BIT(0)); -+ if (rc) -+ dev_err(&pdev->dev, -+ "Failed to initialize the legacy API\n"); -+ } -+ - return 0; - - err_no_dma: -@@ -1032,6 +1041,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) - { - struct bcm2835_dmadev *od = platform_get_drvdata(pdev); - -+ bcm_dmaman_remove(pdev); - dma_async_device_unregister(&od->ddev); - bcm2835_dma_free(od); - -@@ -1047,7 +1057,22 @@ static struct platform_driver bcm2835_dma_driver = { - }, - }; - --module_platform_driver(bcm2835_dma_driver); -+static int bcm2835_dma_init(void) -+{ -+ return platform_driver_register(&bcm2835_dma_driver); -+} -+ -+static void bcm2835_dma_exit(void) -+{ -+ platform_driver_unregister(&bcm2835_dma_driver); -+} -+ ++obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o +diff --git a/sound/soc/bcm/dionaudio_loco.c b/sound/soc/bcm/dionaudio_loco.c +new file mode 100644 +index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98aacb740a +--- /dev/null ++++ b/sound/soc/bcm/dionaudio_loco.c +@@ -0,0 +1,121 @@ +/* -+ * Load after serial driver (arch_initcall) so we see the messages if it fails, -+ * but before drivers (module_init) that need a DMA channel. ++ * ASoC Driver for Dion Audio LOCO DAC-AMP ++ * ++ * Author: Miquel Blauw ++ * Copyright 2016 ++ * ++ * Based on the software of the RPi-DAC writen by Florian Meier ++ * ++ * 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. + */ -+subsys_initcall(bcm2835_dma_init); -+module_exit(bcm2835_dma_exit); - - MODULE_ALIAS("platform:bcm2835-dma"); - MODULE_DESCRIPTION("BCM2835 DMA engine driver"); - -From 5d00014e188fa1eb67d14f525b2daeebd842cf39 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Fri, 22 Apr 2016 16:13:59 +0000 -Subject: [PATCH 131/141] ARM: bcm270x: changed bcrm,dma-channel-mask to mask - out the used channel - -Dma channel0 is used by the legacy api - to avoid confilcts this -needs to get masked out in the device-tree instead of hardcoding it -in the driver. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index 6ea37c57f7b1f298c10a599982f347098219d468..d85862e2028487b0c357b3a7cd8e78524abc3c92 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -59,7 +59,7 @@ - <1 27>; - - #dma-cells = <1>; -- brcm,dma-channel-mask = <0x0f35>; -+ brcm,dma-channel-mask = <0x0f34>; - }; - - intc: interrupt-controller@7e00b200 { - -From d99a15e724b68ff99c96abf73b35b1f43c0e14a5 Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sat, 23 Apr 2016 14:07:03 +0000 -Subject: [PATCH 132/141] ARM: bcm2835: add interrupt-names and apply correct - mapping - -Add interrupt-names properties to dt and apply the correct -mapping between irq and dma channels. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/bcm2708_common.dtsi | 26 ++++++++++++++++++++++++-- - 1 file changed, 24 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708_common.dtsi b/arch/arm/boot/dts/bcm2708_common.dtsi -index d85862e2028487b0c357b3a7cd8e78524abc3c92..18a28c8578a322bdef73cdb5ff4131b40f9321e4 100644 ---- a/arch/arm/boot/dts/bcm2708_common.dtsi -+++ b/arch/arm/boot/dts/bcm2708_common.dtsi -@@ -56,10 +56,32 @@ - <1 24>, - <1 25>, - <1 26>, -- <1 27>; -+ /* dma channel 11-14 share one irq */ -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ <1 27>, -+ /* unused shared irq for all channels */ -+ <1 28>; -+ interrupt-names = "dma0", -+ "dma1", -+ "dma2", -+ "dma3", -+ "dma4", -+ "dma5", -+ "dma6", -+ "dma7", -+ "dma8", -+ "dma9", -+ "dma10", -+ "dma11", -+ "dma12", -+ "dma13", -+ "dma14", -+ "dma-shared-all"; - - #dma-cells = <1>; -- brcm,dma-channel-mask = <0x0f34>; -+ brcm,dma-channel-mask = <0x7f34>; - }; - - intc: interrupt-controller@7e00b200 { - -From 93eb2585bb68f04f5a1ee9ff5f6943d9a8001b7b Mon Sep 17 00:00:00 2001 -From: Martin Sperl -Date: Sat, 23 Apr 2016 14:20:41 +0000 -Subject: [PATCH 133/141] ARM: bcm2835: make dma-channel-0 available for kms - setups - -Enable the use of dma-channel 0 when using the vc4-kms-v3d overlay. - -Signed-off-by: Martin Sperl ---- - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -index a4ca2cabd4cd19d3a82ad1135604dfa52784fb3f..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 100644 ---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -119,6 +119,13 @@ - }; - }; - -+ fragment@15 { -+ target-path = "/soc/dma"; -+ __overlay__ { -+ brcm,dma-channel-mask = <0x7f35>; -+ }; -+ }; + - __overrides__ { - cma-256 = <0>,"+0-1-2-3-4"; - cma-192 = <0>,"-0+1-2-3-4"; - -From b5c0b88c0005b431c583dec3e210895a994d5a99 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Tue, 7 Jun 2016 19:37:10 +0200 -Subject: [PATCH 134/141] dmaengine: bcm2835: Fix cyclic DMA period splitting - -The code responsible for splitting periods into chunks that -can be handled by the DMA controller missed to update total_len, -the number of bytes processed in the current period, when there -are more chunks to follow. - -Therefore total_len was stuck at 0 and the code didn't work at all. -This resulted in a wrong control block layout and audio issues because -the cyclic DMA callback wasn't executing on period boundaries. - -Fix this by adding the missing total_len update. - -Signed-off-by: Matthias Reichl -Signed-off-by: Martin Sperl -Tested-by: Clive Messer ---- - drivers/dma/bcm2835-dma.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 2d7aba118640447854732384351601137b502839..ea58967594c5a2d712026f50307c2d4de7089e8d 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -252,8 +252,11 @@ static void bcm2835_dma_create_cb_set_length( - */ - - /* have we filled in period_length yet? */ -- if (*total_len + control_block->length < period_len) -+ if (*total_len + control_block->length < period_len) { -+ /* update number of bytes in this period so far */ -+ *total_len += control_block->length; - return; -+ } - - /* calculate the length that remains to reach period_length */ - control_block->length = period_len - *total_len; - -From fffe68c8ea72a81115e92d3bf7791fea189f8eec Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Wed, 8 Jun 2016 13:09:56 +0200 -Subject: [PATCH 135/141] dmaengine: bcm2835: Avoid splitting periods into very - small chunks - -The current cyclic DMA period splitting implementation can generate -very small chunks at the end of each period. For example a 65536 byte -period will be split into a 65532 byte chunk and a 4 byte chunk on -the "lite" DMA channels. - -This increases pressure on the RAM controller as the DMA controller -needs to fetch two control blocks from RAM in quick succession and -could potentially cause latency issues if the RAM is tied up by other -devices. - -We can easily avoid these situations by distributing the remaining -length evenly between the last-but-one and the last chunk, making -sure that split chunks will be at least half the maximum length the -DMA controller can handle. - -This patch checks if the last chunk would be less than half of -the maximum DMA length and if yes distributes the max len+4...max_len*1.5 -bytes evenly between the last 2 chunks. This results in chunk sizes -between max_len/2 and max_len*0.75 bytes. - -Signed-off-by: Matthias Reichl -Signed-off-by: Martin Sperl -Tested-by: Clive Messer ---- - drivers/dma/bcm2835-dma.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index ea58967594c5a2d712026f50307c2d4de7089e8d..0173b912afb26b8f59e623a9055513df34cd3caa 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -253,6 +253,20 @@ static void bcm2835_dma_create_cb_set_length( - - /* have we filled in period_length yet? */ - if (*total_len + control_block->length < period_len) { -+ /* -+ * If the next control block is the last in the period -+ * and it's length would be less than half of max_len -+ * change it so that both control blocks are (almost) -+ * equally long. This avoids generating very short -+ * control blocks (worst case would be 4 bytes) which -+ * might be problematic. We also have to make sure the -+ * new length is a multiple of 4 bytes. -+ */ -+ if (*total_len + control_block->length + max_len / 2 > -+ period_len) { -+ control_block->length = -+ DIV_ROUND_UP(period_len - *total_len, 8) * 4; -+ } - /* update number of bytes in this period so far */ - *total_len += control_block->length; - return; - -From 2a0e397fd871007f34f4de8b515fe3270095dc6b Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Fri, 3 Jun 2016 19:29:11 -0700 -Subject: [PATCH 136/141] dmaengine: bcm2835: Fix polling for completion of DMA - with interrupts masked. - -The tx_status hook is supposed to be safe to call from interrupt -context, but it wouldn't ever return completion for the last transfer, -meaning you couldn't poll for DMA completion with interrupts masked. - -This fixes IRQ handling for bcm2835's DSI1, which requires using the -DMA engine to write its registers due to a bug in the AXI bridge. - -Signed-off-by: Eric Anholt ---- - drivers/dma/bcm2835-dma.c | 24 +++++++++++++++++++----- - 1 file changed, 19 insertions(+), 5 deletions(-) - -diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index 0173b912afb26b8f59e623a9055513df34cd3caa..a98e2c2e6888f6351461c25f9f7d2a34330d0a76 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -588,16 +588,16 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, - struct virt_dma_desc *vd; - enum dma_status ret; - unsigned long flags; -+ u32 residue; - - ret = dma_cookie_status(chan, cookie, txstate); -- if (ret == DMA_COMPLETE || !txstate) -+ if (ret == DMA_COMPLETE) - return ret; - - spin_lock_irqsave(&c->vc.lock, flags); - vd = vchan_find_desc(&c->vc, cookie); - if (vd) { -- txstate->residue = -- bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); -+ residue = bcm2835_dma_desc_size(to_bcm2835_dma_desc(&vd->tx)); - } else if (c->desc && c->desc->vd.tx.cookie == cookie) { - struct bcm2835_desc *d = c->desc; - dma_addr_t pos; -@@ -609,11 +609,25 @@ static enum dma_status bcm2835_dma_tx_status(struct dma_chan *chan, - else - pos = 0; - -- txstate->residue = bcm2835_dma_desc_size_pos(d, pos); -+ residue = bcm2835_dma_desc_size_pos(d, pos); ++#include ++#include + -+ /* -+ * If our non-cyclic transfer is done, then report -+ * complete and trigger the next tx now. This lets -+ * the dmaengine API be used synchronously from an IRQ -+ * handler. -+ */ -+ if (!d->cyclic && residue == 0) { -+ vchan_cookie_complete(&c->desc->vd); -+ bcm2835_dma_start_desc(c); -+ ret = dma_cookie_status(chan, cookie, txstate); -+ } - } else { -- txstate->residue = 0; -+ residue = 0; - } - -+ dma_set_residue(txstate, residue); ++#include ++#include ++#include ++#include ++#include + - spin_unlock_irqrestore(&c->vc.lock, flags); - - return ret; - -From 5d66079db4c049b62056903bc7f0a125005c0a65 Mon Sep 17 00:00:00 2001 -From: P33M -Date: Thu, 9 Jun 2016 18:53:56 +0100 -Subject: [PATCH 137/141] dwc_otg: add FIQ latency profiling histogram - -Add a sysfs-based FIQ latency profiler that times differences between -start-of-frame interrupts. Stats readout is via the sof_histogram -attribute. - -Writing to the sof_histogram attribute resets the bucket counters. ---- - drivers/usb/host/dwc_otg/dwc_otg_attr.c | 23 ++++++++++++++++- - drivers/usb/host/dwc_otg/dwc_otg_attr.h | 1 + - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 7 +++++- - drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 6 +++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 38 ++++++++++++++++++++++++++++- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 7 ++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 2 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 27 ++++++++++++++++++++ - 8 files changed, 108 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -index 9da0c92aaeca2fc393016442cc6578cb4a52c978..e536f7e828174c193b3967f022e32e6f0f3e41d2 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -@@ -1016,6 +1016,26 @@ static ssize_t wr_reg_test_show(struct device *_dev, - - DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0); - -+static ssize_t sof_histogram_reset(struct device *_dev, -+ struct device_attribute *attr, const char *buf, size_t count) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ dwc_otg_hcd_t *hcd = otg_dev->hcd; -+ dwc_otg_hcd_sof_histogram_reset(hcd); -+ return count; -+} -+ -+static ssize_t sof_histogram_show(struct device *_dev, struct device_attribute *attr, char *buf) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ dwc_otg_hcd_t *hcd = otg_dev->hcd; -+ -+ return dwc_otg_hcd_dump_sof_histogram(hcd, buf); -+ -+} -+ -+DEVICE_ATTR(sof_histogram, S_IRUGO | S_IWUSR, sof_histogram_show, sof_histogram_reset); -+ - #ifdef CONFIG_USB_DWC_OTG_LPM - - /** -@@ -1113,7 +1133,7 @@ void dwc_otg_attr_create( - ) - { - int error; -- -+ error = device_create_file(&dev->dev, &dev_attr_sof_histogram); - error = device_create_file(&dev->dev, &dev_attr_regoffset); - error = device_create_file(&dev->dev, &dev_attr_regvalue); - error = device_create_file(&dev->dev, &dev_attr_mode); -@@ -1168,6 +1188,7 @@ void dwc_otg_attr_remove( - #endif - ) - { -+ device_remove_file(&dev->dev, &dev_attr_sof_histogram); - device_remove_file(&dev->dev, &dev_attr_regoffset); - device_remove_file(&dev->dev, &dev_attr_regvalue); - device_remove_file(&dev->dev, &dev_attr_mode); -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -index e10b67f97c522094b553b7675741ba1b3cae293d..f86ed9534c0d36329d60b52b4b05f31ac073b1b5 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -@@ -39,6 +39,7 @@ - */ - extern struct device_attribute dev_attr_regoffset; - extern struct device_attribute dev_attr_regvalue; -+extern struct device_attribute dev_attr_sof_histogram; - - extern struct device_attribute dev_attr_mode; - extern struct device_attribute dev_attr_hnpcapable; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -index 85d82f31cb49631f03b23631882d2b6c063b33db..9f7cec1ddfc761e61ebb208ea234e82545bf1e49 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c -@@ -580,8 +580,13 @@ static int notrace noinline fiq_fsm_update_hs_isoc(struct fiq_state *state, int - static int notrace noinline fiq_fsm_do_sof(struct fiq_state *state, int num_channels) - { - hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + HFNUM) }; -- int n; -+ int n, i; - int kick_irq = 0; -+ -+ for (i = FIQ_NR_TIMESTAMPS - 1; i > 0; i--) { -+ state->sof_timestamps[i] = state->sof_timestamps[i - 1]; -+ } -+ state->sof_timestamps[0] = FIQ_READ(STC_LO); - - if ((hfnum.b.frnum & 0x7) == 1) { - /* We cannot issue csplits for transactions in the last frame past (n+1).1 -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -index f9fddfbcffb37f32c808fd78f222b676378398b1..a3e0a784d9567c861410d0d1271d5f95729b5ccb 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #if 0 - #define FLAME_ON(x) \ -@@ -80,6 +81,9 @@ do { \ - #define FIQ_WRITE(_addr_,_data_) (*(volatile unsigned int *) (_addr_) = (_data_)) - #define FIQ_READ(_addr_) (*(volatile unsigned int *) (_addr_)) - -+#define FIQ_NR_TIMESTAMPS 32 -+#define STC_LO __io_address(ST_BASE + 0x04) -+ - /* FIQ-ified register definitions. Offsets are from dwc_regs_base. */ - #define GINTSTS 0x014 - #define GINTMSK 0x018 -@@ -339,12 +343,14 @@ struct fiq_state { - fiq_lock_t lock; - mphi_regs_t mphi_regs; - void *dwc_regs_base; -+ void *stc_base; - dma_addr_t dma_base; - struct fiq_dma_blob *fiq_dmab; - void *dummy_send; - gintmsk_data_t gintmsk_saved; - haintmsk_data_t haintmsk_saved; - int mphi_int_count; -+ int sof_timestamps[FIQ_NR_TIMESTAMPS]; - unsigned int fiq_done; - unsigned int kick_np_queues; - unsigned int next_sched_frame; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index 135b611abe08e141c937612ab7baada6b13113fc..cb7ec4af267459494194be54e5321df8326bf3c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -1047,7 +1047,12 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - sizeof(struct fiq_dma_channel) * num_channels); - - DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024); -- -+ -+ for(i = 0; i < NR_BINS; i++) { -+ hcd->histogram_bins[i] = BIN_START + (i * BIN_STRIDE); -+ hcd->histogram_counts[i] = 0; -+ } -+ - /* pointer for debug in fiq_print */ - hcd->fiq_state->fiq_dmab = hcd->fiq_dmab; - if (fiq_fsm_enable) { -@@ -4001,6 +4006,37 @@ int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) - return freed; - } - -+ssize_t dwc_otg_hcd_dump_sof_histogram(dwc_otg_hcd_t *hcd, char *buf) -+{ -+ ssize_t inc = 0, count = 0; -+ int i; -+ inc = sprintf(buf, "FIQ SOF latency histogram:\n Read overflows: %d\n", -+ hcd->sof_timestamp_overflows); -+ if (inc < 0) -+ return inc; -+ else -+ count += inc; -+ -+ for (i = 0; i < NR_BINS; i++) { -+ inc = sprintf(buf + count, " >%dus : %d\n", hcd->histogram_bins[i], hcd->histogram_counts[i]); -+ if (inc < 0) -+ return inc; -+ else -+ count += inc; -+ } -+ return count; -+} -+ -+void dwc_otg_hcd_sof_histogram_reset(dwc_otg_hcd_t *hcd) -+{ -+ int i; -+ unsigned long flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ for(i = 0; i < NR_BINS; i++) -+ hcd->histogram_counts[i] = 0; -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+} -+ - uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) - { - dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index 43dbed9fddbf5491bab33cc6e551b99ca8dce7dc..53ec21b15feebf91ef3ce9d13dbb265a7f856609 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -589,6 +589,13 @@ struct dwc_otg_hcd { - - struct fiq_stack *fiq_stack; - struct fiq_state *fiq_state; -+ int last_sof_timestamp; -+ int sof_timestamp_overflows; -+#define NR_BINS 16 -+#define BIN_STRIDE 5 -+#define BIN_START 100 -+ int histogram_bins[NR_BINS]; -+ int histogram_counts[NR_BINS]; - - /** Virtual address for split transaction DMA bounce buffers */ - struct fiq_dma_blob *fiq_dmab; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -index fb57db09378f4ab95d57cb58aa570a915ccb61c3..6103f7085b417d29eca323c1ed9667c6614c9ecd 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -@@ -411,6 +411,8 @@ extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); - extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, - void *ep_handle); - -+extern ssize_t dwc_otg_hcd_dump_sof_histogram(dwc_otg_hcd_t *hcd, char *buf); -+extern void dwc_otg_hcd_sof_histogram_reset(dwc_otg_hcd_t *hcd); - /** @} */ - - #endif /* __DWC_HCD_IF_H__ */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -index e6b38ac330b72152204c2a6879c20f0ce02ac2e5..a72438c9ed0b45471c736c52248480399511aca3 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -72,6 +72,31 @@ void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...) - } - #endif - -+void dwc_otg_hcd_update_histogram(dwc_otg_hcd_t *hcd) -+{ -+ int i, j, delta; -+ /* Search through the stack of SOF timestamps to find the last congruent timestamp */ -+ for(i = FIQ_NR_TIMESTAMPS - 1; i >= 0; i--) { -+ if ((hcd->last_sof_timestamp - hcd->fiq_state->sof_timestamps[i]) <= 0) -+ break; -+ } -+ if (i < 0) { -+ hcd->sof_timestamp_overflows++; -+ i += 1; -+ } -+ for(; i < FIQ_NR_TIMESTAMPS - 1; i++) { -+ /* Compute deltas, add to histogram buckets */ -+ delta = hcd->fiq_state->sof_timestamps[i] - hcd->fiq_state->sof_timestamps[i+1]; -+ for (j = 0; j < NR_BINS; j++) { -+ if(hcd->histogram_bins[j] >= delta || j == NR_BINS - 1) { -+ hcd->histogram_counts[j]++; -+ break; -+ } -+ } -+ } -+ hcd->last_sof_timestamp = hcd->fiq_state->sof_timestamps[0]; -+} -+ - /** This function handles interrupts for the HCD. */ - int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - { -@@ -104,6 +129,8 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - /* Pull in from the FIQ's disabled mask */ - gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32); - dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0; -+ -+ dwc_otg_hcd_update_histogram(dwc_otg_hcd); - } - - if (fiq_fsm_enable && ( 0x0000FFFF & ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint))) { - -From 5a66165271577b98c21d0828881ba50e957a144e Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Fri, 17 Jun 2016 12:03:39 +1000 -Subject: [PATCH 138/141] Added support for headphones, microphone and - bclk_ratio settings. - -This patch adds headphone and microphone capability to the Audio Injector sound card. The patch also sets the bit clock ratio for use in the bcm2835-i2s driver. The bcm2835-i2s can't handle an 8 kHz sample rate when the bit clock is at 12 MHz because its register is only 10 bits wide which can't represent the ch2 offset of 1508. For that reason, the rate constraint is added. ---- - sound/soc/bcm/audioinjector-pi-soundcard.c | 67 ++++++++++++++++++++++++++---- - 1 file changed, 58 insertions(+), 9 deletions(-) - -diff --git a/sound/soc/bcm/audioinjector-pi-soundcard.c b/sound/soc/bcm/audioinjector-pi-soundcard.c -index 39f29e26897226a413b4fa0a11a9bc160a485281..5ff0985e07efb96b95634a65995f09f7c68d9e99 100644 ---- a/sound/soc/bcm/audioinjector-pi-soundcard.c -+++ b/sound/soc/bcm/audioinjector-pi-soundcard.c -@@ -29,16 +29,56 @@ - - #include "../codecs/wm8731.h" - --static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) -+static const unsigned int bcm2835_rates_12000000[] = { -+ 32000, 44100, 48000, 96000, 88200, -+}; -+ -+static struct snd_pcm_hw_constraint_list bcm2835_constraints_12000000 = { -+ .list = bcm2835_rates_12000000, -+ .count = ARRAY_SIZE(bcm2835_rates_12000000), -+}; -+ -+static int snd_audioinjector_pi_soundcard_startup(struct snd_pcm_substream *substream) - { -- struct snd_soc_dapm_context *dapm = &rtd->card->dapm; -+ /* Setup constraints, because there is a 12 MHz XTAL on the board */ -+ snd_pcm_hw_constraint_list(substream->runtime, 0, -+ SNDRV_PCM_HW_PARAM_RATE, -+ &bcm2835_constraints_12000000); -+ return 0; -+} - -- // not connected -- snd_soc_dapm_nc_pin(dapm, "Mic Bias"); -- snd_soc_dapm_nc_pin(dapm, "MICIN"); -- snd_soc_dapm_nc_pin(dapm, "RHPOUT"); -- snd_soc_dapm_nc_pin(dapm, "LHPOUT"); -+static int snd_audioinjector_pi_soundcard_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) ++static int snd_rpi_dionaudio_loco_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; + -+ switch (params_rate(params)){ -+ case 8000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 1508); -+ case 32000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 378); -+ case 44100: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 274); -+ case 48000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 252); -+ case 88200: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 136); -+ case 96000: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ default: -+ return snd_soc_dai_set_bclk_ratio(cpu_dai, 126); -+ } ++ 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_audioinjector_pi_soundcard_ops = { -+ .startup = snd_audioinjector_pi_soundcard_startup, -+ .hw_params = snd_audioinjector_pi_soundcard_hw_params, ++static struct snd_soc_ops snd_rpi_dionaudio_loco_ops = { ++ .hw_params = snd_rpi_dionaudio_loco_hw_params, +}; - -+static int audioinjector_pi_soundcard_dai_init(struct snd_soc_pcm_runtime *rtd) ++ ++static struct snd_soc_dai_link snd_rpi_dionaudio_loco_dai[] = { +{ - return snd_soc_dai_set_sysclk(rtd->codec_dai, WM8731_SYSCLK_XTAL, 12000000, SND_SOC_CLOCK_IN); ++ .name = "DionAudio LOCO", ++ .stream_name = "DionAudio LOCO DAC-AMP", ++ .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_dionaudio_loco_ops, ++}, ++}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_dionaudio_loco = { ++ .name = "snd_rpi_dionaudio_loco", ++ .dai_link = snd_rpi_dionaudio_loco_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_dai), ++}; ++ ++static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev) ++{ ++ struct device_node *np; ++ int ret = 0; ++ ++ snd_rpi_dionaudio_loco.dev = &pdev->dev; ++ ++ np = pdev->dev.of_node; ++ if (np) { ++ struct snd_soc_dai_link *dai = &snd_rpi_dionaudio_loco_dai[0]; ++ struct device_node *i2s_np; ++ ++ i2s_np = of_parse_phandle(np, "i2s-controller", 0); ++ if (i2s_np) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_np; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_np; ++ } ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_dionaudio_loco_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco); ++} ++ ++static const struct of_device_id snd_rpi_dionaudio_loco_of_match[] = { ++ { .compatible = "dionaudio,loco-pcm5242-tpa3118", }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, snd_rpi_dionaudio_loco_of_match); ++ ++static struct platform_driver snd_rpi_dionaudio_loco_driver = { ++ .driver = { ++ .name = "snd-dionaudio-loco", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_rpi_dionaudio_loco_of_match, ++ }, ++ .probe = snd_rpi_dionaudio_loco_probe, ++ .remove = snd_rpi_dionaudio_loco_remove, ++}; ++ ++module_platform_driver(snd_rpi_dionaudio_loco_driver); ++ ++MODULE_AUTHOR("Miquel Blauw "); ++MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); ++MODULE_LICENSE("GPL v2"); + +From c29ce2592d5e0975b06dffd115c738a8f7ca9be3 Mon Sep 17 00:00:00 2001 +From: Matt Flax +Date: Fri, 17 Jun 2016 14:48:16 +1000 +Subject: [PATCH 082/111] ASoc: wm8731: add 32bit mode. + +commit cf5ef3a299ba32f6ac24c3c6ba18c1b7f1b5475f upstream. + +This patch adds 32 bit word capability to the wm8731 driver. The wm8731 +codec is capable of handling 32 bit word sizes, however that has not +previously been activated in the codec driver. + +Signed-off-by: Matt Flax +Acked-by: Charles Keepax +Signed-off-by: Mark Brown +--- + sound/soc/codecs/wm8731.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c +index 4bcf5f8ece50f3681948a9fbc47b85400d9a8b51..d18261a442560cd2c108c34295bd5b1776a6ebf4 100644 +--- a/sound/soc/codecs/wm8731.c ++++ b/sound/soc/codecs/wm8731.c +@@ -358,6 +358,9 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, + case 24: + iface |= 0x0008; + break; ++ case 32: ++ iface |= 0x000c; ++ break; + } + + wm8731_set_deemph(codec); +@@ -541,7 +544,7 @@ static int wm8731_startup(struct snd_pcm_substream *substream, + #define WM8731_RATES SNDRV_PCM_RATE_8000_96000 + + #define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ +- SNDRV_PCM_FMTBIT_S24_LE) ++ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + + static const struct snd_soc_dai_ops wm8731_dai_ops = { + .startup = wm8731_startup, + +From 9b3d81c6b2b35518fc918d777b8b78677cb1658a Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:40:58 +0100 +Subject: [PATCH 083/111] Revert "ASoC: bcm2835: Add S16_LE support via packed + DMA transfers" + +This reverts commit beff053c0ef6983897e3481169292e6435ef0a2d. +--- + sound/soc/bcm/bcm2835-i2s.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 6ba20498202ed36906b52096893a88867a79269f..a0026e2d2f0afd700751b1b4fa2523585829173e 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -690,15 +690,6 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 2; + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 2; + +- /* +- * Set the PACK flag to enable S16_LE support (2 S16_LE values +- * packed into 32-bit transfers). +- */ +- dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].flags = +- SND_DMAENGINE_PCM_DAI_FLAG_PACK; +- dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].flags = +- SND_DMAENGINE_PCM_DAI_FLAG_PACK; +- + /* BCLK ratio - use default */ + dev->bclk_ratio = 0; + + +From 9031c85c4614817d9356a6e58e50e98c030f5727 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:01 +0100 +Subject: [PATCH 084/111] Revert "ASoC: bcm2835: setup clock only if CPU is + clock master" + +This reverts commit 60507fe191f524e82986fa737e5b27b4d3ad9289. +--- + sound/soc/bcm/bcm2835-i2s.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index a0026e2d2f0afd700751b1b4fa2523585829173e..d2663e79ece1a2b649377e4a89460aa5a6d150b5 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -276,15 +276,8 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* otherwise calculate a fitting block ratio */ + bclk_ratio = 2 * data_length; + +- /* Clock should only be set up here if CPU is clock master */ +- switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { +- case SND_SOC_DAIFMT_CBS_CFS: +- case SND_SOC_DAIFMT_CBS_CFM: +- clk_set_rate(dev->clk, sampling_rate * bclk_ratio); +- break; +- default: +- break; +- } ++ /* set target clock rate*/ ++ clk_set_rate(dev->clk, sampling_rate * bclk_ratio); + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +From 49d7323355837c4cffd22aa242a8b5d50a2b47e6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:03 +0100 +Subject: [PATCH 085/111] Revert "ASoC: bcm2835: add 24bit support" + +This reverts commit a34b027dca5ea840fbc84121db66488375acfdea. +--- + sound/soc/bcm/bcm2835-i2s.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index d2663e79ece1a2b649377e4a89460aa5a6d150b5..1c1f2210387b26e9551959378f6792f18648652e 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -259,9 +259,6 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + case SNDRV_PCM_FORMAT_S16_LE: + data_length = 16; + break; +- case SNDRV_PCM_FORMAT_S24_LE: +- data_length = 24; +- break; + case SNDRV_PCM_FORMAT_S32_LE: + data_length = 32; + break; +@@ -282,7 +279,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +- if (data_length >= 24) ++ if (data_length > 24) + format |= BCM2835_I2S_CHWEX; + + format |= BCM2835_I2S_CHWID((data_length-8)&0xf); +@@ -573,7 +570,6 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { +@@ -581,7 +577,6 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, + +From 426600f81c84eb9581de55c5c364e402b744d627 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 Jun 2016 15:41:09 +0100 +Subject: [PATCH 086/111] Revert "ASoC: bcm2835: move to use the clock + framework" + +This reverts commit 517e7a1537ae4663268be5d0c0ec62c563b9fc99. +--- + sound/soc/bcm/bcm2835-i2s.c | 284 ++++++++++++++++++++++++++++++++++---------- + 1 file changed, 220 insertions(+), 64 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 1c1f2210387b26e9551959378f6792f18648652e..3303d5f58082f68b68b535b2bdf7ce8d14cafcc4 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -47,6 +46,55 @@ + #include + #include + ++/* Clock registers */ ++#define BCM2835_CLK_PCMCTL_REG 0x00 ++#define BCM2835_CLK_PCMDIV_REG 0x04 ++ ++/* Clock register settings */ ++#define BCM2835_CLK_PASSWD (0x5a000000) ++#define BCM2835_CLK_PASSWD_MASK (0xff000000) ++#define BCM2835_CLK_MASH(v) ((v) << 9) ++#define BCM2835_CLK_FLIP BIT(8) ++#define BCM2835_CLK_BUSY BIT(7) ++#define BCM2835_CLK_KILL BIT(5) ++#define BCM2835_CLK_ENAB BIT(4) ++#define BCM2835_CLK_SRC(v) (v) ++ ++#define BCM2835_CLK_SHIFT (12) ++#define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) ++#define BCM2835_CLK_DIVF(v) (v) ++#define BCM2835_CLK_DIVF_MASK (0xFFF) ++ ++enum { ++ BCM2835_CLK_MASH_0 = 0, ++ BCM2835_CLK_MASH_1, ++ BCM2835_CLK_MASH_2, ++ BCM2835_CLK_MASH_3, ++}; ++ ++enum { ++ BCM2835_CLK_SRC_GND = 0, ++ BCM2835_CLK_SRC_OSC, ++ BCM2835_CLK_SRC_DBG0, ++ BCM2835_CLK_SRC_DBG1, ++ BCM2835_CLK_SRC_PLLA, ++ BCM2835_CLK_SRC_PLLC, ++ BCM2835_CLK_SRC_PLLD, ++ BCM2835_CLK_SRC_HDMI, ++}; ++ ++/* Most clocks are not useable (freq = 0) */ ++static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { ++ [BCM2835_CLK_SRC_GND] = 0, ++ [BCM2835_CLK_SRC_OSC] = 19200000, ++ [BCM2835_CLK_SRC_DBG0] = 0, ++ [BCM2835_CLK_SRC_DBG1] = 0, ++ [BCM2835_CLK_SRC_PLLA] = 0, ++ [BCM2835_CLK_SRC_PLLC] = 0, ++ [BCM2835_CLK_SRC_PLLD] = 500000000, ++ [BCM2835_CLK_SRC_HDMI] = 0, ++}; ++ + /* I2S registers */ + #define BCM2835_I2S_CS_A_REG 0x00 + #define BCM2835_I2S_FIFO_A_REG 0x04 +@@ -110,6 +158,10 @@ + #define BCM2835_I2S_INT_RXR BIT(1) + #define BCM2835_I2S_INT_TXW BIT(0) + ++/* I2S DMA interface */ ++/* FIXME: Needs IOMMU support */ ++#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) ++ + /* General device struct */ + struct bcm2835_i2s_dev { + struct device *dev; +@@ -117,23 +169,21 @@ struct bcm2835_i2s_dev { + unsigned int fmt; + unsigned int bclk_ratio; + +- struct regmap *i2s_regmap; +- struct clk *clk; +- bool clk_prepared; ++ struct regmap *i2s_regmap; ++ struct regmap *clk_regmap; + }; + + static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) + { ++ /* Start the clock if in master mode */ + unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; + +- if (dev->clk_prepared) +- return; +- + switch (master) { + case SND_SOC_DAIFMT_CBS_CFS: + case SND_SOC_DAIFMT_CBS_CFM: +- clk_prepare_enable(dev->clk); +- dev->clk_prepared = true; ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); + break; + default: + break; +@@ -142,9 +192,28 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) + + static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) + { +- if (dev->clk_prepared) +- clk_disable_unprepare(dev->clk); +- dev->clk_prepared = false; ++ uint32_t clkreg; ++ int timeout = 1000; ++ ++ /* Stop clock */ ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD); ++ ++ /* Wait for the BUSY flag going down */ ++ while (--timeout) { ++ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); ++ if (!(clkreg & BCM2835_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, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, ++ BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); ++ } } -@@ -50,30 +90,39 @@ static struct snd_soc_dai_link audioinjector_pi_soundcard_dai[] = { - .codec_dai_name = "wm8731-hifi", - .platform_name = "bcm2835-i2s.0", - .codec_name = "wm8731.1-001a", -+ .ops = &snd_audioinjector_pi_soundcard_ops, - .init = audioinjector_pi_soundcard_dai_init, - .dai_fmt = SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF, + static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, +@@ -154,7 +223,8 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + uint32_t syncval; + uint32_t csreg; + uint32_t i2s_active_state; +- bool clk_was_prepared; ++ uint32_t clkreg; ++ uint32_t clk_active_state; + uint32_t off; + uint32_t clr; + +@@ -168,10 +238,15 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); + i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); + ++ regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); ++ clk_active_state = clkreg & BCM2835_CLK_ENAB; ++ + /* Start clock if not running */ +- clk_was_prepared = dev->clk_prepared; +- if (!clk_was_prepared) +- bcm2835_i2s_start_clock(dev); ++ if (!clk_active_state) { ++ regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, ++ BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); ++ } + + /* Stop I2S module */ + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); +@@ -205,7 +280,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, + dev_err(dev->dev, "I2S SYNC error!\n"); + + /* Stop clock if it was not running before */ +- if (!clk_was_prepared) ++ if (!clk_active_state) + bcm2835_i2s_stop_clock(dev); + + /* Restore I2S state */ +@@ -234,9 +309,19 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + { + struct bcm2835_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 = BCM2835_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; + + /* +@@ -258,9 +343,11 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + 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; +@@ -269,12 +356,69 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* If bclk_ratio already set, use that one. */ + if (dev->bclk_ratio) + bclk_ratio = dev->bclk_ratio; +- else +- /* otherwise calculate a fitting block ratio */ +- bclk_ratio = 2 * data_length; + +- /* set target clock rate*/ +- clk_set_rate(dev->clk, sampling_rate * 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 = BCM2835_CLK_SRC_OSC; ++ mash = BCM2835_CLK_MASH_0; ++ ++ if (bcm2835_clk_freq[clk_src] % target_frequency == 0 ++ && bit_master && frame_master) { ++ divi = bcm2835_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 = BCM2835_CLK_SRC_PLLD; ++ mash = BCM2835_CLK_MASH_1; ++ ++ dividend = bcm2835_clk_freq[clk_src]; ++ dividend <<= BCM2835_CLK_SHIFT; ++ do_div(dividend, target_frequency); ++ divi = dividend >> BCM2835_CLK_SHIFT; ++ divf = dividend & BCM2835_CLK_DIVF_MASK; ++ } ++ ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD ++ | BCM2835_CLK_DIVI(divi) ++ | BCM2835_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD ++ | BCM2835_CLK_MASH(mash) ++ | BCM2835_CLK_SRC(clk_src)); + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; +@@ -548,7 +692,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { + .trigger = bcm2835_i2s_trigger, + .hw_params = bcm2835_i2s_hw_params, + .set_fmt = bcm2835_i2s_set_dai_fmt, +- .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, ++ .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio + }; + + static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) +@@ -606,14 +750,34 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) + }; + } + +-static const struct regmap_config bcm2835_regmap_config = { +- .reg_bits = 32, +- .reg_stride = 4, +- .val_bits = 32, +- .max_register = BCM2835_I2S_GRAY_REG, +- .precious_reg = bcm2835_i2s_precious_reg, +- .volatile_reg = bcm2835_i2s_volatile_reg, +- .cache_type = REGCACHE_RBTREE, ++static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case BCM2835_CLK_PCMCTL_REG: ++ return true; ++ default: ++ return false; ++ }; ++} ++ ++static const struct regmap_config bcm2835_regmap_config[] = { ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2835_I2S_GRAY_REG, ++ .precious_reg = bcm2835_i2s_precious_reg, ++ .volatile_reg = bcm2835_i2s_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ }, ++ { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = BCM2835_CLK_PCMDIV_REG, ++ .volatile_reg = bcm2835_clk_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++ }, + }; + + static const struct snd_soc_component_driver bcm2835_i2s_component = { +@@ -623,50 +787,42 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + static int bcm2835_i2s_probe(struct platform_device *pdev) + { + struct bcm2835_i2s_dev *dev; ++ int i; + int ret; +- struct resource *mem; +- void __iomem *base; +- const __be32 *addr; +- dma_addr_t dma_base; ++ 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, ++ &bcm2835_regmap_config[i]); ++ if (IS_ERR(regmap[i])) ++ return PTR_ERR(regmap[i]); ++ } + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), + GFP_KERNEL); + if (!dev) + return -ENOMEM; + +- /* get the clock */ +- dev->clk_prepared = false; +- dev->clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(dev->clk)) { +- dev_err(&pdev->dev, "could not get clk: %ld\n", +- PTR_ERR(dev->clk)); +- return PTR_ERR(dev->clk); +- } +- +- /* Request ioarea */ +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- base = devm_ioremap_resource(&pdev->dev, mem); +- if (IS_ERR(base)) +- return PTR_ERR(base); +- +- dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base, +- &bcm2835_regmap_config); +- if (IS_ERR(dev->i2s_regmap)) +- return PTR_ERR(dev->i2s_regmap); +- +- /* Set the DMA address - we have to parse DT ourselves */ +- addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); +- if (!addr) { +- dev_err(&pdev->dev, "could not get DMA-register address\n"); +- return -EINVAL; +- } +- dma_base = be32_to_cpup(addr); ++ dev->i2s_regmap = regmap[0]; ++ dev->clk_regmap = regmap[1]; + ++ /* Set the DMA address */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = +- dma_base + BCM2835_I2S_FIFO_A_REG; ++ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG ++ + BCM2835_VCMMU_SHIFT; + + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = +- dma_base + BCM2835_I2S_FIFO_A_REG; ++ (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG ++ + BCM2835_VCMMU_SHIFT; + + /* Set the bus width */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = + +From 6177fc8dc11d1e50040c306c0171b7c42bde4bbf Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 16:44:05 +0200 +Subject: [PATCH 087/111] bcm2835-i2s: get base address for DMA from devicetree + +Code copied from spi-bcm2835. Get physical address from devicetree +instead of using hardcoded constant. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 3303d5f58082f68b68b535b2bdf7ce8d14cafcc4..0f25db4cd198c0a511e8a205b0cb2be62ba94adf 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -158,10 +159,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { + #define BCM2835_I2S_INT_RXR BIT(1) + #define BCM2835_I2S_INT_TXW BIT(0) + +-/* I2S DMA interface */ +-/* FIXME: Needs IOMMU support */ +-#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) +- + /* General device struct */ + struct bcm2835_i2s_dev { + struct device *dev; +@@ -791,6 +788,15 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + int ret; + struct regmap *regmap[2]; + struct resource *mem[2]; ++ const __be32 *addr; ++ dma_addr_t dma_reg_base; ++ ++ addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); ++ if (!addr) { ++ dev_err(&pdev->dev, "could not get DMA-register address\n"); ++ return -ENODEV; ++ } ++ dma_reg_base = be32_to_cpup(addr); + + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { +@@ -817,12 +823,10 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + + /* Set the DMA address */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = +- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG +- + BCM2835_VCMMU_SHIFT; ++ dma_reg_base + BCM2835_I2S_FIFO_A_REG; + + dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = +- (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG +- + BCM2835_VCMMU_SHIFT; ++ dma_reg_base + BCM2835_I2S_FIFO_A_REG; + + /* Set the bus width */ + dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = + +From e985f4747dd5ff6f91e500c50c2de8a9457f583d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:21:16 +0200 +Subject: [PATCH 088/111] bcm2835-i2s: add 24bit support, update bclk_ratio to + more correct values + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit 62c05a0b5328d9376d39c9e74da10b8a2465c234 ("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 + +RPi commit 3e8c672bc4e92d457aa4654bbb4cfd79a18a2327 ("bcm2708-i2s: +Update bclk_ratio to more correct values") + +Discussion about blck_ratio affecting sound quality: +https://github.com/raspberrypi/linux/issues/681 + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 0f25db4cd198c0a511e8a205b0cb2be62ba94adf..0f35d7c0f4026bb50a7223461b907b9797bd9a05 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -340,11 +340,15 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + data_length = 16; +- bclk_ratio = 40; ++ bclk_ratio = 50; ++ break; ++ case SNDRV_PCM_FORMAT_S24_LE: ++ data_length = 24; ++ bclk_ratio = 50; + break; + case SNDRV_PCM_FORMAT_S32_LE: + data_length = 32; +- bclk_ratio = 80; ++ bclk_ratio = 100; + break; + default: + return -EINVAL; +@@ -420,7 +424,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +- if (data_length > 24) ++ if (data_length >= 24) + format |= BCM2835_I2S_CHWEX; + + format |= BCM2835_I2S_CHWID((data_length-8)&0xf); +@@ -711,6 +715,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = { +@@ -718,6 +723,7 @@ static struct snd_soc_dai_driver bcm2835_i2s_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 = &bcm2835_i2s_dai_ops, + +From ab780704d0a48a2d76dcfaca85e980fd0e3f4adc Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:25:51 +0200 +Subject: [PATCH 089/111] bcm2835-i2s: setup clock only if CPU is clock master + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit c14827ecdaa36607f6110f9ce8df96e698672191 ("bcm2708: Allow +option card devices to be configured via DT") + +Original work by Zoltan Szenczi, committed to RPi tree by +Phil Elwell. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 0f35d7c0f4026bb50a7223461b907b9797bd9a05..d5e412302811ed8b007fc53f0aa2b5ddd12774b6 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -411,15 +411,25 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + divf = dividend & BCM2835_CLK_DIVF_MASK; + } + +- /* Set clock divider */ +- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD +- | BCM2835_CLK_DIVI(divi) +- | BCM2835_CLK_DIVF(divf)); +- +- /* Setup clock, but don't start it yet */ +- regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD +- | BCM2835_CLK_MASH(mash) +- | BCM2835_CLK_SRC(clk_src)); ++ /* Clock should only be set up here if CPU is clock master */ ++ switch (dev->fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ case SND_SOC_DAIFMT_CBS_CFM: ++ /* Set clock divider */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, ++ BCM2835_CLK_PASSWD ++ | BCM2835_CLK_DIVI(divi) ++ | BCM2835_CLK_DIVF(divf)); ++ ++ /* Setup clock, but don't start it yet */ ++ regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, ++ BCM2835_CLK_PASSWD ++ | BCM2835_CLK_MASH(mash) ++ | BCM2835_CLK_SRC(clk_src)); ++ break; ++ default: ++ break; ++ } + + /* Setup the frame format */ + format = BCM2835_I2S_CHEN; + +From dd3eeab4f8eea34bceb8b247fb502e86f4f20fdb Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:49:51 +0200 +Subject: [PATCH 090/111] bcm2835-i2s: Eliminate debugfs directory error + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit fd7d7a3dbe9262d16971ef81c234ed28c6499dd7 ("bcm2708: +Eliminate i2s debugfs directory error") + +Qualify the two regmap ranges uses by bcm2708-i2s ('-i2s' and '-clk') +to avoid the name clash when registering debugfs entries. + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index d5e412302811ed8b007fc53f0aa2b5ddd12774b6..2d29050e739b0af02d0f5122d18178b61c024bea 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -782,6 +782,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { + .precious_reg = bcm2835_i2s_precious_reg, + .volatile_reg = bcm2835_i2s_volatile_reg, + .cache_type = REGCACHE_RBTREE, ++ .name = "i2s", + }, + { + .reg_bits = 32, +@@ -790,6 +791,7 @@ static const struct regmap_config bcm2835_regmap_config[] = { + .max_register = BCM2835_CLK_PCMDIV_REG, + .volatile_reg = bcm2835_clk_volatile_reg, + .cache_type = REGCACHE_RBTREE, ++ .name = "clk", }, }; - static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { -+ SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_LINE("Line In Jacks", NULL), -+ SND_SOC_DAPM_MIC("Microphone", NULL), - }; - --/* Corgi machine connections to the codec pins */ - static const struct snd_soc_dapm_route audioinjector_audio_map[] = { -+ /* headphone connected to LHPOUT, RHPOUT */ -+ {"Headphone Jack", NULL, "LHPOUT"}, -+ {"Headphone Jack", NULL, "RHPOUT"}, -+ - /* speaker connected to LOUT, ROUT */ - {"Ext Spk", NULL, "ROUT"}, - {"Ext Spk", NULL, "LOUT"}, - - /* line inputs */ - {"Line In Jacks", NULL, "Line Input"}, -+ -+ /* mic is connected to Mic Jack, with WM8731 Mic Bias */ -+ {"Microphone", NULL, "Mic Bias"}, - }; - - static struct snd_soc_card snd_soc_audioinjector = { - .name = "audioinjector-pi-soundcard", - .dai_link = audioinjector_pi_soundcard_dai, -- .num_links = 1, -+ .num_links = ARRAY_SIZE(audioinjector_pi_soundcard_dai), - - .dapm_widgets = wm8731_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), -From ea1af76f40687d058949b6f06eb174425a99e275 Mon Sep 17 00:00:00 2001 -From: Thomas Kriechbaumer -Date: Fri, 3 Jun 2016 09:40:44 +0200 -Subject: [PATCH 139/141] BCM270X_DT: Add spi-rtc overlay on SPI0.0 +From e59331ce7f065c28e1a50831c8546a96deb5d05d Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:35:20 +0200 +Subject: [PATCH 091/111] bcm2835-i2s: Register PCM device -Initial version only supports PCF2123 RTC. +Code ported from bcm2708-i2s driver in Raspberry Pi tree. -See: https://github.com/raspberrypi/linux/pull/1510 +RPi commit ba46b4935a23aa2caac1855ead52a035d4776680 ("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 + +Signed-off-by: Matthias Reichl --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 +++++ - arch/arm/boot/dts/overlays/spi-rtc-overlay.dts | 33 ++++++++++++++++++++++++++ - 3 files changed, 40 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/spi-rtc-overlay.dts + sound/soc/bcm/bcm2835-i2s.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index ed62846e18e4d3098169f05a1a8ba16caf1619aa..988884db1861a6f1b032e8e88d812e9721e75d26 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -77,6 +77,7 @@ dtbo-$(RPI_DT_OVERLAYS) += smi.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-dev.dtbo - dtbo-$(RPI_DT_OVERLAYS) += smi-nand.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi-gpio35-39.dtbo -+dtbo-$(RPI_DT_OVERLAYS) += spi-rtc.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-1cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-2cs.dtbo - dtbo-$(RPI_DT_OVERLAYS) += spi1-3cs.dtbo -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 628cff3fc60a13b26b3f2f572573884df480c7bf..f105bbc3d55caacfedc346699d96cbc6bc611fce 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -953,6 +953,12 @@ Load: dtoverlay=spi-gpio35-39 - Params: +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 2d29050e739b0af02d0f5122d18178b61c024bea..ce93ef0579ab142c788736f0d309c92636b8983d 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -799,6 +799,25 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + .name = "bcm2835-i2s-comp", + }; - -+Name: spi-rtc -+Info: Adds support for a number of SPI Real Time Clock devices -+Load: dtoverlay=spi-rtc,= -+Params: pcf2123 Select the PCF2123 device -+ -+ - Name: spi1-1cs - Info: Enables spi1 with a single chip select (CS) line and associated spidev - dev node. The gpio pin number for the CS line and spidev device node -diff --git a/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..88d1800d63c9f6727b46d4e590c8e96c671c3755 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi-rtc-overlay.dts -@@ -0,0 +1,33 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&spidev0>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spi0>; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ rtc-pcf2123@0 { -+ compatible = "nxp,rtc-pcf2123"; -+ spi-max-frequency = <5000000>; -+ spi-cs-high = <1>; -+ reg = <0>; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ pcf2123 = <0>, "=0=1"; -+ }; ++static const struct snd_pcm_hardware bcm2835_pcm_hardware = { ++ .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, ++ .periods_min = 2, ++ .periods_max = 255, ++ .buffer_bytes_max = 128 * PAGE_SIZE, +}; ++ ++static const struct snd_dmaengine_pcm_config bcm2835_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &bcm2835_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ + static int bcm2835_i2s_probe(struct platform_device *pdev) + { + struct bcm2835_i2s_dev *dev; +@@ -870,7 +889,9 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + return ret; + } + +- ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, ++ &bcm2835_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); + if (ret) { + dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); + return ret; -From a8f2756b03d610c3fd254452e4babef8f18a4eca Mon Sep 17 00:00:00 2001 +From 0eec3739078dcf418f6804e3df7012f8c87618dd Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 11 Oct 2015 15:55:21 +0200 +Subject: [PATCH 092/111] bcm2835-i2s: Enable MMAP support via a DT property + +Code ported from bcm2708-i2s driver in Raspberry Pi tree. + +RPi commit 7ee829fd77a30127db5d0b3c7d79b8718166e568 ("bcm2708-i2s: +Enable MMAP support via a DT property and overlay") + +The i2s driver used to claim to support MMAP, but that feature was disabled +when some problems were found. Add the ability to enable this feature +through Device Tree, using the i2s-mmap overlay. + +See: #1004 + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/bcm2835-i2s.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index ce93ef0579ab142c788736f0d309c92636b8983d..6f60c2cebb412524bb0e30d0339fe556680e8637 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -799,7 +799,7 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { + .name = "bcm2835-i2s-comp", + }; + +-static const struct snd_pcm_hardware bcm2835_pcm_hardware = { ++static struct snd_pcm_hardware bcm2835_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX, + .formats = SNDRV_PCM_FMTBIT_S16_LE | +@@ -835,6 +835,11 @@ static int bcm2835_i2s_probe(struct platform_device *pdev) + } + dma_reg_base = be32_to_cpup(addr); + ++ if (of_property_read_bool(pdev->dev.of_node, "brcm,enable-mmap")) ++ bcm2835_pcm_hardware.info |= ++ SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID; ++ + /* Request both ioareas */ + for (i = 0; i <= 1; i++) { + void __iomem *base; + +From 5213ee508a24ff0c66e142ffe1fc5a000630dd0e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 21 Apr 2016 15:44:14 +0100 +Subject: [PATCH 093/111] bcm2835-i2s: Reduce the TX DREQ threshold + +TX FIFO overrun is thought to be the cause of channel swapping, so +reducing the DREQ threshold seems reasonable and appears to be +effective. + +See: https://github.com/raspberrypi/linux/issues/1417 + +Signed-off-by: Phil Elwell +--- + sound/soc/bcm/bcm2835-i2s.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 6f60c2cebb412524bb0e30d0339fe556680e8637..b26f9587dec01d62606df3f47b3ef00c908fa05b 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -555,15 +555,22 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + + /* Setup the DMA parameters */ + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, +- BCM2835_I2S_RXTHR(1) +- | BCM2835_I2S_TXTHR(1) +- | BCM2835_I2S_DMAEN, 0xffffffff); ++ BCM2835_I2S_RXTHR(3) ++ | BCM2835_I2S_TXTHR(3) ++ | BCM2835_I2S_DMAEN, ++ BCM2835_I2S_RXTHR(1) ++ | BCM2835_I2S_TXTHR(1) ++ | BCM2835_I2S_DMAEN); + + regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_DREQ_A_REG, +- BCM2835_I2S_TX_PANIC(0x10) +- | BCM2835_I2S_RX_PANIC(0x30) +- | BCM2835_I2S_TX(0x30) +- | BCM2835_I2S_RX(0x20), 0xffffffff); ++ BCM2835_I2S_TX_PANIC(0x7f) ++ | BCM2835_I2S_RX_PANIC(0x7f) ++ | BCM2835_I2S_TX(0x7f) ++ | BCM2835_I2S_RX(0x7f), ++ BCM2835_I2S_TX_PANIC(0x10) ++ | BCM2835_I2S_RX_PANIC(0x30) ++ | BCM2835_I2S_TX(0x20) ++ | BCM2835_I2S_RX(0x20)); + + /* Clear FIFOs */ + bcm2835_i2s_clear_fifos(dev, true, true); + +From 1653c95a0b5cd0bc5e215e74472b1d46cc55735c Mon Sep 17 00:00:00 2001 +From: P33M +Date: Wed, 21 Oct 2015 14:55:21 +0100 +Subject: [PATCH 094/111] rpi_display: add backlight driver and overlay + +Add a mailbox-driven backlight controller for the Raspberry Pi DSI +touchscreen display. Requires updated GPU firmware to recognise the +mailbox request. + +Signed-off-by: Gordon Hollingworth +--- + drivers/video/backlight/Kconfig | 6 ++ + drivers/video/backlight/Makefile | 1 + + drivers/video/backlight/rpi_backlight.c | 119 ++++++++++++++++++++++++++++++++ + 3 files changed, 126 insertions(+) + create mode 100644 drivers/video/backlight/rpi_backlight.c + +diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig +index 5ffa4b4e26c0e874d3f63068456b3d72d8b4beb5..c3023ab052b477dde522a262a360ec312e94de22 100644 +--- a/drivers/video/backlight/Kconfig ++++ b/drivers/video/backlight/Kconfig +@@ -265,6 +265,12 @@ config BACKLIGHT_PWM + If you have a LCD backlight adjustable by PWM, say Y to enable + this driver. + ++config BACKLIGHT_RPI ++ tristate "Raspberry Pi display firmware driven backlight" ++ help ++ If you have the Raspberry Pi DSI touchscreen display, say Y to ++ enable the mailbox-controlled backlight driver. ++ + config BACKLIGHT_DA903X + tristate "Backlight Driver for DA9030/DA9034 using WLED" + depends on PMIC_DA903X +diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile +index 16ec534cff3044209adbae3495c19d97fee3ef73..00eff87fb3391300e78f055fa05d3b9647fa053d 100644 +--- a/drivers/video/backlight/Makefile ++++ b/drivers/video/backlight/Makefile +@@ -50,6 +50,7 @@ obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o + obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o + obj-$(CONFIG_BACKLIGHT_PM8941_WLED) += pm8941-wled.o + obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o ++obj-$(CONFIG_BACKLIGHT_RPI) += rpi_backlight.o + obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o + obj-$(CONFIG_BACKLIGHT_SKY81452) += sky81452-backlight.o + obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o +diff --git a/drivers/video/backlight/rpi_backlight.c b/drivers/video/backlight/rpi_backlight.c +new file mode 100644 +index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd509fcbaad +--- /dev/null ++++ b/drivers/video/backlight/rpi_backlight.c +@@ -0,0 +1,119 @@ ++/* ++ * rpi_bl.c - Backlight controller through VPU ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct rpi_backlight { ++ struct device *dev; ++ struct device *fbdev; ++ struct rpi_firmware *fw; ++}; ++ ++static int rpi_backlight_update_status(struct backlight_device *bl) ++{ ++ struct rpi_backlight *gbl = bl_get_data(bl); ++ int brightness = bl->props.brightness; ++ int ret; ++ ++ if (bl->props.power != FB_BLANK_UNBLANK || ++ bl->props.fb_blank != FB_BLANK_UNBLANK || ++ bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) ++ brightness = 0; ++ ++ ret = rpi_firmware_property(gbl->fw, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT, ++ &brightness, sizeof(brightness)); ++ if (ret) { ++ dev_err(gbl->dev, "Failed to set brightness\n"); ++ return ret; ++ } ++ ++ if (brightness < 0) { ++ dev_err(gbl->dev, "Backlight change failed\n"); ++ return -EAGAIN; ++ } ++ ++ return 0; ++} ++ ++static const struct backlight_ops rpi_backlight_ops = { ++ .options = BL_CORE_SUSPENDRESUME, ++ .update_status = rpi_backlight_update_status, ++}; ++ ++static int rpi_backlight_probe(struct platform_device *pdev) ++{ ++ struct backlight_properties props; ++ struct backlight_device *bl; ++ struct rpi_backlight *gbl; ++ struct device_node *fw_node; ++ ++ gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL); ++ if (gbl == NULL) ++ return -ENOMEM; ++ ++ gbl->dev = &pdev->dev; ++ ++ fw_node = of_parse_phandle(pdev->dev.of_node, "firmware", 0); ++ if (!fw_node) { ++ dev_err(&pdev->dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ gbl->fw = rpi_firmware_get(fw_node); ++ if (!gbl->fw) ++ return -EPROBE_DEFER; ++ ++ memset(&props, 0, sizeof(props)); ++ props.type = BACKLIGHT_RAW; ++ props.max_brightness = 255; ++ bl = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev), ++ &pdev->dev, gbl, &rpi_backlight_ops, ++ &props); ++ if (IS_ERR(bl)) { ++ dev_err(&pdev->dev, "failed to register backlight\n"); ++ return PTR_ERR(bl); ++ } ++ ++ bl->props.brightness = 255; ++ backlight_update_status(bl); ++ ++ platform_set_drvdata(pdev, bl); ++ return 0; ++} ++ ++static const struct of_device_id rpi_backlight_of_match[] = { ++ { .compatible = "raspberrypi,rpi-backlight" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, rpi_backlight_of_match); ++ ++static struct platform_driver rpi_backlight_driver = { ++ .driver = { ++ .name = "rpi-backlight", ++ .of_match_table = of_match_ptr(rpi_backlight_of_match), ++ }, ++ .probe = rpi_backlight_probe, ++}; ++ ++module_platform_driver(rpi_backlight_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth "); ++MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); ++MODULE_LICENSE("GPL"); + +From 81774f735f07a2f7d11977c9fab867ed9911df18 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Tue, 23 Feb 2016 19:56:04 +0000 +Subject: [PATCH 095/111] bcm2835-virtgpio: Virtual GPIO driver + +Add a virtual GPIO driver that uses the firmware mailbox interface to +request that the VPU toggles LEDs. +--- + drivers/gpio/Kconfig | 6 ++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-virt.c | 179 +++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 186 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-virt.c + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index d7860614f87f532caeb21145c78352d38161b2a3..05ca35a0b2c431c39e1b207f560e1b11f118e6fe 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -143,6 +143,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_BCM_VIRT ++ bool "Broadcom Virt GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST) ++ help ++ Turn on virtual GPIO support for Broadcom BCM283X chips. ++ + config GPIO_BRCMSTB + tristate "BRCMSTB GPIO support" + default y if (ARCH_BRCMSTB || BMIPS_GENERIC) +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index 991598ea3fba09ee9e5724a11f41666d5a95f085..281648f98f5e65baa293719fd48e3f01e62926f0 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o + obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o + obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o ++obj-$(CONFIG_GPIO_BCM_VIRT) += gpio-bcm-virt.o + obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o + obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +diff --git a/drivers/gpio/gpio-bcm-virt.c b/drivers/gpio/gpio-bcm-virt.c +new file mode 100644 +index 0000000000000000000000000000000000000000..f3e0f1620b979e4fa3c7e556eb785ac259d8cfc4 +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-virt.c +@@ -0,0 +1,179 @@ ++/* ++ * brcmvirt GPIO driver ++ * ++ * Copyright (C) 2012,2013 Dom Cobley ++ * Based on gpio-clps711x.c by Alexander Shiyan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "brcmvirt-gpio" ++#define NUM_GPIO 2 ++ ++struct brcmvirt_gpio { ++ struct gpio_chip gc; ++ u32 __iomem *ts_base; ++ /* two packed 16-bit counts of enabled and disables ++ Allows host to detect a brief enable that was missed */ ++ u32 enables_disables[NUM_GPIO]; ++}; ++ ++static int brcmvirt_gpio_dir_in(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return -EINVAL; ++} ++ ++static int brcmvirt_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ return 0; ++} ++ ++static int brcmvirt_gpio_get(struct gpio_chip *gc, unsigned off) ++{ ++ struct brcmvirt_gpio *gpio; ++ unsigned v; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ v = readl(gpio->ts_base + off); ++ return (v >> off) & 1; ++} ++ ++static void brcmvirt_gpio_set(struct gpio_chip *gc, unsigned off, int val) ++{ ++ struct brcmvirt_gpio *gpio; ++ u16 enables, disables; ++ s16 diff; ++ bool lit; ++ gpio = container_of(gc, struct brcmvirt_gpio, gc); ++ enables = gpio->enables_disables[off] >> 16; ++ disables = gpio->enables_disables[off] >> 0; ++ diff = (s16)(enables - disables); ++ lit = diff > 0; ++ if ((val && lit) || (!val && !lit)) ++ return; ++ if (val) ++ enables++; ++ else ++ disables++; ++ diff = (s16)(enables - disables); ++ BUG_ON(diff != 0 && diff != 1); ++ gpio->enables_disables[off] = (enables << 16) | (disables << 0); ++ writel(gpio->enables_disables[off], gpio->ts_base + off); ++} ++ ++static int brcmvirt_gpio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmvirt_gpio *ucb; ++ u32 gpiovirtbuf; ++ int err = 0; ++ ++ fw_node = of_parse_phandle(np, "firmware", 0); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ err = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, ++ &gpiovirtbuf, sizeof(gpiovirtbuf)); ++ ++ if (err) { ++ dev_err(dev, "Failed to get gpiovirtbuf\n"); ++ goto err; ++ } ++ ++ if (!gpiovirtbuf) { ++ dev_err(dev, "No virtgpio buffer\n"); ++ err = -ENOENT; ++ goto err; ++ } ++ ++ ucb = devm_kzalloc(dev, sizeof *ucb, GFP_KERNEL); ++ if (!ucb) { ++ err = -EINVAL; ++ goto err; ++ } ++ ++ // mmap the physical memory ++ gpiovirtbuf &= ~0xc0000000; ++ ucb->ts_base = ioremap(gpiovirtbuf, 4096); ++ if (ucb->ts_base == NULL) { ++ dev_err(dev, "Failed to map physical address\n"); ++ err = -ENOENT; ++ goto err; ++ } ++ ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ //ucb->gc.dev = dev; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 100; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmvirt_gpio_dir_in; ++ ucb->gc.direction_output = brcmvirt_gpio_dir_out; ++ ucb->gc.get = brcmvirt_gpio_get; ++ ucb->gc.set = brcmvirt_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ goto err; ++ ++ platform_set_drvdata(pdev, ucb); ++ ++err: ++ return err; ++ ++} ++ ++static int brcmvirt_gpio_remove(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct brcmvirt_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); ++ iounmap(ucb->ts_base); ++ return err; ++} ++ ++static const struct of_device_id __maybe_unused brcmvirt_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-virtgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmvirt_gpio_ids); ++ ++static struct platform_driver brcmvirt_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmvirt_gpio_ids), ++ }, ++ .probe = brcmvirt_gpio_probe, ++ .remove = brcmvirt_gpio_remove, ++}; ++module_platform_driver(brcmvirt_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dom Cobley "); ++MODULE_DESCRIPTION("brcmvirt GPIO driver"); ++MODULE_ALIAS("platform:brcmvirt-gpio"); + +From 064af96e705f3ff93567cac0465bf928bf33ae41 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 4 Mar 2016 12:49:09 +0000 +Subject: [PATCH 096/111] DRM_VC4: Allow to be built for ARCH_BCM270x + +--- + drivers/gpu/drm/vc4/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig +index e53df59cb139f25f8e6ae916bca93abf0c49e063..f6e938208b73512f20eab46a383ca91bf675a845 100644 +--- a/drivers/gpu/drm/vc4/Kconfig ++++ b/drivers/gpu/drm/vc4/Kconfig +@@ -1,6 +1,6 @@ + config DRM_VC4 + tristate "Broadcom VC4 Graphics" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on DRM + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + +From 4b2c5bb334b191e1aa5b7b96c298e743c3e3cf37 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 23 Feb 2016 17:26:48 +0000 +Subject: [PATCH 097/111] amba_pl011: Don't use DT aliases for numbering + +The pl011 driver looks for DT aliases of the form "serial", +and if found uses as the device ID. This can cause +/dev/ttyAMA0 to become /dev/ttyAMA1, which is confusing if the +other serial port is provided by the 8250 driver which doesn't +use the same logic. +--- + drivers/tty/serial/amba-pl011.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 1b7331e40d795e1ec5482d6a82871bd5ce050b60..a04d27ef682792808301ac2d2bfb67d5802fd7e3 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -2414,7 +2414,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, + if (IS_ERR(base)) + return PTR_ERR(base); + ++ /* Don't use DT serial aliases - it causes the device to ++ be renumbered to ttyAMA1 if it is the second serial port in the ++ system, even though the other one is ttyS0. The 8250 driver ++ doesn't use this logic, so always remains ttyS0. + index = pl011_probe_dt_alias(index, dev); ++ */ + + uap->old_cr = 0; + uap->port.dev = dev; + +From 082aed07db3aa644e700e6356da328303db9bba2 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou +Date: Wed, 3 Dec 2014 13:23:28 +0200 +Subject: [PATCH 098/111] OF: DT-Overlay configfs interface + +This is a port of Pantelis Antoniou's v3 port that makes use of the +new upstreamed configfs support for binary attributes. + +Original commit message: + +Add a runtime interface to using configfs for generic device tree overlay +usage. With it its possible to use device tree overlays without having +to use a per-platform overlay manager. + +Please see Documentation/devicetree/configfs-overlays.txt for more info. + +Changes since v2: +- Removed ifdef CONFIG_OF_OVERLAY (since for now it's required) +- Created a documentation entry +- Slight rewording in Kconfig + +Changes since v1: +- of_resolve() -> of_resolve_phandles(). + +Originally-signed-off-by: Pantelis Antoniou +Signed-off-by: Phil Elwell + +DT configfs: Fix build errors on other platforms + +Signed-off-by: Phil Elwell + +DT configfs: fix build error + +There is an error when compiling rpi-4.6.y branch: + CC drivers/of/configfs.o +drivers/of/configfs.c:291:21: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] + .default_groups = of_cfs_def_groups, + ^ +drivers/of/configfs.c:291:21: note: (near initialization for 'of_cfs_subsys.su_group.default_groups.next') + +The .default_groups is linked list since commit +1ae1602de028acaa42a0f6ff18d19756f8e825c6. +This commit uses configfs_add_default_group to fix this problem. + +Signed-off-by: Slawomir Stepien +--- + Documentation/devicetree/configfs-overlays.txt | 31 +++ + drivers/of/Kconfig | 7 + + drivers/of/Makefile | 1 + + drivers/of/configfs.c | 311 +++++++++++++++++++++++++ + 4 files changed, 350 insertions(+) + create mode 100644 Documentation/devicetree/configfs-overlays.txt + create mode 100644 drivers/of/configfs.c + +diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt +new file mode 100644 +index 0000000000000000000000000000000000000000..5fa43e0643072c7963daddc18cec7772910378ad +--- /dev/null ++++ b/Documentation/devicetree/configfs-overlays.txt +@@ -0,0 +1,31 @@ ++Howto use the configfs overlay interface. ++ ++A device-tree configfs entry is created in /config/device-tree/overlays ++and and it is manipulated using standard file system I/O. ++Note that this is a debug level interface, for use by developers and ++not necessarily something accessed by normal users due to the ++security implications of having direct access to the kernel's device tree. ++ ++* To create an overlay you mkdir the directory: ++ ++ # mkdir /config/device-tree/overlays/foo ++ ++* Either you echo the overlay firmware file to the path property file. ++ ++ # echo foo.dtbo >/config/device-tree/overlays/foo/path ++ ++* Or you cat the contents of the overlay to the dtbo file ++ ++ # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo ++ ++The overlay file will be applied, and devices will be created/destroyed ++as required. ++ ++To remove it simply rmdir the directory. ++ ++ # rmdir /config/device-tree/overlays/foo ++ ++The rationalle of the dual interface (firmware & direct copy) is that each is ++better suited to different use patterns. The firmware interface is what's ++intended to be used by hardware managers in the kernel, while the copy interface ++make sense for developers (since it avoids problems with namespaces). +diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig +index b3bec3aaa45d8a34dd206593fec0c13271034b07..4d9a6ba4c8bed537b41a4ff80600c89d775a1e29 100644 +--- a/drivers/of/Kconfig ++++ b/drivers/of/Kconfig +@@ -115,4 +115,11 @@ config OF_OVERLAY + config OF_NUMA + bool + ++config OF_CONFIGFS ++ bool "Device Tree Overlay ConfigFS interface" ++ select CONFIGFS_FS ++ select OF_OVERLAY ++ help ++ Enable a simple user-space driven DT overlay interface. ++ + endif # OF +diff --git a/drivers/of/Makefile b/drivers/of/Makefile +index d7efd9d458aab4554139e93c72a1688aa0eeef6a..aa5ef9dd1fedc14d4ae2d363818fc160df51bad9 100644 +--- a/drivers/of/Makefile ++++ b/drivers/of/Makefile +@@ -1,4 +1,5 @@ + obj-y = base.o device.o platform.o ++obj-$(CONFIG_OF_CONFIGFS) += configfs.o + obj-$(CONFIG_OF_DYNAMIC) += dynamic.o + obj-$(CONFIG_OF_FLATTREE) += fdt.o + obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o +diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b6ea6cad7 +--- /dev/null ++++ b/drivers/of/configfs.c +@@ -0,0 +1,311 @@ ++/* ++ * Configfs entries for device-tree ++ * ++ * Copyright (C) 2013 - Pantelis Antoniou ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "of_private.h" ++ ++struct cfs_overlay_item { ++ struct config_item item; ++ ++ char path[PATH_MAX]; ++ ++ const struct firmware *fw; ++ struct device_node *overlay; ++ int ov_id; ++ ++ void *dtbo; ++ int dtbo_size; ++}; ++ ++static int create_overlay(struct cfs_overlay_item *overlay, void *blob) ++{ ++ int err; ++ ++ /* unflatten the tree */ ++ of_fdt_unflatten_tree(blob, NULL, &overlay->overlay); ++ if (overlay->overlay == NULL) { ++ pr_err("%s: failed to unflatten tree\n", __func__); ++ err = -EINVAL; ++ goto out_err; ++ } ++ pr_debug("%s: unflattened OK\n", __func__); ++ ++ /* mark it as detached */ ++ of_node_set_flag(overlay->overlay, OF_DETACHED); ++ ++ /* perform resolution */ ++ err = of_resolve_phandles(overlay->overlay); ++ if (err != 0) { ++ pr_err("%s: Failed to resolve tree\n", __func__); ++ goto out_err; ++ } ++ pr_debug("%s: resolved OK\n", __func__); ++ ++ err = of_overlay_create(overlay->overlay); ++ if (err < 0) { ++ pr_err("%s: Failed to create overlay (err=%d)\n", ++ __func__, err); ++ goto out_err; ++ } ++ overlay->ov_id = err; ++ ++out_err: ++ return err; ++} ++ ++static inline struct cfs_overlay_item *to_cfs_overlay_item( ++ struct config_item *item) ++{ ++ return item ? container_of(item, struct cfs_overlay_item, item) : NULL; ++} ++ ++static ssize_t cfs_overlay_item_path_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ return sprintf(page, "%s\n", overlay->path); ++} ++ ++static ssize_t cfs_overlay_item_path_store(struct config_item *item, ++ const char *page, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ const char *p = page; ++ char *s; ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy to path buffer (and make sure it's always zero terminated */ ++ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); ++ overlay->path[sizeof(overlay->path) - 1] = '\0'; ++ ++ /* strip trailing newlines */ ++ s = overlay->path + strlen(overlay->path); ++ while (s > overlay->path && *--s == '\n') ++ *s = '\0'; ++ ++ pr_debug("%s: path is '%s'\n", __func__, overlay->path); ++ ++ err = request_firmware(&overlay->fw, overlay->path, NULL); ++ if (err != 0) ++ goto out_err; ++ ++ err = create_overlay(overlay, (void *)overlay->fw->data); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ ++ release_firmware(overlay->fw); ++ overlay->fw = NULL; ++ ++ overlay->path[0] = '\0'; ++ return err; ++} ++ ++static ssize_t cfs_overlay_item_status_show(struct config_item *item, ++ char *page) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ return sprintf(page, "%s\n", ++ overlay->ov_id >= 0 ? "applied" : "unapplied"); ++} ++ ++CONFIGFS_ATTR(cfs_overlay_item_, path); ++CONFIGFS_ATTR_RO(cfs_overlay_item_, status); ++ ++static struct configfs_attribute *cfs_overlay_attrs[] = { ++ &cfs_overlay_item_attr_path, ++ &cfs_overlay_item_attr_status, ++ NULL, ++}; ++ ++ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, ++ void *buf, size_t max_count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ pr_debug("%s: buf=%p max_count=%zu\n", __func__, ++ buf, max_count); ++ ++ if (overlay->dtbo == NULL) ++ return 0; ++ ++ /* copy if buffer provided */ ++ if (buf != NULL) { ++ /* the buffer must be large enough */ ++ if (overlay->dtbo_size > max_count) ++ return -ENOSPC; ++ ++ memcpy(buf, overlay->dtbo, overlay->dtbo_size); ++ } ++ ++ return overlay->dtbo_size; ++} ++ ++ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, ++ const void *buf, size_t count) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ int err; ++ ++ /* if it's set do not allow changes */ ++ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) ++ return -EPERM; ++ ++ /* copy the contents */ ++ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); ++ if (overlay->dtbo == NULL) ++ return -ENOMEM; ++ ++ overlay->dtbo_size = count; ++ ++ err = create_overlay(overlay, overlay->dtbo); ++ if (err != 0) ++ goto out_err; ++ ++ return count; ++ ++out_err: ++ kfree(overlay->dtbo); ++ overlay->dtbo = NULL; ++ overlay->dtbo_size = 0; ++ ++ return err; ++} ++ ++CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); ++ ++static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { ++ &cfs_overlay_item_attr_dtbo, ++ NULL, ++}; ++ ++static void cfs_overlay_release(struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ if (overlay->ov_id >= 0) ++ of_overlay_destroy(overlay->ov_id); ++ if (overlay->fw) ++ release_firmware(overlay->fw); ++ /* kfree with NULL is safe */ ++ kfree(overlay->dtbo); ++ kfree(overlay); ++} ++ ++static struct configfs_item_operations cfs_overlay_item_ops = { ++ .release = cfs_overlay_release, ++}; ++ ++static struct config_item_type cfs_overlay_type = { ++ .ct_item_ops = &cfs_overlay_item_ops, ++ .ct_attrs = cfs_overlay_attrs, ++ .ct_bin_attrs = cfs_overlay_bin_attrs, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct config_item *cfs_overlay_group_make_item( ++ struct config_group *group, const char *name) ++{ ++ struct cfs_overlay_item *overlay; ++ ++ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); ++ if (!overlay) ++ return ERR_PTR(-ENOMEM); ++ overlay->ov_id = -1; ++ ++ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); ++ return &overlay->item; ++} ++ ++static void cfs_overlay_group_drop_item(struct config_group *group, ++ struct config_item *item) ++{ ++ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); ++ ++ config_item_put(&overlay->item); ++} ++ ++static struct configfs_group_operations overlays_ops = { ++ .make_item = cfs_overlay_group_make_item, ++ .drop_item = cfs_overlay_group_drop_item, ++}; ++ ++static struct config_item_type overlays_type = { ++ .ct_group_ops = &overlays_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++static struct configfs_group_operations of_cfs_ops = { ++ /* empty - we don't allow anything to be created */ ++}; ++ ++static struct config_item_type of_cfs_type = { ++ .ct_group_ops = &of_cfs_ops, ++ .ct_owner = THIS_MODULE, ++}; ++ ++struct config_group of_cfs_overlay_group; ++ ++static struct configfs_subsystem of_cfs_subsys = { ++ .su_group = { ++ .cg_item = { ++ .ci_namebuf = "device-tree", ++ .ci_type = &of_cfs_type, ++ }, ++ }, ++ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), ++}; ++ ++static int __init of_cfs_init(void) ++{ ++ int ret; ++ ++ pr_info("%s\n", __func__); ++ ++ config_group_init(&of_cfs_subsys.su_group); ++ config_group_init_type_name(&of_cfs_overlay_group, "overlays", ++ &overlays_type); ++ configfs_add_default_group(&of_cfs_overlay_group, ++ &of_cfs_subsys.su_group); ++ ++ ret = configfs_register_subsystem(&of_cfs_subsys); ++ if (ret != 0) { ++ pr_err("%s: failed to register subsys\n", __func__); ++ goto out; ++ } ++ pr_info("%s: OK\n", __func__); ++out: ++ return ret; ++} ++late_initcall(of_cfs_init); + +From 68e731d04d752b18a9ea4390ad44877db907a15e Mon Sep 17 00:00:00 2001 +From: Cheong2K +Date: Fri, 26 Feb 2016 18:20:10 +0800 +Subject: [PATCH 099/111] brcm: adds support for BCM43341 wifi + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 ++ + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index 67e69bff2545f442c95d80726cbe6ed16584e80d..ea66454a3d7444f51827964aea01bf7573f2b473 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -603,6 +603,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); ++BRCMF_FW_NVRAM_DEF(43341, "brcmfmac43341-sdio.bin", "brcmfmac43341-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); + BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); + BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); +@@ -620,6 +621,7 @@ static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), ++ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43341), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), +diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +index 699f2c2782ee9d898a25c95e0c5d45744d0777ff..15598b3687a213d8c00d45965a6b9351759f47fc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -35,6 +35,7 @@ + #define BRCM_CC_4330_CHIP_ID 0x4330 + #define BRCM_CC_4334_CHIP_ID 0x4334 + #define BRCM_CC_43340_CHIP_ID 43340 ++#define BRCM_CC_43341_CHIP_ID 43341 + #define BRCM_CC_43362_CHIP_ID 43362 + #define BRCM_CC_4335_CHIP_ID 0x4335 + #define BRCM_CC_4339_CHIP_ID 0x4339 + +From f73574193c7e04c75ce884a9846af4ebbda4fa6f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 9 Mar 2016 17:25:59 +0000 +Subject: [PATCH 100/111] brcmfmac: Disable power management + +Disable wireless power saving in the brcmfmac WLAN driver. This is a +temporary measure until the connectivity loss resulting from power +saving is resolved. + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 62f475e31077ca1fa1df15863f02ee0911c46997..d001128266f462beee5f9672c64ed2c0d9200334 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2699,6 +2699,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ ++ pr_info("power management disabled\n"); ++ enabled = false; + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { + + +From 089cba52a9de814bc56c71d41d4e8bc8a3b6d54e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 28 Apr 2016 17:13:47 +0100 +Subject: [PATCH 101/111] brcmfmac: Use original country code as a fallback + +Commit 73345fd212980d2e28a5c6d83801c903bd773680: + + brcmfmac: Configure country code using device specific settings + +prevents region codes from working on devices that lack a region code +translation table. In the event of an absent table, preserve the old +behaviour of using the provided code as-is. + +Signed-off-by: Phil Elwell +--- + .../wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index d001128266f462beee5f9672c64ed2c0d9200334..90eb79cc104427597046f2459e6f46de09702784 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6597,12 +6597,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + struct brcmfmac_pd_cc *country_codes; + struct brcmfmac_pd_cc_entry *cc; + s32 found_index; ++ char ccode[BRCMF_COUNTRY_BUF_SZ]; ++ int rev; + int i; + ++ memcpy(ccode, alpha2, sizeof(ccode)); ++ rev = -1; ++ + country_codes = drvr->settings->country_codes; + if (!country_codes) { +- brcmf_dbg(TRACE, "No country codes configured for device\n"); +- return -EINVAL; ++ brcmf_dbg(TRACE, "No country codes configured for device" ++ " - use requested value\n"); ++ goto use_input_value; + } + + if ((alpha2[0] == ccreq->country_abbrev[0]) && +@@ -6626,10 +6632,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], + brcmf_dbg(TRACE, "No country code match found\n"); + return -EINVAL; + } +- memset(ccreq, 0, sizeof(*ccreq)); +- ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev); +- memcpy(ccreq->ccode, country_codes->table[found_index].cc, ++ rev = country_codes->table[found_index].rev; ++ memcpy(ccode, country_codes->table[found_index].cc, + BRCMF_COUNTRY_BUF_SZ); ++ ++use_input_value: ++ memset(ccreq, 0, sizeof(*ccreq)); ++ ccreq->rev = cpu_to_le32(rev); ++ memcpy(ccreq->ccode, ccode, sizeof(ccode)); + ccreq->country_abbrev[0] = alpha2[0]; + ccreq->country_abbrev[1] = alpha2[1]; + ccreq->country_abbrev[2] = 0; + +From 3a98d12b8d4ca8989dfb0ef12bd866251b5bc592 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 19 May 2016 15:36:09 +0100 +Subject: [PATCH 102/111] brcmfmac: Plug memory leak in brcmf_fill_bss_param + +See: https://github.com/raspberrypi/linux/issues/1471 + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 90eb79cc104427597046f2459e6f46de09702784..27a59a9f7b9c108e728bdc7fc8d95139daec03fc 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2473,7 +2473,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) + WL_BSS_INFO_MAX); + if (err) { + brcmf_err("Failed to get bss info (%d)\n", err); +- return; ++ goto out_err; + } + si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); + si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); +@@ -2485,6 +2485,9 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) + si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; ++ ++out_err: ++ kfree(buf); + } + + static s32 + +From 7162955f6e9b7b838a3bf8bbe681f819024cecd7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 17 Dec 2015 13:37:07 +0000 +Subject: [PATCH 103/111] hci_h5: Don't send conf_req when ACTIVE + +Without this patch, a modem and kernel can continuously bombard each +other with conf_req and conf_rsp messages, in a demented game of tag. +--- + drivers/bluetooth/hci_h5.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index 0879d64b1caf58afb6e5d494c07d9ab7e7cdf983..5161ab30fd533d50f516bb93d5b9f402422e2974 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -310,7 +310,8 @@ static void h5_handle_internal_rx(struct hci_uart *hu) + h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_req, 2) == 0) { + h5_link_control(hu, conf_rsp, 2); +- h5_link_control(hu, conf_req, 3); ++ if (h5->state != H5_ACTIVE) ++ h5_link_control(hu, conf_req, 3); + } else if (memcmp(data, conf_rsp, 2) == 0) { + if (H5_HDR_LEN(hdr) > 2) + h5->tx_win = (data[2] & 0x07); + +From 081af7570d4772f38c75f3ecb6b851a0615b8c61 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Fri, 22 Jan 2016 13:06:39 -0800 +Subject: [PATCH 104/111] drm/vc4: Add a debugfs node for tracking execution + state. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + + drivers/gpu/drm/vc4/vc4_drv.h | 1 + + drivers/gpu/drm/vc4/vc4_gem.c | 14 ++++++++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c +index 245115d49c46a1244ef3e460a03fde397f763de8..94f2154c3685255e2e67d225f77dea372eae371a 100644 +--- a/drivers/gpu/drm/vc4/vc4_debugfs.c ++++ b/drivers/gpu/drm/vc4/vc4_debugfs.c +@@ -18,6 +18,7 @@ + static const struct drm_info_list vc4_debugfs_list[] = { + {"bo_stats", vc4_bo_stats_debugfs, 0}, + {"dpi_regs", vc4_dpi_debugfs_regs, 0}, ++ {"gem_exec", vc4_gem_exec_debugfs, 0}, + {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, + {"hvs_regs", vc4_hvs_debugfs_regs, 0}, + {"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0}, +diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h +index 37cac59401d734e047f4cf41cc6a9ecb5bfc6dbc..4a44e727369fe0dd4e2b421ce139e434cd71001e 100644 +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -445,6 +445,7 @@ void vc4_job_handle_completed(struct vc4_dev *vc4); + int vc4_queue_seqno_cb(struct drm_device *dev, + struct vc4_seqno_cb *cb, uint64_t seqno, + void (*func)(struct vc4_seqno_cb *cb)); ++int vc4_gem_exec_debugfs(struct seq_file *m, void *arg); + + /* vc4_hdmi.c */ + extern struct platform_driver vc4_hdmi_driver; +diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c +index 46899d6de6753c28c7ca6c721119a28d72792148..cbb1bc0b0db88f1c83ce3a630b2efe67a6995456 100644 +--- a/drivers/gpu/drm/vc4/vc4_gem.c ++++ b/drivers/gpu/drm/vc4/vc4_gem.c +@@ -32,6 +32,20 @@ + #include "vc4_regs.h" + #include "vc4_trace.h" + ++#ifdef CONFIG_DEBUG_FS ++int vc4_gem_exec_debugfs(struct seq_file *m, void *unused) ++{ ++ struct drm_info_node *node = (struct drm_info_node *)m->private; ++ struct drm_device *dev = node->minor->dev; ++ struct vc4_dev *vc4 = to_vc4_dev(dev); ++ ++ seq_printf(m, "Emitted seqno: 0x%016llx\n", vc4->emit_seqno); ++ seq_printf(m, "Finished seqno: 0x%016llx\n", vc4->finished_seqno); ++ ++ return 0; ++} ++#endif /* CONFIG_DEBUG_FS */ ++ + static void + vc4_queue_hangcheck(struct drm_device *dev) + { + +From 27166f5ae197a2c23959a7eff08adc65f64588ee Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 25 Jan 2016 13:03:33 -0800 +Subject: [PATCH 105/111] drm/vc4: Include vc4_drm.h in uapi in downstream + build. + +Signed-off-by: Eric Anholt +--- + include/uapi/drm/Kbuild | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild +index 9355dd8eff3ba39401dfe37e7fbf7737f0397f11..68828bf586f05a8d9b0a6ab409ee91a700e3d296 100644 +--- a/include/uapi/drm/Kbuild ++++ b/include/uapi/drm/Kbuild +@@ -15,6 +15,7 @@ header-y += radeon_drm.h + header-y += savage_drm.h + header-y += sis_drm.h + header-y += tegra_drm.h ++header-y += vc4_drm.h + header-y += via_drm.h + header-y += vmwgfx_drm.h + header-y += msm_drm.h + +From 6546a741d421620b3f6ceaa3d205bc44f2664f31 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 30 Mar 2016 17:23:15 +0100 +Subject: [PATCH 106/111] cpufreq: Temporarily ignore io_is_busy=1 + +To speed testing of the new sdhost driver that adapts to changes in +core_freq, hack the on-demand governor to treat io_is_busy=1 as +io_is_busy=0. The io_is_busy feature can still be forced using +io_is_busy=2. + +Signed-off-by: Phil Elwell +--- + drivers/cpufreq/cpufreq_ondemand.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c +index 300163430516766d56b842d8d12dc33175eee66b..9ab7b40005cb7ddfafc3917dc874eea8bdd5ad04 100644 +--- a/drivers/cpufreq/cpufreq_ondemand.c ++++ b/drivers/cpufreq/cpufreq_ondemand.c +@@ -217,7 +217,12 @@ static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf, + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; +- dbs_data->io_is_busy = !!input; ++ // XXX temporary hack ++ if (input > 1) ++ input = 1; ++ else ++ input = 0; ++ dbs_data->io_is_busy = input; + + /* we need to re-evaluate prev_cpu_idle */ + gov_update_cpu_data(dbs_data); + +From b3b6562bdf13284b9a7d129bed5400853735dd0e Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Wed, 14 Oct 2015 11:32:14 -0700 +Subject: [PATCH 107/111] drm/vc4: Force HDMI to connected. + +For some reason on the downstream tree, the HPD GPIO isn't working. + +Signed-off-by: Eric Anholt +--- + drivers/gpu/drm/vc4/vc4_hdmi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c +index fd2644d231ff867a4409840eba7f8234a4a1faba..ed9c5274d06a215331aee44da1f7214a0e1f6e28 100644 +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -166,6 +166,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) + struct drm_device *dev = connector->dev; + struct vc4_dev *vc4 = to_vc4_dev(dev); + ++ return connector_status_connected; ++ + if (vc4->hdmi->hpd_gpio) { + if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^ + vc4->hdmi->hpd_active_low) + +From 2ab2541de11bd82a0f0a2e33c1da98cfba1cc268 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Tue, 19 Apr 2016 15:55:02 -0700 +Subject: [PATCH 108/111] ARM: bcm2708: Enable building power domain driver. + +Signed-off-by: Eric Anholt +--- + drivers/soc/bcm/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig +index 3066edea184d765a670ded0cead470597654abc1..e23518142ceac6651641cc30c327d60dded319d5 100644 +--- a/drivers/soc/bcm/Kconfig ++++ b/drivers/soc/bcm/Kconfig +@@ -1,6 +1,6 @@ + config RASPBERRYPI_POWER + bool "Raspberry Pi power domain driver" +- depends on ARCH_BCM2835 || COMPILE_TEST ++ depends on ARCH_BCM2835 || ARCH_BCM2708 || ARCH_BCM2709 || COMPILE_TEST + depends on RASPBERRYPI_FIRMWARE=y + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM + +From 65dc3c63bb358171b0cff73177a563b2d5b22059 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 140/141] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 109/111] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -137031,42 +134677,75 @@ See: https://github.com/raspberrypi/linux/pull/1510 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c -index da27738b12428eaac52771cfc62261995d1aa58e..3164be24eba3c123ea8cc49f16d409ea1de9e605 100644 +index f22e060709e547528b29b747f796b45c445d23fa..76b7bd7d9d33a0dcefcdb5fe3e0df4ded087cb60 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c -@@ -475,3 +475,4 @@ MODULE_AUTHOR("Chris Verges "); +@@ -471,3 +471,4 @@ module_spi_driver(pcf2123_driver); + MODULE_AUTHOR("Chris Verges "); MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); MODULE_LICENSE("GPL"); - MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("spi:rtc-pcf2123"); -From 138aa92a761eb5d1c41460a167aef1b3c8282d97 Mon Sep 17 00:00:00 2001 +From fd34a5c7e7d87ead50d299aea015bd7483d88a7c Mon Sep 17 00:00:00 2001 From: Phil Elwell -Date: Thu, 23 Jun 2016 16:37:46 +0100 -Subject: [PATCH 141/141] mmc: Apply ERASE_BROKEN quirks correctly +Date: Fri, 1 Jul 2016 22:09:24 +0100 +Subject: [PATCH 110/111] spi-bcm2835: Disable forced software CS + +Select software CS in bcm2708_common.dtsi, and disable the automatic +conversion in the driver to allow hardware CS to be re-enabled with an +overlay. + +See: https://github.com/raspberrypi/linux/issues/1547 Signed-off-by: Phil Elwell --- - drivers/mmc/card/block.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) + drivers/spi/spi-bcm2835.c | 2 ++ + 1 file changed, 2 insertions(+) -diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 9ce8676ff613f5e63503f8280afd6d73ce9dca60..e30060827dce0af390be65e4e170368652f27983 100644 ---- a/drivers/mmc/card/block.c -+++ b/drivers/mmc/card/block.c -@@ -2543,12 +2543,9 @@ static const struct mmc_fixup blk_fixups[] = - * On some Kingston SD cards, multiple erases of less than 64 - * sectors can cause corruption. - */ -- MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -- MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -- MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk_mmc, -- MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), -+ MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN), +diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c +index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2cef9121bf 100644 +--- a/drivers/spi/spi-bcm2835.c ++++ b/drivers/spi/spi-bcm2835.c +@@ -707,6 +707,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) + return -EINVAL; + } - END_FIXUP - }; ++#if 0 + /* now translate native cs to GPIO */ + /* first look for chip select pins in the devices pin groups */ + for (pingroup_index = 0; +@@ -756,6 +757,7 @@ static int bcm2835_spi_setup(struct spi_device *spi) + spi->chip_select, spi->cs_gpio, err); + return err; + } ++#endif + + return 0; + } + +From 3758f08ddbd97dd81fad915d20b11aa9e48bd769 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Mon, 25 Jul 2016 17:06:50 +0100 +Subject: [PATCH 111/111] iqaudio-dac: Compile fix - untested + +--- + sound/soc/bcm/iqaudio-dac.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c +index 4e8e6dec14bcf4a1ff286c43742d4097249d6777..aa15bc4b49ca95edec905fddd8fd0a6d839ca627 100644 +--- a/sound/soc/bcm/iqaudio-dac.c ++++ b/sound/soc/bcm/iqaudio-dac.c +@@ -76,7 +76,11 @@ static void snd_rpi_iqaudio_gpio_unmute(struct snd_soc_card *card) + static int snd_rpi_iqaudio_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) + { +- struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ struct snd_soc_pcm_runtime *rtd; ++ struct snd_soc_dai *codec_dai; ++ ++ rtd = snd_soc_get_pcm_runtime(card, card->dai_link[0].name); ++ codec_dai = rtd->codec_dai; + + if (dapm->dev != codec_dai->dev) + return 0;