diff --git a/projects/RPi/patches/linux/linux-01-RPi_support.patch b/projects/RPi/patches/linux/linux-01-RPi_support.patch index 89c4e92c6e..4ad8d9e7eb 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 6a180236dca8c8347cc51a4b12ca30672340d8cb Mon Sep 17 00:00:00 2001 +From 1271997cdba2766c8e9776d4b5f3cfe6bfa3cba2 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Thu, 19 Feb 2015 18:47:12 +0000 -Subject: [PATCH 001/216] smsx95xx: fix crimes against truesize +Subject: [PATCH 001/150] 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. @@ -13,7 +13,7 @@ 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 831aa33d078ae7d2dd57fdded5de71d1eb915f99..b77935bded8c0ff7808b00f170ff10e594300ad0 100644 +index 5f19fb0f025d9449d0ba20958610e0d1f083f032..ed28f1c3e1d0f2559a62a1c28993794497730c5d 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -82,6 +82,10 @@ static bool turbo_mode = true; @@ -48,10 +48,10 @@ index 831aa33d078ae7d2dd57fdded5de71d1eb915f99..b77935bded8c0ff7808b00f170ff10e5 usbnet_skb_return(dev, ax_skb); } -From 453c16d19a853054db06eca6b98aec60a9c0d2c8 Mon Sep 17 00:00:00 2001 +From a347afc0ccd94c1f7d22b4be89a93729d3482cdb Mon Sep 17 00:00:00 2001 From: Sam Nazarko Date: Fri, 1 Apr 2016 17:27:21 +0100 -Subject: [PATCH 002/216] smsc95xx: Experimental: Enable turbo_mode and +Subject: [PATCH 002/150] smsc95xx: Experimental: Enable turbo_mode and packetsize=2560 by default See: http://forum.kodi.tv/showthread.php?tid=285288 @@ -60,7 +60,7 @@ See: http://forum.kodi.tv/showthread.php?tid=285288 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index b77935bded8c0ff7808b00f170ff10e594300ad0..693f163684de921404738e33244881e0aab92ec9 100644 +index ed28f1c3e1d0f2559a62a1c28993794497730c5d..f758e122c65685799d4aeeb1c3e6ca81df0d7980 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -86,6 +86,10 @@ static bool truesize_mode = false; @@ -94,10 +94,10 @@ index b77935bded8c0ff7808b00f170ff10e594300ad0..693f163684de921404738e33244881e0 netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n", -From 0c54c883869b1984c149345e94624622f792adfb Mon Sep 17 00:00:00 2001 +From 2ce94c606a1de6371f969ec9806c1d929d539524 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 003/216] Allow mac address to be set in smsc95xx +Subject: [PATCH 003/150] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -105,7 +105,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 693f163684de921404738e33244881e0aab92ec9..df60c989fc229bf0aab3c27e95ccd45323367840 100644 +index f758e122c65685799d4aeeb1c3e6ca81df0d7980..f6661e388f6e801c1b88e48a3b71407bd70cf56e 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -60,6 +60,7 @@ @@ -193,10 +193,10 @@ index 693f163684de921404738e33244881e0aab92ec9..df60c989fc229bf0aab3c27e95ccd453 eth_hw_addr_random(dev->net); netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n"); -From ec736202ad01b18a75707d7ed00555ba10d416c8 Mon Sep 17 00:00:00 2001 +From e5fa073af19fea2b4b71dbc10d107f07e726b9ab Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 13 Mar 2015 12:43:36 +0000 -Subject: [PATCH 004/216] Protect __release_resource against resources without +Subject: [PATCH 004/150] Protect __release_resource against resources without parents Without this patch, removing a device tree overlay can crash here. @@ -224,10 +224,10 @@ index 9b5f04404152c296af3a96132f27cfc80ffa9af9..f8a9af6e6b915812be2ba2c1c2b40106 for (;;) { tmp = *p; -From 6bf00b2252065dd38d17a9ecc084100f66b16542 Mon Sep 17 00:00:00 2001 +From 93ce5d5706abd21583e08a43a8cbe6a5a0608fc6 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 18 Dec 2014 16:07:15 -0800 -Subject: [PATCH 005/216] mm: Remove the PFN busy warning +Subject: [PATCH 005/150] mm: Remove the PFN busy warning See commit dae803e165a11bc88ca8dbc07a11077caf97bbcb -- the warning is expected sometimes when using CMA. However, that commit still spams @@ -239,10 +239,10 @@ Signed-off-by: Eric Anholt 1 file changed, 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c -index 1aec370bf9e92cea039c1917fa39dcb67bb111b9..a0f965b552cbb4cf609baf45ff9ab0be0f1400cc 100644 +index 07efbc3a86567676986105005f77c64f9f99597a..01988d3cedfd83546df831d7c4f03e1e6aae1360 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7361,8 +7361,6 @@ int alloc_contig_range(unsigned long start, unsigned long end, +@@ -7515,8 +7515,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)) { @@ -252,10 +252,10 @@ index 1aec370bf9e92cea039c1917fa39dcb67bb111b9..a0f965b552cbb4cf609baf45ff9ab0be goto done; } -From 02cfadd230531dcfd9672685e42be90fd3bd0cfe Mon Sep 17 00:00:00 2001 +From 623cfba2faa2c010ebaab45171f0a390c306f0f5 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 4 Dec 2015 17:41:50 +0000 -Subject: [PATCH 006/216] irq-bcm2836: Prevent spurious interrupts, and trap +Subject: [PATCH 006/150] irq-bcm2836: Prevent spurious interrupts, and trap them early The old arch-specific IRQ macros included a dsb to ensure the @@ -282,10 +282,37 @@ index e7463e3c08143acae3e8cc5682f918c6a0b07ebd..a8db33b50ad9ff83d284fa54fe4d3b65 #endif } else if (stat) { -From ef35e92347f6f93a2d44d5077ee52559ee3618c5 Mon Sep 17 00:00:00 2001 +From 14a9acffeb577ae7251d0036b367118fc7b42c0d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 9 Feb 2017 14:33:30 +0000 +Subject: [PATCH 007/150] irq-bcm2836: Avoid "Invalid trigger warning" + +Initialise the level for each IRQ to avoid a warning from the +arm arch timer code. + +Signed-off-by: Phil Elwell +--- + drivers/irqchip/irq-bcm2836.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c +index a8db33b50ad9ff83d284fa54fe4d3b65f859df0f..c4e151451cf8c8ebde5225515eac2786d6f61d46 100644 +--- a/drivers/irqchip/irq-bcm2836.c ++++ b/drivers/irqchip/irq-bcm2836.c +@@ -157,7 +157,7 @@ static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip) + + irq_set_percpu_devid(irq); + irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq); +- irq_set_status_flags(irq, IRQ_NOAUTOEN); ++ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW); + } + + static void + +From bd516ea1a2695ff2ac13d6332c38b5dd8dc156c0 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 007/216] irqchip: bcm2835: Add FIQ support +Subject: [PATCH 008/150] irqchip: bcm2835: Add FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -414,10 +441,10 @@ index 44d7c38dde479d771f3552e914bf8c1c1f5019f7..42ff5e6a8e0d532f5b60a1e7af7cc4d9 } -From 03cad6839589c779d27bbc6f48345880f4ca5852 Mon Sep 17 00:00:00 2001 +From d79351a2b7599a6e394295c53283d625c1ccb916 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 008/216] irqchip: irq-bcm2835: Add 2836 FIQ support +Subject: [PATCH 009/150] irqchip: irq-bcm2835: Add 2836 FIQ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -516,10 +543,10 @@ index 42ff5e6a8e0d532f5b60a1e7af7cc4d941bd5008..eccf6ed025299cb480884f5bcbe77abf for (b = 0; b < NR_BANKS; b++) { for (i = 0; i < bank_irqs[b]; i++) { -From 4cbb3dd151c3f2bbde82eeeb0cc57e16e3d61aee Mon Sep 17 00:00:00 2001 +From 1840c980ba21dd87bdfccdb94573fd9f8f881c3b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 10:26:09 +0100 -Subject: [PATCH 009/216] spidev: Add "spidev" compatible string to silence +Subject: [PATCH 010/150] spidev: Add "spidev" compatible string to silence warning See: https://github.com/raspberrypi/linux/issues/1054 @@ -540,10 +567,33 @@ index 9e2e099baf8ca5cc6510912a36d4ca03daeb8273..e59640942826db2ea14d0bde0ff5ab22 }; MODULE_DEVICE_TABLE(of, spidev_dt_ids); -From 4c810d9628b6e2382a678aa81652e64da268f15c Mon Sep 17 00:00:00 2001 +From fb243008b7d9f06e65045d26ef221d1cb6ff612c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 30 Jun 2015 14:12:42 +0100 +Subject: [PATCH 011/150] 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 76e03a7de9cc3d790a230948f599ef2db4b93249..0a172c2e6fa288de1e080463e897ea85aa98399f 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) + + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; ++ if (!nr_uarts) ++ return; + + for (i = 0; i < nr_uarts; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; + +From e6fdce6882f36c213a81ac2323a91e57d46b01db Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 3 Jan 2017 18:25:01 +0000 -Subject: [PATCH 010/216] Revert "pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP" +Subject: [PATCH 012/150] Revert "pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP" This reverts commit 85ae9e512f437cd09bf61564bdba29ab88bab3e3. --- @@ -552,7 +602,7 @@ This reverts commit 85ae9e512f437cd09bf61564bdba29ab88bab3e3. 2 files changed, 76 insertions(+), 65 deletions(-) diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig -index 8968dd7aebed2133b0103b39d7b752916dbfaab0..63246770bd74b9dcd3804cee66a960f2404b7092 100644 +index e8c4e4f934a6d388bef3e77b89dc19d1e3a6db66..5691311b93991043e9074c330646d0b4837d296e 100644 --- a/drivers/pinctrl/bcm/Kconfig +++ b/drivers/pinctrl/bcm/Kconfig @@ -20,7 +20,6 @@ config PINCTRL_BCM2835 @@ -837,10 +887,10 @@ index 85d0091128644c446aed878e87769e82c77c3ebf..4f2621272bfd5cbc0d691d2fabe89e2e if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); -From 0b6193559183d5aa087bd369d469b54005cefae4 Mon Sep 17 00:00:00 2001 +From 5fd0d472a1deaab0ad03b9ac0cf03b08c10ad521 Mon Sep 17 00:00:00 2001 From: notro Date: Thu, 10 Jul 2014 13:59:47 +0200 -Subject: [PATCH 011/216] pinctrl-bcm2835: Set base to 0 give expected gpio +Subject: [PATCH 013/150] pinctrl-bcm2835: Set base to 0 give expected gpio numbering Signed-off-by: Noralf Tronnes @@ -862,10 +912,10 @@ index 4f2621272bfd5cbc0d691d2fabe89e2ee428d6db..5b7cb4c415e19f98e25b221ab0ad36b6 .can_sleep = false, }; -From ea1ee213408f36849aafe08988408278f578ec28 Mon Sep 17 00:00:00 2001 +From 62578c5b8f5e71b089a8fdbe30b970428a47af37 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 26 Feb 2015 09:58:22 +0000 -Subject: [PATCH 012/216] pinctrl-bcm2835: Only request the interrupts listed +Subject: [PATCH 014/150] pinctrl-bcm2835: Only request the interrupts listed in the DTB Although the GPIO controller can generate three interrupts (four counting @@ -892,10 +942,10 @@ index 5b7cb4c415e19f98e25b221ab0ad36b6885dae4c..6351fe7f8e314ac5ebb102dd20847b38 pc->irq_data[i].irqgroup = i; -From ca6199bcc0b54ad8f657aac46d445933c641991a Mon Sep 17 00:00:00 2001 +From 854432281d9580b79246f64219cd6296e86ded0f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 -Subject: [PATCH 013/216] spi-bcm2835: Support pin groups other than 7-11 +Subject: [PATCH 015/150] 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 @@ -976,10 +1026,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 7956252bf619d3d8720a61fb3f1e7d753afb08cb Mon Sep 17 00:00:00 2001 +From 98aaea5fb40decc0a296034cbc6c0b93eb4357d8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 014/216] spi-bcm2835: Disable forced software CS +Subject: [PATCH 016/150] 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 @@ -1013,10 +1063,10 @@ index 5dfe20ffc2866fa6789825016c585175a29705b6..8493474d286f7a1ac6454a22c61c8c2c return 0; } -From 191d51a1784a9749cb870875f3982ca042d34db0 Mon Sep 17 00:00:00 2001 +From bb132b31f99358f990f175c903cfdb2a1236b0f5 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 8 Nov 2016 21:35:38 +0000 -Subject: [PATCH 015/216] spi-bcm2835: Remove unused code +Subject: [PATCH 017/150] spi-bcm2835: Remove unused code --- drivers/spi/spi-bcm2835.c | 61 ----------------------------------------------- @@ -1104,10 +1154,10 @@ index 8493474d286f7a1ac6454a22c61c8c2cef9121bf..33d75ad38a7f77d085321ace9101900a } -From cc3f12b35b4c35e5559cba31e68d5621e30d9fa7 Mon Sep 17 00:00:00 2001 +From d22117a61d13599e8f03765a6c0e5c66864b4303 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 016/216] ARM: bcm2835: Set Serial number and Revision +Subject: [PATCH 018/150] ARM: bcm2835: Set Serial number and Revision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1160,10 +1210,10 @@ index 0c1edfc98696da0e0bb7f4a18cdfbcdd27a9795d..8f152266ba9b470df2eaaed9ebcf158e static const char * const bcm2835_compat[] = { -From 2cc505b74d02c2c73266f5a9e924a2a812d080c7 Mon Sep 17 00:00:00 2001 +From ab4022f0215c5a52f8125ec25d672ff663c23876 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 017/216] dmaengine: bcm2835: Load driver early and support +Subject: [PATCH 019/150] dmaengine: bcm2835: Load driver early and support legacy API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -1181,7 +1231,7 @@ Signed-off-by: Noralf Trønnes 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 263495d0adbdfd0a5e079c3ba5c6f71247ee7fde..4415a37a1d84c696efa96bf0b17840d6c0dd3b12 100644 +index d01d59812cf3ec8f171e09641ae2c1c787e0de06..a754288fb8bec3dafea4952f5133703f4e42f7df 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -1194,7 +1244,7 @@ index 263495d0adbdfd0a5e079c3ba5c6f71247ee7fde..4415a37a1d84c696efa96bf0b17840d6 select DMA_VIRTUAL_CHANNELS diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c -index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538bac3892a4d 100644 +index 6204cc32d09c5096df8aec304c3c37b3bcb6be44..599c218dc8a73172dd4bd4a058fc8f95a73f982f 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -37,6 +37,7 @@ @@ -1213,7 +1263,7 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba struct bcm2835_dmadev { struct dma_device ddev; -@@ -922,6 +924,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -925,6 +927,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); @@ -1223,7 +1273,7 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba od->base = base; -@@ -959,6 +964,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) +@@ -962,6 +967,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev) goto err_no_dma; } @@ -1233,7 +1283,7 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba /* get irqs for each channel that we support */ for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) { /* skip masked out channels */ -@@ -1033,6 +1041,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) +@@ -1036,6 +1044,7 @@ static int bcm2835_dma_remove(struct platform_device *pdev) { struct bcm2835_dmadev *od = platform_get_drvdata(pdev); @@ -1241,7 +1291,7 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba dma_async_device_unregister(&od->ddev); bcm2835_dma_free(od); -@@ -1048,7 +1057,22 @@ static struct platform_driver bcm2835_dma_driver = { +@@ -1051,7 +1060,22 @@ static struct platform_driver bcm2835_dma_driver = { }, }; @@ -1266,10 +1316,10 @@ index e18dc596cf2447fa9ef7e41b62d9396e29043426..80d35f760b4a4a51e60c355a84d538ba MODULE_ALIAS("platform:bcm2835-dma"); MODULE_DESCRIPTION("BCM2835 DMA engine driver"); -From 044d6ff9f4bab67c7bc7237252e4e7561aa0c0c1 Mon Sep 17 00:00:00 2001 +From 7e9d1845f9301474cbba920226311defc8f47370 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 25 Jan 2016 17:25:12 +0000 -Subject: [PATCH 018/216] firmware: Updated mailbox header +Subject: [PATCH 020/150] firmware: Updated mailbox header --- include/soc/bcm2835/raspberrypi-firmware.h | 9 +++++++++ @@ -1330,10 +1380,10 @@ index cb979ad90401e299344dd5fae38d09c489d8bd58..30fb37fe175df604a738258a2a632bca RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, -From 6908c41c80da608c824032010ffde46619213c5d Mon Sep 17 00:00:00 2001 +From 792034bb12504f6b73bce102c05767b1eb11145d Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 15 Jun 2016 16:48:41 +0100 -Subject: [PATCH 019/216] rtc: Add SPI alias for pcf2123 driver +Subject: [PATCH 021/150] rtc: Add SPI alias for pcf2123 driver Without this alias, Device Tree won't cause the driver to be loaded. @@ -1353,10 +1403,10 @@ index 8895f77726e8da5444afcd602dceff8f25a9b3fd..1833b8853ceb0e6147cceb93a00e558c MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:rtc-pcf2123"); -From 761b0fc6cb2c65cb2040fa4d7020d778f6ca3688 Mon Sep 17 00:00:00 2001 +From b8c79631cd26c764d1fe5343a400bb6fb681b5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Fri, 7 Oct 2016 16:50:59 +0200 -Subject: [PATCH 020/216] watchdog: bcm2835: Support setting reboot partition +Subject: [PATCH 022/150] watchdog: bcm2835: Support setting reboot partition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1371,44 +1421,41 @@ If the partition doesn't exist, the firmware falls back to partition 0. Signed-off-by: Noralf Trønnes --- - drivers/watchdog/bcm2835_wdt.c | 61 +++++++++++++++++++++++++----------------- - 1 file changed, 36 insertions(+), 25 deletions(-) + drivers/watchdog/bcm2835_wdt.c | 49 +++++++++++++++++++++++------------------- + 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c -index c32c45bd8b097889c8f322255fa63c8ed507d6ab..ef02dfa23aa774e1cdf75f935c5de98535718767 100644 +index b339e0e67b4c1275fd4992fea4f1e24c0575b783..26b7177573fac2af1cd4ab5488d2686f898132fe 100644 --- a/drivers/watchdog/bcm2835_wdt.c +++ b/drivers/watchdog/bcm2835_wdt.c -@@ -35,13 +35,7 @@ +@@ -34,13 +34,7 @@ #define PM_RSTC_WRCFG_SET 0x00000030 #define PM_RSTC_WRCFG_FULL_RESET 0x00000020 #define PM_RSTC_RESET 0x00000102 - -/* -- * The Raspberry Pi firmware uses the RSTS register to know which partiton -- * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. -- * Partiton 63 is a special partition used by the firmware to indicate halt. +- * The Raspberry Pi firmware uses the RSTS register to know which partition +- * to boot from. The partition value is spread into bits 0, 2, 4, 6, 8, 10. +- * Partition 63 is a special partition used by the firmware to indicate halt. - */ -#define PM_RSTS_RASPBERRYPI_HALT 0x555 -+#define PM_RSTS_PARTITION_CLR 0xfffffaaa ++#define PM_RSTS_PARTITION_CLR 0xfffffaaa #define SECS_TO_WDOG_TICKS(x) ((x) << 16) #define WDOG_TICKS_TO_SECS(x) ((x) >> 16) -@@ -120,15 +114,28 @@ static struct watchdog_device bcm2835_wdt_wdd = { - .timeout = WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), - }; +@@ -97,9 +91,24 @@ static unsigned int bcm2835_wdt_get_timeleft(struct watchdog_device *wdog) + return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET); + } --static int --bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) +-static void __bcm2835_restart(struct bcm2835_wdt *wdt) +/* + * The Raspberry Pi firmware uses the RSTS register to know which partiton + * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10. + * Partiton 63 is a special partition used by the firmware to indicate halt. + */ + -+static void bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) ++static void __bcm2835_restart(struct bcm2835_wdt *wdt, u8 partition) { -- struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -- restart_handler); - u32 val; + u32 val, rsts; + @@ -1423,32 +1470,22 @@ index c32c45bd8b097889c8f322255fa63c8ed507d6ab..ef02dfa23aa774e1cdf75f935c5de985 /* use a timeout of 10 ticks (~150us) */ writel_relaxed(10 | PM_PASSWORD, wdt->base + PM_WDOG); -+ - val = readl_relaxed(wdt->base + PM_RSTC); - val &= PM_RSTC_WRCFG_CLR; - val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; -@@ -136,6 +143,20 @@ bcm2835_restart(struct notifier_block *this, unsigned long mode, void *cmd) +@@ -117,7 +126,13 @@ static int bcm2835_restart(struct watchdog_device *wdog, + { + struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); - /* No sleeping, possibly atomic. */ - mdelay(1); -+} -+ -+static int bcm2835_restart_notifier_call(struct notifier_block *this, -+ unsigned long mode, void *cmd) -+{ -+ struct bcm2835_wdt *wdt = container_of(this, struct bcm2835_wdt, -+ restart_handler); +- __bcm2835_restart(wdt); + unsigned long long val; + u8 partition = 0; + -+ if (cmd && !kstrtoull(cmd, 0, &val) && val <= 63) ++ if (data && !kstrtoull(data, 0, &val) && val <= 63) + partition = val; + -+ bcm2835_restart(wdt, partition); ++ __bcm2835_restart(wdt, partition); return 0; } -@@ -151,19 +172,9 @@ static void bcm2835_power_off(void) +@@ -155,19 +170,9 @@ static void bcm2835_power_off(void) of_find_compatible_node(NULL, NULL, "brcm,bcm2835-pm-wdt"); struct platform_device *pdev = of_find_device_by_node(np); struct bcm2835_wdt *wdt = platform_get_drvdata(pdev); @@ -1464,26 +1501,17 @@ index c32c45bd8b097889c8f322255fa63c8ed507d6ab..ef02dfa23aa774e1cdf75f935c5de985 - writel_relaxed(val, wdt->base + PM_RSTS); - /* Continue with normal reset mechanism */ -- bcm2835_restart(&wdt->restart_handler, REBOOT_HARD, NULL); +- __bcm2835_restart(wdt); + /* Partition 63 tells the firmware that this is a halt */ -+ bcm2835_restart(wdt, 63); ++ __bcm2835_restart(wdt, 63); } static int bcm2835_wdt_probe(struct platform_device *pdev) -@@ -208,7 +219,7 @@ static int bcm2835_wdt_probe(struct platform_device *pdev) - return err; - } - -- wdt->restart_handler.notifier_call = bcm2835_restart; -+ wdt->restart_handler.notifier_call = bcm2835_restart_notifier_call; - wdt->restart_handler.priority = 128; - register_restart_handler(&wdt->restart_handler); - if (pm_power_off == NULL) -From 9f0cd7dc290a561c7a0120ebfd795e1475b427e8 Mon Sep 17 00:00:00 2001 +From 77f4bfc67371dba9ee89641d99d765055e4ba0cc Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 5 Apr 2016 19:40:12 +0100 -Subject: [PATCH 021/216] reboot: Use power off rather than busy spinning when +Subject: [PATCH 023/150] reboot: Use power off rather than busy spinning when halt is requested --- @@ -1506,10 +1534,10 @@ index 3fa867a2aae672755c6ce6448f4148c989dbf964..80dca8dcd6709034b643c6a3f35729e0 /* -From 2492efbe9f7c8d08f63e44db196a73daa63616bc Mon Sep 17 00:00:00 2001 +From ba1d8fd9f3886b5927b7b575f24fbf9c12cf0a41 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 9 Nov 2016 13:02:52 +0000 -Subject: [PATCH 022/216] bcm: Make RASPBERRYPI_POWER depend on PM +Subject: [PATCH 024/150] bcm: Make RASPBERRYPI_POWER depend on PM --- drivers/soc/bcm/Kconfig | 1 + @@ -1528,10 +1556,10 @@ index a39b0d58ddd0fdf0ac1cc7295f8aafb12546e226..e037a6dd79d1881a09e3ca9115782709 help This enables support for the RPi power domains which can be enabled -From c05e7c943f4ac63f969f0e98d9e72a75c6b1b916 Mon Sep 17 00:00:00 2001 +From e93254defaad622fd2f99a7a520973dede9be91d Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Fri, 2 Sep 2016 16:45:27 +0100 -Subject: [PATCH 023/216] Register the clocks early during the boot process, so +Subject: [PATCH 025/150] Register the clocks early during the boot process, so that special/critical clocks can get enabled early on in the boot process avoiding the risk of disabling a clock, pll_divider or pll when a claiming driver fails to install propperly - maybe it needs to defer. @@ -1542,10 +1570,10 @@ Signed-off-by: Martin Sperl 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 0d14409097e777ce4546de30e9278fdebf74ec44..093694e00caec6e133eb26712f890691cad999aa 100644 +index 02585387061967ac9408e18ac1bce67e9e9414c0..283d2de45e4f29406d01f24ab1cae3f9f879234a 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1958,8 +1958,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) +@@ -2163,8 +2163,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev) if (ret) return ret; @@ -1562,7 +1590,7 @@ index 0d14409097e777ce4546de30e9278fdebf74ec44..093694e00caec6e133eb26712f890691 } static const struct of_device_id bcm2835_clk_of_match[] = { -@@ -1976,7 +1983,11 @@ static struct platform_driver bcm2835_clk_driver = { +@@ -2181,7 +2188,11 @@ static struct platform_driver bcm2835_clk_driver = { .probe = bcm2835_clk_probe, }; @@ -1576,10 +1604,10 @@ index 0d14409097e777ce4546de30e9278fdebf74ec44..093694e00caec6e133eb26712f890691 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("BCM2835 clock driver"); -From 725f67996181894474793d5e48d4eaaf26b25090 Mon Sep 17 00:00:00 2001 +From b83979886ce6705e91662f7e58566b7eb5595f18 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 6 Dec 2016 17:05:39 +0000 -Subject: [PATCH 024/216] bcm2835-rng: Avoid initialising if already enabled +Subject: [PATCH 026/150] bcm2835-rng: Avoid initialising if already enabled Avoids the 0x40000 cycles of warmup again if firmware has already used it --- @@ -1605,33 +1633,33 @@ index 574211a495491d9d6021dcaefe4274a63ed02055..e66c0fca8c6090e32f72796c0877a1cf err = hwrng_register(&bcm2835_rng_ops); if (err) { -From 0cc5800e12c0ef4271994324553dd9afbd21e395 Mon Sep 17 00:00:00 2001 +From 63aaaf1a9deb01fb7141b2c48b0e119f9ee3f8f8 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Aug 2016 16:28:44 +0100 -Subject: [PATCH 025/216] kbuild: Ignore dtco targets when filtering symbols +Subject: [PATCH 027/150] kbuild: Ignore dtco targets when filtering symbols --- scripts/Kbuild.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include -index 179219845dfcdfbeb586d12c5ec1296095d9fbf4..e0743e44f84188667a0c322e8c3d36f18385dcd3 100644 +index afe3fd3af1e40616857b3e6c425be632c1fa2667..b2bbad417f0c4499a5f49081c8f996b97b01e867 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include -@@ -284,7 +284,7 @@ ksym_dep_filter = \ +@@ -288,7 +288,7 @@ ksym_dep_filter = \ $(CPP) $(call flags_nodeps,c_flags) -D__KSYM_DEPS__ $< ;; \ as_*_S|cpp_s_S) \ $(CPP) $(call flags_nodeps,a_flags) -D__KSYM_DEPS__ $< ;; \ -- boot*|build*|*cpp_lds_S|dtc|host*|vdso*) : ;; \ -+ boot*|build*|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ +- boot*|build*|cpp_its_S|*cpp_lds_S|dtc|host*|vdso*) : ;; \ ++ boot*|build*|cpp_its_S|*cpp_lds_S|dtc*|host*|vdso*) : ;; \ *) echo "Don't know how to preprocess $(1)" >&2; false ;; \ esac | tr ";" "\n" | sed -rn 's/^.*=== __KSYM_(.*) ===.*$$/KSYM_\1/p' -From c4e7a6c271431abaf38699941a6242a7ad569d42 Mon Sep 17 00:00:00 2001 +From e297b2cd65a7b9247d44afff8de0efd3b215925c Mon Sep 17 00:00:00 2001 From: Robert Tiemann Date: Mon, 20 Jul 2015 11:01:25 +0200 -Subject: [PATCH 026/216] BCM2835_DT: Fix I2S register map +Subject: [PATCH 028/150] BCM2835_DT: Fix I2S register map --- Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt | 4 ++-- @@ -1669,10 +1697,688 @@ index 65783de0aedf3da79adc36fd077b7a89954ddb6b..a89fe4220fdc3f26f75ee66daf187554 dmas = <&dma 2>, <&dma 3>; -From 9dcfa128d5902933be31cf846eaf088c41fe4efd Mon Sep 17 00:00:00 2001 +From 97c2818afd6538be920d4e61517384af2a514cca Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Feb 2017 17:20:08 +0000 +Subject: [PATCH 029/150] clk-bcm2835: Mark used PLLs and dividers CRITICAL + +The VPU configures and relies on several PLLs and dividers. Mark all +enabled dividers and their PLLs as CRITICAL to prevent the kernel from +switching them off. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 283d2de45e4f29406d01f24ab1cae3f9f879234a..85df8c74a309f0b877ef65f1c55b086f1bb774a1 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1366,6 +1366,11 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, + divider->div.hw.init = &init; + divider->div.table = NULL; + ++ if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { ++ init.flags |= CLK_IS_CRITICAL; ++ divider->div.flags |= CLK_IS_CRITICAL; ++ } ++ + divider->cprman = cprman; + divider->data = data; + + +From 7a37dcfcc7e625c1325606058f9d728ecd1163a0 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Feb 2017 17:20:08 +0000 +Subject: [PATCH 030/150] clk-bcm2835: Add claim-clocks property + +The claim-clocks property can be used to prevent PLLs and dividers +from being marked as critical. It contains a vector of clock IDs, +as defined by dt-bindings/clock/bcm2835.h. + +Use this mechanism to claim PLLD_DSI0, PLLD_DSI1, PLLH_AUX and +PLLH_PIX for the vc4_kms_v3d driver. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 34 ++++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 85df8c74a309f0b877ef65f1c55b086f1bb774a1..eec6735505c074c0a76ae647bf0e1bb68ab3a488 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1298,6 +1298,8 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { + .debug_init = bcm2835_clock_debug_init, + }; + ++static bool bcm2835_clk_is_claimed(const char *name); ++ + static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, + const struct bcm2835_pll_data *data) + { +@@ -1314,6 +1316,9 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, + init.ops = &bcm2835_pll_clk_ops; + init.flags = CLK_IGNORE_UNUSED; + ++ if (!bcm2835_clk_is_claimed(data->name)) ++ init.flags |= CLK_IS_CRITICAL; ++ + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return NULL; +@@ -1367,8 +1372,10 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, + divider->div.table = NULL; + + if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { +- init.flags |= CLK_IS_CRITICAL; +- divider->div.flags |= CLK_IS_CRITICAL; ++ if (!bcm2835_clk_is_claimed(data->source_pll)) ++ init.flags |= CLK_IS_CRITICAL; ++ if (!bcm2835_clk_is_claimed(data->name)) ++ divider->div.flags |= CLK_IS_CRITICAL; + } + + divider->cprman = cprman; +@@ -2095,6 +2102,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .ctl_reg = CM_PERIICTL), + }; + ++static bool bcm2835_clk_claimed[ARRAY_SIZE(clk_desc_array)]; ++ + /* + * Permanently take a reference on the parent of the SDRAM clock. + * +@@ -2114,6 +2123,19 @@ static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) + return clk_prepare_enable(parent); + } + ++static bool bcm2835_clk_is_claimed(const char *name) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { ++ const char *clk_name = *(const char **)(clk_desc_array[i].data); ++ if (!strcmp(name, clk_name)) ++ return bcm2835_clk_claimed[i]; ++ } ++ ++ return false; ++} ++ + static int bcm2835_clk_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -2123,6 +2145,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); + size_t i; ++ u32 clk_id; + int ret; + + cprman = devm_kzalloc(dev, sizeof(*cprman) + +@@ -2138,6 +2161,13 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + if (IS_ERR(cprman->regs)) + return PTR_ERR(cprman->regs); + ++ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed)); ++ for (i = 0; ++ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", ++ i, &clk_id); ++ i++) ++ bcm2835_clk_claimed[clk_id]= true; ++ + memcpy(cprman->real_parent_names, cprman_parent_names, + sizeof(cprman_parent_names)); + of_clk_parent_fill(dev->of_node, cprman->real_parent_names, + +From ee9076250d2ae0c8141adbae2ee66c9e2186dcf7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 1 Mar 2017 16:06:53 +0000 +Subject: [PATCH 031/150] clk-bcm2835: Correct the prediv logic + +If a clock has the prediv flag set, both the integer and fractional +parts must be scaled when calculating the resulting frequency. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index eec6735505c074c0a76ae647bf0e1bb68ab3a488..e0d28add45efdf70d1eba590282a3a2654af328d 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -616,8 +616,10 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, + using_prediv = cprman_read(cprman, data->ana_reg_base + 4) & + data->ana->fb_prediv_mask; + +- if (using_prediv) ++ if (using_prediv) { + ndiv *= 2; ++ fdiv *= 2; ++ } + + return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv); + } + +From 4bceecaead7ff62990f7b9691d4d01c50bd3f98a Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 6 Mar 2017 09:06:18 +0000 +Subject: [PATCH 032/150] clk-bcm2835: Read max core clock from firmware + +The VPU is responsible for managing the core clock, usually under +direction from the bcm2835-cpufreq driver but not via the clk-bcm2835 +driver. Since the core frequency can change without warning, it is +safer to report the maximum clock rate to users of the core clock - +I2C, SPI and the mini UART - to err on the safe side when calculating +clock divisors. + +If the DT node for the clock driver includes a reference to the +firmware node, use the firmware API to query the maximum core clock +instead of reading the divider registers. + +Prior to this patch, a "100KHz" I2C bus was sometimes clocked at about +160KHz. In particular, switching to the 4.9 kernel was likely to break +SenseHAT usage on a Pi3. + +Signed-off-by: Phil Elwell +--- + drivers/clk/bcm/clk-bcm2835.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index e0d28add45efdf70d1eba590282a3a2654af328d..39f72da6ba1f6ec6ec41d5dc1bf46344aab008da 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #define CM_PASSWORD 0x5a000000 + +@@ -299,6 +300,8 @@ + #define LOCK_TIMEOUT_NS 100000000 + #define BCM2835_MAX_FB_RATE 1750000000u + ++#define VCMSG_ID_CORE_CLOCK 4 ++ + /* + * Names of clocks used within the driver that need to be replaced + * with an external parent's name. This array is in the order that +@@ -317,6 +320,7 @@ static const char *const cprman_parent_names[] = { + struct bcm2835_cprman { + struct device *dev; + void __iomem *regs; ++ struct rpi_firmware *fw; + spinlock_t regs_lock; /* spinlock for all clocks */ + + /* +@@ -1025,6 +1029,30 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, + return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); + } + ++static unsigned long bcm2835_clock_get_rate_vpu(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); ++ struct bcm2835_cprman *cprman = clock->cprman; ++ ++ if (cprman->fw) { ++ struct { ++ u32 id; ++ u32 val; ++ } packet; ++ ++ packet.id = VCMSG_ID_CORE_CLOCK; ++ packet.val = 0; ++ ++ if (!rpi_firmware_property(cprman->fw, ++ RPI_FIRMWARE_GET_MAX_CLOCK_RATE, ++ &packet, sizeof(packet))) ++ return packet.val; ++ } ++ ++ return bcm2835_clock_get_rate(hw, parent_rate); ++} ++ + static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock) + { + struct bcm2835_cprman *cprman = clock->cprman; +@@ -1292,7 +1320,7 @@ static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) + */ + static const struct clk_ops bcm2835_vpu_clock_clk_ops = { + .is_prepared = bcm2835_vpu_clock_is_on, +- .recalc_rate = bcm2835_clock_get_rate, ++ .recalc_rate = bcm2835_clock_get_rate_vpu, + .set_rate = bcm2835_clock_set_rate, + .determine_rate = bcm2835_clock_determine_rate, + .set_parent = bcm2835_clock_set_parent, +@@ -2146,6 +2174,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + struct resource *res; + const struct bcm2835_clk_desc *desc; + const size_t asize = ARRAY_SIZE(clk_desc_array); ++ struct device_node *fw_node; + size_t i; + u32 clk_id; + int ret; +@@ -2163,6 +2192,14 @@ static int bcm2835_clk_probe(struct platform_device *pdev) + if (IS_ERR(cprman->regs)) + return PTR_ERR(cprman->regs); + ++ fw_node = of_parse_phandle(dev->of_node, "firmware", 0); ++ if (fw_node) { ++ struct rpi_firmware *fw = rpi_firmware_get(NULL); ++ if (!fw) ++ return -EPROBE_DEFER; ++ cprman->fw = fw; ++ } ++ + memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed)); + for (i = 0; + !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", + +From cea58498fcb31578e0760f043606cf9a05a2caab Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 9 Feb 2017 14:36:44 +0000 +Subject: [PATCH 033/150] sound: Demote deferral errors to INFO level + +At present there is no mechanism to specify driver load order, +which can lead to deferrals and repeated retries until successful. +Since this situation is expected, reduce the dmesg level to +INFO and mention that the operation will be retried. + +Signed-off-by: Phil Elwell +--- + sound/soc/soc-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c +index 2722bb0c557310d97816cfa7857b24d7c9bd4948..c32d3c31f34fc12195baf873a507d0b46f5c8ba8 100644 +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1057,7 +1057,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, + cpu_dai_component.dai_name = dai_link->cpu_dai_name; + rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component); + if (!rtd->cpu_dai) { +- dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", ++ dev_info(card->dev, "ASoC: CPU DAI %s not registered - will retry\n", + dai_link->cpu_dai_name); + goto _err_defer; + } +@@ -1069,7 +1069,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, + for (i = 0; i < rtd->num_codecs; i++) { + codec_dais[i] = snd_soc_find_dai(&codecs[i]); + if (!codec_dais[i]) { +- dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", ++ dev_info(card->dev, "ASoC: CODEC DAI %s not registered - will retry\n", + codecs[i].dai_name); + goto _err_defer; + } + +From 9c3c67b58c61b0307d6eec6bb85560ae80d4031a Mon Sep 17 00:00:00 2001 +From: Claggy3 +Date: Sat, 11 Feb 2017 14:00:30 +0000 +Subject: [PATCH 034/150] Update vfpmodule.c + +Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m. +This patch fixes a problem with VFP state save and restore related +to exception handling (panic with message "BUG: unsupported FP +instruction in kernel mode") present on VFP11 floating point units +(as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry +Pi boards). This patch was developed and discussed on + + https://github.com/raspberrypi/linux/issues/859 + +A precondition to see the crashes is that floating point exception +traps are enabled. In this case, the VFP11 might determine that a FPU +operation needs to trap at a point in time when it is not possible to +signal this to the ARM11 core any more. The VFP11 will then set the +FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases, +a second opcode might have been accepted by the VFP11 before the +exception was detected and could be reported to the ARM11 - in this +case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in +FPINST2.) + +If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued +by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode +trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits +to decide what actions to take, i.e., whether to emulate the opcodes +found in FPINST and FPINST2, and whether to retry the bounced instruction. + +If a user space application has left the VFP11 in this "pending trap" +state, the next FPU opcode issued to the VFP11 might actually be the +VSTMIA operation vfp_save_state() uses to store the FPU registers +to memory (in our test cases, when building the signal stack frame). +In this case, the kernel crashes as described above. + +This patch fixes the problem by making sure that vfp_save_state() is +always entered with FPEXC.EX cleared. (The current value of FPEXC has +already been saved, so this does not corrupt the context. Clearing +FPEXC.EX has no effects on FPINST or FPINST2. Also note that many +callers already modify FPEXC by setting FPEXC.EN before invoking +vfp_save_state().) + +This patch also addresses a second problem related to FPEXC.EX: After +returning from signal handling, the kernel reloads the VFP context +from the user mode stack. However, the current code explicitly clears +both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these +bits to be preserved, this patch disables clearing them for VFP +implementations belonging to architecture 1. There should be no +negative side effects: the user can set both bits by executing FPU +opcodes anyway, and while user code may now place arbitrary values +into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support +code knows which instructions can be emulated, and rejects other +opcodes with "unhandled bounce" messages, so there should be no +security impact from allowing reloading FPEXC.EX and FPEXC.FP2V. + +Signed-off-by: Christopher Alexander Tobias Schulze +--- + arch/arm/vfp/vfpmodule.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c +index a71a48e71fffa8626fe90106815376c44bbe679b..d6c0a5a0a5ae3510db3ace5e3f5d341075193f99 100644 +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) + * case the thread migrates to a different CPU. The + * restoring is done lazily. + */ +- if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) ++ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) { ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + vfp_save_state(vfp_current_hw_state[cpu], fpexc); ++ } + #endif + + /* +@@ -463,13 +466,16 @@ static int vfp_pm_suspend(void) + /* if vfp is on, then save state for resumption */ + if (fpexc & FPEXC_EN) { + pr_debug("%s: saving vfp state\n", __func__); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + vfp_save_state(&ti->vfpstate, fpexc); + + /* disable, just in case */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); + } else if (vfp_current_hw_state[ti->cpu]) { + #ifndef CONFIG_SMP +- fmxr(FPEXC, fpexc | FPEXC_EN); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); + vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); + fmxr(FPEXC, fpexc); + #endif +@@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info *thread) + /* + * Save the last VFP state on this CPU. + */ +- fmxr(FPEXC, fpexc | FPEXC_EN); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); + vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); + fmxr(FPEXC, fpexc); + } +@@ -604,6 +611,7 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, + struct vfp_hard_struct *hwstate = &thread->vfpstate.hard; + unsigned long fpexc; + int err = 0; ++ u32 fpsid = fmrx(FPSID); + + /* Disable VFP to avoid corrupting the new thread state. */ + vfp_flush_hwstate(thread); +@@ -627,8 +635,12 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, + /* Ensure the VFP is enabled. */ + fpexc |= FPEXC_EN; + +- /* Ensure FPINST2 is invalid and the exception flag is cleared. */ +- fpexc &= ~(FPEXC_EX | FPEXC_FP2V); ++ /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */ ++ if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) { ++ /* Ensure FPINST2 is invalid and the exception flag is cleared. */ ++ fpexc &= ~(FPEXC_EX | FPEXC_FP2V); ++ } ++ + hwstate->fpexc = fpexc; + + __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err); +@@ -698,7 +710,8 @@ void kernel_neon_begin(void) + cpu = get_cpu(); + + fpexc = fmrx(FPEXC) | FPEXC_EN; +- fmxr(FPEXC, fpexc); ++ /* vfp_save_state oopses on VFP11 if EX bit set */ ++ fmxr(FPEXC, fpexc & ~FPEXC_EX); + + /* + * Save the userland NEON/VFP state. Under UP, + +From c253cc202fd374a01e0673547646fb09bdf692f9 Mon Sep 17 00:00:00 2001 +From: Matt Flax +Date: Wed, 8 Mar 2017 21:13:24 +1100 +Subject: [PATCH 035/150] ASoC: bcm2835_i2s.c: relax the ch2 register setting + for 8 channels + +This patch allows ch2 registers to be set for 8 channels of audio. +--- + sound/soc/bcm/bcm2835-i2s.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c +index 6ba20498202ed36906b52096893a88867a79269f..56df7d8a43d0aac055a91b0d24aca8e1b4e308e4 100644 +--- a/sound/soc/bcm/bcm2835-i2s.c ++++ b/sound/soc/bcm/bcm2835-i2s.c +@@ -312,6 +312,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, + + switch (params_channels(params)) { + case 2: ++ case 8: + format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format); + format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos)); + format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos)); + +From 3ae97a5f1b1763ba259ebcd4be0983611947f9af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= +Date: Tue, 1 Nov 2016 15:15:41 +0100 +Subject: [PATCH 036/150] i2c: bcm2835: Add debug support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This adds a debug module parameter to aid in debugging transfer issues +by printing info to the kernel log. When enabled, status values are +collected in the interrupt routine and msg info in +bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid +affecting timing. Having printk in the isr can mask issues. + +debug values (additive): +1: Print info on error +2: Print info on all transfers +3: Print messages before transfer is started + +The value can be changed at runtime: +/sys/module/i2c_bcm2835/parameters/debug + +Example output, debug=3: +[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] +[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] +[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] +[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] +[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] + +Signed-off-by: Noralf Trønnes +--- + drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 98 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c +index cd07a69e2e9355540442785f95e90823b05c9d10..47167f403cc8329bd811b47c7011c299b8ecafee 100644 +--- a/drivers/i2c/busses/i2c-bcm2835.c ++++ b/drivers/i2c/busses/i2c-bcm2835.c +@@ -53,6 +53,18 @@ + #define BCM2835_I2C_CDIV_MIN 0x0002 + #define BCM2835_I2C_CDIV_MAX 0xFFFE + ++static unsigned int debug; ++module_param(debug, uint, 0644); ++MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); ++ ++#define BCM2835_DEBUG_MAX 512 ++struct bcm2835_debug { ++ struct i2c_msg *msg; ++ int msg_idx; ++ size_t remain; ++ u32 status; ++}; ++ + struct bcm2835_i2c_dev { + struct device *dev; + void __iomem *regs; +@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { + u32 msg_err; + u8 *msg_buf; + size_t msg_buf_remaining; ++ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; ++ unsigned int debug_num; ++ unsigned int debug_num_msgs; + }; + ++static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) ++{ ++ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ return; ++ ++ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; ++ i2c_dev->debug[i2c_dev->debug_num].msg_idx = ++ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; ++ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; ++ i2c_dev->debug[i2c_dev->debug_num].status = s; ++ i2c_dev->debug_num++; ++} ++ ++static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, ++ struct bcm2835_debug *d) ++{ ++ u32 s = d->status; ++ ++ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", ++ d->remain, s, ++ s & BCM2835_I2C_S_TA ? "TA " : "", ++ s & BCM2835_I2C_S_DONE ? "DONE " : "", ++ s & BCM2835_I2C_S_TXW ? "TXW " : "", ++ s & BCM2835_I2C_S_RXR ? "RXR " : "", ++ s & BCM2835_I2C_S_TXD ? "TXD " : "", ++ s & BCM2835_I2C_S_RXD ? "RXD " : "", ++ s & BCM2835_I2C_S_TXE ? "TXE " : "", ++ s & BCM2835_I2C_S_RXF ? "RXF " : "", ++ s & BCM2835_I2C_S_ERR ? "ERR " : "", ++ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, ++ struct i2c_msg *msg, int i, int total, ++ const char *fname) ++{ ++ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", ++ fname, i, total, ++ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, ++ msg->flags & I2C_M_TEN ? "TEN" : "", ++ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", ++ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", ++ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", ++ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", ++ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", ++ msg->flags & I2C_M_STOP ? "STOP" : "", ++ i2c_dev->adapter.nr); ++} ++ ++static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) ++{ ++ struct bcm2835_debug *d; ++ unsigned int i; ++ ++ for (i = 0; i < i2c_dev->debug_num; i++) { ++ d = &i2c_dev->debug[i]; ++ if (d->status == ~0) ++ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, ++ i2c_dev->debug_num_msgs, "start_transfer"); ++ else ++ bcm2835_debug_print_status(i2c_dev, d); ++ } ++ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) ++ pr_info("BCM2835_DEBUG_MAX reached\n"); ++} ++ + static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, + u32 reg, u32 val) + { +@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); ++ bcm2835_debug_add(i2c_dev, ~0); + } + + /* +@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) + u32 val, err; + + val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); ++ bcm2835_debug_add(i2c_dev, val); + + err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); + if (err) { +@@ -253,6 +337,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + unsigned long time_left; + int i, ret; + ++ if (debug) ++ i2c_dev->debug_num_msgs = num; ++ ++ if (debug > 2) ++ for (i = 0; i < num; i++) ++ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); ++ + for (i = 0; i < (num - 1); i++) + if (msgs[i].flags & I2C_M_RD) { + dev_warn_once(i2c_dev->dev, +@@ -272,6 +363,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + + time_left = wait_for_completion_timeout(&i2c_dev->completion, + adap->timeout); ++ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) ++ bcm2835_debug_print(i2c_dev); ++ i2c_dev->debug_num_msgs = 0; ++ i2c_dev->debug_num = 0; + if (!time_left) { + bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, + BCM2835_I2C_C_CLEAR); +@@ -282,7 +377,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], + if (!i2c_dev->msg_err) + return num; + +- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); ++ if (debug) ++ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", ++ i2c_dev->msg_err); + + if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) + return -EREMOTEIO; + +From 56e119674e6af3bf05fb2df0660c25e8edae61f3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 027/216] Main bcm2708/bcm2709 linux port +Subject: [PATCH 037/150] Main bcm2708/bcm2709 linux port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -1696,11 +2402,11 @@ Make use of this and remove the code from the platform files. Signed-off-by: Noralf Trønnes --- arch/arm/mach-bcm/Kconfig | 1 + - arch/arm/mach-bcm/board_bcm2835.c | 17 +++++++++++++++++ + arch/arm/mach-bcm/board_bcm2835.c | 9 +++++++++ arch/arm/mm/proc-v6.S | 15 ++++++++++++--- drivers/irqchip/irq-bcm2835.c | 7 ++++++- drivers/mailbox/bcm2835-mailbox.c | 18 ++++++++++++++++-- - 5 files changed, 52 insertions(+), 6 deletions(-) + 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 4ff30d5278a7ce093c9629d4c25d37e3bbbda752..333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20 100644 @@ -1715,16 +2421,10 @@ index 4ff30d5278a7ce093c9629d4c25d37e3bbbda752..333dc3c2e5ffbb2c5ab8fcfb6115b616 This enables support for the Broadcom BCM2835 and BCM2836 SoCs. This SoC is used in the Raspberry Pi and Roku 2 devices. diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c -index 8f152266ba9b470df2eaaed9ebcf158ed2079834..133338f0a21237fda9b7660d2c57a33b991f08ae 100644 +index 8f152266ba9b470df2eaaed9ebcf158ed2079834..9131e56e446a84db42eb97d7f34994aafd516bc5 100644 --- a/arch/arm/mach-bcm/board_bcm2835.c +++ b/arch/arm/mach-bcm/board_bcm2835.c -@@ -16,17 +16,21 @@ - #include - #include - #include -+#include - #include - +@@ -21,6 +21,8 @@ #include #include @@ -1733,14 +2433,7 @@ index 8f152266ba9b470df2eaaed9ebcf158ed2079834..133338f0a21237fda9b7660d2c57a33b static void __init bcm2835_init(void) { struct device_node *np = of_find_node_by_path("/system"); - u32 val; - u64 val64; - -+ vc_cma_early_init(); - bcm2835_init_clocks(); - - if (!of_property_read_u32(np, "linux,revision", &val)) -@@ -35,6 +39,17 @@ static void __init bcm2835_init(void) +@@ -35,6 +37,12 @@ static void __init bcm2835_init(void) system_serial_low = val64; } @@ -1749,20 +2442,14 @@ index 8f152266ba9b470df2eaaed9ebcf158ed2079834..133338f0a21237fda9b7660d2c57a33b + /* dwc_otg needs this for bounce buffers on non-aligned transfers */ + init_dma_coherent_pool_size(SZ_1M); +} -+ -+static void __init bcm2835_board_reserve(void) -+{ -+ vc_cma_reserve(); -+} + static const char * const bcm2835_compat[] = { #ifdef CONFIG_ARCH_MULTI_V6 "brcm,bcm2835", -@@ -47,5 +62,7 @@ static const char * const bcm2835_compat[] = { +@@ -47,5 +55,6 @@ static const char * const bcm2835_compat[] = { DT_MACHINE_START(BCM2835, "BCM2835") .init_machine = bcm2835_init, -+ .reserve = bcm2835_board_reserve, + .init_early = bcm2835_init_early, .dt_compat = bcm2835_compat MACHINE_END @@ -1879,10 +2566,10 @@ index cfb4b4496dd9f61362dea012176c146120fada07..d9c6c217c4d6a2408abe2665bf7f2700 MODULE_AUTHOR("Lubomir Rintel "); MODULE_DESCRIPTION("BCM2835 mailbox IPC driver"); -From b7bac09fc64ade0cc047c151c9d576eb00ce81ba Mon Sep 17 00:00:00 2001 +From 926d0ae6ea2e5d7c76900570af6eb64cb4855fda Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 028/216] Add dwc_otg driver +Subject: [PATCH 038/150] Add dwc_otg driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -2382,6 +3069,12 @@ dwc_otg: Pass struct device to dma_alloc*() This makes it possible to get the bus address from Device Tree. Signed-off-by: Noralf Trønnes + +dwc_otg: fix summarize urb->actual_length for isochronous transfers + +Kernel does not copy input data of ISO transfers to userspace +if actual_length is set only in ISO transfers and not summarized +in urb->actual_length. Fixes raspberrypi/linux#903 --- arch/arm/include/asm/irqflags.h | 16 +- arch/arm/kernel/fiqasm.S | 4 + @@ -2440,7 +3133,7 @@ Signed-off-by: Noralf Trønnes drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1139 ++++ drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 417 ++ drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2727 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 1005 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 1007 +++ drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 963 +++ drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 188 + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2725 ++++++++ @@ -2453,7 +3146,7 @@ Signed-off-by: Noralf Trønnes drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 70 files changed, 59908 insertions(+), 16 deletions(-) + 70 files changed, 59910 insertions(+), 16 deletions(-) create mode 100644 drivers/usb/gadget/file_storage.c create mode 100644 drivers/usb/host/dwc_common_port/Makefile create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd @@ -2584,7 +3277,7 @@ index bd3e0c5a6db25e7a162d922c6508de1ad0b68025..15c80079c97bb9eeec478932af88a293 return i; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c -index 48fbf523d186e21802ad21a1590ab2e4a9fb7f87..f3dbdbe0a779490316d3c90099a1864cad71b239 100644 +index 5286bf67869a83e1d7e1d3f1ca0ebc87db5cf7a4..509caca9f86d9d43279476ae53bab964c10a9cd0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5018,7 +5018,7 @@ static void port_event(struct usb_hub *hub, int port1) @@ -2597,10 +3290,10 @@ index 48fbf523d186e21802ad21a1590ab2e4a9fb7f87..f3dbdbe0a779490316d3c90099a1864c 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 dea55914d6410c5b472c36562864baee3143bf86..17fbb7bfd2c92d84169281008915453f5b8f949b 100644 +index 2184ef40a82ae494c11e82b4090545bd0dad30c8..39e932ea9a0e80aea29101ac5bb02f2fc35cae56 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c -@@ -1911,6 +1911,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) +@@ -1908,6 +1908,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -6526,7 +7219,7 @@ index 0000000000000000000000000000000000000000..a896d73f7a9336f5a34015c44ea5a6b0 +} +module_exit(fsg_cleanup); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 6361fc73930669750317b4fa4e995d74e8954e3c..99bc52546b8c912de72b4381ba8cf8e8ad61d7ee 100644 +index 407d947b34ea5b524c467c7c992d9774ded5414a..ed0cd59de37e8f47369f86dba751c78933722abc 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -763,6 +763,19 @@ config USB_HWA_HCD @@ -47690,10 +48383,10 @@ index 0000000000000000000000000000000000000000..e6b38ac330b72152204c2a6879c20f0c +#endif /* DWC_DEVICE_ONLY */ diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c new file mode 100644 -index 0000000000000000000000000000000000000000..74cd5fa54aed5241b61371477ef67d706477fd30 +index 0000000000000000000000000000000000000000..96ec6338bbcb8ebe69a233d21a4b9d244ff6fe95 --- /dev/null +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -0,0 +1,1005 @@ +@@ -0,0 +1,1007 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ @@ -48021,10 +48714,12 @@ index 0000000000000000000000000000000000000000..74cd5fa54aed5241b61371477ef67d70 + int i; + + urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); ++ urb->actual_length = 0; + for (i = 0; i < urb->number_of_packets; ++i) { + urb->iso_frame_desc[i].actual_length = + dwc_otg_hcd_urb_get_iso_desc_actual_length + (dwc_otg_urb, i); ++ urb->actual_length += urb->iso_frame_desc[i].actual_length; + urb->iso_frame_desc[i].status = + dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); + } @@ -62939,10 +63634,10 @@ index 0000000000000000000000000000000000000000..cdc9963176e5a4a0d5250613b61e26c5 +test_main(); +0; -From ba285a7e7c888b89bf9e5f6d180387167facc47c Mon Sep 17 00:00:00 2001 +From 5ca9b4aba0e463a01232c6ebf133800b52df2614 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 17:06:34 +0100 -Subject: [PATCH 029/216] bcm2708 framebuffer driver +Subject: [PATCH 039/150] bcm2708 framebuffer driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -63024,10 +63719,10 @@ 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 5d3b0db5ce0af34997a3aa748292b6bd8d48c191..0ff4f80531e013f028ca4d05559c5464f8cfa5ef 100644 +index 922e4eaed9c5b5278572a79eb1cfc14e267a8bd5..2fae1676fafc16900d56622e3eef887e27b01eed 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -228,6 +228,20 @@ config FB_TILEBLITTING +@@ -236,6 +236,20 @@ config FB_TILEBLITTING comment "Frame buffer hardware drivers" depends on FB @@ -66401,10 +67096,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 694ab881864aad37571a604488ff0d71df414246 Mon Sep 17 00:00:00 2001 +From f220a92de0e2787135019e7601a76a1cff03833b Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 14:22:53 +0100 -Subject: [PATCH 030/216] dmaengine: Add support for BCM2708 +Subject: [PATCH 040/150] dmaengine: Add support for BCM2708 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -66563,7 +67258,7 @@ bcm2708-dmaengine - Fix arm64 portability/build issues create mode 100644 include/linux/platform_data/dma-bcm2708.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig -index 4415a37a1d84c696efa96bf0b17840d6c0dd3b12..6f3aba9c1f8d35d9abb25ecc4a51825a922a4c03 100644 +index a754288fb8bec3dafea4952f5133703f4e42f7df..5485ce0b2004d87e0ac012e2559479b1f7da28e5 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -108,7 +108,7 @@ config COH901318 @@ -66587,7 +67282,7 @@ index 4415a37a1d84c696efa96bf0b17840d6c0dd3b12..6f3aba9c1f8d35d9abb25ecc4a51825a tristate "AM33xx CPPI41 DMA support" depends on ARCH_OMAP diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile -index a4fa3360e609d1ef81bf89dc7086b76e6ae52048..853a30a5f4500b54e33cb61d3b99137d4198925c 100644 +index 0b723e94d9e6d3751d1ceea4509b173cbd84b458..a114b110fc2277615ca2e3f4c58a9a20166ee58b 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_AT_HDMAC) += at_hdmac.o @@ -67035,10 +67730,10 @@ index 0000000000000000000000000000000000000000..c5bfff2765be4606077e6c8af73040ec + +#endif /* _PLAT_BCM2708_DMA_H */ -From 18b4ffa6713787e118fb204c48c9fcee4a5ec675 Mon Sep 17 00:00:00 2001 +From bda941c478284aa0effe756e60a02b91017ad274 Mon Sep 17 00:00:00 2001 From: gellert Date: Fri, 15 Aug 2014 16:35:06 +0100 -Subject: [PATCH 031/216] MMC: added alternative MMC driver +Subject: [PATCH 041/150] MMC: added alternative MMC driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -67121,42 +67816,14 @@ See: https://github.com/raspberrypi/linux/issues/1327 Signed-off-by: Phil Elwell --- - drivers/mmc/core/quirks.c | 10 + drivers/mmc/host/Kconfig | 29 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/bcm2835-mmc.c | 1574 ++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 1614 insertions(+) + 3 files changed, 1604 insertions(+) create mode 100644 drivers/mmc/host/bcm2835-mmc.c -diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c -index ca9cade317c7eccee354bb1a075b091f59a62de1..5e9e3518e0eb6be78f6e2847846a90ddd0febb77 100644 ---- a/drivers/mmc/core/quirks.c -+++ b/drivers/mmc/core/quirks.c -@@ -53,6 +53,9 @@ static const struct mmc_fixup mmc_fixup_methods[] = { - - void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - { -+#ifdef CONFIG_MMC_BCM2835 -+ extern unsigned mmc_debug; -+#endif - const struct mmc_fixup *f; - u64 rev = cid_rev_card(card); - -@@ -79,5 +82,12 @@ void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) - f->vendor_fixup(card, f->data); - } - } -+ /* SDHCI on BCM2708 - bug causes a certain sequence of CMD23 operations to fail. -+ * Disable this flag for all cards (fall-back to CMD25/CMD18 multi-block transfers). -+ */ -+#ifdef CONFIG_MMC_BCM2835 -+ if (mmc_debug & (1<<13)) -+ card->quirks |= MMC_QUIRK_BLK_NO_CMD23; -+#endif - } - EXPORT_SYMBOL(mmc_fixup_device); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 2eb97014dc3f2073c3b471688ba31598d023bc9e..ffa08df2adb9072de7f6e7662cd07239b97c2aea 100644 +index f08691a58d7e02220e8a3ef7d6c552eef7c2a79d..77142222a730b76d46a2492fef8f6f1773072687 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -4,6 +4,35 @@ @@ -67196,7 +67863,7 @@ index 2eb97014dc3f2073c3b471688ba31598d023bc9e..ffa08df2adb9072de7f6e7662cd07239 tristate "ARM AMBA Multimedia Card Interface support" depends on ARM_AMBA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index ccc9c4cba154c6ba1849151353526e555d63c8a6..821366b1bb4d206523794382bf9b14ce37a9cb17 100644 +index 6d548c4ee2fa311ce75b02bbbdd3ca53e9d68788..c987038c9f3a1cea98931efe868c933b767c1664 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o @@ -68788,10 +69455,10 @@ index 0000000000000000000000000000000000000000..4fe8d1fe44578fbefcd48f8c327ba3d0 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); -From 3aa02ae95b691a9223ff61b6ec5836719db9deb2 Mon Sep 17 00:00:00 2001 +From 834ade8254834159be9ae2ba41dfb4722efd9c8c Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 25 Mar 2015 17:49:47 +0000 -Subject: [PATCH 032/216] Adding bcm2835-sdhost driver, and an overlay to +Subject: [PATCH 042/150] Adding bcm2835-sdhost driver, and an overlay to enable it BCM2835 has two SD card interfaces. This driver uses the other one. @@ -68952,25 +69619,16 @@ See: https://github.com/raspberrypi/linux/pull/1492 Signed-off-by: Phil Elwell --- - drivers/mmc/host/Kconfig | 12 +- + drivers/mmc/host/Kconfig | 10 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/bcm2835-sdhost.c | 2189 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 2201 insertions(+), 1 deletion(-) + 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 ffa08df2adb9072de7f6e7662cd07239b97c2aea..0015d8ad85b565ed789d7dd9dc056a8014614e4c 100644 +index 77142222a730b76d46a2492fef8f6f1773072687..94f0a180596cba76e67edac5b9f3797215109e18 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig -@@ -6,7 +6,7 @@ comment "MMC/SD/SDIO Host Controller Drivers" - - config MMC_BCM2835 - tristate "MMC support on BCM2835" -- depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835 -+ depends on ARCH_BCM2835 - help - This selects the MMC Interface on BCM2835. - @@ -33,6 +33,16 @@ config MMC_BCM2835_PIO_DMA_BARRIER If unsure, say 2 here. @@ -68989,17 +69647,17 @@ index ffa08df2adb9072de7f6e7662cd07239b97c2aea..0015d8ad85b565ed789d7dd9dc056a80 tristate "ARM AMBA Multimedia Card Interface support" depends on ARM_AMBA diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index 821366b1bb4d206523794382bf9b14ce37a9cb17..62ef8f9b100876d876590b12fe94b8d45fbb5c8c 100644 +index c987038c9f3a1cea98931efe868c933b767c1664..9f7e1930f8e85e8994a8d3e7d2537cc1903ba3dc 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o - obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o +@@ -19,6 +19,7 @@ obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o -+obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o obj-$(CONFIG_MMC_BCM2835) += bcm2835-mmc.o ++obj-$(CONFIG_MMC_BCM2835_SDHOST) += bcm2835-sdhost.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o + obj-$(CONFIG_MMC_MTK) += mtk-sd.o diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c new file mode 100644 index 0000000000000000000000000000000000000000..a9bc79bfdbb71807819dfe2d8f1651445997f92a @@ -71196,4226 +71854,10 @@ index 0000000000000000000000000000000000000000..a9bc79bfdbb71807819dfe2d8f165144 +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Phil Elwell"); -From af09dc1c1feb0fefd75badf3b228561e919d524a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 11 May 2016 12:50:33 +0100 -Subject: [PATCH 033/216] 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, -and set it for cards of that type. - -Signed-off-by: Phil Elwell - -mmc: Apply QUIRK_BROKEN_ERASE to other capacities - -Signed-off-by: Phil Elwell - -mmc: Add card_quirks module parameter, log quirks - -Use mmc_block.card_quirks to override the quirks for all SD or MMC -cards. The value is a bitfield using the bit positions defined in -include/linux/mmc/card.h. If the module parameter is placed in the -kernel command line (or bootargs) stored on the card then, assuming the -device only has one SD card interface, the override effectively becomes -card-specific. - -Signed-off-by: Phil Elwell ---- - drivers/mmc/core/block.c | 39 ++++++++++++++++++++++++++++++++++++--- - drivers/mmc/core/core.c | 3 ++- - include/linux/mmc/card.h | 3 +++ - 3 files changed, 41 insertions(+), 4 deletions(-) - -diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c -index 7f4927a05be0ab0d4054e090ea5aa6fa7dbe80a7..3114c3ba207d21aaaa612f61a22845b5eb9cc399 100644 ---- a/drivers/mmc/core/block.c -+++ b/drivers/mmc/core/block.c -@@ -125,6 +125,13 @@ static DEFINE_MUTEX(open_lock); - module_param(perdev_minors, int, 0444); - MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); - -+/* -+ * Allow quirks to be overridden for the current card -+ */ -+static char *card_quirks; -+module_param(card_quirks, charp, 0644); -+MODULE_PARM_DESC(card_quirks, "Force the use of the indicated quirks (a bitfield)"); -+ - 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); -@@ -2165,6 +2172,17 @@ static const struct mmc_fixup blk_fixups[] = - MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, - MMC_QUIRK_TRIM_BROKEN), - -+ /* -+ * 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), -+ - END_FIXUP - }; - -@@ -2172,6 +2190,7 @@ static int mmc_blk_probe(struct mmc_card *card) - { - struct mmc_blk_data *md, *part_md; - char cap_str[10]; -+ char quirk_str[24]; - - /* - * Check that the card supports the command class(es) we need. -@@ -2179,7 +2198,16 @@ static int mmc_blk_probe(struct mmc_card *card) - if (!(card->csd.cmdclass & CCC_BLOCK_READ)) - return -ENODEV; - -- mmc_fixup_device(card, blk_fixups); -+ if (card_quirks) { -+ unsigned long quirks; -+ if (kstrtoul(card_quirks, 0, &quirks) == 0) -+ card->quirks = (unsigned int)quirks; -+ else -+ pr_err("mmc_block: Invalid card_quirks parameter '%s'\n", -+ card_quirks); -+ } -+ else -+ mmc_fixup_device(card, blk_fixups); - - md = mmc_blk_alloc(card); - if (IS_ERR(md)) -@@ -2187,9 +2215,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)); -- pr_info("%s: %s %s %s %s\n", -+ if (card->quirks) -+ snprintf(quirk_str, sizeof(quirk_str), -+ " (quirks 0x%08x)", card->quirks); -+ else -+ quirk_str[0] = '\0'; -+ pr_info("%s: %s %s %s%s%s\n", - md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), -- cap_str, md->read_only ? "(ro)" : ""); -+ cap_str, md->read_only ? " (ro)" : "", quirk_str); - - if (mmc_blk_alloc_parts(card, md)) - goto out; -diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c -index 1076b9d89df38e26bfb088fae3586a6c577fd70e..06907db55a930e4a03dfa13cf1c93c867c7e4aba 100644 ---- a/drivers/mmc/core/core.c -+++ b/drivers/mmc/core/core.c -@@ -2386,7 +2386,8 @@ EXPORT_SYMBOL(mmc_erase); - int mmc_can_erase(struct mmc_card *card) - { - if ((card->host->caps & MMC_CAP_ERASE) && -- (card->csd.cmdclass & CCC_ERASE) && card->erase_size) -+ (card->csd.cmdclass & CCC_ERASE) && card->erase_size && -+ !(card->quirks & MMC_QUIRK_ERASE_BROKEN)) - return 1; - return 0; - } -diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h -index 95d69d4982965aa30fb65d9ffecfad13f4e7be8f..a97b881a04f4b3294cf3ede393cde7178a3e9aff 100644 ---- a/include/linux/mmc/card.h -+++ b/include/linux/mmc/card.h -@@ -273,6 +273,9 @@ struct mmc_card { - #define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */ - - -+#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */ -+ -+ - unsigned int erase_size; /* erase size in sectors */ - unsigned int erase_shift; /* if erase unit is power 2 */ - unsigned int pref_erase; /* in sectors */ - -From 9043217dd23b8ebd7c1036cbc15fce37c4242257 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 034/216] 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 - -Signed-off-by: popcornmix - -vc_cma: Make the vc_cma area the default contiguous DMA area - -vc_cma: Provide empty functions when module is not built - -Providing empty functions saves the users from guarding the -function call with an #if clause. -Move __init markings from prototypes to functions. - -Signed-off-by: Noralf Trønnes ---- - drivers/char/Kconfig | 2 + - drivers/char/Makefile | 1 + - drivers/char/broadcom/Kconfig | 15 + - drivers/char/broadcom/Makefile | 1 + - drivers/char/broadcom/vc_cma/Makefile | 7 + - drivers/char/broadcom/vc_cma/vc_cma.c | 1193 +++++++++++++++++++++++++++++++++ - include/linux/broadcom/vc_cma.h | 36 + - 7 files changed, 1255 insertions(+) - create mode 100644 drivers/char/broadcom/Kconfig - create mode 100644 drivers/char/broadcom/Makefile - create mode 100644 drivers/char/broadcom/vc_cma/Makefile - create mode 100644 drivers/char/broadcom/vc_cma/vc_cma.c - create mode 100644 include/linux/broadcom/vc_cma.h - -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index 4ee2a10207d0eee59163ce52ef5d8643e7acc7ca..5c5644dec3f6bb2fee1d7a4dd3c10cc3835e8ff0 100644 ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -4,6 +4,8 @@ - - menu "Character devices" - -+source "drivers/char/broadcom/Kconfig" -+ - source "drivers/tty/Kconfig" - - config DEVMEM -diff --git a/drivers/char/Makefile b/drivers/char/Makefile -index 6e6c244a66a02c4efd57229b0f31d331377bbc55..67c40b8f2ff25f423cb74b64de9afa6f32479aed 100644 ---- a/drivers/char/Makefile -+++ b/drivers/char/Makefile -@@ -60,3 +60,4 @@ js-rtc-y = rtc.o - obj-$(CONFIG_TILE_SROM) += tile-srom.o - obj-$(CONFIG_XILLYBUS) += xillybus/ - obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o -+obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/ -diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..89d6fac780410e370ca2316b357e599c7eb5a9b3 ---- /dev/null -+++ b/drivers/char/broadcom/Kconfig -@@ -0,0 +1,15 @@ -+# -+# Broadcom char driver config -+# -+ -+menuconfig BRCM_CHAR_DRIVERS -+ bool "Broadcom Char Drivers" -+ help -+ Broadcom's char drivers -+ -+config BCM_VC_CMA -+ bool "Videocore CMA" -+ depends on CMA && BRCM_CHAR_DRIVERS && BCM2835_VCHIQ -+ default n -+ help -+ Helper for videocore CMA access. -diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..13c5bca291ccc0df090c4e61169ace8f18ba60fe ---- /dev/null -+++ b/drivers/char/broadcom/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ -diff --git a/drivers/char/broadcom/vc_cma/Makefile b/drivers/char/broadcom/vc_cma/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..d222313e28995bb54e9448192f5c99a352dde2e8 ---- /dev/null -+++ b/drivers/char/broadcom/vc_cma/Makefile -@@ -0,0 +1,7 @@ -+ccflags-$(CONFIG_BCM_VC_CMA) += -Wall -Wstrict-prototypes -Wno-trigraphs -Werror -+ccflags-$(CONFIG_BCM_VC_CMA) += -Iinclude/linux/broadcom -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vchi -Idrivers/staging/vc04_services/interface/vchiq_arm -+ccflags-$(CONFIG_BCM_VC_CMA) += -D__KERNEL__ -D__linux__ -+ -+obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o -+ -+vc-cma-objs := vc_cma.o -diff --git a/drivers/char/broadcom/vc_cma/vc_cma.c b/drivers/char/broadcom/vc_cma/vc_cma.c -new file mode 100644 -index 0000000000000000000000000000000000000000..85f6e9da9e5baa0abfba618a171881c078f38496 ---- /dev/null -+++ b/drivers/char/broadcom/vc_cma/vc_cma.c -@@ -0,0 +1,1193 @@ -+/** -+ * Copyright (c) 2010-2012 Broadcom. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") version 2, as published by the Free -+ * Software Foundation. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "vc_cma.h" -+ -+#include "vchiq_util.h" -+#include "vchiq_connected.h" -+//#include "debug_sym.h" -+//#include "vc_mem.h" -+ -+#define DRIVER_NAME "vc-cma" -+ -+#define LOG_DBG(fmt, ...) \ -+ if (vc_cma_debug) \ -+ printk(KERN_INFO fmt "\n", ##__VA_ARGS__) -+#define LOG_INFO(fmt, ...) \ -+ printk(KERN_INFO fmt "\n", ##__VA_ARGS__) -+#define LOG_ERR(fmt, ...) \ -+ printk(KERN_ERR fmt "\n", ##__VA_ARGS__) -+ -+#define VC_CMA_FOURCC VCHIQ_MAKE_FOURCC('C', 'M', 'A', ' ') -+#define VC_CMA_VERSION 2 -+ -+#define VC_CMA_CHUNK_ORDER 6 /* 256K */ -+#define VC_CMA_CHUNK_SIZE (4096 << VC_CMA_CHUNK_ORDER) -+#define VC_CMA_MAX_PARAMS_PER_MSG \ -+ ((VCHIQ_MAX_MSG_SIZE - sizeof(unsigned short))/sizeof(unsigned short)) -+#define VC_CMA_RESERVE_COUNT_MAX 16 -+ -+#define PAGES_PER_CHUNK (VC_CMA_CHUNK_SIZE / PAGE_SIZE) -+ -+#define VCADDR_TO_PHYSADDR(vcaddr) (mm_vc_mem_phys_addr + vcaddr) -+ -+#define loud_error(...) \ -+ LOG_ERR("===== " __VA_ARGS__) -+ -+enum { -+ VC_CMA_MSG_QUIT, -+ VC_CMA_MSG_OPEN, -+ VC_CMA_MSG_TICK, -+ VC_CMA_MSG_ALLOC, /* chunk count */ -+ VC_CMA_MSG_FREE, /* chunk, chunk, ... */ -+ VC_CMA_MSG_ALLOCATED, /* chunk, chunk, ... */ -+ VC_CMA_MSG_REQUEST_ALLOC, /* chunk count */ -+ VC_CMA_MSG_REQUEST_FREE, /* chunk count */ -+ VC_CMA_MSG_RESERVE, /* bytes lo, bytes hi */ -+ VC_CMA_MSG_UPDATE_RESERVE, -+ VC_CMA_MSG_MAX -+}; -+ -+struct cma_msg { -+ unsigned short type; -+ unsigned short params[VC_CMA_MAX_PARAMS_PER_MSG]; -+}; -+ -+struct vc_cma_reserve_user { -+ unsigned int pid; -+ unsigned int reserve; -+}; -+ -+/* Device (/dev) related variables */ -+static dev_t vc_cma_devnum; -+static struct class *vc_cma_class; -+static struct cdev vc_cma_cdev; -+static int vc_cma_inited; -+static int vc_cma_debug; -+ -+/* Proc entry */ -+static struct proc_dir_entry *vc_cma_proc_entry; -+ -+phys_addr_t vc_cma_base; -+struct page *vc_cma_base_page; -+unsigned int vc_cma_size; -+EXPORT_SYMBOL(vc_cma_size); -+unsigned int vc_cma_initial; -+unsigned int vc_cma_chunks; -+unsigned int vc_cma_chunks_used; -+unsigned int vc_cma_chunks_reserved; -+ -+ -+void *vc_cma_dma_alloc; -+unsigned int vc_cma_dma_size; -+ -+static int in_loud_error; -+ -+unsigned int vc_cma_reserve_total; -+unsigned int vc_cma_reserve_count; -+struct vc_cma_reserve_user vc_cma_reserve_users[VC_CMA_RESERVE_COUNT_MAX]; -+static DEFINE_SEMAPHORE(vc_cma_reserve_mutex); -+static DEFINE_SEMAPHORE(vc_cma_worker_queue_push_mutex); -+ -+static u64 vc_cma_dma_mask = DMA_BIT_MASK(32); -+static struct platform_device vc_cma_device = { -+ .name = "vc-cma", -+ .id = 0, -+ .dev = { -+ .dma_mask = &vc_cma_dma_mask, -+ .coherent_dma_mask = DMA_BIT_MASK(32), -+ }, -+}; -+ -+static VCHIQ_INSTANCE_T cma_instance; -+static VCHIQ_SERVICE_HANDLE_T cma_service; -+static VCHIU_QUEUE_T cma_msg_queue; -+static struct task_struct *cma_worker; -+ -+static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid); -+static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply); -+static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T * header, -+ VCHIQ_SERVICE_HANDLE_T service, -+ void *bulk_userdata); -+static void send_vc_msg(unsigned short type, -+ unsigned short param1, unsigned short param2); -+static bool send_worker_msg(VCHIQ_HEADER_T * msg); -+ -+static int early_vc_cma_mem(char *p) -+{ -+ unsigned int new_size; -+ printk(KERN_NOTICE "early_vc_cma_mem(%s)", p); -+ vc_cma_size = memparse(p, &p); -+ vc_cma_initial = vc_cma_size; -+ if (*p == '/') -+ vc_cma_size = memparse(p + 1, &p); -+ if (*p == '@') -+ vc_cma_base = memparse(p + 1, &p); -+ -+ new_size = (vc_cma_size - ((-vc_cma_base) & (VC_CMA_CHUNK_SIZE - 1))) -+ & ~(VC_CMA_CHUNK_SIZE - 1); -+ if (new_size > vc_cma_size) -+ vc_cma_size = 0; -+ vc_cma_initial = (vc_cma_initial + VC_CMA_CHUNK_SIZE - 1) -+ & ~(VC_CMA_CHUNK_SIZE - 1); -+ if (vc_cma_initial > vc_cma_size) -+ vc_cma_initial = vc_cma_size; -+ vc_cma_base = (vc_cma_base + VC_CMA_CHUNK_SIZE - 1) -+ & ~(VC_CMA_CHUNK_SIZE - 1); -+ -+ printk(KERN_NOTICE " -> initial %x, size %x, base %x", vc_cma_initial, -+ vc_cma_size, (unsigned int)vc_cma_base); -+ -+ return 0; -+} -+ -+early_param("vc-cma-mem", early_vc_cma_mem); -+ -+void __init vc_cma_early_init(void) -+{ -+ LOG_DBG("vc_cma_early_init - vc_cma_chunks = %d", vc_cma_chunks); -+ if (vc_cma_size) { -+ int rc = platform_device_register(&vc_cma_device); -+ LOG_DBG("platform_device_register -> %d", rc); -+ } -+} -+ -+void __init vc_cma_reserve(void) -+{ -+ /* if vc_cma_size is set, then declare vc CMA area of the same -+ * size from the end of memory -+ */ -+ if (vc_cma_size) { -+ if (dma_declare_contiguous(&vc_cma_device.dev, vc_cma_size, -+ vc_cma_base, 0) == 0) { -+ if (!dev_get_cma_area(NULL)) { -+ /* There is no default CMA area - make this -+ the default */ -+ struct cma *vc_cma_area = dev_get_cma_area( -+ &vc_cma_device.dev); -+ dma_contiguous_set_default(vc_cma_area); -+ LOG_INFO("vc_cma_reserve - using vc_cma as " -+ "the default contiguous DMA area"); -+ } -+ } else { -+ LOG_ERR("vc_cma: dma_declare_contiguous(%x,%x) failed", -+ vc_cma_size, (unsigned int)vc_cma_base); -+ vc_cma_size = 0; -+ } -+ } -+ vc_cma_chunks = vc_cma_size / VC_CMA_CHUNK_SIZE; -+} -+ -+/**************************************************************************** -+* -+* vc_cma_open -+* -+***************************************************************************/ -+ -+static int vc_cma_open(struct inode *inode, struct file *file) -+{ -+ (void)inode; -+ (void)file; -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_cma_release -+* -+***************************************************************************/ -+ -+static int vc_cma_release(struct inode *inode, struct file *file) -+{ -+ (void)inode; -+ (void)file; -+ -+ vc_cma_set_reserve(0, current->tgid); -+ -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_cma_ioctl -+* -+***************************************************************************/ -+ -+static long vc_cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ int rc = 0; -+ -+ (void)cmd; -+ (void)arg; -+ -+ switch (cmd) { -+ case VC_CMA_IOC_RESERVE: -+ rc = vc_cma_set_reserve((unsigned int)arg, current->tgid); -+ if (rc >= 0) -+ rc = 0; -+ break; -+ default: -+ LOG_ERR("vc-cma: Unknown ioctl %x", cmd); -+ return -ENOTTY; -+ } -+ -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for the driver. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_cma_fops = { -+ .owner = THIS_MODULE, -+ .open = vc_cma_open, -+ .release = vc_cma_release, -+ .unlocked_ioctl = vc_cma_ioctl, -+}; -+ -+/**************************************************************************** -+* -+* vc_cma_proc_open -+* -+***************************************************************************/ -+ -+static int vc_cma_show_info(struct seq_file *m, void *v) -+{ -+ int i; -+ -+ seq_printf(m, "Videocore CMA:\n"); -+ seq_printf(m, " Base : %08x\n", (unsigned int)vc_cma_base); -+ seq_printf(m, " Length : %08x\n", vc_cma_size); -+ seq_printf(m, " Initial : %08x\n", vc_cma_initial); -+ seq_printf(m, " Chunk size : %08x\n", VC_CMA_CHUNK_SIZE); -+ seq_printf(m, " Chunks : %4d (%d bytes)\n", -+ (int)vc_cma_chunks, -+ (int)(vc_cma_chunks * VC_CMA_CHUNK_SIZE)); -+ seq_printf(m, " Used : %4d (%d bytes)\n", -+ (int)vc_cma_chunks_used, -+ (int)(vc_cma_chunks_used * VC_CMA_CHUNK_SIZE)); -+ seq_printf(m, " Reserved : %4d (%d bytes)\n", -+ (unsigned int)vc_cma_chunks_reserved, -+ (int)(vc_cma_chunks_reserved * VC_CMA_CHUNK_SIZE)); -+ -+ for (i = 0; i < vc_cma_reserve_count; i++) { -+ struct vc_cma_reserve_user *user = &vc_cma_reserve_users[i]; -+ seq_printf(m, " PID %5d: %d bytes\n", user->pid, -+ user->reserve); -+ } -+ seq_printf(m, " dma_alloc : %p (%d pages)\n", -+ vc_cma_dma_alloc ? page_address(vc_cma_dma_alloc) : 0, -+ vc_cma_dma_size); -+ -+ seq_printf(m, "\n"); -+ -+ return 0; -+} -+ -+static int vc_cma_proc_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, vc_cma_show_info, NULL); -+} -+ -+/**************************************************************************** -+* -+* vc_cma_proc_write -+* -+***************************************************************************/ -+ -+static int vc_cma_proc_write(struct file *file, -+ const char __user *buffer, -+ size_t size, loff_t *ppos) -+{ -+ int rc = -EFAULT; -+ char input_str[20]; -+ -+ memset(input_str, 0, sizeof(input_str)); -+ -+ if (size > sizeof(input_str)) { -+ LOG_ERR("%s: input string length too long", __func__); -+ goto out; -+ } -+ -+ if (copy_from_user(input_str, buffer, size - 1)) { -+ LOG_ERR("%s: failed to get input string", __func__); -+ goto out; -+ } -+#define ALLOC_STR "alloc" -+#define FREE_STR "free" -+#define DEBUG_STR "debug" -+#define RESERVE_STR "reserve" -+#define DMA_ALLOC_STR "dma_alloc" -+#define DMA_FREE_STR "dma_free" -+ if (strncmp(input_str, ALLOC_STR, strlen(ALLOC_STR)) == 0) { -+ int alloc_size; -+ char *p = input_str + strlen(ALLOC_STR); -+ -+ while (*p == ' ') -+ p++; -+ alloc_size = memparse(p, NULL); -+ LOG_INFO("/proc/vc-cma: alloc %d", alloc_size); -+ if (alloc_size) -+ send_vc_msg(VC_CMA_MSG_REQUEST_FREE, -+ alloc_size / VC_CMA_CHUNK_SIZE, 0); -+ else -+ LOG_ERR("invalid size '%s'", p); -+ rc = size; -+ } else if (strncmp(input_str, FREE_STR, strlen(FREE_STR)) == 0) { -+ int alloc_size; -+ char *p = input_str + strlen(FREE_STR); -+ -+ while (*p == ' ') -+ p++; -+ alloc_size = memparse(p, NULL); -+ LOG_INFO("/proc/vc-cma: free %d", alloc_size); -+ if (alloc_size) -+ send_vc_msg(VC_CMA_MSG_REQUEST_ALLOC, -+ alloc_size / VC_CMA_CHUNK_SIZE, 0); -+ else -+ LOG_ERR("invalid size '%s'", p); -+ rc = size; -+ } else if (strncmp(input_str, DEBUG_STR, strlen(DEBUG_STR)) == 0) { -+ char *p = input_str + strlen(DEBUG_STR); -+ while (*p == ' ') -+ p++; -+ if ((strcmp(p, "on") == 0) || (strcmp(p, "1") == 0)) -+ vc_cma_debug = 1; -+ else if ((strcmp(p, "off") == 0) || (strcmp(p, "0") == 0)) -+ vc_cma_debug = 0; -+ LOG_INFO("/proc/vc-cma: debug %s", vc_cma_debug ? "on" : "off"); -+ rc = size; -+ } else if (strncmp(input_str, RESERVE_STR, strlen(RESERVE_STR)) == 0) { -+ int alloc_size; -+ int reserved; -+ char *p = input_str + strlen(RESERVE_STR); -+ while (*p == ' ') -+ p++; -+ alloc_size = memparse(p, NULL); -+ -+ reserved = vc_cma_set_reserve(alloc_size, current->tgid); -+ rc = (reserved >= 0) ? size : reserved; -+ } else if (strncmp(input_str, DMA_ALLOC_STR, strlen(DMA_ALLOC_STR)) == 0) { -+ int alloc_size; -+ char *p = input_str + strlen(DMA_ALLOC_STR); -+ while (*p == ' ') -+ p++; -+ alloc_size = memparse(p, NULL); -+ -+ if (vc_cma_dma_alloc) { -+ dma_release_from_contiguous(NULL, vc_cma_dma_alloc, -+ vc_cma_dma_size); -+ vc_cma_dma_alloc = NULL; -+ vc_cma_dma_size = 0; -+ } -+ vc_cma_dma_alloc = dma_alloc_from_contiguous(NULL, alloc_size, 0); -+ vc_cma_dma_size = (vc_cma_dma_alloc ? alloc_size : 0); -+ if (vc_cma_dma_alloc) -+ LOG_INFO("dma_alloc(%d pages) -> %p", alloc_size, page_address(vc_cma_dma_alloc)); -+ else -+ LOG_ERR("dma_alloc(%d pages) failed", alloc_size); -+ rc = size; -+ } else if (strncmp(input_str, DMA_FREE_STR, strlen(DMA_FREE_STR)) == 0) { -+ if (vc_cma_dma_alloc) { -+ dma_release_from_contiguous(NULL, vc_cma_dma_alloc, -+ vc_cma_dma_size); -+ vc_cma_dma_alloc = NULL; -+ vc_cma_dma_size = 0; -+ } -+ rc = size; -+ } -+ -+out: -+ return rc; -+} -+ -+/**************************************************************************** -+* -+* File Operations for /proc interface. -+* -+***************************************************************************/ -+ -+static const struct file_operations vc_cma_proc_fops = { -+ .open = vc_cma_proc_open, -+ .read = seq_read, -+ .write = vc_cma_proc_write, -+ .llseek = seq_lseek, -+ .release = single_release -+}; -+ -+static int vc_cma_set_reserve(unsigned int reserve, unsigned int pid) -+{ -+ struct vc_cma_reserve_user *user = NULL; -+ int delta = 0; -+ int i; -+ -+ if (down_interruptible(&vc_cma_reserve_mutex)) -+ return -ERESTARTSYS; -+ -+ for (i = 0; i < vc_cma_reserve_count; i++) { -+ if (pid == vc_cma_reserve_users[i].pid) { -+ user = &vc_cma_reserve_users[i]; -+ delta = reserve - user->reserve; -+ if (reserve) -+ user->reserve = reserve; -+ else { -+ /* Remove this entry by copying downwards */ -+ while ((i + 1) < vc_cma_reserve_count) { -+ user[0].pid = user[1].pid; -+ user[0].reserve = user[1].reserve; -+ user++; -+ i++; -+ } -+ vc_cma_reserve_count--; -+ user = NULL; -+ } -+ break; -+ } -+ } -+ -+ if (reserve && !user) { -+ if (vc_cma_reserve_count == VC_CMA_RESERVE_COUNT_MAX) { -+ LOG_ERR("vc-cma: Too many reservations - " -+ "increase CMA_RESERVE_COUNT_MAX"); -+ up(&vc_cma_reserve_mutex); -+ return -EBUSY; -+ } -+ user = &vc_cma_reserve_users[vc_cma_reserve_count]; -+ user->pid = pid; -+ user->reserve = reserve; -+ delta = reserve; -+ vc_cma_reserve_count++; -+ } -+ -+ vc_cma_reserve_total += delta; -+ -+ send_vc_msg(VC_CMA_MSG_RESERVE, -+ vc_cma_reserve_total & 0xffff, vc_cma_reserve_total >> 16); -+ -+ send_worker_msg((VCHIQ_HEADER_T *) VC_CMA_MSG_UPDATE_RESERVE); -+ -+ LOG_DBG("/proc/vc-cma: reserve %d (PID %d) - total %u", -+ reserve, pid, vc_cma_reserve_total); -+ -+ up(&vc_cma_reserve_mutex); -+ -+ return vc_cma_reserve_total; -+} -+ -+static VCHIQ_STATUS_T cma_service_callback(VCHIQ_REASON_T reason, -+ VCHIQ_HEADER_T * header, -+ VCHIQ_SERVICE_HANDLE_T service, -+ void *bulk_userdata) -+{ -+ switch (reason) { -+ case VCHIQ_MESSAGE_AVAILABLE: -+ if (!send_worker_msg(header)) -+ return VCHIQ_RETRY; -+ break; -+ case VCHIQ_SERVICE_CLOSED: -+ LOG_DBG("CMA service closed"); -+ break; -+ default: -+ LOG_ERR("Unexpected CMA callback reason %d", reason); -+ break; -+ } -+ return VCHIQ_SUCCESS; -+} -+ -+static void send_vc_msg(unsigned short type, -+ unsigned short param1, unsigned short param2) -+{ -+ unsigned short msg[] = { type, param1, param2 }; -+ VCHIQ_ELEMENT_T elem = { &msg, sizeof(msg) }; -+ VCHIQ_STATUS_T ret; -+ vchiq_use_service(cma_service); -+ ret = vchiq_queue_message(cma_service, &elem, 1); -+ vchiq_release_service(cma_service); -+ if (ret != VCHIQ_SUCCESS) -+ LOG_ERR("vchiq_queue_message returned %x", ret); -+} -+ -+static bool send_worker_msg(VCHIQ_HEADER_T * msg) -+{ -+ if (down_interruptible(&vc_cma_worker_queue_push_mutex)) -+ return false; -+ vchiu_queue_push(&cma_msg_queue, msg); -+ up(&vc_cma_worker_queue_push_mutex); -+ return true; -+} -+ -+static int vc_cma_alloc_chunks(int num_chunks, struct cma_msg *reply) -+{ -+ int i; -+ for (i = 0; i < num_chunks; i++) { -+ struct page *chunk; -+ unsigned int chunk_num; -+ uint8_t *chunk_addr; -+ size_t chunk_size = PAGES_PER_CHUNK << PAGE_SHIFT; -+ -+ chunk = dma_alloc_from_contiguous(&vc_cma_device.dev, -+ PAGES_PER_CHUNK, -+ VC_CMA_CHUNK_ORDER); -+ if (!chunk) -+ break; -+ -+ chunk_addr = page_address(chunk); -+ dmac_flush_range(chunk_addr, chunk_addr + chunk_size); -+ outer_inv_range(__pa(chunk_addr), __pa(chunk_addr) + -+ chunk_size); -+ -+ chunk_num = -+ (page_to_phys(chunk) - vc_cma_base) / VC_CMA_CHUNK_SIZE; -+ BUG_ON(((page_to_phys(chunk) - vc_cma_base) % -+ VC_CMA_CHUNK_SIZE) != 0); -+ if (chunk_num >= vc_cma_chunks) { -+ phys_addr_t _pa = vc_cma_base + vc_cma_size - 1; -+ LOG_ERR("%s: ===============================", -+ __func__); -+ LOG_ERR("%s: chunk phys %x, vc_cma %pa-%pa - " -+ "bad SPARSEMEM configuration?", -+ __func__, (unsigned int)page_to_phys(chunk), -+ &vc_cma_base, &_pa); -+ LOG_ERR("%s: dev->cma_area = %p", __func__, -+ (void*)0/*vc_cma_device.dev.cma_area*/); -+ LOG_ERR("%s: ===============================", -+ __func__); -+ break; -+ } -+ reply->params[i] = chunk_num; -+ vc_cma_chunks_used++; -+ } -+ -+ if (i < num_chunks) { -+ LOG_ERR("%s: dma_alloc_from_contiguous failed " -+ "for %x bytes (alloc %d of %d, %d free)", -+ __func__, VC_CMA_CHUNK_SIZE, i, -+ num_chunks, vc_cma_chunks - vc_cma_chunks_used); -+ num_chunks = i; -+ } -+ -+ LOG_DBG("CMA allocated %d chunks -> %d used", -+ num_chunks, vc_cma_chunks_used); -+ reply->type = VC_CMA_MSG_ALLOCATED; -+ -+ { -+ VCHIQ_ELEMENT_T elem = { -+ reply, -+ offsetof(struct cma_msg, params[0]) + -+ num_chunks * sizeof(reply->params[0]) -+ }; -+ VCHIQ_STATUS_T ret; -+ vchiq_use_service(cma_service); -+ ret = vchiq_queue_message(cma_service, &elem, 1); -+ vchiq_release_service(cma_service); -+ if (ret != VCHIQ_SUCCESS) -+ LOG_ERR("vchiq_queue_message return " "%x", ret); -+ } -+ -+ return num_chunks; -+} -+ -+static int cma_worker_proc(void *param) -+{ -+ static struct cma_msg reply; -+ (void)param; -+ -+ while (1) { -+ VCHIQ_HEADER_T *msg; -+ static struct cma_msg msg_copy; -+ struct cma_msg *cma_msg = &msg_copy; -+ int type, msg_size; -+ -+ msg = vchiu_queue_pop(&cma_msg_queue); -+ if ((unsigned int)msg >= VC_CMA_MSG_MAX) { -+ msg_size = msg->size; -+ memcpy(&msg_copy, msg->data, msg_size); -+ type = cma_msg->type; -+ vchiq_release_message(cma_service, msg); -+ } else { -+ msg_size = 0; -+ type = (int)msg; -+ if (type == VC_CMA_MSG_QUIT) -+ break; -+ else if (type == VC_CMA_MSG_UPDATE_RESERVE) { -+ msg = NULL; -+ cma_msg = NULL; -+ } else { -+ BUG(); -+ continue; -+ } -+ } -+ -+ switch (type) { -+ case VC_CMA_MSG_ALLOC:{ -+ int num_chunks, free_chunks; -+ num_chunks = cma_msg->params[0]; -+ free_chunks = -+ vc_cma_chunks - vc_cma_chunks_used; -+ LOG_DBG("CMA_MSG_ALLOC(%d chunks)", num_chunks); -+ if (num_chunks > VC_CMA_MAX_PARAMS_PER_MSG) { -+ LOG_ERR -+ ("CMA_MSG_ALLOC - chunk count (%d) " -+ "exceeds VC_CMA_MAX_PARAMS_PER_MSG (%d)", -+ num_chunks, -+ VC_CMA_MAX_PARAMS_PER_MSG); -+ num_chunks = VC_CMA_MAX_PARAMS_PER_MSG; -+ } -+ -+ if (num_chunks > free_chunks) { -+ LOG_ERR -+ ("CMA_MSG_ALLOC - chunk count (%d) " -+ "exceeds free chunks (%d)", -+ num_chunks, free_chunks); -+ num_chunks = free_chunks; -+ } -+ -+ vc_cma_alloc_chunks(num_chunks, &reply); -+ } -+ break; -+ -+ case VC_CMA_MSG_FREE:{ -+ int chunk_count = -+ (msg_size - -+ offsetof(struct cma_msg, -+ params)) / -+ sizeof(cma_msg->params[0]); -+ int i; -+ BUG_ON(chunk_count <= 0); -+ -+ LOG_DBG("CMA_MSG_FREE(%d chunks - %x, ...)", -+ chunk_count, cma_msg->params[0]); -+ for (i = 0; i < chunk_count; i++) { -+ int chunk_num = cma_msg->params[i]; -+ struct page *page = vc_cma_base_page + -+ chunk_num * PAGES_PER_CHUNK; -+ if (chunk_num >= vc_cma_chunks) { -+ LOG_ERR -+ ("CMA_MSG_FREE - chunk %d of %d" -+ " (value %x) exceeds maximum " -+ "(%x)", i, chunk_count, -+ chunk_num, -+ vc_cma_chunks - 1); -+ break; -+ } -+ -+ if (!dma_release_from_contiguous -+ (&vc_cma_device.dev, page, -+ PAGES_PER_CHUNK)) { -+ phys_addr_t _pa = page_to_phys(page); -+ LOG_ERR -+ ("CMA_MSG_FREE - failed to " -+ "release chunk %d (phys %pa, " -+ "page %x)", chunk_num, -+ &_pa, -+ (unsigned int)page); -+ } -+ vc_cma_chunks_used--; -+ } -+ LOG_DBG("CMA released %d chunks -> %d used", -+ i, vc_cma_chunks_used); -+ } -+ break; -+ -+ case VC_CMA_MSG_UPDATE_RESERVE:{ -+ int chunks_needed = -+ ((vc_cma_reserve_total + VC_CMA_CHUNK_SIZE - -+ 1) -+ / VC_CMA_CHUNK_SIZE) - -+ vc_cma_chunks_reserved; -+ -+ LOG_DBG -+ ("CMA_MSG_UPDATE_RESERVE(%d chunks needed)", -+ chunks_needed); -+ -+ /* Cap the reservations to what is available */ -+ if (chunks_needed > 0) { -+ if (chunks_needed > -+ (vc_cma_chunks - -+ vc_cma_chunks_used)) -+ chunks_needed = -+ (vc_cma_chunks - -+ vc_cma_chunks_used); -+ -+ chunks_needed = -+ vc_cma_alloc_chunks(chunks_needed, -+ &reply); -+ } -+ -+ LOG_DBG -+ ("CMA_MSG_UPDATE_RESERVE(%d chunks allocated)", -+ chunks_needed); -+ vc_cma_chunks_reserved += chunks_needed; -+ } -+ break; -+ -+ default: -+ LOG_ERR("unexpected msg type %d", type); -+ break; -+ } -+ } -+ -+ LOG_DBG("quitting..."); -+ return 0; -+} -+ -+/**************************************************************************** -+* -+* vc_cma_connected_init -+* -+* This function is called once the videocore has been connected. -+* -+***************************************************************************/ -+ -+static void vc_cma_connected_init(void) -+{ -+ VCHIQ_SERVICE_PARAMS_T service_params; -+ -+ LOG_DBG("vc_cma_connected_init"); -+ -+ if (!vchiu_queue_init(&cma_msg_queue, 16)) { -+ LOG_ERR("could not create CMA msg queue"); -+ goto fail_queue; -+ } -+ -+ if (vchiq_initialise(&cma_instance) != VCHIQ_SUCCESS) -+ goto fail_vchiq_init; -+ -+ vchiq_connect(cma_instance); -+ -+ service_params.fourcc = VC_CMA_FOURCC; -+ service_params.callback = cma_service_callback; -+ service_params.userdata = NULL; -+ service_params.version = VC_CMA_VERSION; -+ service_params.version_min = VC_CMA_VERSION; -+ -+ if (vchiq_open_service(cma_instance, &service_params, -+ &cma_service) != VCHIQ_SUCCESS) { -+ LOG_ERR("failed to open service - already in use?"); -+ goto fail_vchiq_open; -+ } -+ -+ vchiq_release_service(cma_service); -+ -+ cma_worker = kthread_create(cma_worker_proc, NULL, "cma_worker"); -+ if (!cma_worker) { -+ LOG_ERR("could not create CMA worker thread"); -+ goto fail_worker; -+ } -+ set_user_nice(cma_worker, -20); -+ wake_up_process(cma_worker); -+ -+ return; -+ -+fail_worker: -+ vchiq_close_service(cma_service); -+fail_vchiq_open: -+ vchiq_shutdown(cma_instance); -+fail_vchiq_init: -+ vchiu_queue_delete(&cma_msg_queue); -+fail_queue: -+ return; -+} -+ -+void -+loud_error_header(void) -+{ -+ if (in_loud_error) -+ return; -+ -+ LOG_ERR("============================================================" -+ "================"); -+ LOG_ERR("============================================================" -+ "================"); -+ LOG_ERR("====="); -+ -+ in_loud_error = 1; -+} -+ -+void -+loud_error_footer(void) -+{ -+ if (!in_loud_error) -+ return; -+ -+ LOG_ERR("====="); -+ LOG_ERR("============================================================" -+ "================"); -+ LOG_ERR("============================================================" -+ "================"); -+ -+ in_loud_error = 0; -+} -+ -+#if 1 -+static int check_cma_config(void) { return 1; } -+#else -+static int -+read_vc_debug_var(VC_MEM_ACCESS_HANDLE_T handle, -+ const char *symbol, -+ void *buf, size_t bufsize) -+{ -+ VC_MEM_ADDR_T vcMemAddr; -+ size_t vcMemSize; -+ uint8_t *mapAddr; -+ off_t vcMapAddr; -+ -+ if (!LookupVideoCoreSymbol(handle, symbol, -+ &vcMemAddr, -+ &vcMemSize)) { -+ loud_error_header(); -+ loud_error( -+ "failed to find VC symbol \"%s\".", -+ symbol); -+ loud_error_footer(); -+ return 0; -+ } -+ -+ if (vcMemSize != bufsize) { -+ loud_error_header(); -+ loud_error( -+ "VC symbol \"%s\" is the wrong size.", -+ symbol); -+ loud_error_footer(); -+ return 0; -+ } -+ -+ vcMapAddr = (off_t)vcMemAddr & VC_MEM_TO_ARM_ADDR_MASK; -+ vcMapAddr += mm_vc_mem_phys_addr; -+ mapAddr = ioremap_nocache(vcMapAddr, vcMemSize); -+ if (mapAddr == 0) { -+ loud_error_header(); -+ loud_error( -+ "failed to ioremap \"%s\" @ 0x%x " -+ "(phys: 0x%x, size: %u).", -+ symbol, -+ (unsigned int)vcMapAddr, -+ (unsigned int)vcMemAddr, -+ (unsigned int)vcMemSize); -+ loud_error_footer(); -+ return 0; -+ } -+ -+ memcpy(buf, mapAddr, bufsize); -+ iounmap(mapAddr); -+ -+ return 1; -+} -+ -+ -+static int -+check_cma_config(void) -+{ -+ VC_MEM_ACCESS_HANDLE_T mem_hndl; -+ VC_MEM_ADDR_T mempool_start; -+ VC_MEM_ADDR_T mempool_end; -+ VC_MEM_ADDR_T mempool_offline_start; -+ VC_MEM_ADDR_T mempool_offline_end; -+ VC_MEM_ADDR_T cam_alloc_base; -+ VC_MEM_ADDR_T cam_alloc_size; -+ VC_MEM_ADDR_T cam_alloc_end; -+ int success = 0; -+ -+ if (OpenVideoCoreMemory(&mem_hndl) != 0) -+ goto out; -+ -+ /* Read the relevant VideoCore variables */ -+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_START", -+ &mempool_start, -+ sizeof(mempool_start))) -+ goto close; -+ -+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_END", -+ &mempool_end, -+ sizeof(mempool_end))) -+ goto close; -+ -+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_START", -+ &mempool_offline_start, -+ sizeof(mempool_offline_start))) -+ goto close; -+ -+ if (!read_vc_debug_var(mem_hndl, "__MEMPOOL_OFFLINE_END", -+ &mempool_offline_end, -+ sizeof(mempool_offline_end))) -+ goto close; -+ -+ if (!read_vc_debug_var(mem_hndl, "cam_alloc_base", -+ &cam_alloc_base, -+ sizeof(cam_alloc_base))) -+ goto close; -+ -+ if (!read_vc_debug_var(mem_hndl, "cam_alloc_size", -+ &cam_alloc_size, -+ sizeof(cam_alloc_size))) -+ goto close; -+ -+ cam_alloc_end = cam_alloc_base + cam_alloc_size; -+ -+ success = 1; -+ -+ /* Now the sanity checks */ -+ if (!mempool_offline_start) -+ mempool_offline_start = mempool_start; -+ if (!mempool_offline_end) -+ mempool_offline_end = mempool_end; -+ -+ if (VCADDR_TO_PHYSADDR(mempool_offline_start) != vc_cma_base) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_OFFLINE_START(%x -> %lx) doesn't match " -+ "vc_cma_base(%x)", -+ mempool_offline_start, -+ VCADDR_TO_PHYSADDR(mempool_offline_start), -+ vc_cma_base); -+ success = 0; -+ } -+ -+ if (VCADDR_TO_PHYSADDR(mempool_offline_end) != -+ (vc_cma_base + vc_cma_size)) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_OFFLINE_END(%x -> %lx) doesn't match " -+ "vc_cma_base(%x) + vc_cma_size(%x) = %x", -+ mempool_offline_start, -+ VCADDR_TO_PHYSADDR(mempool_offline_end), -+ vc_cma_base, vc_cma_size, vc_cma_base + vc_cma_size); -+ success = 0; -+ } -+ -+ if (mempool_end < mempool_start) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_END(%x) must not be before " -+ "__MEMPOOL_START(%x)", -+ mempool_end, -+ mempool_start); -+ success = 0; -+ } -+ -+ if (mempool_offline_end < mempool_offline_start) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_OFFLINE_END(%x) must not be before " -+ "__MEMPOOL_OFFLINE_START(%x)", -+ mempool_offline_end, -+ mempool_offline_start); -+ success = 0; -+ } -+ -+ if (mempool_offline_start < mempool_start) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_OFFLINE_START(%x) must not be before " -+ "__MEMPOOL_START(%x)", -+ mempool_offline_start, -+ mempool_start); -+ success = 0; -+ } -+ -+ if (mempool_offline_end > mempool_end) { -+ loud_error_header(); -+ loud_error( -+ "__MEMPOOL_OFFLINE_END(%x) must not be after " -+ "__MEMPOOL_END(%x)", -+ mempool_offline_end, -+ mempool_end); -+ success = 0; -+ } -+ -+ if ((cam_alloc_base < mempool_end) && -+ (cam_alloc_end > mempool_start)) { -+ loud_error_header(); -+ loud_error( -+ "cam_alloc pool(%x-%x) overlaps " -+ "mempool(%x-%x)", -+ cam_alloc_base, cam_alloc_end, -+ mempool_start, mempool_end); -+ success = 0; -+ } -+ -+ loud_error_footer(); -+ -+close: -+ CloseVideoCoreMemory(mem_hndl); -+ -+out: -+ return success; -+} -+#endif -+ -+static int vc_cma_init(void) -+{ -+ int rc = -EFAULT; -+ struct device *dev; -+ -+ if (!check_cma_config()) -+ goto out_release; -+ -+ LOG_INFO("vc-cma: Videocore CMA driver"); -+ LOG_INFO("vc-cma: vc_cma_base = %pa", &vc_cma_base); -+ LOG_INFO("vc-cma: vc_cma_size = 0x%08x (%u MiB)", -+ vc_cma_size, vc_cma_size / (1024 * 1024)); -+ LOG_INFO("vc-cma: vc_cma_initial = 0x%08x (%u MiB)", -+ vc_cma_initial, vc_cma_initial / (1024 * 1024)); -+ -+ vc_cma_base_page = phys_to_page(vc_cma_base); -+ -+ if (vc_cma_chunks) { -+ int chunks_needed = vc_cma_initial / VC_CMA_CHUNK_SIZE; -+ -+ for (vc_cma_chunks_used = 0; -+ vc_cma_chunks_used < chunks_needed; vc_cma_chunks_used++) { -+ struct page *chunk; -+ chunk = dma_alloc_from_contiguous(&vc_cma_device.dev, -+ PAGES_PER_CHUNK, -+ VC_CMA_CHUNK_ORDER); -+ if (!chunk) -+ break; -+ BUG_ON(((page_to_phys(chunk) - vc_cma_base) % -+ VC_CMA_CHUNK_SIZE) != 0); -+ } -+ if (vc_cma_chunks_used != chunks_needed) { -+ LOG_ERR("%s: dma_alloc_from_contiguous failed (%d " -+ "bytes, allocation %d of %d)", -+ __func__, VC_CMA_CHUNK_SIZE, -+ vc_cma_chunks_used, chunks_needed); -+ goto out_release; -+ } -+ -+ vchiq_add_connected_callback(vc_cma_connected_init); -+ } -+ -+ rc = alloc_chrdev_region(&vc_cma_devnum, 0, 1, DRIVER_NAME); -+ if (rc < 0) { -+ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); -+ goto out_release; -+ } -+ -+ cdev_init(&vc_cma_cdev, &vc_cma_fops); -+ rc = cdev_add(&vc_cma_cdev, vc_cma_devnum, 1); -+ if (rc != 0) { -+ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc); -+ goto out_unregister; -+ } -+ -+ vc_cma_class = class_create(THIS_MODULE, DRIVER_NAME); -+ if (IS_ERR(vc_cma_class)) { -+ rc = PTR_ERR(vc_cma_class); -+ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc); -+ goto out_cdev_del; -+ } -+ -+ dev = device_create(vc_cma_class, NULL, vc_cma_devnum, NULL, -+ DRIVER_NAME); -+ if (IS_ERR(dev)) { -+ rc = PTR_ERR(dev); -+ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc); -+ goto out_class_destroy; -+ } -+ -+ vc_cma_proc_entry = proc_create(DRIVER_NAME, 0444, NULL, &vc_cma_proc_fops); -+ if (vc_cma_proc_entry == NULL) { -+ rc = -EFAULT; -+ LOG_ERR("%s: proc_create failed", __func__); -+ goto out_device_destroy; -+ } -+ -+ vc_cma_inited = 1; -+ return 0; -+ -+out_device_destroy: -+ device_destroy(vc_cma_class, vc_cma_devnum); -+ -+out_class_destroy: -+ class_destroy(vc_cma_class); -+ vc_cma_class = NULL; -+ -+out_cdev_del: -+ cdev_del(&vc_cma_cdev); -+ -+out_unregister: -+ unregister_chrdev_region(vc_cma_devnum, 1); -+ -+out_release: -+ /* It is tempting to try to clean up by calling -+ dma_release_from_contiguous for all allocated chunks, but it isn't -+ a very safe thing to do. If vc_cma_initial is non-zero it is because -+ VideoCore is already using that memory, so giving it back to Linux -+ is likely to be fatal. -+ */ -+ return -1; -+} -+ -+/**************************************************************************** -+* -+* vc_cma_exit -+* -+***************************************************************************/ -+ -+static void __exit vc_cma_exit(void) -+{ -+ LOG_DBG("%s: called", __func__); -+ -+ if (vc_cma_inited) { -+ remove_proc_entry(DRIVER_NAME, NULL); -+ device_destroy(vc_cma_class, vc_cma_devnum); -+ class_destroy(vc_cma_class); -+ cdev_del(&vc_cma_cdev); -+ unregister_chrdev_region(vc_cma_devnum, 1); -+ } -+} -+ -+module_init(vc_cma_init); -+module_exit(vc_cma_exit); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Broadcom Corporation"); -diff --git a/include/linux/broadcom/vc_cma.h b/include/linux/broadcom/vc_cma.h -new file mode 100644 -index 0000000000000000000000000000000000000000..be2819d5d41f9d5ed65daf8eedb94c9e9a4c2f1a ---- /dev/null -+++ b/include/linux/broadcom/vc_cma.h -@@ -0,0 +1,36 @@ -+/***************************************************************************** -+* Copyright 2012 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#if !defined( VC_CMA_H ) -+#define VC_CMA_H -+ -+#include -+ -+#define VC_CMA_IOC_MAGIC 0xc5 -+ -+#define VC_CMA_IOC_RESERVE _IO(VC_CMA_IOC_MAGIC, 0) -+ -+#ifdef __KERNEL__ -+ -+#ifdef CONFIG_BCM_VC_CMA -+void vc_cma_early_init(void); -+void vc_cma_reserve(void); -+#else -+static inline void vc_cma_early_init(void) { } -+static inline void vc_cma_reserve(void) { } -+#endif -+ -+#endif -+ -+#endif /* VC_CMA_H */ - -From 0decd2212682604a492f62259f5ec1ba432434fb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 035/216] bcm2708: alsa sound driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: popcornmix - -alsa: add mmap support and some cleanups to bcm2835 ALSA driver - -snd-bcm2835: Add support for spdif/hdmi passthrough - -This adds a dedicated subdevice which can be used for passthrough of non-audio -formats (ie encoded a52) through the hdmi audio link. In addition to this -driver extension an appropriate card config is required to make alsa-lib -support the AES parameters for this device. - -snd-bcm2708: Add mutex, improve logging - -Fix for ALSA driver crash - -Avoids an issue when closing and opening vchiq where a message can arrive before service handle has been written - -alsa: reduce severity of expected warning message - -snd-bcm2708: Fix dmesg spam for non-error case - -alsa: Ensure mutexes are released through error paths - -alsa: Make interrupted close paths quieter - -BCM270x: Add onboard sound device to Device Tree - -Add Device Tree support to alsa driver. -Add device to Device Tree. -Don't add platform devices when booting in DT mode. - -Signed-off-by: Noralf Trønnes - -bcm2835: access controls under the audio mutex - -I don't think the ALSA framework provides any kind of automatic -synchronization within the control callbacks. We most likely need -to ensure this manually, so add locking around all access to shared -mutable data. In particular, bcm2835_audio_set_ctls() should -probably always be called under our own audio lock. - -snd-bcm2835: Don't allow responses from VC to be interrupted by user signals - -There should always be a response, and retry after a signal interruption is not handled, so don't report -we are interruptible. - -See: https://github.com/raspberrypi/linux/issues/1560 - -snd-bcm2835: Use bcm2835_hw params in preallocate ---- - sound/arm/Kconfig | 7 + - sound/arm/Makefile | 5 + - sound/arm/bcm2835-ctl.c | 350 +++++++++++++++ - sound/arm/bcm2835-pcm.c | 563 +++++++++++++++++++++++ - sound/arm/bcm2835-vchiq.c | 889 +++++++++++++++++++++++++++++++++++++ - sound/arm/bcm2835.c | 511 +++++++++++++++++++++ - sound/arm/bcm2835.h | 167 +++++++ - sound/arm/vc_vchi_audioserv_defs.h | 116 +++++ - 8 files changed, 2608 insertions(+) - create mode 100755 sound/arm/bcm2835-ctl.c - create mode 100755 sound/arm/bcm2835-pcm.c - create mode 100755 sound/arm/bcm2835-vchiq.c - create mode 100644 sound/arm/bcm2835.c - create mode 100755 sound/arm/bcm2835.h - create mode 100644 sound/arm/vc_vchi_audioserv_defs.h - -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 65171f6657a2984ccc14ce907a4c7c87d77d196b..42581e2f65dfedba6207b6a377a1e1b5df4f2e4b 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -32,6 +32,13 @@ config SND_PXA2XX_AC97 - Say Y or M if you want to support any AC97 codec attached to - the PXA2xx AC97 interface. - -+config SND_BCM2835 -+ tristate "BCM2835 ALSA driver" -+ depends on ARCH_BCM2835 && BCM2835_VCHIQ && SND -+ select SND_PCM -+ help -+ Say Y or M if you want to support BCM2835 Alsa pcm card driver -+ - endif # SND_ARM - - config SND_PXA2XX_LIB -diff --git a/sound/arm/Makefile b/sound/arm/Makefile -index 8c0c851d464109819beb296c2624bbec7af131e9..26aabea79a0b5f141f7644a96684470d9b72f681 100644 ---- a/sound/arm/Makefile -+++ b/sound/arm/Makefile -@@ -14,3 +14,8 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o - - obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o - snd-pxa2xx-ac97-objs := pxa2xx-ac97.o -+ -+obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o -+snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o -+ -+ccflags-y += -Idrivers/staging/vc04_services -Idrivers/staging/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 -diff --git a/sound/arm/bcm2835-ctl.c b/sound/arm/bcm2835-ctl.c -new file mode 100755 -index 0000000000000000000000000000000000000000..75dc3224be7ce8353378e9676ad2c6847dd0750b ---- /dev/null -+++ b/sound/arm/bcm2835-ctl.c -@@ -0,0 +1,350 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bcm2835.h" -+ -+/* volume maximum and minimum in terms of 0.01dB */ -+#define CTRL_VOL_MAX 400 -+#define CTRL_VOL_MIN -10239 /* originally -10240 */ -+ -+ -+static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ audio_info(" ... IN\n"); -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = CTRL_VOL_MIN; -+ uinfo->value.integer.max = CTRL_VOL_MAX; /* 2303 */ -+ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 1; -+ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = AUDIO_DEST_MAX-1; -+ } -+ audio_info(" ... OUT\n"); -+ return 0; -+} -+ -+/* toggles mute on or off depending on the value of nmute, and returns -+ * 1 if the mute value was changed, otherwise 0 -+ */ -+static int toggle_mute(struct bcm2835_chip *chip, int nmute) -+{ -+ /* if settings are ok, just return 0 */ -+ if(chip->mute == nmute) -+ return 0; -+ -+ /* if the sound is muted then we need to unmute */ -+ if(chip->mute == CTRL_VOL_MUTE) -+ { -+ chip->volume = chip->old_volume; /* copy the old volume back */ -+ audio_info("Unmuting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume); -+ } -+ else /* otherwise we mute */ -+ { -+ chip->old_volume = chip->volume; -+ chip->volume = 26214; /* set volume to minimum level AKA mute */ -+ audio_info("Muting, old_volume = %d, volume = %d ...\n", chip->old_volume, chip->volume); -+ } -+ -+ chip->mute = nmute; -+ return 1; -+} -+ -+static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK)); -+ -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) -+ ucontrol->value.integer.value[0] = chip2alsa(chip->volume); -+ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) -+ ucontrol->value.integer.value[0] = chip->mute; -+ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) -+ ucontrol->value.integer.value[0] = chip->dest; -+ -+ mutex_unlock(&chip->audio_mutex); -+ return 0; -+} -+ -+static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ int changed = 0; -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { -+ audio_info("Volume change attempted.. volume = %d new_volume = %d\n", chip->volume, (int)ucontrol->value.integer.value[0]); -+ if (chip->mute == CTRL_VOL_MUTE) { -+ /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */ -+ changed = 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */ -+ goto unlock; -+ } -+ if (changed -+ || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) { -+ -+ chip->volume = alsa2chip(ucontrol->value.integer.value[0]); -+ changed = 1; -+ } -+ -+ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { -+ /* Now implemented */ -+ audio_info(" Mute attempted\n"); -+ changed = toggle_mute(chip, ucontrol->value.integer.value[0]); -+ -+ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { -+ if (ucontrol->value.integer.value[0] != chip->dest) { -+ chip->dest = ucontrol->value.integer.value[0]; -+ changed = 1; -+ } -+ } -+ -+ if (changed) { -+ if (bcm2835_audio_set_ctls(chip)) -+ printk(KERN_ERR "Failed to set ALSA controls..\n"); -+ } -+ -+unlock: -+ mutex_unlock(&chip->audio_mutex); -+ return changed; -+} -+ -+static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1); -+ -+static struct snd_kcontrol_new snd_bcm2835_ctl[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Volume", -+ .index = 0, -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, -+ .private_value = PCM_PLAYBACK_VOLUME, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ .tlv = {.p = snd_bcm2835_db_scale} -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Switch", -+ .index = 0, -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, -+ .private_value = PCM_PLAYBACK_MUTE, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Route", -+ .index = 0, -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, -+ .private_value = PCM_PLAYBACK_DEVICE, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ }, -+}; -+ -+static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ int i; -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ for (i = 0; i < 4; i++) -+ ucontrol->value.iec958.status[i] = -+ (chip->spdif_status >> (i * 8)) && 0xff; -+ -+ mutex_unlock(&chip->audio_mutex); -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ unsigned int val = 0; -+ int i, change; -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ for (i = 0; i < 4; i++) -+ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); -+ -+ change = val != chip->spdif_status; -+ chip->spdif_status = val; -+ -+ mutex_unlock(&chip->audio_mutex); -+ return change; -+} -+ -+static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ /* bcm2835 supports only consumer mode and sets all other format flags -+ * automatically. So the only thing left is signalling non-audio -+ * content */ -+ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO; -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ int i; -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ for (i = 0; i < 4; i++) -+ ucontrol->value.iec958.status[i] = -+ (chip->spdif_status >> (i * 8)) & 0xff; -+ -+ mutex_unlock(&chip->audio_mutex); -+ return 0; -+} -+ -+static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ unsigned int val = 0; -+ int i, change; -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ for (i = 0; i < 4; i++) -+ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8); -+ change = val != chip->spdif_status; -+ chip->spdif_status = val; -+ -+ mutex_unlock(&chip->audio_mutex); -+ return change; -+} -+ -+static struct snd_kcontrol_new snd_bcm2835_spdif[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_PCM, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), -+ .info = snd_bcm2835_spdif_default_info, -+ .get = snd_bcm2835_spdif_default_get, -+ .put = snd_bcm2835_spdif_default_put -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .iface = SNDRV_CTL_ELEM_IFACE_PCM, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), -+ .info = snd_bcm2835_spdif_mask_info, -+ .get = snd_bcm2835_spdif_mask_get, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | -+ SNDRV_CTL_ELEM_ACCESS_INACTIVE, -+ .iface = SNDRV_CTL_ELEM_IFACE_PCM, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), -+ .info = snd_bcm2835_spdif_stream_info, -+ .get = snd_bcm2835_spdif_stream_get, -+ .put = snd_bcm2835_spdif_stream_put, -+ }, -+}; -+ -+int snd_bcm2835_new_ctl(bcm2835_chip_t * chip) -+{ -+ int err; -+ unsigned int idx; -+ -+ strcpy(chip->card->mixername, "Broadcom Mixer"); -+ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) { -+ err = -+ snd_ctl_add(chip->card, -+ snd_ctl_new1(&snd_bcm2835_ctl[idx], chip)); -+ if (err < 0) -+ return err; -+ } -+ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) { -+ err = snd_ctl_add(chip->card, -+ snd_ctl_new1(&snd_bcm2835_spdif[idx], chip)); -+ if (err < 0) -+ return err; -+ } -+ return 0; -+} -diff --git a/sound/arm/bcm2835-pcm.c b/sound/arm/bcm2835-pcm.c -new file mode 100755 -index 0000000000000000000000000000000000000000..71b128924affac2b7a01d1169e43d437bb1d0c1a ---- /dev/null -+++ b/sound/arm/bcm2835-pcm.c -@@ -0,0 +1,563 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+ -+#include -+ -+#include "bcm2835.h" -+ -+/* hardware definition */ -+static struct snd_pcm_hardware snd_bcm2835_playback_hw = { -+ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | -+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), -+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, -+ .rate_min = 8000, -+ .rate_max = 48000, -+ .channels_min = 1, -+ .channels_max = 2, -+ .buffer_bytes_max = 128 * 1024, -+ .period_bytes_min = 1 * 1024, -+ .period_bytes_max = 128 * 1024, -+ .periods_min = 1, -+ .periods_max = 128, -+}; -+ -+static struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = { -+ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | -+ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID), -+ .formats = SNDRV_PCM_FMTBIT_S16_LE, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 | -+ SNDRV_PCM_RATE_48000, -+ .rate_min = 44100, -+ .rate_max = 48000, -+ .channels_min = 2, -+ .channels_max = 2, -+ .buffer_bytes_max = 128 * 1024, -+ .period_bytes_min = 1 * 1024, -+ .period_bytes_max = 128 * 1024, -+ .periods_min = 1, -+ .periods_max = 128, -+}; -+ -+static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime) -+{ -+ audio_info("Freeing up alsa stream here ..\n"); -+ if (runtime->private_data) -+ kfree(runtime->private_data); -+ runtime->private_data = NULL; -+} -+ -+static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) -+{ -+ bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id; -+ uint32_t consumed = 0; -+ int new_period = 0; -+ -+ audio_info(" .. IN\n"); -+ -+ audio_info("alsa_stream=%p substream=%p\n", alsa_stream, -+ alsa_stream ? alsa_stream->substream : 0); -+ -+ if (alsa_stream->open) -+ consumed = bcm2835_audio_retrieve_buffers(alsa_stream); -+ -+ /* We get called only if playback was triggered, So, the number of buffers we retrieve in -+ * each iteration are the buffers that have been played out already -+ */ -+ -+ if (alsa_stream->period_size) { -+ if ((alsa_stream->pos / alsa_stream->period_size) != -+ ((alsa_stream->pos + consumed) / alsa_stream->period_size)) -+ new_period = 1; -+ } -+ audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n", -+ alsa_stream->pos, -+ consumed, -+ alsa_stream->buffer_size, -+ (int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods), -+ frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr), -+ new_period); -+ if (alsa_stream->buffer_size) { -+ alsa_stream->pos += consumed &~ (1<<30); -+ alsa_stream->pos %= alsa_stream->buffer_size; -+ } -+ -+ if (alsa_stream->substream) { -+ if (new_period) -+ snd_pcm_period_elapsed(alsa_stream->substream); -+ } else { -+ audio_warning(" unexpected NULL substream\n"); -+ } -+ audio_info(" .. OUT\n"); -+ -+ return IRQ_HANDLED; -+} -+ -+/* open callback */ -+static int snd_bcm2835_playback_open_generic( -+ struct snd_pcm_substream *substream, int spdif) -+{ -+ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int idx; -+ int err; -+ -+ audio_info(" .. IN (%d)\n", substream->number); -+ -+ if(mutex_lock_interruptible(&chip->audio_mutex)) -+ { -+ audio_error("Interrupted whilst waiting for lock\n"); -+ return -EINTR; -+ } -+ audio_info("Alsa open (%d)\n", substream->number); -+ idx = substream->number; -+ -+ if (spdif && chip->opened != 0) { -+ err = -EBUSY; -+ goto out; -+ } -+ else if (!spdif && (chip->opened & (1 << idx))) { -+ err = -EBUSY; -+ goto out; -+ } -+ if (idx > MAX_SUBSTREAMS) { -+ audio_error -+ ("substream(%d) device doesn't exist max(%d) substreams allowed\n", -+ idx, MAX_SUBSTREAMS); -+ err = -ENODEV; -+ goto out; -+ } -+ -+ /* Check if we are ready */ -+ if (!(chip->avail_substreams & (1 << idx))) { -+ /* We are not ready yet */ -+ audio_error("substream(%d) device is not ready yet\n", idx); -+ err = -EAGAIN; -+ goto out; -+ } -+ -+ alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL); -+ if (alsa_stream == NULL) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ /* Initialise alsa_stream */ -+ alsa_stream->chip = chip; -+ alsa_stream->substream = substream; -+ alsa_stream->idx = idx; -+ -+ sema_init(&alsa_stream->buffers_update_sem, 0); -+ sema_init(&alsa_stream->control_sem, 0); -+ spin_lock_init(&alsa_stream->lock); -+ -+ /* Enabled in start trigger, called on each "fifo irq" after that */ -+ alsa_stream->enable_fifo_irq = 0; -+ alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq; -+ -+ err = bcm2835_audio_open(alsa_stream); -+ if (err != 0) { -+ kfree(alsa_stream); -+ goto out; -+ } -+ runtime->private_data = alsa_stream; -+ runtime->private_free = snd_bcm2835_playback_free; -+ if (spdif) { -+ runtime->hw = snd_bcm2835_playback_spdif_hw; -+ } else { -+ /* clear spdif status, as we are not in spdif mode */ -+ chip->spdif_status = 0; -+ runtime->hw = snd_bcm2835_playback_hw; -+ } -+ /* minimum 16 bytes alignment (for vchiq bulk transfers) */ -+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -+ 16); -+ -+ chip->alsa_stream[idx] = alsa_stream; -+ -+ chip->opened |= (1 << idx); -+ alsa_stream->open = 1; -+ alsa_stream->draining = 1; -+ -+out: -+ mutex_unlock(&chip->audio_mutex); -+ -+ audio_info(" .. OUT =%d\n", err); -+ -+ return err; -+} -+ -+static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) -+{ -+ return snd_bcm2835_playback_open_generic(substream, 0); -+} -+ -+static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream) -+{ -+ return snd_bcm2835_playback_open_generic(substream, 1); -+} -+ -+/* close callback */ -+static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) -+{ -+ /* the hardware-specific codes will be here */ -+ -+ bcm2835_chip_t *chip; -+ struct snd_pcm_runtime *runtime; -+ bcm2835_alsa_stream_t *alsa_stream; -+ -+ audio_info(" .. IN\n"); -+ -+ chip = snd_pcm_substream_chip(substream); -+ if(mutex_lock_interruptible(&chip->audio_mutex)) -+ { -+ audio_error("Interrupted whilst waiting for lock\n"); -+ return -EINTR; -+ } -+ runtime = substream->runtime; -+ alsa_stream = runtime->private_data; -+ -+ audio_info("Alsa close\n"); -+ -+ /* -+ * Call stop if it's still running. This happens when app -+ * is force killed and we don't get a stop trigger. -+ */ -+ if (alsa_stream->running) { -+ int err; -+ err = bcm2835_audio_stop(alsa_stream); -+ alsa_stream->running = 0; -+ if (err != 0) -+ audio_error(" Failed to STOP alsa device\n"); -+ } -+ -+ alsa_stream->period_size = 0; -+ alsa_stream->buffer_size = 0; -+ -+ if (alsa_stream->open) { -+ alsa_stream->open = 0; -+ bcm2835_audio_close(alsa_stream); -+ } -+ if (alsa_stream->chip) -+ alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL; -+ /* -+ * Do not free up alsa_stream here, it will be freed up by -+ * runtime->private_free callback we registered in *_open above -+ */ -+ -+ chip->opened &= ~(1 << substream->number); -+ -+ mutex_unlock(&chip->audio_mutex); -+ audio_info(" .. OUT\n"); -+ -+ return 0; -+} -+ -+/* hw_params callback */ -+static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ int err; -+ -+ audio_info(" .. IN\n"); -+ -+ err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); -+ if (err < 0) { -+ audio_error -+ (" pcm_lib_malloc failed to allocated pages for buffers\n"); -+ return err; -+ } -+ -+ alsa_stream->channels = params_channels(params); -+ alsa_stream->params_rate = params_rate(params); -+ alsa_stream->pcm_format_width = snd_pcm_format_width(params_format (params)); -+ audio_info(" .. OUT\n"); -+ -+ return err; -+} -+ -+/* hw_free callback */ -+static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ audio_info(" .. IN\n"); -+ return snd_pcm_lib_free_pages(substream); -+} -+ -+/* prepare callback */ -+static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ int channels; -+ int err; -+ -+ audio_info(" .. IN\n"); -+ -+ if (mutex_lock_interruptible(&chip->audio_mutex)) -+ return -EINTR; -+ -+ /* notify the vchiq that it should enter spdif passthrough mode by -+ * setting channels=0 (see -+ * https://github.com/raspberrypi/linux/issues/528) */ -+ if (chip->spdif_status & IEC958_AES0_NONAUDIO) -+ channels = 0; -+ else -+ channels = alsa_stream->channels; -+ -+ err = bcm2835_audio_set_params(alsa_stream, channels, -+ alsa_stream->params_rate, -+ alsa_stream->pcm_format_width); -+ if (err < 0) { -+ audio_error(" error setting hw params\n"); -+ } -+ -+ bcm2835_audio_setup(alsa_stream); -+ -+ /* in preparation of the stream, set the controls (volume level) of the stream */ -+ bcm2835_audio_set_ctls(alsa_stream->chip); -+ -+ -+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect)); -+ -+ alsa_stream->pcm_indirect.hw_buffer_size = -+ alsa_stream->pcm_indirect.sw_buffer_size = -+ snd_pcm_lib_buffer_bytes(substream); -+ -+ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); -+ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); -+ alsa_stream->pos = 0; -+ -+ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n", -+ alsa_stream->buffer_size, alsa_stream->period_size, -+ alsa_stream->pos, runtime->frame_bits); -+ -+ mutex_unlock(&chip->audio_mutex); -+ audio_info(" .. OUT\n"); -+ return 0; -+} -+ -+static void snd_bcm2835_pcm_transfer(struct snd_pcm_substream *substream, -+ struct snd_pcm_indirect *rec, size_t bytes) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ void *src = (void *)(substream->runtime->dma_area + rec->sw_data); -+ int err; -+ -+ err = bcm2835_audio_write(alsa_stream, bytes, src); -+ if (err) -+ audio_error(" Failed to transfer to alsa device (%d)\n", err); -+ -+} -+ -+static int snd_bcm2835_pcm_ack(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ struct snd_pcm_indirect *pcm_indirect = &alsa_stream->pcm_indirect; -+ -+ pcm_indirect->hw_queue_size = runtime->hw.buffer_bytes_max; -+ snd_pcm_indirect_playback_transfer(substream, pcm_indirect, -+ snd_bcm2835_pcm_transfer); -+ return 0; -+} -+ -+/* trigger callback */ -+static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ int err = 0; -+ -+ audio_info(" .. IN\n"); -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n", -+ alsa_stream->running); -+ if (!alsa_stream->running) { -+ err = bcm2835_audio_start(alsa_stream); -+ if (err == 0) { -+ alsa_stream->pcm_indirect.hw_io = -+ alsa_stream->pcm_indirect.hw_data = -+ bytes_to_frames(runtime, -+ alsa_stream->pos); -+ substream->ops->ack(substream); -+ alsa_stream->running = 1; -+ alsa_stream->draining = 1; -+ } else { -+ audio_error(" Failed to START alsa device (%d)\n", err); -+ } -+ } -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ audio_debug -+ ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n", -+ alsa_stream->running, runtime->status->state == SNDRV_PCM_STATE_DRAINING); -+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { -+ audio_info("DRAINING\n"); -+ alsa_stream->draining = 1; -+ } else { -+ audio_info("DROPPING\n"); -+ alsa_stream->draining = 0; -+ } -+ if (alsa_stream->running) { -+ err = bcm2835_audio_stop(alsa_stream); -+ if (err != 0) -+ audio_error(" Failed to STOP alsa device (%d)\n", err); -+ alsa_stream->running = 0; -+ } -+ break; -+ default: -+ err = -EINVAL; -+ } -+ -+ audio_info(" .. OUT\n"); -+ return err; -+} -+ -+/* pointer callback */ -+static snd_pcm_uframes_t -+snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ -+ audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0, -+ frames_to_bytes(runtime, runtime->status->hw_ptr), -+ frames_to_bytes(runtime, runtime->control->appl_ptr), -+ alsa_stream->pos); -+ -+ audio_info(" .. OUT\n"); -+ return snd_pcm_indirect_playback_pointer(substream, -+ &alsa_stream->pcm_indirect, -+ alsa_stream->pos); -+} -+ -+static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream, -+ unsigned int cmd, void *arg) -+{ -+ int ret = snd_pcm_lib_ioctl(substream, cmd, arg); -+ audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream, -+ cmd, arg, arg ? *(unsigned *)arg : 0, ret); -+ return ret; -+} -+ -+/* operators */ -+static struct snd_pcm_ops snd_bcm2835_playback_ops = { -+ .open = snd_bcm2835_playback_open, -+ .close = snd_bcm2835_playback_close, -+ .ioctl = snd_bcm2835_pcm_lib_ioctl, -+ .hw_params = snd_bcm2835_pcm_hw_params, -+ .hw_free = snd_bcm2835_pcm_hw_free, -+ .prepare = snd_bcm2835_pcm_prepare, -+ .trigger = snd_bcm2835_pcm_trigger, -+ .pointer = snd_bcm2835_pcm_pointer, -+ .ack = snd_bcm2835_pcm_ack, -+}; -+ -+static struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = { -+ .open = snd_bcm2835_playback_spdif_open, -+ .close = snd_bcm2835_playback_close, -+ .ioctl = snd_bcm2835_pcm_lib_ioctl, -+ .hw_params = snd_bcm2835_pcm_hw_params, -+ .hw_free = snd_bcm2835_pcm_hw_free, -+ .prepare = snd_bcm2835_pcm_prepare, -+ .trigger = snd_bcm2835_pcm_trigger, -+ .pointer = snd_bcm2835_pcm_pointer, -+ .ack = snd_bcm2835_pcm_ack, -+}; -+ -+/* create a pcm device */ -+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip) -+{ -+ struct snd_pcm *pcm; -+ int err; -+ -+ audio_info(" .. IN\n"); -+ mutex_init(&chip->audio_mutex); -+ if(mutex_lock_interruptible(&chip->audio_mutex)) -+ { -+ audio_error("Interrupted whilst waiting for lock\n"); -+ return -EINTR; -+ } -+ err = -+ snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm); -+ if (err < 0) -+ goto out; -+ pcm->private_data = chip; -+ strcpy(pcm->name, "bcm2835 ALSA"); -+ chip->pcm = pcm; -+ chip->dest = AUDIO_DEST_AUTO; -+ chip->volume = alsa2chip(0); -+ chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */ -+ /* set operators */ -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, -+ &snd_bcm2835_playback_ops); -+ -+ /* pre-allocation of buffers */ -+ /* NOTE: this may fail */ -+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, -+ snd_dma_continuous_data (GFP_KERNEL), -+ snd_bcm2835_playback_hw.buffer_bytes_max, snd_bcm2835_playback_hw.buffer_bytes_max); -+ -+ -+out: -+ mutex_unlock(&chip->audio_mutex); -+ audio_info(" .. OUT\n"); -+ -+ return 0; -+} -+ -+int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip) -+{ -+ struct snd_pcm *pcm; -+ int err; -+ -+ audio_info(" .. IN\n"); -+ if(mutex_lock_interruptible(&chip->audio_mutex)) -+ { -+ audio_error("Interrupted whilst waiting for lock\n"); -+ return -EINTR; -+ } -+ err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm); -+ if (err < 0) -+ goto out; -+ -+ pcm->private_data = chip; -+ strcpy(pcm->name, "bcm2835 IEC958/HDMI"); -+ chip->pcm_spdif = pcm; -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, -+ &snd_bcm2835_playback_spdif_ops); -+ -+ /* pre-allocation of buffers */ -+ /* NOTE: this may fail */ -+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, -+ snd_dma_continuous_data (GFP_KERNEL), -+ snd_bcm2835_playback_spdif_hw.buffer_bytes_max, snd_bcm2835_playback_spdif_hw.buffer_bytes_max); -+out: -+ mutex_unlock(&chip->audio_mutex); -+ audio_info(" .. OUT\n"); -+ -+ return 0; -+} -diff --git a/sound/arm/bcm2835-vchiq.c b/sound/arm/bcm2835-vchiq.c -new file mode 100755 -index 0000000000000000000000000000000000000000..7ee436ca9fa2903d41d1bdd8f8f0774025d22ae0 ---- /dev/null -+++ b/sound/arm/bcm2835-vchiq.c -@@ -0,0 +1,889 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bcm2835.h" -+ -+/* ---- Include Files -------------------------------------------------------- */ -+ -+#include "interface/vchi/vchi.h" -+#include "vc_vchi_audioserv_defs.h" -+ -+/* ---- Private Constants and Types ------------------------------------------ */ -+ -+#define BCM2835_AUDIO_STOP 0 -+#define BCM2835_AUDIO_START 1 -+#define BCM2835_AUDIO_WRITE 2 -+ -+/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */ -+#ifdef AUDIO_DEBUG_ENABLE -+ #define LOG_ERR( fmt, arg... ) pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg) -+ #define LOG_WARN( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) -+ #define LOG_INFO( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) -+ #define LOG_DBG( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) -+#else -+ #define LOG_ERR( fmt, arg... ) pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg) -+ #define LOG_WARN( fmt, arg... ) -+ #define LOG_INFO( fmt, arg... ) -+ #define LOG_DBG( fmt, arg... ) -+#endif -+ -+typedef struct opaque_AUDIO_INSTANCE_T { -+ uint32_t num_connections; -+ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS]; -+ struct completion msg_avail_comp; -+ struct mutex vchi_mutex; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int32_t result; -+ short peer_version; -+} AUDIO_INSTANCE_T; -+ -+bool force_bulk = false; -+ -+/* ---- Private Variables ---------------------------------------------------- */ -+ -+/* ---- Private Function Prototypes ------------------------------------------ */ -+ -+/* ---- Private Functions ---------------------------------------------------- */ -+ -+static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream); -+static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream); -+static int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream, -+ uint32_t count, void *src); -+ -+typedef struct { -+ struct work_struct my_work; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int cmd; -+ void *src; -+ uint32_t count; -+} my_work_t; -+ -+static void my_wq_function(struct work_struct *work) -+{ -+ my_work_t *w = (my_work_t *) work; -+ int ret = -9; -+ LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->cmd); -+ switch (w->cmd) { -+ case BCM2835_AUDIO_START: -+ ret = bcm2835_audio_start_worker(w->alsa_stream); -+ break; -+ case BCM2835_AUDIO_STOP: -+ ret = bcm2835_audio_stop_worker(w->alsa_stream); -+ break; -+ case BCM2835_AUDIO_WRITE: -+ ret = bcm2835_audio_write_worker(w->alsa_stream, w->count, -+ w->src); -+ break; -+ default: -+ LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->cmd); -+ break; -+ } -+ kfree((void *)work); -+ LOG_DBG(" .. OUT %d\n", ret); -+} -+ -+int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ int ret = -1; -+ LOG_DBG(" .. IN\n"); -+ if (alsa_stream->my_wq) { -+ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); -+ /*--- Queue some work (item 1) ---*/ -+ if (work) { -+ INIT_WORK((struct work_struct *)work, my_wq_function); -+ work->alsa_stream = alsa_stream; -+ work->cmd = BCM2835_AUDIO_START; -+ if (queue_work -+ (alsa_stream->my_wq, (struct work_struct *)work)) -+ ret = 0; -+ } else -+ LOG_ERR(" .. Error: NULL work kmalloc\n"); -+ } -+ LOG_DBG(" .. OUT %d\n", ret); -+ return ret; -+} -+ -+int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ int ret = -1; -+ LOG_DBG(" .. IN\n"); -+ if (alsa_stream->my_wq) { -+ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); -+ /*--- Queue some work (item 1) ---*/ -+ if (work) { -+ INIT_WORK((struct work_struct *)work, my_wq_function); -+ work->alsa_stream = alsa_stream; -+ work->cmd = BCM2835_AUDIO_STOP; -+ if (queue_work -+ (alsa_stream->my_wq, (struct work_struct *)work)) -+ ret = 0; -+ } else -+ LOG_ERR(" .. Error: NULL work kmalloc\n"); -+ } -+ LOG_DBG(" .. OUT %d\n", ret); -+ return ret; -+} -+ -+int bcm2835_audio_write(bcm2835_alsa_stream_t *alsa_stream, -+ uint32_t count, void *src) -+{ -+ int ret = -1; -+ LOG_DBG(" .. IN\n"); -+ if (alsa_stream->my_wq) { -+ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); -+ /*--- Queue some work (item 1) ---*/ -+ if (work) { -+ INIT_WORK((struct work_struct *)work, my_wq_function); -+ work->alsa_stream = alsa_stream; -+ work->cmd = BCM2835_AUDIO_WRITE; -+ work->src = src; -+ work->count = count; -+ if (queue_work -+ (alsa_stream->my_wq, (struct work_struct *)work)) -+ ret = 0; -+ } else -+ LOG_ERR(" .. Error: NULL work kmalloc\n"); -+ } -+ LOG_DBG(" .. OUT %d\n", ret); -+ return ret; -+} -+ -+void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1); -+ return; -+} -+ -+void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ if (alsa_stream->my_wq) { -+ flush_workqueue(alsa_stream->my_wq); -+ destroy_workqueue(alsa_stream->my_wq); -+ alsa_stream->my_wq = NULL; -+ } -+ return; -+} -+ -+static void audio_vchi_callback(void *param, -+ const VCHI_CALLBACK_REASON_T reason, -+ void *msg_handle) -+{ -+ AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param; -+ int32_t status; -+ int32_t msg_len; -+ VC_AUDIO_MSG_T m; -+ LOG_DBG(" .. IN instance=%p, handle=%p, alsa=%p, reason=%d, handle=%p\n", -+ instance, instance ? instance->vchi_handle[0] : NULL, instance ? instance->alsa_stream : NULL, reason, msg_handle); -+ -+ if (reason != VCHI_CALLBACK_MSG_AVAILABLE) { -+ return; -+ } -+ if (!instance) { -+ LOG_ERR(" .. instance is null\n"); -+ BUG(); -+ return; -+ } -+ if (!instance->vchi_handle[0]) { -+ LOG_ERR(" .. instance->vchi_handle[0] is null\n"); -+ BUG(); -+ return; -+ } -+ status = vchi_msg_dequeue(instance->vchi_handle[0], -+ &m, sizeof m, &msg_len, VCHI_FLAGS_NONE); -+ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { -+ LOG_DBG -+ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n", -+ instance, m.u.result.success); -+ instance->result = m.u.result.success; -+ complete(&instance->msg_avail_comp); -+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { -+ bcm2835_alsa_stream_t *alsa_stream = instance->alsa_stream; -+ irq_handler_t callback = (irq_handler_t) m.u.complete.callback; -+ LOG_DBG -+ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n", -+ instance, m.u.complete.count); -+ if (alsa_stream && callback) { -+ atomic_add(m.u.complete.count, &alsa_stream->retrieved); -+ callback(0, alsa_stream); -+ } else { -+ LOG_ERR(" .. unexpected alsa_stream=%p, callback=%p\n", -+ alsa_stream, callback); -+ } -+ } else { -+ LOG_ERR(" .. unexpected m.type=%d\n", m.type); -+ } -+ LOG_DBG(" .. OUT\n"); -+} -+ -+static AUDIO_INSTANCE_T *vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, -+ VCHI_CONNECTION_T ** -+ vchi_connections, -+ uint32_t num_connections) -+{ -+ uint32_t i; -+ AUDIO_INSTANCE_T *instance; -+ int status; -+ -+ LOG_DBG("%s: start", __func__); -+ -+ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) { -+ LOG_ERR("%s: unsupported number of connections %u (max=%u)\n", -+ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS); -+ -+ return NULL; -+ } -+ /* Allocate memory for this instance */ -+ instance = kmalloc(sizeof(*instance), GFP_KERNEL); -+ if (!instance) -+ return NULL; -+ -+ memset(instance, 0, sizeof(*instance)); -+ instance->num_connections = num_connections; -+ -+ /* Create a lock for exclusive, serialized VCHI connection access */ -+ mutex_init(&instance->vchi_mutex); -+ /* Open the VCHI service connections */ -+ for (i = 0; i < num_connections; i++) { -+ SERVICE_CREATION_T params = { -+ VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), -+ VC_AUDIO_SERVER_NAME, // 4cc service code -+ vchi_connections[i], // passed in fn pointers -+ 0, // rx fifo size (unused) -+ 0, // tx fifo size (unused) -+ audio_vchi_callback, // service callback -+ instance, // service callback parameter -+ 1, //TODO: remove VCOS_FALSE, // unaligned bulk recieves -+ 1, //TODO: remove VCOS_FALSE, // unaligned bulk transmits -+ 0 // want crc check on bulk transfers -+ }; -+ -+ LOG_DBG("%s: about to open %i\n", __func__, i); -+ status = vchi_service_open(vchi_instance, ¶ms, -+ &instance->vchi_handle[i]); -+ LOG_DBG("%s: opened %i: %p=%d\n", __func__, i, instance->vchi_handle[i], status); -+ if (status) { -+ LOG_ERR -+ ("%s: failed to open VCHI service connection (status=%d)\n", -+ __func__, status); -+ -+ goto err_close_services; -+ } -+ /* Finished with the service for now */ -+ vchi_service_release(instance->vchi_handle[i]); -+ } -+ -+ LOG_DBG("%s: okay\n", __func__); -+ return instance; -+ -+err_close_services: -+ for (i = 0; i < instance->num_connections; i++) { -+ LOG_ERR("%s: closing %i: %p\n", __func__, i, instance->vchi_handle[i]); -+ if (instance->vchi_handle[i]) -+ vchi_service_close(instance->vchi_handle[i]); -+ } -+ -+ kfree(instance); -+ LOG_ERR("%s: error\n", __func__); -+ -+ return NULL; -+} -+ -+static int32_t vc_vchi_audio_deinit(AUDIO_INSTANCE_T * instance) -+{ -+ uint32_t i; -+ -+ LOG_DBG(" .. IN\n"); -+ -+ if (instance == NULL) { -+ LOG_ERR("%s: invalid handle %p\n", __func__, instance); -+ -+ return -1; -+ } -+ -+ LOG_DBG(" .. about to lock (%d)\n", instance->num_connections); -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ -+ /* Close all VCHI service connections */ -+ for (i = 0; i < instance->num_connections; i++) { -+ int32_t success; -+ LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]); -+ vchi_service_use(instance->vchi_handle[i]); -+ -+ success = vchi_service_close(instance->vchi_handle[i]); -+ if (success != 0) { -+ LOG_DBG -+ ("%s: failed to close VCHI service connection (status=%d)\n", -+ __func__, success); -+ } -+ } -+ -+ mutex_unlock(&instance->vchi_mutex); -+ -+ kfree(instance); -+ -+ LOG_DBG(" .. OUT\n"); -+ -+ return 0; -+} -+ -+static int bcm2835_audio_open_connection(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ static VCHI_INSTANCE_T vchi_instance; -+ static VCHI_CONNECTION_T *vchi_connection; -+ static int initted; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO("%s: start\n", __func__); -+ BUG_ON(instance); -+ if (instance) { -+ LOG_ERR("%s: VCHI instance already open (%p)\n", -+ __func__, instance); -+ instance->alsa_stream = alsa_stream; -+ alsa_stream->instance = instance; -+ ret = 0; // xxx todo -1; -+ goto err_free_mem; -+ } -+ -+ /* Initialize and create a VCHI connection */ -+ if (!initted) { -+ ret = vchi_initialise(&vchi_instance); -+ if (ret != 0) { -+ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n", -+ __func__, ret); -+ -+ ret = -EIO; -+ goto err_free_mem; -+ } -+ ret = vchi_connect(NULL, 0, vchi_instance); -+ if (ret != 0) { -+ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n", -+ __func__, ret); -+ -+ ret = -EIO; -+ goto err_free_mem; -+ } -+ initted = 1; -+ } -+ -+ /* Initialize an instance of the audio service */ -+ instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1); -+ -+ if (instance == NULL) { -+ LOG_ERR("%s: failed to initialize audio service\n", __func__); -+ -+ ret = -EPERM; -+ goto err_free_mem; -+ } -+ -+ instance->alsa_stream = alsa_stream; -+ alsa_stream->instance = instance; -+ -+ LOG_DBG(" success !\n"); -+err_free_mem: -+ LOG_DBG(" .. OUT\n"); -+ -+ return ret; -+} -+ -+int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ AUDIO_INSTANCE_T *instance; -+ VC_AUDIO_MSG_T m; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ my_workqueue_init(alsa_stream); -+ -+ ret = bcm2835_audio_open_connection(alsa_stream); -+ if (ret != 0) { -+ ret = -1; -+ goto exit; -+ } -+ instance = alsa_stream->instance; -+ LOG_DBG(" instance (%p)\n", instance); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_OPEN; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+exit: -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream, -+ bcm2835_chip_t * chip) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO -+ (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ instance->result = -1; -+ -+ m.type = VC_AUDIO_MSG_TYPE_CONTROL; -+ m.u.control.dest = chip->dest; -+ m.u.control.volume = chip->volume; -+ -+ /* Create the message available completion */ -+ init_completion(&instance->msg_avail_comp); -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ /* We are expecting a reply from the videocore */ -+ wait_for_completion(&instance->msg_avail_comp); -+ -+ if (instance->result != 0) { -+ LOG_ERR("%s: result=%d\n", __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_set_ctls(bcm2835_chip_t * chip) -+{ -+ int i; -+ int ret = 0; -+ LOG_DBG(" .. IN\n"); -+ LOG_DBG(" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); -+ -+ /* change ctls for all substreams */ -+ for (i = 0; i < MAX_SUBSTREAMS; i++) { -+ if (chip->avail_substreams & (1 << i)) { -+ if (!chip->alsa_stream[i]) -+ { -+ LOG_DBG(" No ALSA stream available?! %i:%p (%x)\n", i, chip->alsa_stream[i], chip->avail_substreams); -+ ret = 0; -+ } -+ else if (bcm2835_audio_set_ctls_chan /* returns 0 on success */ -+ (chip->alsa_stream[i], chip) != 0) -+ { -+ LOG_ERR("Couldn't set the controls for stream %d\n", i); -+ ret = -1; -+ } -+ else LOG_DBG(" Controls set for stream %d\n", i); -+ } -+ } -+ LOG_DBG(" .. OUT ret=%d\n", ret); -+ return ret; -+} -+ -+int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, -+ uint32_t channels, uint32_t samplerate, -+ uint32_t bps) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO -+ (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n", -+ channels, samplerate, bps); -+ -+ /* resend ctls - alsa_stream may not have been open when first send */ -+ ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip); -+ if (ret != 0) { -+ LOG_ERR(" Alsa controls not supported\n"); -+ return -EINVAL; -+ } -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ instance->result = -1; -+ -+ m.type = VC_AUDIO_MSG_TYPE_CONFIG; -+ m.u.config.channels = channels; -+ m.u.config.samplerate = samplerate; -+ m.u.config.bps = bps; -+ -+ /* Create the message available completion */ -+ init_completion(&instance->msg_avail_comp); -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ /* We are expecting a reply from the videocore */ -+ wait_for_completion(&instance->msg_avail_comp); -+ -+ if (instance->result != 0) { -+ LOG_ERR("%s: result=%d", __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_DBG(" .. OUT\n"); -+ -+ return 0; -+} -+ -+static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_START; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_STOP; -+ m.u.stop.draining = alsa_stream->draining; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ my_workqueue_quit(alsa_stream); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_CLOSE; -+ -+ /* Create the message available completion */ -+ init_completion(&instance->msg_avail_comp); -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ ret = -1; -+ goto unlock; -+ } -+ -+ /* We are expecting a reply from the videocore */ -+ wait_for_completion(&instance->msg_avail_comp); -+ -+ if (instance->result != 0) { -+ LOG_ERR("%s: failed result (result=%d)\n", -+ __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ -+ /* Stop the audio service */ -+ if (instance) { -+ vc_vchi_audio_deinit(instance); -+ alsa_stream->instance = NULL; -+ } -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream, -+ uint32_t count, void *src) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO(" Writing %d bytes from %p\n", count, src); -+ -+ if(mutex_lock_interruptible(&instance->vchi_mutex)) -+ { -+ LOG_DBG("Interrupted whilst waiting for lock on (%d)\n",instance->num_connections); -+ return -EINTR; -+ } -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ if ( instance->peer_version==0 && vchi_get_peer_version(instance->vchi_handle[0], &instance->peer_version) == 0 ) { -+ LOG_DBG("%s: client version %d connected\n", __func__, instance->peer_version); -+ } -+ m.type = VC_AUDIO_MSG_TYPE_WRITE; -+ m.u.write.count = count; -+ // old version uses bulk, new version uses control -+ m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000; -+ m.u.write.callback = alsa_stream->fifo_irq_handler; -+ m.u.write.cookie = alsa_stream; -+ m.u.write.silence = src == NULL; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ if (!m.u.write.silence) { -+ if (m.u.write.max_packet == 0) { -+ /* Send the message to the videocore */ -+ success = vchi_bulk_queue_transmit(instance->vchi_handle[0], -+ src, count, -+ 0 * -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED -+ + -+ 1 * -+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, -+ NULL); -+ } else { -+ while (count > 0) { -+ int bytes = min((int)m.u.write.max_packet, (int)count); -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ src, bytes, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ src = (char *)src + bytes; -+ count -= bytes; -+ } -+ } -+ if (success != 0) { -+ LOG_ERR -+ ("%s: failed on vchi_bulk_queue_transmit (status=%d)\n", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ } -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+/** -+ * Returns all buffers from arm->vc -+ */ -+void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ LOG_DBG(" .. OUT\n"); -+ return; -+} -+ -+/** -+ * Forces VC to flush(drop) its filled playback buffers and -+ * return them the us. (VC->ARM) -+ */ -+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ LOG_DBG(" .. OUT\n"); -+} -+ -+uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ uint32_t count = atomic_read(&alsa_stream->retrieved); -+ atomic_sub(count, &alsa_stream->retrieved); -+ return count; -+} -+ -+module_param(force_bulk, bool, 0444); -+MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio"); -diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c -new file mode 100644 -index 0000000000000000000000000000000000000000..7a2ed78ba19912aad37d46430c7ab36899880581 ---- /dev/null -+++ b/sound/arm/bcm2835.c -@@ -0,0 +1,511 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "bcm2835.h" -+ -+/* module parameters (see "Module Parameters") */ -+/* SNDRV_CARDS: maximum number of cards supported by this module */ -+static int index[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = -1 }; -+static char *id[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = NULL }; -+static int enable[MAX_SUBSTREAMS] = {[0 ... (MAX_SUBSTREAMS - 1)] = 1 }; -+ -+/* HACKY global pointers needed for successive probes to work : ssp -+ * But compared against the changes we will have to do in VC audio_ipc code -+ * to export 8 audio_ipc devices as a single IPC device and then monitor all -+ * four devices in a thread, this gets things done quickly and should be easier -+ * to debug if we run into issues -+ */ -+ -+static struct snd_card *g_card = NULL; -+static bcm2835_chip_t *g_chip = NULL; -+ -+static int snd_bcm2835_free(bcm2835_chip_t * chip) -+{ -+ kfree(chip); -+ return 0; -+} -+ -+/* component-destructor -+ * (see "Management of Cards and Components") -+ */ -+static int snd_bcm2835_dev_free(struct snd_device *device) -+{ -+ return snd_bcm2835_free(device->device_data); -+} -+ -+/* chip-specific constructor -+ * (see "Management of Cards and Components") -+ */ -+static int snd_bcm2835_create(struct snd_card *card, -+ struct platform_device *pdev, -+ bcm2835_chip_t ** rchip) -+{ -+ bcm2835_chip_t *chip; -+ int err; -+ static struct snd_device_ops ops = { -+ .dev_free = snd_bcm2835_dev_free, -+ }; -+ -+ *rchip = NULL; -+ -+ chip = kzalloc(sizeof(*chip), GFP_KERNEL); -+ if (chip == NULL) -+ return -ENOMEM; -+ -+ chip->card = card; -+ -+ err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); -+ if (err < 0) { -+ snd_bcm2835_free(chip); -+ return err; -+ } -+ -+ *rchip = chip; -+ return 0; -+} -+ -+static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ bcm2835_chip_t *chip; -+ struct snd_card *card; -+ u32 numchans; -+ int err, i; -+ -+ err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", -+ &numchans); -+ if (err) { -+ dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); -+ return err; -+ } -+ -+ if (numchans == 0 || numchans > MAX_SUBSTREAMS) { -+ numchans = MAX_SUBSTREAMS; -+ dev_warn(dev, "Illegal 'brcm,pwm-channels' value, will use %u\n", -+ numchans); -+ } -+ -+ err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card); -+ if (err) { -+ dev_err(dev, "Failed to create soundcard structure\n"); -+ return err; -+ } -+ -+ snd_card_set_dev(card, dev); -+ strcpy(card->driver, "bcm2835"); -+ strcpy(card->shortname, "bcm2835 ALSA"); -+ sprintf(card->longname, "%s", card->shortname); -+ -+ err = snd_bcm2835_create(card, pdev, &chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create bcm2835 chip\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_spdif_pcm(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 spdif pcm device\n"); -+ goto err_free; -+ } -+ -+ err = snd_bcm2835_new_ctl(chip); -+ if (err < 0) { -+ dev_err(dev, "Failed to create new bcm2835 ctl\n"); -+ goto err_free; -+ } -+ -+ for (i = 0; i < numchans; i++) { -+ chip->avail_substreams |= (1 << i); -+ chip->pdev[i] = pdev; -+ } -+ -+ err = snd_card_register(card); -+ if (err) { -+ dev_err(dev, "Failed to register bcm2835 ALSA card \n"); -+ goto err_free; -+ } -+ -+ g_card = card; -+ g_chip = chip; -+ platform_set_drvdata(pdev, card); -+ audio_info("bcm2835 ALSA card created with %u channels\n", numchans); -+ -+ return 0; -+ -+err_free: -+ snd_card_free(card); -+ -+ return err; -+} -+ -+static int snd_bcm2835_alsa_probe(struct platform_device *pdev) -+{ -+ static int dev; -+ bcm2835_chip_t *chip; -+ struct snd_card *card; -+ int err; -+ -+ if (pdev->dev.of_node) -+ return snd_bcm2835_alsa_probe_dt(pdev); -+ -+ if (dev >= MAX_SUBSTREAMS) -+ return -ENODEV; -+ -+ if (!enable[dev]) { -+ dev++; -+ return -ENOENT; -+ } -+ -+ if (dev > 0) -+ goto add_register_map; -+ -+ err = snd_card_new(&pdev->dev, index[dev], id[dev], THIS_MODULE, 0, &g_card); -+ if (err < 0) -+ goto out; -+ -+ snd_card_set_dev(g_card, &pdev->dev); -+ strcpy(g_card->driver, "bcm2835"); -+ strcpy(g_card->shortname, "bcm2835 ALSA"); -+ sprintf(g_card->longname, "%s", g_card->shortname); -+ -+ err = snd_bcm2835_create(g_card, pdev, &chip); -+ if (err < 0) { -+ dev_err(&pdev->dev, "Failed to create bcm2835 chip\n"); -+ goto out_bcm2835_create; -+ } -+ -+ g_chip = chip; -+ err = snd_bcm2835_new_pcm(chip); -+ if (err < 0) { -+ dev_err(&pdev->dev, "Failed to create new BCM2835 pcm device\n"); -+ goto out_bcm2835_new_pcm; -+ } -+ -+ err = snd_bcm2835_new_spdif_pcm(chip); -+ if (err < 0) { -+ dev_err(&pdev->dev, "Failed to create new BCM2835 spdif pcm device\n"); -+ goto out_bcm2835_new_spdif; -+ } -+ -+ err = snd_bcm2835_new_ctl(chip); -+ if (err < 0) { -+ dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n"); -+ goto out_bcm2835_new_ctl; -+ } -+ -+add_register_map: -+ card = g_card; -+ chip = g_chip; -+ -+ BUG_ON(!(card && chip)); -+ -+ chip->avail_substreams |= (1 << dev); -+ chip->pdev[dev] = pdev; -+ -+ if (dev == 0) { -+ err = snd_card_register(card); -+ if (err < 0) { -+ dev_err(&pdev->dev, -+ "Failed to register bcm2835 ALSA card \n"); -+ goto out_card_register; -+ } -+ platform_set_drvdata(pdev, card); -+ audio_info("bcm2835 ALSA card created!\n"); -+ } else { -+ audio_info("bcm2835 ALSA chip created!\n"); -+ platform_set_drvdata(pdev, (void *)dev); -+ } -+ -+ dev++; -+ -+ return 0; -+ -+out_card_register: -+out_bcm2835_new_ctl: -+out_bcm2835_new_spdif: -+out_bcm2835_new_pcm: -+out_bcm2835_create: -+ BUG_ON(!g_card); -+ if (snd_card_free(g_card)) -+ dev_err(&pdev->dev, "Failed to free Registered alsa card\n"); -+ g_card = NULL; -+out: -+ dev = SNDRV_CARDS; /* stop more avail_substreams from being probed */ -+ dev_err(&pdev->dev, "BCM2835 ALSA Probe failed !!\n"); -+ return err; -+} -+ -+static int snd_bcm2835_alsa_remove(struct platform_device *pdev) -+{ -+ uint32_t idx; -+ void *drv_data; -+ -+ drv_data = platform_get_drvdata(pdev); -+ -+ if (drv_data == (void *)g_card) { -+ /* This is the card device */ -+ snd_card_free((struct snd_card *)drv_data); -+ g_card = NULL; -+ g_chip = NULL; -+ } else { -+ idx = (uint32_t) drv_data; -+ if (g_card != NULL) { -+ BUG_ON(!g_chip); -+ /* We pass chip device numbers in audio ipc devices -+ * other than the one we registered our card with -+ */ -+ idx = (uint32_t) drv_data; -+ BUG_ON(!idx || idx > MAX_SUBSTREAMS); -+ g_chip->avail_substreams &= ~(1 << idx); -+ /* There should be atleast one substream registered -+ * after we are done here, as it wil be removed when -+ * the *remove* is called for the card device -+ */ -+ BUG_ON(!g_chip->avail_substreams); -+ } -+ } -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int snd_bcm2835_alsa_suspend(struct platform_device *pdev, -+ pm_message_t state) -+{ -+ return 0; -+} -+ -+static int snd_bcm2835_alsa_resume(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+#endif -+ -+static const struct of_device_id snd_bcm2835_of_match_table[] = { -+ { .compatible = "brcm,bcm2835-audio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); -+ -+static struct platform_driver bcm2835_alsa0_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD0", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_bcm2835_of_match_table, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa1_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD1", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa2_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD2", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa3_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD3", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa4_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD4", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa5_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD5", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa6_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD6", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static struct platform_driver bcm2835_alsa7_driver = { -+ .probe = snd_bcm2835_alsa_probe, -+ .remove = snd_bcm2835_alsa_remove, -+#ifdef CONFIG_PM -+ .suspend = snd_bcm2835_alsa_suspend, -+ .resume = snd_bcm2835_alsa_resume, -+#endif -+ .driver = { -+ .name = "bcm2835_AUD7", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int bcm2835_alsa_device_init(void) -+{ -+ int err; -+ err = platform_driver_register(&bcm2835_alsa0_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto out; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa1_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_0; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa2_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_1; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa3_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_2; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa4_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_3; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa5_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_4; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa6_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_5; -+ } -+ -+ err = platform_driver_register(&bcm2835_alsa7_driver); -+ if (err) { -+ pr_err("Error registering bcm2835_alsa0_driver %d .\n", err); -+ goto unregister_6; -+ } -+ -+ return 0; -+ -+unregister_6: -+ platform_driver_unregister(&bcm2835_alsa6_driver); -+unregister_5: -+ platform_driver_unregister(&bcm2835_alsa5_driver); -+unregister_4: -+ platform_driver_unregister(&bcm2835_alsa4_driver); -+unregister_3: -+ platform_driver_unregister(&bcm2835_alsa3_driver); -+unregister_2: -+ platform_driver_unregister(&bcm2835_alsa2_driver); -+unregister_1: -+ platform_driver_unregister(&bcm2835_alsa1_driver); -+unregister_0: -+ platform_driver_unregister(&bcm2835_alsa0_driver); -+out: -+ return err; -+} -+ -+static void bcm2835_alsa_device_exit(void) -+{ -+ platform_driver_unregister(&bcm2835_alsa0_driver); -+ platform_driver_unregister(&bcm2835_alsa1_driver); -+ platform_driver_unregister(&bcm2835_alsa2_driver); -+ platform_driver_unregister(&bcm2835_alsa3_driver); -+ platform_driver_unregister(&bcm2835_alsa4_driver); -+ platform_driver_unregister(&bcm2835_alsa5_driver); -+ platform_driver_unregister(&bcm2835_alsa6_driver); -+ platform_driver_unregister(&bcm2835_alsa7_driver); -+} -+ -+late_initcall(bcm2835_alsa_device_init); -+module_exit(bcm2835_alsa_device_exit); -+ -+MODULE_AUTHOR("Dom Cobley"); -+MODULE_DESCRIPTION("Alsa driver for BCM2835 chip"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm2835_alsa"); -diff --git a/sound/arm/bcm2835.h b/sound/arm/bcm2835.h -new file mode 100755 -index 0000000000000000000000000000000000000000..0f71c5def314a63252fa4fe18ae2ba5a339f2cfb ---- /dev/null -+++ b/sound/arm/bcm2835.h -@@ -0,0 +1,167 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#ifndef __SOUND_ARM_BCM2835_H -+#define __SOUND_ARM_BCM2835_H -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+#define AUDIO_DEBUG_ENABLE -+#define AUDIO_VERBOSE_DEBUG_ENABLE -+*/ -+ -+/* Debug macros */ -+ -+#ifdef AUDIO_DEBUG_ENABLE -+#ifdef AUDIO_VERBOSE_DEBUG_ENABLE -+ -+#define audio_debug(fmt, arg...) \ -+ printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+#define audio_info(fmt, arg...) \ -+ printk(KERN_INFO"%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+#else -+ -+#define audio_debug(fmt, arg...) -+ -+#define audio_info(fmt, arg...) -+ -+#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */ -+ -+#else -+ -+#define audio_debug(fmt, arg...) -+ -+#define audio_info(fmt, arg...) -+ -+#endif /* AUDIO_DEBUG_ENABLE */ -+ -+#define audio_error(fmt, arg...) \ -+ printk(KERN_ERR"%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+#define audio_warning(fmt, arg...) \ -+ printk(KERN_WARNING"%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+#define audio_alert(fmt, arg...) \ -+ printk(KERN_ALERT"%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+#define MAX_SUBSTREAMS (8) -+#define AVAIL_SUBSTREAMS_MASK (0xff) -+enum { -+ CTRL_VOL_MUTE, -+ CTRL_VOL_UNMUTE -+}; -+ -+/* macros for alsa2chip and chip2alsa, instead of functions */ -+ -+#define alsa2chip(vol) (uint)(-((vol << 8) / 100)) /* convert alsa to chip volume (defined as macro rather than function call) */ -+#define chip2alsa(vol) -((vol * 100) >> 8) /* convert chip to alsa volume */ -+ -+/* Some constants for values .. */ -+typedef enum { -+ AUDIO_DEST_AUTO = 0, -+ AUDIO_DEST_HEADPHONES = 1, -+ AUDIO_DEST_HDMI = 2, -+ AUDIO_DEST_MAX, -+} SND_BCM2835_ROUTE_T; -+ -+typedef enum { -+ PCM_PLAYBACK_VOLUME, -+ PCM_PLAYBACK_MUTE, -+ PCM_PLAYBACK_DEVICE, -+} SND_BCM2835_CTRL_T; -+ -+/* definition of the chip-specific record */ -+typedef struct bcm2835_chip { -+ struct snd_card *card; -+ struct snd_pcm *pcm; -+ struct snd_pcm *pcm_spdif; -+ /* Bitmat for valid reg_base and irq numbers */ -+ uint32_t avail_substreams; -+ struct platform_device *pdev[MAX_SUBSTREAMS]; -+ struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS]; -+ -+ int volume; -+ int old_volume; /* stores the volume value whist muted */ -+ int dest; -+ int mute; -+ -+ unsigned int opened; -+ unsigned int spdif_status; -+ struct mutex audio_mutex; -+} bcm2835_chip_t; -+ -+typedef struct bcm2835_alsa_stream { -+ bcm2835_chip_t *chip; -+ struct snd_pcm_substream *substream; -+ struct snd_pcm_indirect pcm_indirect; -+ -+ struct semaphore buffers_update_sem; -+ struct semaphore control_sem; -+ spinlock_t lock; -+ volatile uint32_t control; -+ volatile uint32_t status; -+ -+ int open; -+ int running; -+ int draining; -+ -+ int channels; -+ int params_rate; -+ int pcm_format_width; -+ -+ unsigned int pos; -+ unsigned int buffer_size; -+ unsigned int period_size; -+ -+ uint32_t enable_fifo_irq; -+ irq_handler_t fifo_irq_handler; -+ -+ atomic_t retrieved; -+ struct opaque_AUDIO_INSTANCE_T *instance; -+ struct workqueue_struct *my_wq; -+ int idx; -+} bcm2835_alsa_stream_t; -+ -+int snd_bcm2835_new_ctl(bcm2835_chip_t * chip); -+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip); -+int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip); -+ -+int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream); -+int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream); -+int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, -+ uint32_t channels, uint32_t samplerate, -+ uint32_t bps); -+int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream); -+int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream); -+int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream); -+int bcm2835_audio_set_ctls(bcm2835_chip_t * chip); -+int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count, -+ void *src); -+uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream); -+void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream); -+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream); -+ -+#endif /* __SOUND_ARM_BCM2835_H */ -diff --git a/sound/arm/vc_vchi_audioserv_defs.h b/sound/arm/vc_vchi_audioserv_defs.h -new file mode 100644 -index 0000000000000000000000000000000000000000..af3e6eb690113fc32ce9e06bd2f0f294da7a7f00 ---- /dev/null -+++ b/sound/arm/vc_vchi_audioserv_defs.h -@@ -0,0 +1,116 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#ifndef _VC_AUDIO_DEFS_H_ -+#define _VC_AUDIO_DEFS_H_ -+ -+#define VC_AUDIOSERV_MIN_VER 1 -+#define VC_AUDIOSERV_VER 2 -+ -+// FourCC code used for VCHI connection -+#define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS") -+ -+// Maximum message length -+#define VC_AUDIO_MAX_MSG_LEN (sizeof( VC_AUDIO_MSG_T )) -+ -+// List of screens that are currently supported -+// All message types supported for HOST->VC direction -+typedef enum { -+ VC_AUDIO_MSG_TYPE_RESULT, // Generic result -+ VC_AUDIO_MSG_TYPE_COMPLETE, // Generic result -+ VC_AUDIO_MSG_TYPE_CONFIG, // Configure audio -+ VC_AUDIO_MSG_TYPE_CONTROL, // Configure audio -+ VC_AUDIO_MSG_TYPE_OPEN, // Configure audio -+ VC_AUDIO_MSG_TYPE_CLOSE, // Configure audio -+ VC_AUDIO_MSG_TYPE_START, // Configure audio -+ VC_AUDIO_MSG_TYPE_STOP, // Configure audio -+ VC_AUDIO_MSG_TYPE_WRITE, // Configure audio -+ VC_AUDIO_MSG_TYPE_MAX -+} VC_AUDIO_MSG_TYPE; -+ -+// configure the audio -+typedef struct { -+ uint32_t channels; -+ uint32_t samplerate; -+ uint32_t bps; -+ -+} VC_AUDIO_CONFIG_T; -+ -+typedef struct { -+ uint32_t volume; -+ uint32_t dest; -+ -+} VC_AUDIO_CONTROL_T; -+ -+// audio -+typedef struct { -+ uint32_t dummy; -+ -+} VC_AUDIO_OPEN_T; -+ -+// audio -+typedef struct { -+ uint32_t dummy; -+ -+} VC_AUDIO_CLOSE_T; -+// audio -+typedef struct { -+ uint32_t dummy; -+ -+} VC_AUDIO_START_T; -+// audio -+typedef struct { -+ uint32_t draining; -+ -+} VC_AUDIO_STOP_T; -+ -+// configure the write audio samples -+typedef struct { -+ uint32_t count; // in bytes -+ void *callback; -+ void *cookie; -+ uint16_t silence; -+ uint16_t max_packet; -+} VC_AUDIO_WRITE_T; -+ -+// Generic result for a request (VC->HOST) -+typedef struct { -+ int32_t success; // Success value -+ -+} VC_AUDIO_RESULT_T; -+ -+// Generic result for a request (VC->HOST) -+typedef struct { -+ int32_t count; // Success value -+ void *callback; -+ void *cookie; -+} VC_AUDIO_COMPLETE_T; -+ -+// Message header for all messages in HOST->VC direction -+typedef struct { -+ int32_t type; // Message type (VC_AUDIO_MSG_TYPE) -+ union { -+ VC_AUDIO_CONFIG_T config; -+ VC_AUDIO_CONTROL_T control; -+ VC_AUDIO_OPEN_T open; -+ VC_AUDIO_CLOSE_T close; -+ VC_AUDIO_START_T start; -+ VC_AUDIO_STOP_T stop; -+ VC_AUDIO_WRITE_T write; -+ VC_AUDIO_RESULT_T result; -+ VC_AUDIO_COMPLETE_T complete; -+ } u; -+} VC_AUDIO_MSG_T; -+ -+#endif // _VC_AUDIO_DEFS_H_ - -From a5249fc19ef0f7e74f7c6d2e51f7f44f49c705f7 Mon Sep 17 00:00:00 2001 +From 480910587a44789d33027900a719c50df96eaa1c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 28 Oct 2016 15:36:43 +0100 -Subject: [PATCH 036/216] vc_mem: Add vc_mem driver for querying firmware +Subject: [PATCH 043/150] vc_mem: Add vc_mem driver for querying firmware memory addresses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -75429,31 +71871,32 @@ Make the vc_mem module available for ARCH_BCM2835 by moving it. Signed-off-by: Noralf Trønnes --- - drivers/char/broadcom/Kconfig | 12 +- + drivers/char/broadcom/Kconfig | 18 ++ drivers/char/broadcom/Makefile | 1 + drivers/char/broadcom/vc_mem.c | 422 ++++++++++++++++++++++++++++++++++++++++ include/linux/broadcom/vc_mem.h | 35 ++++ - 4 files changed, 469 insertions(+), 1 deletion(-) + 4 files changed, 476 insertions(+) + create mode 100644 drivers/char/broadcom/Kconfig + create mode 100644 drivers/char/broadcom/Makefile create mode 100644 drivers/char/broadcom/vc_mem.c create mode 100644 include/linux/broadcom/vc_mem.h diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 89d6fac780410e370ca2316b357e599c7eb5a9b3..e4fbd82b9384fa3fa23802697293e706a58efed9 100644 ---- a/drivers/char/broadcom/Kconfig +new file mode 100644 +index 0000000000000000000000000000000000000000..fc1315209dab9fbb1436ef1a6fafdc25917cf45a +--- /dev/null +++ b/drivers/char/broadcom/Kconfig -@@ -7,9 +7,19 @@ menuconfig BRCM_CHAR_DRIVERS - help - Broadcom's char drivers - -+if BRCM_CHAR_DRIVERS +@@ -0,0 +1,18 @@ ++# ++# Broadcom char driver config ++# + - config BCM_VC_CMA - bool "Videocore CMA" -- depends on CMA && BRCM_CHAR_DRIVERS && BCM2835_VCHIQ -+ depends on CMA && BCM2835_VCHIQ - default n - help - Helper for videocore CMA access. ++menuconfig BRCM_CHAR_DRIVERS ++ bool "Broadcom Char Drivers" ++ help ++ Broadcom's char drivers ++ ++if BRCM_CHAR_DRIVERS + +config BCM2708_VCMEM + bool "Videocore Memory" @@ -75463,11 +71906,11 @@ index 89d6fac780410e370ca2316b357e599c7eb5a9b3..e4fbd82b9384fa3fa23802697293e706 + +endif diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 13c5bca291ccc0df090c4e61169ace8f18ba60fe..fce918c369f7a9430136fea3ab098350339f1b01 100644 ---- a/drivers/char/broadcom/Makefile +new file mode 100644 +index 0000000000000000000000000000000000000000..06c5c8ad00e75204ae1ec200f690a8cbccd1d91d +--- /dev/null +++ b/drivers/char/broadcom/Makefile -@@ -1 +1,2 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ +@@ -0,0 +1 @@ +obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o diff --git a/drivers/char/broadcom/vc_mem.c b/drivers/char/broadcom/vc_mem.c new file mode 100644 @@ -75939,10 +72382,10 @@ index 0000000000000000000000000000000000000000..20a475377eb3078ea1ecaef2b24efc35 + +#endif /* _VC_MEM_H */ -From 622d86c9de390813221bcc3e498fcb04c12f6b9a Mon Sep 17 00:00:00 2001 +From f5d2418eee21b196ab7126b8bab88916272bae35 Mon Sep 17 00:00:00 2001 From: Tim Gover Date: Tue, 22 Jul 2014 15:41:04 +0100 -Subject: [PATCH 037/216] vcsm: VideoCore shared memory service for BCM2835 +Subject: [PATCH 044/150] vcsm: VideoCore shared memory service for BCM2835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -75983,16 +72426,18 @@ vc-sm: Move headers out of arch directory Signed-off-by: Noralf Trønnes --- + drivers/char/Kconfig | 2 + + drivers/char/Makefile | 1 + drivers/char/broadcom/Kconfig | 9 + drivers/char/broadcom/Makefile | 1 + drivers/char/broadcom/vc_sm/Makefile | 9 + drivers/char/broadcom/vc_sm/vc_sm_defs.h | 181 ++ drivers/char/broadcom/vc_sm/vc_sm_knl.h | 55 + - drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 492 +++++ + drivers/char/broadcom/vc_sm/vc_vchi_sm.c | 499 +++++ drivers/char/broadcom/vc_sm/vc_vchi_sm.h | 82 + drivers/char/broadcom/vc_sm/vmcs_sm.c | 3213 ++++++++++++++++++++++++++++++ include/linux/broadcom/vmcs_sm_ioctl.h | 248 +++ - 9 files changed, 4290 insertions(+) + 11 files changed, 4300 insertions(+) create mode 100644 drivers/char/broadcom/vc_sm/Makefile create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_defs.h create mode 100644 drivers/char/broadcom/vc_sm/vc_sm_knl.h @@ -76001,11 +72446,33 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/char/broadcom/vc_sm/vmcs_sm.c create mode 100644 include/linux/broadcom/vmcs_sm_ioctl.h +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 31adbebf812edb23bdd203192785c085155248da..ce14b380bf447bfa92825a526894ac55d02eba2b 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -4,6 +4,8 @@ + + menu "Character devices" + ++source "drivers/char/broadcom/Kconfig" ++ + source "drivers/tty/Kconfig" + + config DEVMEM +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 6e6c244a66a02c4efd57229b0f31d331377bbc55..67c40b8f2ff25f423cb74b64de9afa6f32479aed 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -60,3 +60,4 @@ js-rtc-y = rtc.o + obj-$(CONFIG_TILE_SROM) += tile-srom.o + obj-$(CONFIG_XILLYBUS) += xillybus/ + obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o ++obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/ diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index e4fbd82b9384fa3fa23802697293e706a58efed9..3bf1358bf1dd89d7a41e4ed3fd8fb2990d77ebbe 100644 +index fc1315209dab9fbb1436ef1a6fafdc25917cf45a..09a43da7bcf85c3506c1b4f1b06369c3b6c2bbe6 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -23,3 +23,12 @@ config BCM2708_VCMEM +@@ -16,3 +16,12 @@ config BCM2708_VCMEM Helper for videocore memory access and total size allocation. endif @@ -76019,11 +72486,10 @@ index e4fbd82b9384fa3fa23802697293e706a58efed9..3bf1358bf1dd89d7a41e4ed3fd8fb299 + Support for the VC shared memory on the Broadcom reference + design. Uses the VCHIQ stack. diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index fce918c369f7a9430136fea3ab098350339f1b01..de8feb98c63ff1e6437d80a6db85a8d30f433705 100644 +index 06c5c8ad00e75204ae1ec200f690a8cbccd1d91d..419af4180deb058ce8d91b606af821d4d3ebda4c 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ +@@ -1 +1,2 @@ obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +obj-$(CONFIG_BCM_VC_SM) += vc_sm/ diff --git a/drivers/char/broadcom/vc_sm/Makefile b/drivers/char/broadcom/vc_sm/Makefile @@ -76291,10 +72757,10 @@ index 0000000000000000000000000000000000000000..965f9a209a025202fea8065d3947c36f +#endif /* __VC_SM_KNL_H__INCLUDED__ */ diff --git a/drivers/char/broadcom/vc_sm/vc_vchi_sm.c b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c new file mode 100644 -index 0000000000000000000000000000000000000000..7c6ba1a244a8aff8132e0177e02b2b2a6cd364e0 +index 0000000000000000000000000000000000000000..76abd126c4617b6310fcf0ebd7ab1d5f73a18a70 --- /dev/null +++ b/drivers/char/broadcom/vc_sm/vc_vchi_sm.c -@@ -0,0 +1,492 @@ +@@ -0,0 +1,499 @@ +/***************************************************************************** +* Copyright 2011-2012 Broadcom Corporation. All rights reserved. +* @@ -76368,6 +72834,16 @@ index 0000000000000000000000000000000000000000..7c6ba1a244a8aff8132e0177e02b2b2a +/* ---- Private Function Prototypes -------------------------------------- */ + +/* ---- Private Functions ------------------------------------------------ */ ++static int ++bcm2835_vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, ++ void *data, ++ unsigned int size) ++{ ++ return vchi_queue_kernel_message(handle, ++ data, ++ size); ++} ++ +static struct +sm_cmd_rsp_blk *vc_vchi_cmd_create(struct sm_instance *instance, + VC_SM_MSG_TYPE id, void *msg, @@ -76440,7 +72916,6 @@ index 0000000000000000000000000000000000000000..7c6ba1a244a8aff8132e0177e02b2b2a + svc_use = 1; + + do { -+ unsigned int flags; + /* + * Get new command and move it to response list + */ @@ -76459,11 +72934,9 @@ index 0000000000000000000000000000000000000000..7c6ba1a244a8aff8132e0177e02b2b2a + mutex_unlock(&instance->lock); + + /* Send the command */ -+ flags = VCHI_FLAGS_BLOCK_UNTIL_QUEUED; -+ status = vchi_msg_queue( ++ status = bcm2835_vchi_msg_queue( + instance->vchi_handle[0], -+ cmd->msg, cmd->length, -+ flags, NULL); ++ cmd->msg, cmd->length); + if (status) { + pr_err("%s: failed to queue message (%d)", + __func__, status); @@ -76877,7 +73350,7 @@ index 0000000000000000000000000000000000000000..5e279f5a95fac7227cea15941bf0570d +#endif /* __VC_VCHI_SM_H__INCLUDED__ */ diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c new file mode 100644 -index 0000000000000000000000000000000000000000..8b6f2476769e956fb30d4c8a24789565e78444c1 +index 0000000000000000000000000000000000000000..fd71d9fbb400d71bb8cfb8672080e7c3053e3ae9 --- /dev/null +++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c @@ -0,0 +1,3213 @@ @@ -77746,7 +74219,7 @@ index 0000000000000000000000000000000000000000..8b6f2476769e956fb30d4c8a24789565 + resource_map_list) { + ret = + do_munmap(current->mm, map->res_addr, -+ resource->res_size); ++ resource->res_size, NULL); + if (ret) { + pr_err("[%s]: could not unmap resource %p\n", + __func__, resource); @@ -78002,9 +74475,9 @@ index 0000000000000000000000000000000000000000..8b6f2476769e956fb30d4c8a24789565 + vmcs_sm_remove_map(sm_state, map->resource, map); +} + -+static int vcsm_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++static int vcsm_vma_fault(struct vm_fault *vmf) +{ -+ struct sm_mmap *map = (struct sm_mmap *)vma->vm_private_data; ++ struct sm_mmap *map = (struct sm_mmap *)vmf->vma->vm_private_data; + struct SM_RESOURCE_T *resource = map->resource; + pgoff_t page_offset; + unsigned long pfn; @@ -78052,14 +74525,14 @@ index 0000000000000000000000000000000000000000..8b6f2476769e956fb30d4c8a24789565 + } + + /* We don't use vmf->pgoff since that has the fake offset */ -+ page_offset = ((unsigned long)vmf->address - vma->vm_start); ++ page_offset = ((unsigned long)vmf->address - vmf->vma->vm_start); + pfn = (uint32_t)resource->res_base_mem & 0x3FFFFFFF; + pfn += mm_vc_mem_phys_addr; + pfn += page_offset; + pfn >>= PAGE_SHIFT; + + /* Finally, remap it */ -+ ret = vm_insert_pfn(vma, (unsigned long)vmf->address, pfn); ++ ret = vm_insert_pfn(vmf->vma, (unsigned long)vmf->address, pfn); + + switch (ret) { + case 0: @@ -80349,10 +76822,10 @@ index 0000000000000000000000000000000000000000..334f36d0d697b047df2922b5f2db67f3 + +#endif /* __VMCS_SM_IOCTL_H__INCLUDED__ */ -From 5cbdb105c8c2737b64abd686f7956cb38210aaa6 Mon Sep 17 00:00:00 2001 +From ee23b1d598c89bf23f8a887f67fb3965c7df3bb8 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Fri, 21 Aug 2015 23:14:48 +0100 -Subject: [PATCH 038/216] Add /dev/gpiomem device for rootless user GPIO access +Subject: [PATCH 045/150] Add /dev/gpiomem device for rootless user GPIO access Signed-off-by: Luke Wren @@ -80364,15 +76837,15 @@ See: https://github.com/raspberrypi/linux/issues/1154 --- drivers/char/broadcom/Kconfig | 9 ++ drivers/char/broadcom/Makefile | 3 + - drivers/char/broadcom/bcm2835-gpiomem.c | 260 ++++++++++++++++++++++++++++++++ - 3 files changed, 272 insertions(+) + drivers/char/broadcom/bcm2835-gpiomem.c | 258 ++++++++++++++++++++++++++++++++ + 3 files changed, 270 insertions(+) create mode 100644 drivers/char/broadcom/bcm2835-gpiomem.c diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 3bf1358bf1dd89d7a41e4ed3fd8fb2990d77ebbe..ffb12f4023b2db4cf75f1a13562d483608eead2e 100644 +index 09a43da7bcf85c3506c1b4f1b06369c3b6c2bbe6..ede8b5ca7aa1012507aa2006e89b5c47ea267351 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -32,3 +32,12 @@ config BCM_VC_SM +@@ -25,3 +25,12 @@ config BCM_VC_SM help Support for the VC shared memory on the Broadcom reference design. Uses the VCHIQ stack. @@ -80386,11 +76859,10 @@ index 3bf1358bf1dd89d7a41e4ed3fd8fb2990d77ebbe..ffb12f4023b2db4cf75f1a13562d4836 + register page to the user's pointer. + diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index de8feb98c63ff1e6437d80a6db85a8d30f433705..1eb06e9788663c3e75d201a559db55556cecfe2b 100644 +index 419af4180deb058ce8d91b606af821d4d3ebda4c..187a0b02f189669d751964df5275eb21827b0440 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -1,3 +1,6 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ +@@ -1,2 +1,5 @@ obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o obj-$(CONFIG_BCM_VC_SM) += vc_sm/ + @@ -80398,10 +76870,10 @@ index de8feb98c63ff1e6437d80a6db85a8d30f433705..1eb06e9788663c3e75d201a559db5555 + diff --git a/drivers/char/broadcom/bcm2835-gpiomem.c b/drivers/char/broadcom/bcm2835-gpiomem.c new file mode 100644 -index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae6463453f9c +index 0000000000000000000000000000000000000000..f5e7f1ba8fb6f18dee77fad06a17480c6603cb4e --- /dev/null +++ b/drivers/char/broadcom/bcm2835-gpiomem.c -@@ -0,0 +1,260 @@ +@@ -0,0 +1,258 @@ +/** + * GPIO memory device driver + * @@ -80480,8 +76952,6 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 + int dev = iminor(inode); + int ret = 0; + -+ dev_info(inst->dev, "gpiomem device opened."); -+ + if (dev != DEVICE_MINOR) { + dev_err(inst->dev, "Unknown minor device: %d", dev); + ret = -ENXIO; @@ -80663,10 +77133,10 @@ index 0000000000000000000000000000000000000000..911f5b7393ed48ceed8751f06967ae64 +MODULE_DESCRIPTION("gpiomem driver for accessing GPIO from userspace"); +MODULE_AUTHOR("Luke Wren "); -From 665e765b6324199be7b591c62639c6964ddd4530 Mon Sep 17 00:00:00 2001 +From b19936f231a9a2c6f8e970159f8c9b7db7ad5f60 Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:14:45 +0100 -Subject: [PATCH 039/216] Add SMI driver +Subject: [PATCH 046/150] Add SMI driver Signed-off-by: Luke Wren --- @@ -80764,10 +77234,10 @@ index 0000000000000000000000000000000000000000..b76dc694f1ac0b8044000ae54d312c80 +}; + diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index ffb12f4023b2db4cf75f1a13562d483608eead2e..026ebde319c49c91f11b21edd78da62270883eac 100644 +index ede8b5ca7aa1012507aa2006e89b5c47ea267351..87ea29bb65f98375e7326d9da74161fea5869514 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -41,3 +41,11 @@ config BCM2835_DEVGPIOMEM +@@ -34,3 +34,11 @@ config BCM2835_DEVGPIOMEM on the 2835. Calling mmap(/dev/gpiomem) will map the GPIO register page to the user's pointer. @@ -80780,10 +77250,10 @@ index ffb12f4023b2db4cf75f1a13562d483608eead2e..026ebde319c49c91f11b21edd78da622 + Broadcom's Secondary Memory interface. The low-level functionality is provided + by the SMI driver itself. diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 1eb06e9788663c3e75d201a559db55556cecfe2b..667d33ef38f3512b52818537c11d369798b6f1c0 100644 +index 187a0b02f189669d751964df5275eb21827b0440..d0ad04f8e49815e626814fd0375a24b8c1232dca 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -3,4 +3,4 @@ obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +@@ -2,4 +2,4 @@ obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o obj-$(CONFIG_BCM_VC_SM) += vc_sm/ obj-$(CONFIG_BCM2835_DEVGPIOMEM)+= bcm2835-gpiomem.o @@ -81198,7 +77668,7 @@ index 0000000000000000000000000000000000000000..d6efd92fdfe46df5cfe219d2123e0dff + "Character device driver for BCM2835's secondary memory interface"); +MODULE_AUTHOR("Luke Wren "); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index 64971baf11faebaff879c58067d23fd9bf29895a..779f7d61a1779decd4dcbba3bc0e6b330e47f335 100644 +index c290990d73edf87ece9b179ac3d845eef27531e9..a1594b7ca53bca17a9c2ca3a66ba14cb9de21e37 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -10,6 +10,14 @@ config SENSORS_LIS3LV02D @@ -81217,7 +77687,7 @@ index 64971baf11faebaff879c58067d23fd9bf29895a..779f7d61a1779decd4dcbba3bc0e6b33 tristate "Analog Devices Digital Potentiometers" depends on (I2C || SPI) && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 31983366090a781441a3235cac5883d6fbb27fa4..6c400f0fb92f5af49e04911b7f103ce1a60af093 100644 +index 7a3ea89339b4d07c34289a539c4f9bd2f12d2aff..7323ce864f409213c3187dcfc3118335149d2989 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o @@ -82617,10 +79087,10 @@ index 0000000000000000000000000000000000000000..ee3a75edfc033eeb0d90a687ffb68b10 + +#endif /* BCM2835_SMI_H */ -From 75ab4d39fcf6d8fe6905bd38fb272ba0cb3f1cd8 Mon Sep 17 00:00:00 2001 +From 7647b4071e3940d12461bb01739ff3085e3fcff6 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 26 Apr 2016 14:59:21 +0000 -Subject: [PATCH 040/216] MISC: bcm2835: smi: use clock manager and fix reload +Subject: [PATCH 047/150] MISC: bcm2835: smi: use clock manager and fix reload issues Use clock manager instead of self-made clockmanager. @@ -82790,10 +79260,10 @@ index 63a4ea08b9930a3a31a985f0a1d969b488ed49ec..1261540703127d1d63b9f3c87042c6e5 return 0; } -From 2790b88223e14bcdaf9e00452546a870d51a2e61 Mon Sep 17 00:00:00 2001 +From e382f780c6077aaad6c7ce1e87bf81bacf1bde1e Mon Sep 17 00:00:00 2001 From: Luke Wren Date: Sat, 5 Sep 2015 01:16:10 +0100 -Subject: [PATCH 041/216] Add SMI NAND driver +Subject: [PATCH 048/150] Add SMI NAND driver Signed-off-by: Luke Wren --- @@ -82855,7 +79325,7 @@ index 0000000000000000000000000000000000000000..159544d6579070d376d146bd24a86653 +}; \ No newline at end of file diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig -index 9ce5dcb4abd0f5026384ed4e0466d1ddfa44c617..a8008746d960fecaf106c71869372f9c8a79c571 100644 +index 6d4d5672d1d8ea0945cdaebcbf06d17f5984017b..a3b161befa01064add2b561cb0404306d83efb7e 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -41,6 +41,13 @@ config MTD_SM_COMMON @@ -83158,10 +79628,10 @@ index 0000000000000000000000000000000000000000..02adda6da18bd0ba9ab19a104975b79d + ("Driver for NAND chips using Broadcom Secondary Memory Interface"); +MODULE_AUTHOR("Luke Wren "); -From 3ec1d1648b611fa6c606314023f30f363c52dad9 Mon Sep 17 00:00:00 2001 +From 1509c0159348716d5b37b1b30d3105a5fcd07ec9 Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 042/216] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 049/150] 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 @@ -83226,12 +79696,12 @@ spurious interrupts. create mode 100644 include/linux/platform_data/bcm2708.h diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig -index 25b7e7ccf55479ec7a3d83a6e4b8b6aaba207a26..066f4bed3687391055dd3b15f278ed206c1bee6b 100644 +index bc67da254262318f43cb81ab58fb2053339f2e73..d2f72463a1bad7a44d67e0329cadc4cf63e0268f 100644 --- a/drivers/staging/media/lirc/Kconfig +++ b/drivers/staging/media/lirc/Kconfig -@@ -32,6 +32,12 @@ config LIRC_PARALLEL - help - Driver for Homebrew Parallel Port Receivers +@@ -12,6 +12,12 @@ menuconfig LIRC_STAGING + + if LIRC_STAGING +config LIRC_RPI + tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi" @@ -83243,13 +79713,13 @@ index 25b7e7ccf55479ec7a3d83a6e4b8b6aaba207a26..066f4bed3687391055dd3b15f278ed20 tristate "Sasem USB IR Remote" depends on LIRC && USB diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile -index 7f919eab1989e33f49917f51e9857bc439f51d1f..99726bfaa700d5b54063f155b4821aa5be30df09 100644 +index 28740c94349c4e412ee0b77bc800c8fb0705297c..89d5544045bc8275f43cf0df9c711f6c067dd48a 100644 --- a/drivers/staging/media/lirc/Makefile +++ b/drivers/staging/media/lirc/Makefile -@@ -6,6 +6,7 @@ - obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o - obj-$(CONFIG_LIRC_IMON) += lirc_imon.o - obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o +@@ -3,6 +3,7 @@ + + # Each configuration option enables a list of files. + +obj-$(CONFIG_LIRC_RPI) += lirc_rpi.o obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o obj-$(CONFIG_LIRC_SIR) += lirc_sir.o @@ -84024,10 +80494,10 @@ index 0000000000000000000000000000000000000000..fb69624ccef00ddbdccf8256d6baf1b1 + +#endif -From ee043523f7a9865e5e58c3ac1386f012611b23da Mon Sep 17 00:00:00 2001 +From 6dfad5b352106011fe51f3e2e9013ff643363b51 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 043/216] Add cpufreq driver +Subject: [PATCH 050/150] Add cpufreq driver Signed-off-by: popcornmix --- @@ -84038,7 +80508,7 @@ 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 920c469f3953e890bd747413750be8ad6a4352e2..e15f8324174ced05bcf9289dc474751fc6d3cba7 100644 +index 74fa5c5904d388444f357bc7b7e9e1737a45fd29..d5d9ec0bd5d6f5d5c9cc2f8df881d28e081ebb97 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -233,6 +233,15 @@ config ARM_STI_CPUFREQ @@ -84058,7 +80528,7 @@ index 920c469f3953e890bd747413750be8ad6a4352e2..e15f8324174ced05bcf9289dc474751f bool "Tegra20 CPUFreq support" depends on ARCH_TEGRA diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 1e46c3918e7a630647d744549a46c184e5e8fd80..6fd3f67a8fbffc304d105683e4f8443d7346ffe8 100644 +index 9f5a8045f36d37710c8196e8ddf1145817664f05..3de3eebd30a3f5e5e6c0a94c47e39545e9d8cbfe 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o @@ -84068,7 +80538,7 @@ index 1e46c3918e7a630647d744549a46c184e5e8fd80..6fd3f67a8fbffc304d105683e4f8443d +obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o - obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o + obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o diff --git a/drivers/cpufreq/bcm2835-cpufreq.c b/drivers/cpufreq/bcm2835-cpufreq.c new file mode 100644 index 0000000000000000000000000000000000000000..414fbdc10dfbfc6e4bb47870a7af3fd5780f9c9a @@ -84294,10 +80764,10 @@ index 0000000000000000000000000000000000000000..414fbdc10dfbfc6e4bb47870a7af3fd5 +module_init(bcm2835_cpufreq_module_init); +module_exit(bcm2835_cpufreq_module_exit); -From 996357a2a9e94fca09ae7e7af3e546dc2019520f Mon Sep 17 00:00:00 2001 +From 15130f6e27b5f8eb4f691a304cb50f6efc255844 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 044/216] Added hwmon/thermal driver for reporting core +Subject: [PATCH 051/150] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 @@ -84318,10 +80788,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 c2c056cc7ea52e1a7170b35de2832c1b1dcf40b4..b43058bee69ca62d9480fa7782e456aac1dbeedb 100644 +index 776b34396144a4612ec5ebfff5a549be9f6e33ca..592a1c319ca130f0d82649c60989c05d4ec184b2 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -304,6 +304,13 @@ config INTEL_POWERCLAMP +@@ -313,6 +313,13 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -84336,10 +80806,10 @@ index c2c056cc7ea52e1a7170b35de2832c1b1dcf40b4..b43058bee69ca62d9480fa7782e456aa tristate "X86 package temperature thermal driver" depends on X86_THERMAL_VECTOR diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index 6a3d7b57303655f58b7fec456cc43519fa29dc91..f3d8fe6cc10146b0b27e72f4b6e75664b3bf91cd 100644 +index 7adae2029355639b03359fb542c6030f93808ab5..adc17796d5e17787f632b3f36c48d0bba141132d 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -42,6 +42,7 @@ obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o +@@ -43,6 +43,7 @@ obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o obj-$(CONFIG_QORIQ_THERMAL) += qoriq_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o @@ -84463,10 +80933,10 @@ index 0000000000000000000000000000000000000000..c63fb9f9d143e19612a18fe530c7b2b3 +MODULE_DESCRIPTION("Thermal driver for bcm2835 chip"); +MODULE_LICENSE("GPL"); -From 06e00f56cbf023de9efcf4e084788a91cbd3674e Mon Sep 17 00:00:00 2001 +From 1acc6899f4a96fe0a524d0e61090ed0b911a7373 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Jun 2015 15:44:08 +0100 -Subject: [PATCH 045/216] Add Chris Boot's i2c driver +Subject: [PATCH 052/150] Add Chris Boot's i2c driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -84570,7 +81040,7 @@ both bcm2708_bsc_fifo_fill and ~drain are changed as well. create mode 100644 drivers/i2c/busses/i2c-bcm2708.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 0cdc8443deab611d6574ba07b77ddec95ee5cebd..09e4774d2688a8bb8ec1174bf746593dd354f068 100644 +index 8adc0f1d7ad0ba72240fcae0ff2feb8e7c517456..c893a2b75eacb717b508bab60b1e5b175712fdf2 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -8,6 +8,25 @@ menu "I2C Hardware Bus support" @@ -84600,7 +81070,7 @@ index 0cdc8443deab611d6574ba07b77ddec95ee5cebd..09e4774d2688a8bb8ec1174bf746593d tristate "ALI 1535" depends on PCI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 1c1bac87a9db8cb9a4ee35792a52571262051bc8..3bc2ecfa6839946ee6f61c7ecb45ac16fe3b9a68 100644 +index 30b60855fbcd1e353d4dbd687d480a52f4811761..c1ca31b413255ee00cc9bfa94ff1340aac6e1100 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -2,6 +2,8 @@ @@ -85131,10 +81601,10 @@ index 0000000000000000000000000000000000000000..962f2e5c7455d91bf32925d785f5f16b +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -From 1cb3352e4469386f02493223b2d89a1f67683a61 Mon Sep 17 00:00:00 2001 +From bb70ba5b144109a5622dd1f0ff5de103b4195e4d 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 046/216] char: broadcom: Add vcio module +Subject: [PATCH 053/150] char: broadcom: Add vcio module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -85151,10 +81621,10 @@ Signed-off-by: Noralf Trønnes create mode 100644 drivers/char/broadcom/vcio.c diff --git a/drivers/char/broadcom/Kconfig b/drivers/char/broadcom/Kconfig -index 026ebde319c49c91f11b21edd78da62270883eac..f83cf0c279d9d2ddb1257504d578dc34a53325ca 100644 +index 87ea29bb65f98375e7326d9da74161fea5869514..014c7a15e85c6eff99f840fbc44fc6c83f2d9c91 100644 --- a/drivers/char/broadcom/Kconfig +++ b/drivers/char/broadcom/Kconfig -@@ -22,6 +22,12 @@ config BCM2708_VCMEM +@@ -15,6 +15,12 @@ config BCM2708_VCMEM help Helper for videocore memory access and total size allocation. @@ -85168,11 +81638,10 @@ index 026ebde319c49c91f11b21edd78da62270883eac..f83cf0c279d9d2ddb1257504d578dc34 config BCM_VC_SM diff --git a/drivers/char/broadcom/Makefile b/drivers/char/broadcom/Makefile -index 667d33ef38f3512b52818537c11d369798b6f1c0..14775c9b20b4b6a58f681f3687614676b5e2a871 100644 +index d0ad04f8e49815e626814fd0375a24b8c1232dca..7d9cb3e0b1c3c4f64c74e3d1b664a4d94170a3e0 100644 --- a/drivers/char/broadcom/Makefile +++ b/drivers/char/broadcom/Makefile -@@ -1,5 +1,6 @@ - obj-$(CONFIG_BCM_VC_CMA) += vc_cma/ +@@ -1,4 +1,5 @@ obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o +obj-$(CONFIG_BCM_VCIO) += vcio.o obj-$(CONFIG_BCM_VC_SM) += vc_sm/ @@ -85360,10 +81829,10 @@ index 0000000000000000000000000000000000000000..c19bc2075c77879563ef5e59038b5a14 +MODULE_DESCRIPTION("Mailbox userspace access"); +MODULE_LICENSE("GPL"); -From 1f74b4c13781661a9f675a1187bd0da23072e293 Mon Sep 17 00:00:00 2001 +From 8b423788b13ba0db9c3fd7272244efeef84d4c58 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 047/216] firmware: bcm2835: Support ARCH_BCM270x +Subject: [PATCH 054/150] firmware: bcm2835: Support ARCH_BCM270x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -85446,7755 +81915,10 @@ index dd506cd3a5b874f9e1acd07efb8cd151bb6145d1..3f070bd38a91511c986e3fb114b15bd4 MODULE_AUTHOR("Eric Anholt "); MODULE_DESCRIPTION("Raspberry Pi firmware driver"); -From 0de890ae35aff146eb31e0cd21df530bd76c5fdc Mon Sep 17 00:00:00 2001 -From: Vincent Sanders -Date: Wed, 30 Jan 2013 12:45:18 +0000 -Subject: [PATCH 048/216] bcm2835: add v4l2 camera device - -- Supports raw YUV capture, preview, JPEG and H264. -- Uses videobuf2 for data transfer, using dma_buf. -- Uses 3.6.10 timestamping -- Camera power based on use -- Uses immutable input mode on video encoder - -Signed-off-by: Daniel Stone -Signed-off-by: Luke Diamand - -V4L2: Fixes from 6by9 - -V4L2: Fix EV values. Add manual shutter speed control - -V4L2 EV values should be in units of 1/1000. Corrected. -Add support for V4L2_CID_EXPOSURE_ABSOLUTE which should -give manual shutter control. Requires manual exposure mode -to be selected first. - -Signed-off-by: Dave Stevenson - -V4L2: Correct JPEG Q-factor range - -Should be 1-100, not 0-100 - -Signed-off-by: Dave Stevenson - -V4L2: Fix issue of driver jamming if STREAMON failed. - -Fix issue where the driver was left in a partially enabled -state if STREAMON failed, and would then reject many IOCTLs -as it thought it was streaming. - -Signed-off-by: Dave Stevenson - -V4L2: Fix ISO controls. - -Driver was passing the index to the GPU, and not the desired -ISO value. - -Signed-off-by: Dave Stevenson - -V4L2: Add flicker avoidance controls - -Add support for V4L2_CID_POWER_LINE_FREQUENCY to set flicker -avoidance frequencies. - -Signed-off-by: Dave Stevenson - -V4L2: Add support for frame rate control. - -Add support for frame rate (or time per frame as V4L2 -inverts it) control via s_parm. - -Signed-off-by: Dave Stevenson - -V4L2: Improve G_FBUF handling so we pass conformance - -Return some sane numbers for get framebuffer so that -we pass conformance. - -Signed-off-by: Dave Stevenson - -V4L2: Fix information advertised through g_vidfmt - -Width and height were being stored based on incorrect -values. - -Signed-off-by: Dave Stevenson - -V4L2: Add support for inline H264 headers - -Add support for V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER -to control H264 inline headers. -Requires firmware fix to work correctly, otherwise format -has to be set to H264 before this parameter is set. - -Signed-off-by: Dave Stevenson - -V4L2: Fix JPEG timestamp issue - -JPEG images were coming through from the GPU with timestamp -of 0. Detect this and give current system time instead -of some invalid value. - -Signed-off-by: Dave Stevenson - -V4L2: Fix issue when switching down JPEG resolution. - -JPEG buffer size calculation is based on input resolution. -Input resolution was being configured after output port -format. Caused failures if switching from one JPEG resolution -to a smaller one. - -Signed-off-by: Dave Stevenson - -V4L2: Enable MJPEG encoding - -Requires GPU firmware update to support MJPEG encoder. - -Signed-off-by: Dave Stevenson - -V4L2: Correct flag settings for compressed formats - -Set flags field correctly on enum_fmt_vid_cap for compressed -image formats. - -Signed-off-by: Dave Stevenson - -V4L2: H264 profile & level ctrls, FPS control and auto exp pri - -Several control handling updates. -H264 profile and level controls. -Timeperframe/FPS reworked to add V4L2_CID_EXPOSURE_AUTO_PRIORITY to -select whether AE is allowed to override the framerate specified. - -Signed-off-by: Dave Stevenson - -V4L2: Correct BGR24 to RGB24 in format table - -Signed-off-by: Dave Stevenson - -V4L2: Add additional pixel formats. Correct colourspace - -Adds the other flavours of YUYV, and NV12. -Corrects the overlay advertised colourspace. - -Signed-off-by: Dave Stevenson - -V4L2: Drop logging msg from info to debug - -Signed-off-by: Dave Stevenson - -V4L2: Initial pass at scene modes. - -Only supports exposure mode and metering modes. - -Signed-off-by: Dave Stevenson - -V4L2: Add manual white balance control. - -Adds support for V4L2_CID_RED_BALANCE and -V4L2_CID_BLUE_BALANCE. Only has an effect if -V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE has -V4L2_WHITE_BALANCE_MANUAL selected. - -Signed-off-by: Dave Stevenson - -config: Enable V4L / MMAL driver - -V4L2: Increase the MMAL timeout to 3sec - -MJPEG codec flush is now taking longer and results -in a kernel panic if the driver has stopped waiting for -the result when it finally completes. -Increase the timeout value from 1 to 3secs. - -Signed-off-by: Dave Stevenson - -V4L2: Add support for setting H264_I_PERIOD - -Adds support for the parameter V4L2_CID_MPEG_VIDEO_H264_I_PERIOD -to set the frequency with which I frames are produced. - -Signed-off-by: Dave Stevenson - -V4L2: Enable GPU function for removing padding from images. - -GPU can now support arbitrary strides, although may require -additional processing to achieve it. Enable this feature -so that the images delivered are the size requested. - -Signed-off-by: Dave Stevenson - -V4L2: Add support for V4L2_PIX_FMT_BGR32 - -Signed-off-by: Dave Stevenson - -V4L2: Set the colourspace to avoid odd YUV-RGB conversions - -Removes the amiguity from the conversion routines and stops -them dropping back to the SD vs HD choice of coeffs. - -Signed-off-by: Dave Stevenson - -V4L2: Make video/still threshold a run-time param - -Move the define for at what resolution the driver -switches from a video mode capture to a stills mode -capture to module parameters. - -Signed-off-by: Dave Stevenson - -V4L2: Fix incorrect pool sizing - -Signed-off-by: Dave Stevenson - -V4L2: Add option to disable enum_framesizes. - -Gstreamer's handling of a driver that advertises -V4L2_FRMSIZE_TYPE_STEPWISE to define the supported -resolutions is broken. See bug -https://bugzilla.gnome.org/show_bug.cgi?id=726521 - -Optional parameter of gst_v4l2src_is_broken added. -If non-zero, the driver claims not to support that -ioctl, and gstreamer should be happy again (it -guesses a set of defaults for itself). - -Signed-off-by: Dave Stevenson - -V4L2: Add support for more image formats - -Adds YVU420 (YV12), YVU420SP (NV21), and BGR888. - -Signed-off-by: Dave Stevenson - -V4L2: Extend range for V4L2_CID_MPEG_VIDEO_H264_I_PERIOD - -Request to extend the range from the fairly arbitrary -1000 frames (33 seconds at 30fps). Extend out to the -max range supported (int32 value). -Also allow 0, which is handled by the codec as only -send an I-frame on the first frame and never again. -There may be an exception if it detects a significant -scene change, but there's no easy way around that. - -Signed-off-by: Dave Stevenson - -bcm2835-camera: stop_streaming now has a void return - -BCM2835-V4L2: Fix compliance test failures - -VIDIOC_TRY_FMT and VIDIOC_S_FMT tests were faling due -to reporting V4L2_COLORSPACE_JPEG when the colour -format wasn't V4L2_PIX_FMT_JPEG. -Now reports V4L2_COLORSPACE_SMPTE170M for YUV formats. - -bcm2835 camera planar/packed stride length - -Added a field to the mmal_fmt struct used to compute the bytes per line -when using a particular format. This results in the correct stride being -calculated even when the format is planar. - -Signed-off-by: Garrett Wilson - -bcm2835: camera: check for scene not being found - -static analysis by cppcheck detected some potential NULL pointer -dereference issues: - -[drivers/media/platform/bcm2835/controls.c:854]: (error) Possible null - pointer dereference: scene - (and lines 858, 859 too) - -it is possible that scene is not found because of an invalue ctrl->val -and is therefore NULL and hence causing a null pointer dereference. - -Signed-off-by: Colin Ian King - -bcm2835: memcpy port data to m rather than rmsg - -static analysis by cppcheck detected a memcpy to rmsg which is -not actually initialized at that point. The memcpy should be copying -to variable m instead. - -Signed-off-by: Colin Ian King - -BCM2835-V4L2: Return buffers to videobuf2 on shutdown - -https://github.com/raspberrypi/linux/issues/817 -Fixes the kernel warning from videobuf2 as buffers -are now returned as they are being flushed on -stop_streaming. - -squash: Fixup bcm2835-camera for changes in kernel 4.4 api - -v4l2: Fix up driver to upstream timestamp changes - -bcm2835-camera: fix a bug in computation of frame timestamp - -Fixes #1318 - -V4L2 driver updates (#1393) - -* BCM2835-V4L2: Correct ISO control and add V4L2_CID_ISO_SENSITIVITY_AUTO - -https://github.com/raspberrypi/linux/issues/1251 - -V4L2_CID_ISO_SENSITIVITY was not advertising ISO*1000 as it should. -V4L2_CID_ISO_SENSITIVITY_AUTO was not implemented, so was taking -V4L2_CID_ISO_SENSITIVITY as 0 for auto mode. -Still accepts 0 for auto, but also abides by the new parameter. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -* BCM2835-V4L2: Add a video_nr parameter. - -Adds a kernel parameter "video_nr" to specify the preferred -/dev/videoX device node. -https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=136120&p=905545 - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -* BCM2835-V4L2: Add support for multiple cameras - -Ask GPU on load how many cameras have been detected, and -enumerate that number of devices. -Only applicable on the Compute Module as no other device -exposes multiple CSI2 interfaces. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -* BCM2835-V4L2: Add control of the overlay location and alpha. - -Actually do something useful in vidioc_s_fmt_vid_overlay and -vidioc_try_fmt_vid_overlay, rather than effectively having -read-only fields. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -* BCM2835-V4L2: V4L2-Compliance failure fix - -VIDIOC_TRY_FMT was failing due to bytesperline not -being set correctly by default. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -* BCM2835-V4L2: Make all module parameters static - -Clean up to correct variable scope - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -V4L2: Request maximum resolution from GPU - -Get resolution information about the sensors from the GPU -and advertise it correctly. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -BCM2835-V4L2: Increase minimum resolution to 32x32 - -https://github.com/raspberrypi/linux/issues/1498 showed -up that 16x16 is failing to work on the GPU for some reason. - -GPU bug being tracked on -https://github.com/raspberrypi/firmware/issues/607 -Workaround here by increasing minimum resolution via V4L2 -to 32x32. - -Signed-off-by: Dave Stevenson <6by9@users.noreply.github.com> - -[media]: bcm2835-camera: fix compilation error - -There is an error when compiling rpi-4.6.y branch: - CC [M] drivers/media/platform/bcm2835/bcm2835-camera.o -drivers/media/platform/bcm2835/bcm2835-camera.c:639:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] - .queue_setup = queue_setup, - ^ -drivers/media/platform/bcm2835/bcm2835-camera.c:639:17: note: (near initialization for 'bm2835_mmal_video_qops.queue_setup') - -The const void *parg in setup_queue callback is not needed since commit: -df9ecb0cad14b952a2865f8b3af86b2bbadfab45. -This commit removes it. - -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> - -BCM2835-v4l2: Fix a conformance test failure - -Format ioctls: - test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK - warn: v4l2-test-formats.cpp(1195): S_PARM is supported but - doesn't report V4L2_CAP_TIMEPERFRAME. - fail: v4l2-test-formats.cpp(1118): node->has_frmintervals - && !cap->capability ---- - 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 | 2016 ++++++++++++++++++++++ - 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 ++ - drivers/media/platform/bcm2835/mmal-msg-common.h | 50 + - drivers/media/platform/bcm2835/mmal-msg-format.h | 81 + - 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.h | 178 ++ - 17 files changed, 7205 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 - create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.c - create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.h - create mode 100644 drivers/media/platform/bcm2835/controls.c - create mode 100644 drivers/media/platform/bcm2835/mmal-common.h - create mode 100644 drivers/media/platform/bcm2835/mmal-encodings.h - create mode 100644 drivers/media/platform/bcm2835/mmal-msg-common.h - create mode 100644 drivers/media/platform/bcm2835/mmal-msg-format.h - create mode 100644 drivers/media/platform/bcm2835/mmal-msg-port.h - create mode 100644 drivers/media/platform/bcm2835/mmal-msg.h - create mode 100644 drivers/media/platform/bcm2835/mmal-parameters.h - create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.c - create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.h - -diff --git a/Documentation/video4linux/bcm2835-v4l2.txt b/Documentation/video4linux/bcm2835-v4l2.txt -new file mode 100644 -index 0000000000000000000000000000000000000000..c585a8fadf91c5a04453e442fc29ed893c65bf99 ---- /dev/null -+++ b/Documentation/video4linux/bcm2835-v4l2.txt -@@ -0,0 +1,60 @@ -+ -+BCM2835 (aka Raspberry Pi) V4L2 driver -+====================================== -+ -+1. Copyright -+============ -+ -+Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ -+2. License -+========== -+ -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License as published by -+the Free Software Foundation; either version 2 of the License, or -+(at your option) any later version. -+ -+This program is distributed in the hope that it will be useful, -+but WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+GNU General Public License for more details. -+ -+You should have received a copy of the GNU General Public License -+along with this program; if not, write to the Free Software -+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+3. Quick Start -+============== -+ -+You need a version 1.0 or later of v4l2-ctl, available from: -+ git://git.linuxtv.org/v4l-utils.git -+ -+$ sudo modprobe bcm2835-v4l2 -+ -+Turn on the overlay: -+ -+$ v4l2-ctl --overlay=1 -+ -+Turn off the overlay: -+ -+$ v4l2-ctl --overlay=0 -+ -+Set the capture format for video: -+ -+$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4 -+ -+(Note: 1088 not 1080). -+ -+Capture: -+ -+$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264 -+ -+Stills capture: -+ -+$ v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=3 -+$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg -+ -+List of available formats: -+ -+$ v4l2-ctl --list-formats -diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig -index d944421e392d7b0af9e1c93b6bd63ea902bc5e60..10baabea617f114068cd88240571a811eb8ea50f 100644 ---- a/drivers/media/platform/Kconfig -+++ b/drivers/media/platform/Kconfig -@@ -11,6 +11,8 @@ menuconfig V4L_PLATFORM_DRIVERS - - if V4L_PLATFORM_DRIVERS - -+source "drivers/media/platform/bcm2835/Kconfig" -+ - source "drivers/media/platform/marvell-ccic/Kconfig" - - config VIDEO_VIA_CAMERA -diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile -index 5b3cb271d2b8ccf3a2d47a00dcfe90bdb5a95e3c..38273667e6c241fc5487d5600d8fc1e2355feba6 100644 ---- a/drivers/media/platform/Makefile -+++ b/drivers/media/platform/Makefile -@@ -2,6 +2,8 @@ - # Makefile for the video capture/playback device drivers. - # - -+obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/ -+ - obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o - - obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o -diff --git a/drivers/media/platform/bcm2835/Kconfig b/drivers/media/platform/bcm2835/Kconfig -new file mode 100644 -index 0000000000000000000000000000000000000000..e2f992c7710e9e6df9ea57387e1c3dd64400abdd ---- /dev/null -+++ b/drivers/media/platform/bcm2835/Kconfig -@@ -0,0 +1,25 @@ -+# Broadcom VideoCore IV v4l2 camera support -+ -+config VIDEO_BCM2835 -+ bool "Broadcom BCM2835 camera interface driver" -+ depends on VIDEO_V4L2 && ARCH_BCM2835 -+ ---help--- -+ Say Y here to enable camera host interface devices for -+ Broadcom BCM2835 SoC. This operates over the VCHIQ interface -+ to a service running on VideoCore. -+ -+ -+if VIDEO_BCM2835 -+ -+config VIDEO_BCM2835_MMAL -+ tristate "Broadcom BM2835 MMAL camera interface driver" -+ depends on BCM2835_VCHIQ -+ select VIDEOBUF2_VMALLOC -+ ---help--- -+ This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface -+ -+ To compile this driver as a module, choose M here: the -+ module will be called bcm2835-v4l2.o -+ -+ -+endif # VIDEO_BM2835 -diff --git a/drivers/media/platform/bcm2835/Makefile b/drivers/media/platform/bcm2835/Makefile -new file mode 100644 -index 0000000000000000000000000000000000000000..b14ea91ac79c60f83bc63156436ef8cbcc893e9b ---- /dev/null -+++ b/drivers/media/platform/bcm2835/Makefile -@@ -0,0 +1,5 @@ -+bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o -+ -+obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o -+ -+ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/staging/vc04_services -Idrivers/staging/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..4f03949aecf3afbf2e04df38289447195a8847a6 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -0,0 +1,2016 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mmal-common.h" -+#include "mmal-encodings.h" -+#include "mmal-vchiq.h" -+#include "mmal-msg.h" -+#include "mmal-parameters.h" -+#include "bcm2835-camera.h" -+ -+#define BM2835_MMAL_VERSION "0.0.2" -+#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2" -+#define MIN_WIDTH 32 -+#define MIN_HEIGHT 32 -+#define MIN_BUFFER_SIZE (80*1024) -+ -+#define MAX_VIDEO_MODE_WIDTH 1280 -+#define MAX_VIDEO_MODE_HEIGHT 720 -+ -+#define MAX_BCM2835_CAMERAS 2 -+ -+MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); -+MODULE_AUTHOR("Vincent Sanders"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(BM2835_MMAL_VERSION); -+ -+int bcm2835_v4l2_debug; -+module_param_named(debug, bcm2835_v4l2_debug, int, 0644); -+MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2"); -+ -+#define UNSET (-1) -+static int video_nr[] = {[0 ... (MAX_BCM2835_CAMERAS - 1)] = UNSET }; -+module_param_array(video_nr, int, NULL, 0644); -+MODULE_PARM_DESC(video_nr, "videoX start numbers, -1 is autodetect"); -+ -+static int max_video_width = MAX_VIDEO_MODE_WIDTH; -+static int max_video_height = MAX_VIDEO_MODE_HEIGHT; -+module_param(max_video_width, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -+MODULE_PARM_DESC(max_video_width, "Threshold for video mode"); -+module_param(max_video_height, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -+MODULE_PARM_DESC(max_video_height, "Threshold for video mode"); -+ -+/* Gstreamer bug https://bugzilla.gnome.org/show_bug.cgi?id=726521 -+ * v4l2src does bad (and actually wrong) things when the vidioc_enum_framesizes -+ * function says type V4L2_FRMSIZE_TYPE_STEPWISE, which we do by default. -+ * It's happier if we just don't say anything at all, when it then -+ * sets up a load of defaults that it thinks might work. -+ * If gst_v4l2src_is_broken is non-zero, then we remove the function from -+ * our function table list (actually switch to an alternate set, but same -+ * result). -+ */ -+static int gst_v4l2src_is_broken; -+module_param(gst_v4l2src_is_broken, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -+MODULE_PARM_DESC(gst_v4l2src_is_broken, "If non-zero, enable workaround for Gstreamer"); -+ -+/* global device data array */ -+static struct bm2835_mmal_dev *gdev[MAX_BCM2835_CAMERAS]; -+ -+#define FPS_MIN 1 -+#define FPS_MAX 90 -+ -+/* timeperframe: min/max and default */ -+static const struct v4l2_fract -+ tpf_min = {.numerator = 1, .denominator = FPS_MAX}, -+ tpf_max = {.numerator = 1, .denominator = FPS_MIN}, -+ tpf_default = {.numerator = 1000, .denominator = 30000}; -+ -+/* video formats */ -+static struct mmal_fmt formats[] = { -+ { -+ .name = "4:2:0, planar, YUV", -+ .fourcc = V4L2_PIX_FMT_YUV420, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_I420, -+ .depth = 12, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 1, -+ }, -+ { -+ .name = "4:2:2, packed, YUYV", -+ .fourcc = V4L2_PIX_FMT_YUYV, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_YUYV, -+ .depth = 16, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 2, -+ }, -+ { -+ .name = "RGB24 (LE)", -+ .fourcc = V4L2_PIX_FMT_RGB24, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_RGB24, -+ .depth = 24, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 3, -+ }, -+ { -+ .name = "JPEG", -+ .fourcc = V4L2_PIX_FMT_JPEG, -+ .flags = V4L2_FMT_FLAG_COMPRESSED, -+ .mmal = MMAL_ENCODING_JPEG, -+ .depth = 8, -+ .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE, -+ .ybbp = 0, -+ }, -+ { -+ .name = "H264", -+ .fourcc = V4L2_PIX_FMT_H264, -+ .flags = V4L2_FMT_FLAG_COMPRESSED, -+ .mmal = MMAL_ENCODING_H264, -+ .depth = 8, -+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, -+ .ybbp = 0, -+ }, -+ { -+ .name = "MJPEG", -+ .fourcc = V4L2_PIX_FMT_MJPEG, -+ .flags = V4L2_FMT_FLAG_COMPRESSED, -+ .mmal = MMAL_ENCODING_MJPEG, -+ .depth = 8, -+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE, -+ .ybbp = 0, -+ }, -+ { -+ .name = "4:2:2, packed, YVYU", -+ .fourcc = V4L2_PIX_FMT_YVYU, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_YVYU, -+ .depth = 16, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 2, -+ }, -+ { -+ .name = "4:2:2, packed, VYUY", -+ .fourcc = V4L2_PIX_FMT_VYUY, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_VYUY, -+ .depth = 16, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 2, -+ }, -+ { -+ .name = "4:2:2, packed, UYVY", -+ .fourcc = V4L2_PIX_FMT_UYVY, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_UYVY, -+ .depth = 16, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 2, -+ }, -+ { -+ .name = "4:2:0, planar, NV12", -+ .fourcc = V4L2_PIX_FMT_NV12, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_NV12, -+ .depth = 12, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 1, -+ }, -+ { -+ .name = "RGB24 (BE)", -+ .fourcc = V4L2_PIX_FMT_BGR24, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_BGR24, -+ .depth = 24, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 3, -+ }, -+ { -+ .name = "4:2:0, planar, YVU", -+ .fourcc = V4L2_PIX_FMT_YVU420, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_YV12, -+ .depth = 12, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 1, -+ }, -+ { -+ .name = "4:2:0, planar, NV21", -+ .fourcc = V4L2_PIX_FMT_NV21, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_NV21, -+ .depth = 12, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 1, -+ }, -+ { -+ .name = "RGB32 (BE)", -+ .fourcc = V4L2_PIX_FMT_BGR32, -+ .flags = 0, -+ .mmal = MMAL_ENCODING_BGRA, -+ .depth = 32, -+ .mmal_component = MMAL_COMPONENT_CAMERA, -+ .ybbp = 4, -+ }, -+}; -+ -+static struct mmal_fmt *get_format(struct v4l2_format *f) -+{ -+ struct mmal_fmt *fmt; -+ unsigned int k; -+ -+ for (k = 0; k < ARRAY_SIZE(formats); k++) { -+ fmt = &formats[k]; -+ if (fmt->fourcc == f->fmt.pix.pixelformat) -+ break; -+ } -+ -+ if (k == ARRAY_SIZE(formats)) -+ return NULL; -+ -+ return &formats[k]; -+} -+ -+/* ------------------------------------------------------------------ -+ Videobuf queue operations -+ ------------------------------------------------------------------*/ -+ -+static int queue_setup(struct vb2_queue *vq, -+ unsigned int *nbuffers, unsigned int *nplanes, -+ unsigned int sizes[], struct device *alloc_ctxs[]) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); -+ unsigned long size; -+ -+ /* refuse queue setup if port is not configured */ -+ if (dev->capture.port == NULL) { -+ v4l2_err(&dev->v4l2_dev, -+ "%s: capture port not configured\n", __func__); -+ return -EINVAL; -+ } -+ -+ size = dev->capture.port->current_buffer.size; -+ if (size == 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "%s: capture port buffer size is zero\n", __func__); -+ return -EINVAL; -+ } -+ -+ if (*nbuffers < (dev->capture.port->current_buffer.num + 2)) -+ *nbuffers = (dev->capture.port->current_buffer.num + 2); -+ -+ *nplanes = 1; -+ -+ sizes[0] = size; -+ -+ /* -+ * videobuf2-vmalloc allocator is context-less so no need to set -+ * alloc_ctxs array. -+ */ -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", -+ __func__, dev); -+ -+ return 0; -+} -+ -+static int buffer_prepare(struct vb2_buffer *vb) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); -+ unsigned long size; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", -+ __func__, dev); -+ -+ BUG_ON(dev->capture.port == NULL); -+ BUG_ON(dev->capture.fmt == NULL); -+ -+ size = dev->capture.stride * dev->capture.height; -+ if (vb2_plane_size(vb, 0) < size) { -+ v4l2_err(&dev->v4l2_dev, -+ "%s data will not fit into plane (%lu < %lu)\n", -+ __func__, vb2_plane_size(vb, 0), size); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static inline bool is_capturing(struct bm2835_mmal_dev *dev) -+{ -+ return dev->capture.camera_port == -+ &dev-> -+ component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE]; -+} -+ -+static void buffer_cb(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ int status, -+ struct mmal_buffer *buf, -+ unsigned long length, u32 mmal_flags, s64 dts, s64 pts) -+{ -+ struct bm2835_mmal_dev *dev = port->cb_ctx; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n", -+ __func__, status, buf, length, mmal_flags, pts); -+ -+ if (status != 0) { -+ /* error in transfer */ -+ if (buf != NULL) { -+ /* there was a buffer with the error so return it */ -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); -+ } -+ return; -+ } else if (length == 0) { -+ /* stream ended */ -+ if (buf != NULL) { -+ /* this should only ever happen if the port is -+ * disabled and there are buffers still queued -+ */ -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); -+ pr_debug("Empty buffer"); -+ } else if (dev->capture.frame_count) { -+ /* grab another frame */ -+ if (is_capturing(dev)) { -+ pr_debug("Grab another frame"); -+ vchiq_mmal_port_parameter_set( -+ instance, -+ dev->capture. -+ camera_port, -+ MMAL_PARAMETER_CAPTURE, -+ &dev->capture. -+ frame_count, -+ sizeof(dev->capture.frame_count)); -+ } -+ } else { -+ /* signal frame completion */ -+ complete(&dev->capture.frame_cmplt); -+ } -+ } else { -+ if (dev->capture.frame_count) { -+ if (dev->capture.vc_start_timestamp != -1 && -+ pts != 0) { -+ struct timeval timestamp; -+ s64 runtime_us = pts - -+ dev->capture.vc_start_timestamp; -+ u32 div = 0; -+ u32 rem = 0; -+ -+ div = -+ div_u64_rem(runtime_us, USEC_PER_SEC, &rem); -+ timestamp.tv_sec = -+ dev->capture.kernel_start_ts.tv_sec + div; -+ timestamp.tv_usec = -+ dev->capture.kernel_start_ts.tv_usec + rem; -+ -+ if (timestamp.tv_usec >= -+ USEC_PER_SEC) { -+ timestamp.tv_sec++; -+ timestamp.tv_usec -= -+ USEC_PER_SEC; -+ } -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Convert start time %d.%06d and %llu " -+ "with offset %llu to %d.%06d\n", -+ (int)dev->capture.kernel_start_ts. -+ tv_sec, -+ (int)dev->capture.kernel_start_ts. -+ tv_usec, -+ dev->capture.vc_start_timestamp, pts, -+ (int)timestamp.tv_sec, -+ (int)timestamp.tv_usec); -+ buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL + -+ timestamp.tv_usec * 1000ULL; -+ } else { -+ buf->vb.vb2_buf.timestamp = ktime_get_ns(); -+ } -+ -+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); -+ -+ if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && -+ is_capturing(dev)) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Grab another frame as buffer has EOS"); -+ vchiq_mmal_port_parameter_set( -+ instance, -+ dev->capture. -+ camera_port, -+ MMAL_PARAMETER_CAPTURE, -+ &dev->capture. -+ frame_count, -+ sizeof(dev->capture.frame_count)); -+ } -+ } else { -+ /* signal frame completion */ -+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); -+ complete(&dev->capture.frame_cmplt); -+ } -+ } -+} -+ -+static int enable_camera(struct bm2835_mmal_dev *dev) -+{ -+ int ret; -+ if (!dev->camera_use_count) { -+ ret = vchiq_mmal_port_parameter_set( -+ dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]->control, -+ MMAL_PARAMETER_CAMERA_NUM, &dev->camera_num, -+ sizeof(dev->camera_num)); -+ if (ret < 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed setting camera num, ret %d\n", ret); -+ return -EINVAL; -+ } -+ -+ ret = vchiq_mmal_component_enable( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA]); -+ if (ret < 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed enabling camera, ret %d\n", ret); -+ return -EINVAL; -+ } -+ } -+ dev->camera_use_count++; -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, "enabled camera (refcount %d)\n", -+ dev->camera_use_count); -+ return 0; -+} -+ -+static int disable_camera(struct bm2835_mmal_dev *dev) -+{ -+ int ret; -+ if (!dev->camera_use_count) { -+ v4l2_err(&dev->v4l2_dev, -+ "Disabled the camera when already disabled\n"); -+ return -EINVAL; -+ } -+ dev->camera_use_count--; -+ if (!dev->camera_use_count) { -+ unsigned int i = 0xFFFFFFFF; -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Disabling camera\n"); -+ ret = -+ vchiq_mmal_component_disable( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA]); -+ if (ret < 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed disabling camera, ret %d\n", ret); -+ return -EINVAL; -+ } -+ vchiq_mmal_port_parameter_set( -+ dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]->control, -+ MMAL_PARAMETER_CAMERA_NUM, &i, -+ sizeof(i)); -+ } -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Camera refcount now %d\n", dev->camera_use_count); -+ return 0; -+} -+ -+static void buffer_queue(struct vb2_buffer *vb) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); -+ struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); -+ struct mmal_buffer *buf = container_of(vb2, struct mmal_buffer, vb); -+ int ret; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: dev:%p buf:%p\n", __func__, dev, buf); -+ -+ buf->buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); -+ buf->buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0); -+ -+ ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf); -+ if (ret < 0) -+ v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n", -+ __func__); -+} -+ -+static int start_streaming(struct vb2_queue *vq, unsigned int count) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); -+ int ret; -+ int parameter_size; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", -+ __func__, dev); -+ -+ /* ensure a format has actually been set */ -+ if (dev->capture.port == NULL) -+ return -EINVAL; -+ -+ if (enable_camera(dev) < 0) { -+ v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n"); -+ return -EINVAL; -+ } -+ -+ /*init_completion(&dev->capture.frame_cmplt); */ -+ -+ /* enable frame capture */ -+ dev->capture.frame_count = 1; -+ -+ /* if the preview is not already running, wait for a few frames for AGC -+ * to settle down. -+ */ -+ if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled) -+ msleep(300); -+ -+ /* enable the connection from camera to encoder (if applicable) */ -+ if (dev->capture.camera_port != dev->capture.port -+ && dev->capture.camera_port) { -+ ret = vchiq_mmal_port_enable(dev->instance, -+ dev->capture.camera_port, NULL); -+ if (ret) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed to enable encode tunnel - error %d\n", -+ ret); -+ return -1; -+ } -+ } -+ -+ /* Get VC timestamp at this point in time */ -+ parameter_size = sizeof(dev->capture.vc_start_timestamp); -+ if (vchiq_mmal_port_parameter_get(dev->instance, -+ dev->capture.camera_port, -+ MMAL_PARAMETER_SYSTEM_TIME, -+ &dev->capture.vc_start_timestamp, -+ ¶meter_size)) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed to get VC start time - update your VC f/w\n"); -+ -+ /* Flag to indicate just to rely on kernel timestamps */ -+ dev->capture.vc_start_timestamp = -1; -+ } else -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Start time %lld size %d\n", -+ dev->capture.vc_start_timestamp, parameter_size); -+ -+ v4l2_get_timestamp(&dev->capture.kernel_start_ts); -+ -+ /* enable the camera port */ -+ dev->capture.port->cb_ctx = dev; -+ ret = -+ vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb); -+ if (ret) { -+ v4l2_err(&dev->v4l2_dev, -+ "Failed to enable capture port - error %d. " -+ "Disabling camera port again\n", ret); -+ -+ vchiq_mmal_port_disable(dev->instance, -+ dev->capture.camera_port); -+ if (disable_camera(dev) < 0) { -+ v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); -+ return -EINVAL; -+ } -+ return -1; -+ } -+ -+ /* capture the first frame */ -+ vchiq_mmal_port_parameter_set(dev->instance, -+ dev->capture.camera_port, -+ MMAL_PARAMETER_CAPTURE, -+ &dev->capture.frame_count, -+ sizeof(dev->capture.frame_count)); -+ return 0; -+} -+ -+/* abort streaming and wait for last buffer */ -+static void stop_streaming(struct vb2_queue *vq) -+{ -+ int ret; -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", -+ __func__, dev); -+ -+ init_completion(&dev->capture.frame_cmplt); -+ dev->capture.frame_count = 0; -+ -+ /* ensure a format has actually been set */ -+ if (dev->capture.port == NULL) { -+ v4l2_err(&dev->v4l2_dev, -+ "no capture port - stream not started?\n"); -+ return; -+ } -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n"); -+ -+ /* stop capturing frames */ -+ vchiq_mmal_port_parameter_set(dev->instance, -+ dev->capture.camera_port, -+ MMAL_PARAMETER_CAPTURE, -+ &dev->capture.frame_count, -+ sizeof(dev->capture.frame_count)); -+ -+ /* wait for last frame to complete */ -+ ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ); -+ if (ret <= 0) -+ v4l2_err(&dev->v4l2_dev, -+ "error %d waiting for frame completion\n", ret); -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "disabling connection\n"); -+ -+ /* disable the connection from camera to encoder */ -+ ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port); -+ if (!ret && dev->capture.camera_port != dev->capture.port) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "disabling port\n"); -+ ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port); -+ } else if (dev->capture.camera_port != dev->capture.port) { -+ v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n", -+ ret); -+ } -+ -+ if (disable_camera(dev) < 0) -+ v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); -+} -+ -+static void bm2835_mmal_lock(struct vb2_queue *vq) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); -+ mutex_lock(&dev->mutex); -+} -+ -+static void bm2835_mmal_unlock(struct vb2_queue *vq) -+{ -+ struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq); -+ mutex_unlock(&dev->mutex); -+} -+ -+static struct vb2_ops bm2835_mmal_video_qops = { -+ .queue_setup = queue_setup, -+ .buf_prepare = buffer_prepare, -+ .buf_queue = buffer_queue, -+ .start_streaming = start_streaming, -+ .stop_streaming = stop_streaming, -+ .wait_prepare = bm2835_mmal_unlock, -+ .wait_finish = bm2835_mmal_lock, -+}; -+ -+/* ------------------------------------------------------------------ -+ IOCTL operations -+ ------------------------------------------------------------------*/ -+ -+static int set_overlay_params(struct bm2835_mmal_dev *dev, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ struct mmal_parameter_displayregion prev_config = { -+ .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA | -+ MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN, -+ .layer = PREVIEW_LAYER, -+ .alpha = dev->overlay.global_alpha, -+ .fullscreen = 0, -+ .dest_rect = { -+ .x = dev->overlay.w.left, -+ .y = dev->overlay.w.top, -+ .width = dev->overlay.w.width, -+ .height = dev->overlay.w.height, -+ }, -+ }; -+ ret = vchiq_mmal_port_parameter_set(dev->instance, port, -+ MMAL_PARAMETER_DISPLAYREGION, -+ &prev_config, sizeof(prev_config)); -+ -+ return ret; -+} -+ -+/* overlay ioctl */ -+static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ struct mmal_fmt *fmt; -+ -+ if (f->index >= ARRAY_SIZE(formats)) -+ return -EINVAL; -+ -+ fmt = &formats[f->index]; -+ -+ strlcpy(f->description, fmt->name, sizeof(f->description)); -+ f->pixelformat = fmt->fourcc; -+ f->flags = fmt->flags; -+ -+ return 0; -+} -+ -+static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ -+ f->fmt.win = dev->overlay; -+ -+ return 0; -+} -+ -+static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ -+ f->fmt.win.field = V4L2_FIELD_NONE; -+ f->fmt.win.chromakey = 0; -+ f->fmt.win.clips = NULL; -+ f->fmt.win.clipcount = 0; -+ f->fmt.win.bitmap = NULL; -+ -+ v4l_bound_align_image(&f->fmt.win.w.width, MIN_WIDTH, dev->max_width, 1, -+ &f->fmt.win.w.height, MIN_HEIGHT, dev->max_height, -+ 1, 0); -+ v4l_bound_align_image(&f->fmt.win.w.left, MIN_WIDTH, dev->max_width, 1, -+ &f->fmt.win.w.top, MIN_HEIGHT, dev->max_height, -+ 1, 0); -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Overlay: Now w/h %dx%d l/t %dx%d\n", -+ f->fmt.win.w.width, f->fmt.win.w.height, -+ f->fmt.win.w.left, f->fmt.win.w.top); -+ -+ v4l2_dump_win_format(1, -+ bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ &f->fmt.win, -+ __func__); -+ return 0; -+} -+ -+static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ -+ vidioc_try_fmt_vid_overlay(file, priv, f); -+ -+ dev->overlay = f->fmt.win; -+ if (dev->component[MMAL_COMPONENT_PREVIEW]->enabled) { -+ set_overlay_params(dev, -+ &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]); -+ } -+ -+ return 0; -+} -+ -+static int vidioc_overlay(struct file *file, void *f, unsigned int on) -+{ -+ int ret; -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ struct vchiq_mmal_port *src; -+ struct vchiq_mmal_port *dst; -+ if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) || -+ (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled)) -+ return 0; /* already in requested state */ -+ -+ src = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW]; -+ -+ if (!on) { -+ /* disconnect preview ports and disable component */ -+ ret = vchiq_mmal_port_disable(dev->instance, src); -+ if (!ret) -+ ret = -+ vchiq_mmal_port_connect_tunnel(dev->instance, src, -+ NULL); -+ if (ret >= 0) -+ ret = vchiq_mmal_component_disable( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_PREVIEW]); -+ -+ disable_camera(dev); -+ return ret; -+ } -+ -+ /* set preview port format and connect it to output */ -+ dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]; -+ -+ ret = vchiq_mmal_port_set_format(dev->instance, src); -+ if (ret < 0) -+ goto error; -+ -+ ret = set_overlay_params(dev, dst); -+ if (ret < 0) -+ goto error; -+ -+ if (enable_camera(dev) < 0) -+ goto error; -+ -+ ret = vchiq_mmal_component_enable( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_PREVIEW]); -+ if (ret < 0) -+ goto error; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n", -+ src, dst); -+ ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst); -+ if (!ret) -+ ret = vchiq_mmal_port_enable(dev->instance, src, NULL); -+error: -+ return ret; -+} -+ -+static int vidioc_g_fbuf(struct file *file, void *fh, -+ struct v4l2_framebuffer *a) -+{ -+ /* The video overlay must stay within the framebuffer and can't be -+ positioned independently. */ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ struct vchiq_mmal_port *preview_port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW]; -+ -+ a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | -+ V4L2_FBUF_CAP_GLOBAL_ALPHA; -+ a->flags = V4L2_FBUF_FLAG_OVERLAY; -+ a->fmt.width = preview_port->es.video.width; -+ a->fmt.height = preview_port->es.video.height; -+ a->fmt.pixelformat = V4L2_PIX_FMT_YUV420; -+ a->fmt.bytesperline = preview_port->es.video.width; -+ a->fmt.sizeimage = (preview_port->es.video.width * -+ preview_port->es.video.height * 3)>>1; -+ a->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; -+ -+ return 0; -+} -+ -+/* input ioctls */ -+static int vidioc_enum_input(struct file *file, void *priv, -+ struct v4l2_input *inp) -+{ -+ /* only a single camera input */ -+ if (inp->index != 0) -+ return -EINVAL; -+ -+ inp->type = V4L2_INPUT_TYPE_CAMERA; -+ sprintf(inp->name, "Camera %u", inp->index); -+ return 0; -+} -+ -+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -+{ -+ *i = 0; -+ return 0; -+} -+ -+static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -+{ -+ if (i != 0) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+/* capture ioctls */ -+static int vidioc_querycap(struct file *file, void *priv, -+ struct v4l2_capability *cap) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ u32 major; -+ u32 minor; -+ -+ vchiq_mmal_version(dev->instance, &major, &minor); -+ -+ strcpy(cap->driver, "bm2835 mmal"); -+ snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d", -+ major, minor); -+ -+ snprintf(cap->bus_info, sizeof(cap->bus_info), -+ "platform:%s", dev->v4l2_dev.name); -+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | -+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; -+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; -+ -+ return 0; -+} -+ -+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_fmtdesc *f) -+{ -+ struct mmal_fmt *fmt; -+ -+ if (f->index >= ARRAY_SIZE(formats)) -+ return -EINVAL; -+ -+ fmt = &formats[f->index]; -+ -+ strlcpy(f->description, fmt->name, sizeof(f->description)); -+ f->pixelformat = fmt->fourcc; -+ f->flags = fmt->flags; -+ -+ return 0; -+} -+ -+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ -+ f->fmt.pix.width = dev->capture.width; -+ f->fmt.pix.height = dev->capture.height; -+ f->fmt.pix.field = V4L2_FIELD_NONE; -+ f->fmt.pix.pixelformat = dev->capture.fmt->fourcc; -+ f->fmt.pix.bytesperline = dev->capture.stride; -+ f->fmt.pix.sizeimage = dev->capture.buffersize; -+ -+ if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24) -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; -+ else if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG) -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; -+ else -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; -+ f->fmt.pix.priv = 0; -+ -+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, -+ __func__); -+ return 0; -+} -+ -+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ struct mmal_fmt *mfmt; -+ -+ mfmt = get_format(f); -+ if (!mfmt) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Fourcc format (0x%08x) unknown.\n", -+ f->fmt.pix.pixelformat); -+ f->fmt.pix.pixelformat = formats[0].fourcc; -+ mfmt = get_format(f); -+ } -+ -+ f->fmt.pix.field = V4L2_FIELD_NONE; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Clipping/aligning %dx%d format %08X\n", -+ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); -+ -+ v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, dev->max_width, 1, -+ &f->fmt.pix.height, MIN_HEIGHT, dev->max_height, -+ 1, 0); -+ f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp; -+ -+ /* Image buffer has to be padded to allow for alignment, even though -+ * we then remove that padding before delivering the buffer. -+ */ -+ f->fmt.pix.sizeimage = ((f->fmt.pix.height+15)&~15) * -+ (((f->fmt.pix.width+31)&~31) * mfmt->depth) >> 3; -+ -+ if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) && -+ f->fmt.pix.sizeimage < MIN_BUFFER_SIZE) -+ f->fmt.pix.sizeimage = MIN_BUFFER_SIZE; -+ -+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; -+ else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; -+ else -+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; -+ f->fmt.pix.priv = 0; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Now %dx%d format %08X\n", -+ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); -+ -+ v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, -+ __func__); -+ return 0; -+} -+ -+static int mmal_setup_components(struct bm2835_mmal_dev *dev, -+ struct v4l2_format *f) -+{ -+ int ret; -+ struct vchiq_mmal_port *port = NULL, *camera_port = NULL; -+ struct vchiq_mmal_component *encode_component = NULL; -+ struct mmal_fmt *mfmt = get_format(f); -+ -+ BUG_ON(!mfmt); -+ -+ if (dev->capture.encode_component) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "vid_cap - disconnect previous tunnel\n"); -+ -+ /* Disconnect any previous connection */ -+ vchiq_mmal_port_connect_tunnel(dev->instance, -+ dev->capture.camera_port, NULL); -+ dev->capture.camera_port = NULL; -+ ret = vchiq_mmal_component_disable(dev->instance, -+ dev->capture. -+ encode_component); -+ if (ret) -+ v4l2_err(&dev->v4l2_dev, -+ "Failed to disable encode component %d\n", -+ ret); -+ -+ dev->capture.encode_component = NULL; -+ } -+ /* format dependant port setup */ -+ switch (mfmt->mmal_component) { -+ case MMAL_COMPONENT_CAMERA: -+ /* Make a further decision on port based on resolution */ -+ if (f->fmt.pix.width <= max_video_width -+ && f->fmt.pix.height <= max_video_height) -+ camera_port = port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO]; -+ else -+ camera_port = port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE]; -+ break; -+ case MMAL_COMPONENT_IMAGE_ENCODE: -+ encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE]; -+ port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0]; -+ camera_port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE]; -+ break; -+ case MMAL_COMPONENT_VIDEO_ENCODE: -+ encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE]; -+ port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; -+ camera_port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO]; -+ break; -+ default: -+ break; -+ } -+ -+ if (!port) -+ return -EINVAL; -+ -+ if (encode_component) -+ camera_port->format.encoding = MMAL_ENCODING_OPAQUE; -+ 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; -+ camera_port->es.video.crop.x = 0; -+ camera_port->es.video.crop.y = 0; -+ camera_port->es.video.crop.width = f->fmt.pix.width; -+ camera_port->es.video.crop.height = f->fmt.pix.height; -+ camera_port->es.video.frame_rate.num = 0; -+ camera_port->es.video.frame_rate.den = 1; -+ camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF; -+ -+ ret = vchiq_mmal_port_set_format(dev->instance, camera_port); -+ -+ if (!ret -+ && camera_port == -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO]) { -+ bool overlay_enabled = -+ !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled; -+ struct vchiq_mmal_port *preview_port = -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW]; -+ /* Preview and encode ports need to match on resolution */ -+ if (overlay_enabled) { -+ /* Need to disable the overlay before we can update -+ * the resolution -+ */ -+ ret = -+ vchiq_mmal_port_disable(dev->instance, -+ preview_port); -+ if (!ret) -+ ret = -+ vchiq_mmal_port_connect_tunnel( -+ dev->instance, -+ preview_port, -+ NULL); -+ } -+ preview_port->es.video.width = f->fmt.pix.width; -+ preview_port->es.video.height = f->fmt.pix.height; -+ preview_port->es.video.crop.x = 0; -+ preview_port->es.video.crop.y = 0; -+ preview_port->es.video.crop.width = f->fmt.pix.width; -+ preview_port->es.video.crop.height = f->fmt.pix.height; -+ preview_port->es.video.frame_rate.num = -+ dev->capture.timeperframe.denominator; -+ preview_port->es.video.frame_rate.den = -+ dev->capture.timeperframe.numerator; -+ ret = vchiq_mmal_port_set_format(dev->instance, preview_port); -+ if (overlay_enabled) { -+ ret = vchiq_mmal_port_connect_tunnel( -+ dev->instance, -+ preview_port, -+ &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]); -+ if (!ret) -+ ret = vchiq_mmal_port_enable(dev->instance, -+ preview_port, -+ NULL); -+ } -+ } -+ -+ if (ret) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s failed to set format %dx%d %08X\n", __func__, -+ f->fmt.pix.width, f->fmt.pix.height, -+ f->fmt.pix.pixelformat); -+ /* ensure capture is not going to be tried */ -+ dev->capture.port = NULL; -+ } else { -+ if (encode_component) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "vid_cap - set up encode comp\n"); -+ -+ /* configure buffering */ -+ camera_port->current_buffer.size = -+ camera_port->recommended_buffer.size; -+ camera_port->current_buffer.num = -+ camera_port->recommended_buffer.num; -+ -+ ret = -+ vchiq_mmal_port_connect_tunnel( -+ dev->instance, -+ camera_port, -+ &encode_component->input[0]); -+ if (ret) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "%s failed to create connection\n", -+ __func__); -+ /* ensure capture is not going to be tried */ -+ dev->capture.port = NULL; -+ } else { -+ port->es.video.width = f->fmt.pix.width; -+ port->es.video.height = f->fmt.pix.height; -+ port->es.video.crop.x = 0; -+ port->es.video.crop.y = 0; -+ port->es.video.crop.width = f->fmt.pix.width; -+ port->es.video.crop.height = f->fmt.pix.height; -+ port->es.video.frame_rate.num = -+ dev->capture.timeperframe.denominator; -+ port->es.video.frame_rate.den = -+ dev->capture.timeperframe.numerator; -+ -+ port->format.encoding = mfmt->mmal; -+ port->format.encoding_variant = 0; -+ /* Set any encoding specific parameters */ -+ switch (mfmt->mmal_component) { -+ case MMAL_COMPONENT_VIDEO_ENCODE: -+ port->format.bitrate = -+ dev->capture.encode_bitrate; -+ break; -+ case MMAL_COMPONENT_IMAGE_ENCODE: -+ /* Could set EXIF parameters here */ -+ break; -+ default: -+ break; -+ } -+ ret = vchiq_mmal_port_set_format(dev->instance, -+ port); -+ if (ret) -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "%s failed to set format %dx%d fmt %08X\n", -+ __func__, -+ f->fmt.pix.width, -+ f->fmt.pix.height, -+ f->fmt.pix.pixelformat -+ ); -+ } -+ -+ if (!ret) { -+ ret = vchiq_mmal_component_enable( -+ dev->instance, -+ encode_component); -+ if (ret) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "%s Failed to enable encode components\n", -+ __func__); -+ } -+ } -+ if (!ret) { -+ /* configure buffering */ -+ port->current_buffer.num = 1; -+ port->current_buffer.size = -+ f->fmt.pix.sizeimage; -+ if (port->format.encoding == -+ MMAL_ENCODING_JPEG) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "JPG - buf size now %d was %d\n", -+ f->fmt.pix.sizeimage, -+ port->current_buffer.size); -+ port->current_buffer.size = -+ (f->fmt.pix.sizeimage < -+ (100 << 10)) -+ ? (100 << 10) : f->fmt.pix. -+ sizeimage; -+ } -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "vid_cap - cur_buf.size set to %d\n", -+ f->fmt.pix.sizeimage); -+ port->current_buffer.alignment = 0; -+ } -+ } else { -+ /* configure buffering */ -+ camera_port->current_buffer.num = 1; -+ camera_port->current_buffer.size = f->fmt.pix.sizeimage; -+ camera_port->current_buffer.alignment = 0; -+ } -+ -+ if (!ret) { -+ dev->capture.fmt = mfmt; -+ dev->capture.stride = f->fmt.pix.bytesperline; -+ dev->capture.width = camera_port->es.video.crop.width; -+ dev->capture.height = camera_port->es.video.crop.height; -+ dev->capture.buffersize = port->current_buffer.size; -+ -+ /* select port for capture */ -+ dev->capture.port = port; -+ dev->capture.camera_port = camera_port; -+ dev->capture.encode_component = encode_component; -+ v4l2_dbg(1, bcm2835_v4l2_debug, -+ &dev->v4l2_dev, -+ "Set dev->capture.fmt %08X, %dx%d, stride %d, size %d", -+ port->format.encoding, -+ dev->capture.width, dev->capture.height, -+ dev->capture.stride, dev->capture.buffersize); -+ } -+ } -+ -+ /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */ -+ return ret; -+} -+ -+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, -+ struct v4l2_format *f) -+{ -+ int ret; -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ struct mmal_fmt *mfmt; -+ -+ /* try the format to set valid parameters */ -+ ret = vidioc_try_fmt_vid_cap(file, priv, f); -+ if (ret) { -+ v4l2_err(&dev->v4l2_dev, -+ "vid_cap - vidioc_try_fmt_vid_cap failed\n"); -+ return ret; -+ } -+ -+ /* if a capture is running refuse to set format */ -+ if (vb2_is_busy(&dev->capture.vb_vidq)) { -+ v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__); -+ return -EBUSY; -+ } -+ -+ /* If the format is unsupported v4l2 says we should switch to -+ * a supported one and not return an error. */ -+ mfmt = get_format(f); -+ if (!mfmt) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Fourcc format (0x%08x) unknown.\n", -+ f->fmt.pix.pixelformat); -+ f->fmt.pix.pixelformat = formats[0].fourcc; -+ mfmt = get_format(f); -+ } -+ -+ ret = mmal_setup_components(dev, f); -+ if (ret != 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "%s: failed to setup mmal components: %d\n", -+ __func__, ret); -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+int vidioc_enum_framesizes(struct file *file, void *fh, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ static const struct v4l2_frmsize_stepwise sizes = { -+ MIN_WIDTH, 0, 2, -+ MIN_HEIGHT, 0, 2 -+ }; -+ int i; -+ -+ if (fsize->index) -+ return -EINVAL; -+ for (i = 0; i < ARRAY_SIZE(formats); i++) -+ if (formats[i].fourcc == fsize->pixel_format) -+ break; -+ if (i == ARRAY_SIZE(formats)) -+ return -EINVAL; -+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; -+ fsize->stepwise = sizes; -+ fsize->stepwise.max_width = dev->max_width; -+ fsize->stepwise.max_height = dev->max_height; -+ return 0; -+} -+ -+/* timeperframe is arbitrary and continous */ -+static int vidioc_enum_frameintervals(struct file *file, void *priv, -+ struct v4l2_frmivalenum *fival) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ int i; -+ -+ if (fival->index) -+ return -EINVAL; -+ -+ for (i = 0; i < ARRAY_SIZE(formats); i++) -+ if (formats[i].fourcc == fival->pixel_format) -+ break; -+ if (i == ARRAY_SIZE(formats)) -+ return -EINVAL; -+ -+ /* regarding width & height - we support any within range */ -+ if (fival->width < MIN_WIDTH || fival->width > dev->max_width || -+ fival->height < MIN_HEIGHT || fival->height > dev->max_height) -+ return -EINVAL; -+ -+ fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; -+ -+ /* fill in stepwise (step=1.0 is requred by V4L2 spec) */ -+ fival->stepwise.min = tpf_min; -+ fival->stepwise.max = tpf_max; -+ fival->stepwise.step = (struct v4l2_fract) {1, 1}; -+ -+ return 0; -+} -+ -+static int vidioc_g_parm(struct file *file, void *priv, -+ struct v4l2_streamparm *parm) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ -+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; -+ parm->parm.capture.timeperframe = dev->capture.timeperframe; -+ parm->parm.capture.readbuffers = 1; -+ return 0; -+} -+ -+#define FRACT_CMP(a, OP, b) \ -+ ((u64)(a).numerator * (b).denominator OP \ -+ (u64)(b).numerator * (a).denominator) -+ -+static int vidioc_s_parm(struct file *file, void *priv, -+ struct v4l2_streamparm *parm) -+{ -+ struct bm2835_mmal_dev *dev = video_drvdata(file); -+ struct v4l2_fract tpf; -+ struct mmal_parameter_rational fps_param; -+ -+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) -+ return -EINVAL; -+ -+ tpf = parm->parm.capture.timeperframe; -+ -+ /* tpf: {*, 0} resets timing; clip to [min, max]*/ -+ tpf = tpf.denominator ? tpf : tpf_default; -+ tpf = FRACT_CMP(tpf, <, tpf_min) ? tpf_min : tpf; -+ tpf = FRACT_CMP(tpf, >, tpf_max) ? tpf_max : tpf; -+ -+ dev->capture.timeperframe = tpf; -+ parm->parm.capture.timeperframe = tpf; -+ parm->parm.capture.readbuffers = 1; -+ parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; -+ -+ fps_param.num = 0; /* Select variable fps, and then use -+ * FPS_RANGE to select the actual limits. -+ */ -+ fps_param.den = 1; -+ set_framerate_params(dev); -+ -+ return 0; -+} -+ -+static const struct v4l2_ioctl_ops camera0_ioctl_ops = { -+ /* overlay */ -+ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, -+ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, -+ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, -+ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, -+ .vidioc_overlay = vidioc_overlay, -+ .vidioc_g_fbuf = vidioc_g_fbuf, -+ -+ /* inputs */ -+ .vidioc_enum_input = vidioc_enum_input, -+ .vidioc_g_input = vidioc_g_input, -+ .vidioc_s_input = vidioc_s_input, -+ -+ /* capture */ -+ .vidioc_querycap = vidioc_querycap, -+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, -+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -+ -+ /* buffer management */ -+ .vidioc_reqbufs = vb2_ioctl_reqbufs, -+ .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, -+ .vidioc_querybuf = vb2_ioctl_querybuf, -+ .vidioc_qbuf = vb2_ioctl_qbuf, -+ .vidioc_dqbuf = vb2_ioctl_dqbuf, -+ .vidioc_enum_framesizes = vidioc_enum_framesizes, -+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals, -+ .vidioc_g_parm = vidioc_g_parm, -+ .vidioc_s_parm = vidioc_s_parm, -+ .vidioc_streamon = vb2_ioctl_streamon, -+ .vidioc_streamoff = vb2_ioctl_streamoff, -+ -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+}; -+ -+static const struct v4l2_ioctl_ops camera0_ioctl_ops_gstreamer = { -+ /* overlay */ -+ .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, -+ .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, -+ .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, -+ .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, -+ .vidioc_overlay = vidioc_overlay, -+ .vidioc_g_fbuf = vidioc_g_fbuf, -+ -+ /* inputs */ -+ .vidioc_enum_input = vidioc_enum_input, -+ .vidioc_g_input = vidioc_g_input, -+ .vidioc_s_input = vidioc_s_input, -+ -+ /* capture */ -+ .vidioc_querycap = vidioc_querycap, -+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, -+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, -+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, -+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, -+ -+ /* buffer management */ -+ .vidioc_reqbufs = vb2_ioctl_reqbufs, -+ .vidioc_create_bufs = vb2_ioctl_create_bufs, -+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, -+ .vidioc_querybuf = vb2_ioctl_querybuf, -+ .vidioc_qbuf = vb2_ioctl_qbuf, -+ .vidioc_dqbuf = vb2_ioctl_dqbuf, -+ /* Remove this function ptr to fix gstreamer bug -+ .vidioc_enum_framesizes = vidioc_enum_framesizes, */ -+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals, -+ .vidioc_g_parm = vidioc_g_parm, -+ .vidioc_s_parm = vidioc_s_parm, -+ .vidioc_streamon = vb2_ioctl_streamon, -+ .vidioc_streamoff = vb2_ioctl_streamoff, -+ -+ .vidioc_log_status = v4l2_ctrl_log_status, -+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, -+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -+}; -+ -+/* ------------------------------------------------------------------ -+ Driver init/finalise -+ ------------------------------------------------------------------*/ -+ -+static const struct v4l2_file_operations camera0_fops = { -+ .owner = THIS_MODULE, -+ .open = v4l2_fh_open, -+ .release = vb2_fop_release, -+ .read = vb2_fop_read, -+ .poll = vb2_fop_poll, -+ .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ -+ .mmap = vb2_fop_mmap, -+}; -+ -+static struct video_device vdev_template = { -+ .name = "camera0", -+ .fops = &camera0_fops, -+ .ioctl_ops = &camera0_ioctl_ops, -+ .release = video_device_release_empty, -+}; -+ -+/* Returns the number of cameras, and also the max resolution supported -+ * by those cameras. -+ */ -+static int get_num_cameras(struct vchiq_mmal_instance *instance, -+ unsigned int resolutions[][2], int num_resolutions) -+{ -+ int ret; -+ struct vchiq_mmal_component *cam_info_component; -+ struct mmal_parameter_camera_info_t cam_info = {0}; -+ int param_size = sizeof(cam_info); -+ int i; -+ -+ /* create a camera_info component */ -+ ret = vchiq_mmal_component_init(instance, "camera_info", -+ &cam_info_component); -+ if (ret < 0) -+ /* Unusual failure - let's guess one camera. */ -+ return 1; -+ -+ if (vchiq_mmal_port_parameter_get(instance, -+ &cam_info_component->control, -+ MMAL_PARAMETER_CAMERA_INFO, -+ &cam_info, -+ ¶m_size)) { -+ pr_info("Failed to get camera info\n"); -+ } -+ for (i = 0; -+ i < (cam_info.num_cameras > num_resolutions ? -+ num_resolutions : -+ cam_info.num_cameras); -+ i++) { -+ resolutions[i][0] = cam_info.cameras[i].max_width; -+ resolutions[i][1] = cam_info.cameras[i].max_height; -+ } -+ -+ vchiq_mmal_component_finalise(instance, -+ cam_info_component); -+ -+ return cam_info.num_cameras; -+} -+ -+static int set_camera_parameters(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *camera, -+ struct bm2835_mmal_dev *dev) -+{ -+ int ret; -+ struct mmal_parameter_camera_config cam_config = { -+ .max_stills_w = dev->max_width, -+ .max_stills_h = dev->max_height, -+ .stills_yuv422 = 1, -+ .one_shot_stills = 1, -+ .max_preview_video_w = (max_video_width > 1920) ? -+ max_video_width : 1920, -+ .max_preview_video_h = (max_video_height > 1088) ? -+ max_video_height : 1088, -+ .num_preview_video_frames = 3, -+ .stills_capture_circular_buffer_height = 0, -+ .fast_preview_resume = 0, -+ .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC -+ }; -+ -+ ret = vchiq_mmal_port_parameter_set(instance, &camera->control, -+ MMAL_PARAMETER_CAMERA_CONFIG, -+ &cam_config, sizeof(cam_config)); -+ 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) -+ return ret; -+ -+ /* get the camera component ready */ -+ ret = vchiq_mmal_component_init(dev->instance, "ril.camera", -+ &dev->component[MMAL_COMPONENT_CAMERA]); -+ if (ret < 0) -+ goto unreg_mmal; -+ -+ camera = dev->component[MMAL_COMPONENT_CAMERA]; -+ if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { -+ ret = -EINVAL; -+ goto unreg_camera; -+ } -+ -+ ret = set_camera_parameters(dev->instance, -+ camera, -+ dev); -+ if (ret < 0) -+ goto unreg_camera; -+ -+ /* 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; -+ -+ format->es->video.width = 1024; -+ format->es->video.height = 768; -+ format->es->video.crop.x = 0; -+ format->es->video.crop.y = 0; -+ format->es->video.crop.width = 1024; -+ format->es->video.crop.height = 768; -+ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ -+ format->es->video.frame_rate.den = 1; -+ -+ format = &camera->output[MMAL_CAMERA_PORT_VIDEO].format; -+ -+ format->encoding = MMAL_ENCODING_OPAQUE; -+ format->encoding_variant = MMAL_ENCODING_I420; -+ -+ format->es->video.width = 1024; -+ format->es->video.height = 768; -+ format->es->video.crop.x = 0; -+ format->es->video.crop.y = 0; -+ format->es->video.crop.width = 1024; -+ format->es->video.crop.height = 768; -+ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ -+ format->es->video.frame_rate.den = 1; -+ -+ vchiq_mmal_port_parameter_set(dev->instance, -+ &camera->output[MMAL_CAMERA_PORT_VIDEO], -+ MMAL_PARAMETER_NO_IMAGE_PADDING, -+ &bool_true, sizeof(bool_true)); -+ -+ format = &camera->output[MMAL_CAMERA_PORT_CAPTURE].format; -+ -+ format->encoding = MMAL_ENCODING_OPAQUE; -+ -+ format->es->video.width = 2592; -+ format->es->video.height = 1944; -+ format->es->video.crop.x = 0; -+ format->es->video.crop.y = 0; -+ format->es->video.crop.width = 2592; -+ format->es->video.crop.height = 1944; -+ format->es->video.frame_rate.num = 0; /* Rely on fps_range */ -+ format->es->video.frame_rate.den = 1; -+ -+ dev->capture.width = format->es->video.width; -+ dev->capture.height = format->es->video.height; -+ dev->capture.fmt = &formats[0]; -+ dev->capture.encode_component = NULL; -+ dev->capture.timeperframe = tpf_default; -+ dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; -+ dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; -+ -+ vchiq_mmal_port_parameter_set(dev->instance, -+ &camera->output[MMAL_CAMERA_PORT_CAPTURE], -+ MMAL_PARAMETER_NO_IMAGE_PADDING, -+ &bool_true, sizeof(bool_true)); -+ -+ /* get the preview component ready */ -+ ret = vchiq_mmal_component_init( -+ dev->instance, "ril.video_render", -+ &dev->component[MMAL_COMPONENT_PREVIEW]); -+ if (ret < 0) -+ goto unreg_camera; -+ -+ if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) { -+ ret = -EINVAL; -+ pr_debug("too few input ports %d needed %d\n", -+ dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1); -+ goto unreg_preview; -+ } -+ -+ /* get the image encoder component ready */ -+ ret = vchiq_mmal_component_init( -+ dev->instance, "ril.image_encode", -+ &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]); -+ if (ret < 0) -+ goto unreg_preview; -+ -+ if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) { -+ ret = -EINVAL; -+ v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", -+ dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs, -+ 1); -+ goto unreg_image_encoder; -+ } -+ -+ /* get the video encoder component ready */ -+ ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode", -+ &dev-> -+ component[MMAL_COMPONENT_VIDEO_ENCODE]); -+ if (ret < 0) -+ goto unreg_image_encoder; -+ -+ if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) { -+ ret = -EINVAL; -+ v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", -+ dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs, -+ 1); -+ goto unreg_vid_encoder; -+ } -+ -+ { -+ struct vchiq_mmal_port *encoder_port = -+ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; -+ encoder_port->format.encoding = MMAL_ENCODING_H264; -+ ret = vchiq_mmal_port_set_format(dev->instance, -+ encoder_port); -+ } -+ -+ { -+ unsigned int enable = 1; -+ vchiq_mmal_port_parameter_set( -+ dev->instance, -+ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control, -+ MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, -+ &enable, sizeof(enable)); -+ -+ vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control, -+ MMAL_PARAMETER_MINIMISE_FRAGMENTATION, -+ &enable, -+ sizeof(enable)); -+ } -+ ret = bm2835_mmal_set_all_camera_controls(dev); -+ if (ret < 0) -+ goto unreg_vid_encoder; -+ -+ return 0; -+ -+unreg_vid_encoder: -+ pr_err("Cleanup: Destroy video encoder\n"); -+ vchiq_mmal_component_finalise( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_VIDEO_ENCODE]); -+ -+unreg_image_encoder: -+ pr_err("Cleanup: Destroy image encoder\n"); -+ vchiq_mmal_component_finalise( -+ dev->instance, -+ dev->component[MMAL_COMPONENT_IMAGE_ENCODE]); -+ -+unreg_preview: -+ pr_err("Cleanup: Destroy video render\n"); -+ vchiq_mmal_component_finalise(dev->instance, -+ dev->component[MMAL_COMPONENT_PREVIEW]); -+ -+unreg_camera: -+ pr_err("Cleanup: Destroy camera\n"); -+ vchiq_mmal_component_finalise(dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA]); -+ -+unreg_mmal: -+ vchiq_mmal_finalise(dev->instance); -+ return ret; -+} -+ -+static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev, -+ struct video_device *vfd) -+{ -+ int ret; -+ -+ *vfd = vdev_template; -+ if (gst_v4l2src_is_broken) { -+ v4l2_info(&dev->v4l2_dev, -+ "Work-around for gstreamer issue is active.\n"); -+ vfd->ioctl_ops = &camera0_ioctl_ops_gstreamer; -+ } -+ -+ vfd->v4l2_dev = &dev->v4l2_dev; -+ -+ vfd->lock = &dev->mutex; -+ -+ vfd->queue = &dev->capture.vb_vidq; -+ -+ /* video device needs to be able to access instance data */ -+ video_set_drvdata(vfd, dev); -+ -+ ret = video_register_device(vfd, -+ VFL_TYPE_GRABBER, -+ video_nr[dev->camera_num]); -+ if (ret < 0) -+ return ret; -+ -+ v4l2_info(vfd->v4l2_dev, -+ "V4L2 device registered as %s - stills mode > %dx%d\n", -+ video_device_node_name(vfd), max_video_width, max_video_height); -+ -+ return 0; -+} -+ -+void bcm2835_cleanup_instance(struct bm2835_mmal_dev *dev) -+{ -+ if (!dev) -+ return; -+ -+ v4l2_info(&dev->v4l2_dev, "unregistering %s\n", -+ video_device_node_name(&dev->vdev)); -+ -+ video_unregister_device(&dev->vdev); -+ -+ if (dev->capture.encode_component) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "mmal_exit - disconnect tunnel\n"); -+ vchiq_mmal_port_connect_tunnel(dev->instance, -+ dev->capture.camera_port, NULL); -+ vchiq_mmal_component_disable(dev->instance, -+ dev->capture.encode_component); -+ } -+ vchiq_mmal_component_disable(dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA]); -+ -+ vchiq_mmal_component_finalise(dev->instance, -+ dev-> -+ component[MMAL_COMPONENT_VIDEO_ENCODE]); -+ -+ vchiq_mmal_component_finalise(dev->instance, -+ dev-> -+ component[MMAL_COMPONENT_IMAGE_ENCODE]); -+ -+ vchiq_mmal_component_finalise(dev->instance, -+ dev->component[MMAL_COMPONENT_PREVIEW]); -+ -+ vchiq_mmal_component_finalise(dev->instance, -+ dev->component[MMAL_COMPONENT_CAMERA]); -+ -+ v4l2_ctrl_handler_free(&dev->ctrl_handler); -+ -+ v4l2_device_unregister(&dev->v4l2_dev); -+ -+ kfree(dev); -+} -+ -+static struct v4l2_format default_v4l2_format = { -+ .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG, -+ .fmt.pix.width = 1024, -+ .fmt.pix.bytesperline = 0, -+ .fmt.pix.height = 768, -+ .fmt.pix.sizeimage = 1024*768, -+}; -+ -+static int __init bm2835_mmal_init(void) -+{ -+ int ret; -+ struct bm2835_mmal_dev *dev; -+ struct vb2_queue *q; -+ int camera; -+ unsigned int num_cameras; -+ struct vchiq_mmal_instance *instance; -+ unsigned int resolutions[MAX_BCM2835_CAMERAS][2]; -+ -+ ret = vchiq_mmal_init(&instance); -+ if (ret < 0) -+ return ret; -+ -+ num_cameras = get_num_cameras(instance, -+ resolutions, -+ MAX_BCM2835_CAMERAS); -+ if (num_cameras > MAX_BCM2835_CAMERAS) -+ num_cameras = MAX_BCM2835_CAMERAS; -+ -+ for (camera = 0; camera < num_cameras; camera++) { -+ dev = kzalloc(sizeof(struct bm2835_mmal_dev), GFP_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ -+ dev->camera_num = camera; -+ dev->max_width = resolutions[camera][0]; -+ dev->max_height = resolutions[camera][1]; -+ -+ /* setup device defaults */ -+ dev->overlay.w.left = 150; -+ dev->overlay.w.top = 50; -+ dev->overlay.w.width = 1024; -+ dev->overlay.w.height = 768; -+ dev->overlay.clipcount = 0; -+ dev->overlay.field = V4L2_FIELD_NONE; -+ dev->overlay.global_alpha = 255; -+ -+ dev->capture.fmt = &formats[3]; /* JPEG */ -+ -+ /* v4l device registration */ -+ snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), -+ "%s", BM2835_MMAL_MODULE_NAME); -+ ret = v4l2_device_register(NULL, &dev->v4l2_dev); -+ if (ret) -+ goto free_dev; -+ -+ /* setup v4l controls */ -+ ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler); -+ if (ret < 0) -+ goto unreg_dev; -+ dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; -+ -+ /* mmal init */ -+ dev->instance = instance; -+ ret = mmal_init(dev); -+ if (ret < 0) -+ goto unreg_dev; -+ -+ /* initialize queue */ -+ q = &dev->capture.vb_vidq; -+ memset(q, 0, sizeof(*q)); -+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; -+ q->drv_priv = dev; -+ q->buf_struct_size = sizeof(struct mmal_buffer); -+ q->ops = &bm2835_mmal_video_qops; -+ q->mem_ops = &vb2_vmalloc_memops; -+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; -+ ret = vb2_queue_init(q); -+ if (ret < 0) -+ goto unreg_dev; -+ -+ /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ -+ mutex_init(&dev->mutex); -+ -+ /* initialise video devices */ -+ ret = bm2835_mmal_init_device(dev, &dev->vdev); -+ if (ret < 0) -+ goto unreg_dev; -+ -+ /* Really want to call vidioc_s_fmt_vid_cap with the default -+ * format, but currently the APIs don't join up. -+ */ -+ ret = mmal_setup_components(dev, &default_v4l2_format); -+ if (ret < 0) { -+ v4l2_err(&dev->v4l2_dev, -+ "%s: could not setup components\n", __func__); -+ goto unreg_dev; -+ } -+ -+ v4l2_info(&dev->v4l2_dev, -+ "Broadcom 2835 MMAL video capture ver %s loaded.\n", -+ BM2835_MMAL_VERSION); -+ -+ gdev[camera] = dev; -+ } -+ return 0; -+ -+unreg_dev: -+ v4l2_ctrl_handler_free(&dev->ctrl_handler); -+ v4l2_device_unregister(&dev->v4l2_dev); -+ -+free_dev: -+ kfree(dev); -+ -+ for ( ; camera > 0; camera--) { -+ bcm2835_cleanup_instance(gdev[camera]); -+ gdev[camera] = NULL; -+ } -+ pr_info("%s: error %d while loading driver\n", -+ BM2835_MMAL_MODULE_NAME, ret); -+ -+ return ret; -+} -+ -+static void __exit bm2835_mmal_exit(void) -+{ -+ int camera; -+ struct vchiq_mmal_instance *instance = gdev[0]->instance; -+ -+ for (camera = 0; camera < MAX_BCM2835_CAMERAS; camera++) { -+ bcm2835_cleanup_instance(gdev[camera]); -+ gdev[camera] = NULL; -+ } -+ vchiq_mmal_finalise(instance); -+} -+ -+module_init(bm2835_mmal_init); -+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..e6aeb7e7e381de65d6c6586205069a4c5cd33274 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -0,0 +1,145 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ * -+ * core driver device -+ */ -+ -+#define V4L2_CTRL_COUNT 29 /* number of v4l controls */ -+ -+enum { -+ MMAL_COMPONENT_CAMERA = 0, -+ MMAL_COMPONENT_PREVIEW, -+ MMAL_COMPONENT_IMAGE_ENCODE, -+ MMAL_COMPONENT_VIDEO_ENCODE, -+ MMAL_COMPONENT_COUNT -+}; -+ -+enum { -+ MMAL_CAMERA_PORT_PREVIEW = 0, -+ MMAL_CAMERA_PORT_VIDEO, -+ MMAL_CAMERA_PORT_CAPTURE, -+ MMAL_CAMERA_PORT_COUNT -+}; -+ -+#define PREVIEW_LAYER 2 -+ -+extern int bcm2835_v4l2_debug; -+ -+struct bm2835_mmal_dev { -+ /* v4l2 devices */ -+ struct v4l2_device v4l2_dev; -+ struct video_device vdev; -+ struct mutex mutex; -+ -+ /* controls */ -+ struct v4l2_ctrl_handler ctrl_handler; -+ struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT]; -+ enum v4l2_scene_mode scene_mode; -+ struct mmal_colourfx colourfx; -+ int hflip; -+ int vflip; -+ int red_gain; -+ int blue_gain; -+ enum mmal_parameter_exposuremode exposure_mode_user; -+ enum v4l2_exposure_auto_type exposure_mode_v4l2_user; -+ /* active exposure mode may differ if selected via a scene mode */ -+ enum mmal_parameter_exposuremode exposure_mode_active; -+ enum mmal_parameter_exposuremeteringmode metering_mode; -+ unsigned int manual_shutter_speed; -+ bool exp_auto_priority; -+ bool manual_iso_enabled; -+ uint32_t iso; -+ -+ /* allocated mmal instance and components */ -+ struct vchiq_mmal_instance *instance; -+ struct vchiq_mmal_component *component[MMAL_COMPONENT_COUNT]; -+ int camera_use_count; -+ -+ struct v4l2_window overlay; -+ -+ struct { -+ unsigned int width; /* width */ -+ unsigned int height; /* height */ -+ unsigned int stride; /* stride */ -+ unsigned int buffersize; /* buffer size with padding */ -+ struct mmal_fmt *fmt; -+ struct v4l2_fract timeperframe; -+ -+ /* H264 encode bitrate */ -+ int encode_bitrate; -+ /* H264 bitrate mode. CBR/VBR */ -+ int encode_bitrate_mode; -+ /* H264 profile */ -+ enum v4l2_mpeg_video_h264_profile enc_profile; -+ /* H264 level */ -+ enum v4l2_mpeg_video_h264_level enc_level; -+ /* JPEG Q-factor */ -+ int q_factor; -+ -+ struct vb2_queue vb_vidq; -+ -+ /* VC start timestamp for streaming */ -+ s64 vc_start_timestamp; -+ /* Kernel start timestamp for streaming */ -+ struct timeval kernel_start_ts; -+ -+ struct vchiq_mmal_port *port; /* port being used for capture */ -+ /* camera port being used for capture */ -+ struct vchiq_mmal_port *camera_port; -+ /* component being used for encode */ -+ struct vchiq_mmal_component *encode_component; -+ /* number of frames remaining which driver should capture */ -+ unsigned int frame_count; -+ /* last frame completion */ -+ struct completion frame_cmplt; -+ -+ } capture; -+ -+ unsigned int camera_num; -+ unsigned int max_width; -+ unsigned int max_height; -+ unsigned int rgb_bgr_swapped; -+}; -+ -+int bm2835_mmal_init_controls( -+ struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl_handler *hdl); -+ -+int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev); -+int set_framerate_params(struct bm2835_mmal_dev *dev); -+ -+/* Debug helpers */ -+ -+#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \ -+{ \ -+ v4l2_dbg(level, debug, dev, \ -+"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \ -+ desc == NULL ? "" : desc, \ -+ (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field, \ -+ (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \ -+ (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \ -+} -+#define v4l2_dump_win_format(level, debug, dev, win_fmt, desc) \ -+{ \ -+ v4l2_dbg(level, debug, dev, \ -+"%s: w %u h %u l %u t %u field %u chromakey %06X clip %p " \ -+"clipcount %u bitmap %p\n", \ -+ desc == NULL ? "" : desc, \ -+ (win_fmt)->w.width, (win_fmt)->w.height, \ -+ (win_fmt)->w.left, (win_fmt)->w.top, \ -+ (win_fmt)->field, \ -+ (win_fmt)->chromakey, \ -+ (win_fmt)->clips, (win_fmt)->clipcount, \ -+ (win_fmt)->bitmap); \ -+} -diff --git a/drivers/media/platform/bcm2835/controls.c b/drivers/media/platform/bcm2835/controls.c -new file mode 100644 -index 0000000000000000000000000000000000000000..fe61330ba2a64f850ff3e4930ff813f648889804 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/controls.c -@@ -0,0 +1,1345 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mmal-common.h" -+#include "mmal-vchiq.h" -+#include "mmal-parameters.h" -+#include "bcm2835-camera.h" -+ -+/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -4.0 to +4.0. -+ * MMAL values are in 1/6th increments so the MMAL range is -24 to +24. -+ * V4L2 docs say value "is expressed in terms of EV, drivers should interpret -+ * the values as 0.001 EV units, where the value 1000 stands for +1 EV." -+ * V4L2 is limited to a max of 32 values in a menu, so count in 1/3rds from -+ * -4 to +4 -+ */ -+static const s64 ev_bias_qmenu[] = { -+ -4000, -3667, -3333, -+ -3000, -2667, -2333, -+ -2000, -1667, -1333, -+ -1000, -667, -333, -+ 0, 333, 667, -+ 1000, 1333, 1667, -+ 2000, 2333, 2667, -+ 3000, 3333, 3667, -+ 4000 -+}; -+ -+/* Supported ISO values (*1000) -+ * ISOO = auto ISO -+ */ -+static const s64 iso_qmenu[] = { -+ 0, 100000, 200000, 400000, 800000, -+}; -+static const uint32_t iso_values[] = { -+ 0, 100, 200, 400, 800, -+}; -+ -+static const s64 mains_freq_qmenu[] = { -+ V4L2_CID_POWER_LINE_FREQUENCY_DISABLED, -+ V4L2_CID_POWER_LINE_FREQUENCY_50HZ, -+ V4L2_CID_POWER_LINE_FREQUENCY_60HZ, -+ V4L2_CID_POWER_LINE_FREQUENCY_AUTO -+}; -+ -+/* Supported video encode modes */ -+static const s64 bitrate_mode_qmenu[] = { -+ (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, -+ (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, -+}; -+ -+enum bm2835_mmal_ctrl_type { -+ MMAL_CONTROL_TYPE_STD, -+ MMAL_CONTROL_TYPE_STD_MENU, -+ MMAL_CONTROL_TYPE_INT_MENU, -+ MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */ -+}; -+ -+struct bm2835_mmal_v4l2_ctrl; -+ -+typedef int(bm2835_mmal_v4l2_ctrl_cb)( -+ struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl); -+ -+struct bm2835_mmal_v4l2_ctrl { -+ u32 id; /* v4l2 control identifier */ -+ enum bm2835_mmal_ctrl_type type; -+ /* control minimum value or -+ * mask for MMAL_CONTROL_TYPE_STD_MENU */ -+ s32 min; -+ s32 max; /* maximum value of control */ -+ s32 def; /* default value of control */ -+ s32 step; /* step size of the control */ -+ const s64 *imenu; /* integer menu array */ -+ u32 mmal_id; /* mmal parameter id */ -+ bm2835_mmal_v4l2_ctrl_cb *setter; -+ bool ignore_errors; -+}; -+ -+struct v4l2_to_mmal_effects_setting { -+ u32 v4l2_effect; -+ u32 mmal_effect; -+ s32 col_fx_enable; -+ s32 col_fx_fixed_cbcr; -+ u32 u; -+ u32 v; -+ u32 num_effect_params; -+ u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS]; -+}; -+ -+static const struct v4l2_to_mmal_effects_setting -+ v4l2_to_mmal_effects_values[] = { -+ { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE, -+ 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE, -+ 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE, -+ 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM, -+ 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, -+ { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE, -+ 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} }, -+ { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE, -+ 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} }, -+ { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE, -+ 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} } -+}; -+ -+struct v4l2_mmal_scene_config { -+ enum v4l2_scene_mode v4l2_scene; -+ enum mmal_parameter_exposuremode exposure_mode; -+ enum mmal_parameter_exposuremeteringmode metering_mode; -+}; -+ -+static const struct v4l2_mmal_scene_config scene_configs[] = { -+ /* V4L2_SCENE_MODE_NONE automatically added */ -+ { -+ V4L2_SCENE_MODE_NIGHT, -+ MMAL_PARAM_EXPOSUREMODE_NIGHT, -+ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE -+ }, -+ { -+ V4L2_SCENE_MODE_SPORTS, -+ MMAL_PARAM_EXPOSUREMODE_SPORTS, -+ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE -+ }, -+}; -+ -+/* control handlers*/ -+ -+static int ctrl_set_rational(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ struct mmal_parameter_rational rational_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ rational_value.num = ctrl->val; -+ rational_value.den = 100; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &rational_value, -+ sizeof(rational_value)); -+} -+ -+static int ctrl_set_value(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ u32_value = ctrl->val; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_iso(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *control; -+ -+ if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min) -+ return 1; -+ -+ if (ctrl->id == V4L2_CID_ISO_SENSITIVITY) -+ dev->iso = iso_values[ctrl->val]; -+ else if (ctrl->id == V4L2_CID_ISO_SENSITIVITY_AUTO) -+ dev->manual_iso_enabled = -+ (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL ? -+ true : -+ false); -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ if (dev->manual_iso_enabled) -+ u32_value = dev->iso; -+ else -+ u32_value = 0; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_ISO, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_value_ev(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ s32 s32_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ s32_value = (ctrl->val-12)*2; /* Convert from index to 1/6ths */ -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &s32_value, sizeof(s32_value)); -+} -+ -+static int ctrl_set_rotate(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret; -+ u32 u32_value; -+ struct vchiq_mmal_component *camera; -+ -+ camera = dev->component[MMAL_COMPONENT_CAMERA]; -+ -+ u32_value = ((ctrl->val % 360) / 90) * 90; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ if (ret < 0) -+ return ret; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ if (ret < 0) -+ return ret; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ -+ return ret; -+} -+ -+static int ctrl_set_flip(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret; -+ u32 u32_value; -+ struct vchiq_mmal_component *camera; -+ -+ if (ctrl->id == V4L2_CID_HFLIP) -+ dev->hflip = ctrl->val; -+ else -+ dev->vflip = ctrl->val; -+ -+ camera = dev->component[MMAL_COMPONENT_CAMERA]; -+ -+ if (dev->hflip && dev->vflip) -+ u32_value = MMAL_PARAM_MIRROR_BOTH; -+ else if (dev->hflip) -+ u32_value = MMAL_PARAM_MIRROR_HORIZONTAL; -+ else if (dev->vflip) -+ u32_value = MMAL_PARAM_MIRROR_VERTICAL; -+ else -+ u32_value = MMAL_PARAM_MIRROR_NONE; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ if (ret < 0) -+ return ret; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ if (ret < 0) -+ return ret; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ -+ return ret; -+ -+} -+ -+static int ctrl_set_exposure(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user; -+ u32 shutter_speed = 0; -+ struct vchiq_mmal_port *control; -+ int ret = 0; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) { -+ /* V4L2 is in 100usec increments. -+ * MMAL is 1usec. -+ */ -+ dev->manual_shutter_speed = ctrl->val * 100; -+ } else if (mmal_ctrl->mmal_id == MMAL_PARAMETER_EXPOSURE_MODE) { -+ switch (ctrl->val) { -+ case V4L2_EXPOSURE_AUTO: -+ exp_mode = MMAL_PARAM_EXPOSUREMODE_AUTO; -+ break; -+ -+ case V4L2_EXPOSURE_MANUAL: -+ exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF; -+ break; -+ } -+ dev->exposure_mode_user = exp_mode; -+ dev->exposure_mode_v4l2_user = ctrl->val; -+ } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) { -+ dev->exp_auto_priority = ctrl->val; -+ } -+ -+ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { -+ if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF) -+ shutter_speed = dev->manual_shutter_speed; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_SHUTTER_SPEED, -+ &shutter_speed, -+ sizeof(shutter_speed)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &exp_mode, -+ sizeof(u32)); -+ dev->exposure_mode_active = exp_mode; -+ } -+ /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should -+ * always apply irrespective of scene mode. -+ */ -+ ret += set_framerate_params(dev); -+ -+ return ret; -+} -+ -+static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ switch (ctrl->val) { -+ case V4L2_EXPOSURE_METERING_AVERAGE: -+ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; -+ break; -+ -+ case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: -+ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; -+ break; -+ -+ case V4L2_EXPOSURE_METERING_SPOT: -+ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT; -+ break; -+ -+ /* todo matrix weighting not added to Linux API till 3.9 -+ case V4L2_EXPOSURE_METERING_MATRIX: -+ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; -+ break; -+ */ -+ -+ } -+ -+ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { -+ struct vchiq_mmal_port *control; -+ u32 u32_value = dev->metering_mode; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+ } else -+ return 0; -+} -+ -+static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ switch (ctrl->val) { -+ case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED: -+ u32_value = MMAL_PARAM_FLICKERAVOID_OFF; -+ break; -+ case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: -+ u32_value = MMAL_PARAM_FLICKERAVOID_50HZ; -+ break; -+ case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: -+ u32_value = MMAL_PARAM_FLICKERAVOID_60HZ; -+ break; -+ case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: -+ u32_value = MMAL_PARAM_FLICKERAVOID_AUTO; -+ break; -+ } -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ switch (ctrl->val) { -+ case V4L2_WHITE_BALANCE_MANUAL: -+ u32_value = MMAL_PARAM_AWBMODE_OFF; -+ break; -+ -+ case V4L2_WHITE_BALANCE_AUTO: -+ u32_value = MMAL_PARAM_AWBMODE_AUTO; -+ break; -+ -+ case V4L2_WHITE_BALANCE_INCANDESCENT: -+ u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT; -+ break; -+ -+ case V4L2_WHITE_BALANCE_FLUORESCENT: -+ u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT; -+ break; -+ -+ case V4L2_WHITE_BALANCE_FLUORESCENT_H: -+ u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN; -+ break; -+ -+ case V4L2_WHITE_BALANCE_HORIZON: -+ u32_value = MMAL_PARAM_AWBMODE_HORIZON; -+ break; -+ -+ case V4L2_WHITE_BALANCE_DAYLIGHT: -+ u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT; -+ break; -+ -+ case V4L2_WHITE_BALANCE_FLASH: -+ u32_value = MMAL_PARAM_AWBMODE_FLASH; -+ break; -+ -+ case V4L2_WHITE_BALANCE_CLOUDY: -+ u32_value = MMAL_PARAM_AWBMODE_CLOUDY; -+ break; -+ -+ case V4L2_WHITE_BALANCE_SHADE: -+ u32_value = MMAL_PARAM_AWBMODE_SHADE; -+ break; -+ -+ } -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_awb_gains(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ struct vchiq_mmal_port *control; -+ struct mmal_parameter_awbgains gains; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ if (ctrl->id == V4L2_CID_RED_BALANCE) -+ dev->red_gain = ctrl->val; -+ else if (ctrl->id == V4L2_CID_BLUE_BALANCE) -+ dev->blue_gain = ctrl->val; -+ -+ gains.r_gain.num = dev->red_gain; -+ gains.b_gain.num = dev->blue_gain; -+ gains.r_gain.den = gains.b_gain.den = 1000; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, control, -+ mmal_ctrl->mmal_id, -+ &gains, sizeof(gains)); -+} -+ -+static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret = -EINVAL; -+ int i, j; -+ struct vchiq_mmal_port *control; -+ struct mmal_parameter_imagefx_parameters imagefx; -+ -+ for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) { -+ if (ctrl->val == v4l2_to_mmal_effects_values[i].v4l2_effect) { -+ -+ imagefx.effect = -+ v4l2_to_mmal_effects_values[i].mmal_effect; -+ imagefx.num_effect_params = -+ v4l2_to_mmal_effects_values[i].num_effect_params; -+ -+ if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS) -+ imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS; -+ -+ for (j = 0; j < imagefx.num_effect_params; j++) -+ imagefx.effect_parameter[j] = -+ v4l2_to_mmal_effects_values[i].effect_params[j]; -+ -+ dev->colourfx.enable = -+ v4l2_to_mmal_effects_values[i].col_fx_enable; -+ if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) { -+ dev->colourfx.u = -+ v4l2_to_mmal_effects_values[i].u; -+ dev->colourfx.v = -+ v4l2_to_mmal_effects_values[i].v; -+ } -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ ret = vchiq_mmal_port_parameter_set( -+ dev->instance, control, -+ MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, -+ &imagefx, sizeof(imagefx)); -+ if (ret) -+ goto exit; -+ -+ ret = vchiq_mmal_port_parameter_set( -+ dev->instance, control, -+ MMAL_PARAMETER_COLOUR_EFFECT, -+ &dev->colourfx, sizeof(dev->colourfx)); -+ } -+ } -+ -+exit: -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n", -+ mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect, -+ dev->colourfx.enable ? "true" : "false", -+ dev->colourfx.u, dev->colourfx.v, -+ ret, (ret == 0 ? 0 : -EINVAL)); -+ return (ret == 0 ? 0 : EINVAL); -+} -+ -+static int ctrl_set_colfx(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret = -EINVAL; -+ struct vchiq_mmal_port *control; -+ -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ dev->colourfx.enable = (ctrl->val & 0xff00) >> 8; -+ dev->colourfx.enable = ctrl->val & 0xff; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_COLOUR_EFFECT, -+ &dev->colourfx, sizeof(dev->colourfx)); -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n", -+ __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, -+ (ret == 0 ? 0 : -EINVAL)); -+ return (ret == 0 ? 0 : EINVAL); -+} -+ -+static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret; -+ struct vchiq_mmal_port *encoder_out; -+ -+ dev->capture.encode_bitrate = ctrl->val; -+ -+ encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out, -+ mmal_ctrl->mmal_id, -+ &ctrl->val, sizeof(ctrl->val)); -+ ret = 0; -+ return ret; -+} -+ -+static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 bitrate_mode; -+ struct vchiq_mmal_port *encoder_out; -+ -+ encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; -+ -+ dev->capture.encode_bitrate_mode = ctrl->val; -+ switch (ctrl->val) { -+ default: -+ case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR: -+ bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE; -+ break; -+ case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR: -+ bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT; -+ break; -+ } -+ -+ vchiq_mmal_port_parameter_set(dev->instance, encoder_out, -+ mmal_ctrl->mmal_id, -+ &bitrate_mode, -+ sizeof(bitrate_mode)); -+ return 0; -+} -+ -+static int ctrl_set_image_encode_output(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *jpeg_out; -+ -+ jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0]; -+ -+ u32_value = ctrl->val; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_video_encode_param_output(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ u32 u32_value; -+ struct vchiq_mmal_port *vid_enc_ctl; -+ -+ vid_enc_ctl = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0]; -+ -+ u32_value = ctrl->val; -+ -+ return vchiq_mmal_port_parameter_set(dev->instance, vid_enc_ctl, -+ mmal_ctrl->mmal_id, -+ &u32_value, sizeof(u32_value)); -+} -+ -+static int ctrl_set_video_encode_profile_level(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ struct mmal_parameter_video_profile param; -+ int ret = 0; -+ -+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) { -+ switch (ctrl->val) { -+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: -+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: -+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: -+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: -+ dev->capture.enc_profile = ctrl->val; -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) { -+ switch (ctrl->val) { -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1B: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: -+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: -+ dev->capture.enc_level = ctrl->val; -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ } -+ -+ if (!ret) { -+ switch (dev->capture.enc_profile) { -+ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: -+ param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE; -+ break; -+ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: -+ param.profile = -+ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE; -+ break; -+ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: -+ param.profile = MMAL_VIDEO_PROFILE_H264_MAIN; -+ break; -+ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: -+ param.profile = MMAL_VIDEO_PROFILE_H264_HIGH; -+ break; -+ default: -+ /* Should never get here */ -+ break; -+ } -+ -+ switch (dev->capture.enc_level) { -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: -+ param.level = MMAL_VIDEO_LEVEL_H264_1; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1B: -+ param.level = MMAL_VIDEO_LEVEL_H264_1b; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: -+ param.level = MMAL_VIDEO_LEVEL_H264_11; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: -+ param.level = MMAL_VIDEO_LEVEL_H264_12; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: -+ param.level = MMAL_VIDEO_LEVEL_H264_13; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: -+ param.level = MMAL_VIDEO_LEVEL_H264_2; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: -+ param.level = MMAL_VIDEO_LEVEL_H264_21; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: -+ param.level = MMAL_VIDEO_LEVEL_H264_22; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: -+ param.level = MMAL_VIDEO_LEVEL_H264_3; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: -+ param.level = MMAL_VIDEO_LEVEL_H264_31; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: -+ param.level = MMAL_VIDEO_LEVEL_H264_32; -+ break; -+ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: -+ param.level = MMAL_VIDEO_LEVEL_H264_4; -+ break; -+ default: -+ /* Should never get here */ -+ break; -+ } -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0], -+ mmal_ctrl->mmal_id, -+ ¶m, sizeof(param)); -+ } -+ return ret; -+} -+ -+static int ctrl_set_scene_mode(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl *ctrl, -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl) -+{ -+ int ret = 0; -+ int shutter_speed; -+ struct vchiq_mmal_port *control; -+ -+ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "scene mode selected %d, was %d\n", ctrl->val, -+ dev->scene_mode); -+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control; -+ -+ if (ctrl->val == dev->scene_mode) -+ return 0; -+ -+ if (ctrl->val == V4L2_SCENE_MODE_NONE) { -+ /* Restore all user selections */ -+ dev->scene_mode = V4L2_SCENE_MODE_NONE; -+ -+ if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF) -+ shutter_speed = dev->manual_shutter_speed; -+ else -+ shutter_speed = 0; -+ -+ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", -+ __func__, shutter_speed, dev->exposure_mode_user, -+ dev->metering_mode); -+ ret = vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_SHUTTER_SPEED, -+ &shutter_speed, -+ sizeof(shutter_speed)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &dev->exposure_mode_user, -+ sizeof(u32)); -+ dev->exposure_mode_active = dev->exposure_mode_user; -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_EXP_METERING_MODE, -+ &dev->metering_mode, -+ sizeof(u32)); -+ ret += set_framerate_params(dev); -+ } else { -+ /* Set up scene mode */ -+ int i; -+ const struct v4l2_mmal_scene_config *scene = NULL; -+ int shutter_speed; -+ enum mmal_parameter_exposuremode exposure_mode; -+ enum mmal_parameter_exposuremeteringmode metering_mode; -+ -+ for (i = 0; i < ARRAY_SIZE(scene_configs); i++) { -+ if (scene_configs[i].v4l2_scene == -+ ctrl->val) { -+ scene = &scene_configs[i]; -+ break; -+ } -+ } -+ if (!scene) -+ return -EINVAL; -+ if (i >= ARRAY_SIZE(scene_configs)) -+ return -EINVAL; -+ -+ /* Set all the values */ -+ dev->scene_mode = ctrl->val; -+ -+ if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF) -+ shutter_speed = dev->manual_shutter_speed; -+ else -+ shutter_speed = 0; -+ exposure_mode = scene->exposure_mode; -+ metering_mode = scene->metering_mode; -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", -+ __func__, shutter_speed, exposure_mode, metering_mode); -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_SHUTTER_SPEED, -+ &shutter_speed, -+ sizeof(shutter_speed)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ control, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &exposure_mode, -+ sizeof(u32)); -+ dev->exposure_mode_active = exposure_mode; -+ ret += vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &exposure_mode, -+ sizeof(u32)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, control, -+ MMAL_PARAMETER_EXP_METERING_MODE, -+ &metering_mode, -+ sizeof(u32)); -+ ret += set_framerate_params(dev); -+ } -+ if (ret) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "%s: Setting scene to %d, ret=%d\n", -+ __func__, ctrl->val, ret); -+ ret = -EINVAL; -+ } -+ return 0; -+} -+ -+static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl) -+{ -+ struct bm2835_mmal_dev *dev = -+ container_of(ctrl->handler, struct bm2835_mmal_dev, -+ ctrl_handler); -+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv; -+ int ret; -+ -+ if ((mmal_ctrl == NULL) || -+ (mmal_ctrl->id != ctrl->id) || -+ (mmal_ctrl->setter == NULL)) { -+ pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id); -+ return -EINVAL; -+ } -+ -+ ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl); -+ if (ret) -+ pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n", -+ ctrl->id, mmal_ctrl->mmal_id, ret); -+ if (mmal_ctrl->ignore_errors) -+ ret = 0; -+ return ret; -+} -+ -+static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = { -+ .s_ctrl = bm2835_mmal_s_ctrl, -+}; -+ -+ -+ -+static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = { -+ { -+ V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD, -+ -100, 100, 0, 1, NULL, -+ MMAL_PARAMETER_SATURATION, -+ &ctrl_set_rational, -+ false -+ }, -+ { -+ V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD, -+ -100, 100, 0, 1, NULL, -+ MMAL_PARAMETER_SHARPNESS, -+ &ctrl_set_rational, -+ false -+ }, -+ { -+ V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD, -+ -100, 100, 0, 1, NULL, -+ MMAL_PARAMETER_CONTRAST, -+ &ctrl_set_rational, -+ false -+ }, -+ { -+ V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD, -+ 0, 100, 50, 1, NULL, -+ MMAL_PARAMETER_BRIGHTNESS, -+ &ctrl_set_rational, -+ false -+ }, -+ { -+ V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU, -+ 0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu, -+ MMAL_PARAMETER_ISO, -+ &ctrl_set_iso, -+ false -+ }, -+ { -+ V4L2_CID_ISO_SENSITIVITY_AUTO, MMAL_CONTROL_TYPE_STD_MENU, -+ 0, 1, V4L2_ISO_SENSITIVITY_AUTO, 1, NULL, -+ MMAL_PARAMETER_ISO, -+ &ctrl_set_iso, -+ false -+ }, -+ { -+ V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD, -+ 0, 1, 0, 1, NULL, -+ MMAL_PARAMETER_VIDEO_STABILISATION, -+ &ctrl_set_value, -+ false -+ }, -+/* { -+ 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL -+ }, */ -+ { -+ V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU, -+ ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL, -+ MMAL_PARAMETER_EXPOSURE_MODE, -+ &ctrl_set_exposure, -+ false -+ }, -+/* todo this needs mixing in with set exposure -+ { -+ V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU, -+ }, -+ */ -+ { -+ V4L2_CID_EXPOSURE_ABSOLUTE, MMAL_CONTROL_TYPE_STD, -+ /* Units of 100usecs */ -+ 1, 1*1000*10, 100*10, 1, NULL, -+ MMAL_PARAMETER_SHUTTER_SPEED, -+ &ctrl_set_exposure, -+ false -+ }, -+ { -+ V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU, -+ 0, ARRAY_SIZE(ev_bias_qmenu) - 1, -+ (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu, -+ MMAL_PARAMETER_EXPOSURE_COMP, -+ &ctrl_set_value_ev, -+ false -+ }, -+ { -+ V4L2_CID_EXPOSURE_AUTO_PRIORITY, MMAL_CONTROL_TYPE_STD, -+ 0, 1, -+ 0, 1, NULL, -+ 0, /* Dummy MMAL ID as it gets mapped into FPS range*/ -+ &ctrl_set_exposure, -+ false -+ }, -+ { -+ V4L2_CID_EXPOSURE_METERING, -+ MMAL_CONTROL_TYPE_STD_MENU, -+ ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL, -+ MMAL_PARAMETER_EXP_METERING_MODE, -+ &ctrl_set_metering_mode, -+ false -+ }, -+ { -+ V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, -+ MMAL_CONTROL_TYPE_STD_MENU, -+ ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL, -+ MMAL_PARAMETER_AWB_MODE, -+ &ctrl_set_awb_mode, -+ false -+ }, -+ { -+ V4L2_CID_RED_BALANCE, MMAL_CONTROL_TYPE_STD, -+ 1, 7999, 1000, 1, NULL, -+ MMAL_PARAMETER_CUSTOM_AWB_GAINS, -+ &ctrl_set_awb_gains, -+ false -+ }, -+ { -+ V4L2_CID_BLUE_BALANCE, MMAL_CONTROL_TYPE_STD, -+ 1, 7999, 1000, 1, NULL, -+ MMAL_PARAMETER_CUSTOM_AWB_GAINS, -+ &ctrl_set_awb_gains, -+ false -+ }, -+ { -+ V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU, -+ 0, 15, V4L2_COLORFX_NONE, 0, NULL, -+ MMAL_PARAMETER_IMAGE_EFFECT, -+ &ctrl_set_image_effect, -+ false -+ }, -+ { -+ V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD, -+ 0, 0xffff, 0x8080, 1, NULL, -+ MMAL_PARAMETER_COLOUR_EFFECT, -+ &ctrl_set_colfx, -+ false -+ }, -+ { -+ V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD, -+ 0, 360, 0, 90, NULL, -+ MMAL_PARAMETER_ROTATION, -+ &ctrl_set_rotate, -+ false -+ }, -+ { -+ V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD, -+ 0, 1, 0, 1, NULL, -+ MMAL_PARAMETER_MIRROR, -+ &ctrl_set_flip, -+ false -+ }, -+ { -+ V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD, -+ 0, 1, 0, 1, NULL, -+ MMAL_PARAMETER_MIRROR, -+ &ctrl_set_flip, -+ false -+ }, -+ { -+ V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU, -+ 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1, -+ 0, 0, bitrate_mode_qmenu, -+ MMAL_PARAMETER_RATECONTROL, -+ &ctrl_set_bitrate_mode, -+ false -+ }, -+ { -+ V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD, -+ 25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL, -+ MMAL_PARAMETER_VIDEO_BIT_RATE, -+ &ctrl_set_bitrate, -+ false -+ }, -+ { -+ V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD, -+ 1, 100, -+ 30, 1, NULL, -+ MMAL_PARAMETER_JPEG_Q_FACTOR, -+ &ctrl_set_image_encode_output, -+ false -+ }, -+ { -+ V4L2_CID_POWER_LINE_FREQUENCY, MMAL_CONTROL_TYPE_STD_MENU, -+ 0, ARRAY_SIZE(mains_freq_qmenu) - 1, -+ 1, 1, NULL, -+ MMAL_PARAMETER_FLICKER_AVOID, -+ &ctrl_set_flicker_avoidance, -+ false -+ }, -+ { -+ V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, MMAL_CONTROL_TYPE_STD, -+ 0, 1, -+ 0, 1, NULL, -+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, -+ &ctrl_set_video_encode_param_output, -+ true /* Errors ignored as requires latest firmware to work */ -+ }, -+ { -+ V4L2_CID_MPEG_VIDEO_H264_PROFILE, -+ MMAL_CONTROL_TYPE_STD_MENU, -+ ~((1<ctrls[c]) && (v4l2_ctrls[c].setter)) { -+ ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c], -+ &v4l2_ctrls[c]); -+ if (!v4l2_ctrls[c].ignore_errors && ret) { -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Failed when setting default values for ctrl %d\n", -+ c); -+ break; -+ } -+ } -+ } -+ return ret; -+} -+ -+int set_framerate_params(struct bm2835_mmal_dev *dev) -+{ -+ struct mmal_parameter_fps_range fps_range; -+ int ret; -+ -+ if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) && -+ (dev->exp_auto_priority)) { -+ /* Variable FPS. Define min FPS as 1fps. -+ * Max as max defined FPS. -+ */ -+ fps_range.fps_low.num = 1; -+ fps_range.fps_low.den = 1; -+ fps_range.fps_high.num = dev->capture.timeperframe.denominator; -+ fps_range.fps_high.den = dev->capture.timeperframe.numerator; -+ } else { -+ /* Fixed FPS - set min and max to be the same */ -+ fps_range.fps_low.num = fps_range.fps_high.num = -+ dev->capture.timeperframe.denominator; -+ fps_range.fps_low.den = fps_range.fps_high.den = -+ dev->capture.timeperframe.numerator; -+ } -+ -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Set fps range to %d/%d to %d/%d\n", -+ fps_range.fps_low.num, -+ fps_range.fps_low.den, -+ fps_range.fps_high.num, -+ fps_range.fps_high.den -+ ); -+ -+ ret = vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_PREVIEW], -+ MMAL_PARAMETER_FPS_RANGE, -+ &fps_range, sizeof(fps_range)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_VIDEO], -+ MMAL_PARAMETER_FPS_RANGE, -+ &fps_range, sizeof(fps_range)); -+ ret += vchiq_mmal_port_parameter_set(dev->instance, -+ &dev->component[MMAL_COMPONENT_CAMERA]-> -+ output[MMAL_CAMERA_PORT_CAPTURE], -+ MMAL_PARAMETER_FPS_RANGE, -+ &fps_range, sizeof(fps_range)); -+ if (ret) -+ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Failed to set fps ret %d\n", -+ ret); -+ -+ return ret; -+ -+} -+ -+int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev, -+ struct v4l2_ctrl_handler *hdl) -+{ -+ int c; -+ const struct bm2835_mmal_v4l2_ctrl *ctrl; -+ -+ v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT); -+ -+ for (c = 0; c < V4L2_CTRL_COUNT; c++) { -+ ctrl = &v4l2_ctrls[c]; -+ -+ switch (ctrl->type) { -+ case MMAL_CONTROL_TYPE_STD: -+ dev->ctrls[c] = v4l2_ctrl_new_std(hdl, -+ &bm2835_mmal_ctrl_ops, ctrl->id, -+ ctrl->min, ctrl->max, ctrl->step, ctrl->def); -+ break; -+ -+ case MMAL_CONTROL_TYPE_STD_MENU: -+ { -+ int mask = ctrl->min; -+ -+ if (ctrl->id == V4L2_CID_SCENE_MODE) { -+ /* Special handling to work out the mask -+ * value based on the scene_configs array -+ * at runtime. Reduces the chance of -+ * mismatches. -+ */ -+ int i; -+ mask = 1<ctrls[c] = v4l2_ctrl_new_std_menu(hdl, -+ &bm2835_mmal_ctrl_ops, ctrl->id, -+ ctrl->max, mask, ctrl->def); -+ break; -+ } -+ -+ case MMAL_CONTROL_TYPE_INT_MENU: -+ dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl, -+ &bm2835_mmal_ctrl_ops, ctrl->id, -+ ctrl->max, ctrl->def, ctrl->imenu); -+ break; -+ -+ case MMAL_CONTROL_TYPE_CLUSTER: -+ /* skip this entry when constructing controls */ -+ continue; -+ } -+ -+ if (hdl->error) -+ break; -+ -+ dev->ctrls[c]->priv = (void *)ctrl; -+ } -+ -+ if (hdl->error) { -+ pr_err("error adding control %d/%d id 0x%x\n", c, -+ V4L2_CTRL_COUNT, ctrl->id); -+ return hdl->error; -+ } -+ -+ for (c = 0; c < V4L2_CTRL_COUNT; c++) { -+ ctrl = &v4l2_ctrls[c]; -+ -+ switch (ctrl->type) { -+ case MMAL_CONTROL_TYPE_CLUSTER: -+ v4l2_ctrl_auto_cluster(ctrl->min, -+ &dev->ctrls[c+1], -+ ctrl->max, -+ ctrl->def); -+ break; -+ -+ case MMAL_CONTROL_TYPE_STD: -+ case MMAL_CONTROL_TYPE_STD_MENU: -+ case MMAL_CONTROL_TYPE_INT_MENU: -+ break; -+ } -+ -+ } -+ -+ return 0; -+} -diff --git a/drivers/media/platform/bcm2835/mmal-common.h b/drivers/media/platform/bcm2835/mmal-common.h -new file mode 100644 -index 0000000000000000000000000000000000000000..840fd139e03315b5d9ac2d5742ab589bc6b17ade ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-common.h -@@ -0,0 +1,53 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ * -+ * MMAL structures -+ * -+ */ -+ -+#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24)) -+#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l') -+ -+/** Special value signalling that time is not known */ -+#define MMAL_TIME_UNKNOWN (1LL<<63) -+ -+/* mapping between v4l and mmal video modes */ -+struct mmal_fmt { -+ char *name; -+ u32 fourcc; /* v4l2 format id */ -+ int flags; /* v4l2 flags field */ -+ u32 mmal; -+ int depth; -+ u32 mmal_component; /* MMAL component index to be used to encode */ -+ u32 ybbp; /* depth of first Y plane for planar formats */ -+}; -+ -+/* buffer for one video frame */ -+struct mmal_buffer { -+ /* v4l buffer data -- must be first */ -+ struct vb2_v4l2_buffer vb; -+ -+ /* list of buffers available */ -+ struct list_head list; -+ -+ void *buffer; /* buffer pointer */ -+ unsigned long buffer_size; /* size of allocated buffer */ -+}; -+ -+/* */ -+struct mmal_colourfx { -+ s32 enable; -+ u32 u; -+ u32 v; -+}; -diff --git a/drivers/media/platform/bcm2835/mmal-encodings.h b/drivers/media/platform/bcm2835/mmal-encodings.h -new file mode 100644 -index 0000000000000000000000000000000000000000..024d620dc1dfda006a9d36dffeeec691faf24ac5 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-encodings.h -@@ -0,0 +1,127 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+#ifndef MMAL_ENCODINGS_H -+#define MMAL_ENCODINGS_H -+ -+#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4') -+#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3') -+#define MMAL_ENCODING_MP4V MMAL_FOURCC('M', 'P', '4', 'V') -+#define MMAL_ENCODING_MP2V MMAL_FOURCC('M', 'P', '2', 'V') -+#define MMAL_ENCODING_MP1V MMAL_FOURCC('M', 'P', '1', 'V') -+#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W', 'M', 'V', '3') -+#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W', 'M', 'V', '2') -+#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W', 'M', 'V', '1') -+#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W', 'V', 'C', '1') -+#define MMAL_ENCODING_VP8 MMAL_FOURCC('V', 'P', '8', ' ') -+#define MMAL_ENCODING_VP7 MMAL_FOURCC('V', 'P', '7', ' ') -+#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ') -+#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O') -+#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K') -+#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M', 'J', 'P', 'G') -+ -+#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G') -+#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ') -+#define MMAL_ENCODING_PNG MMAL_FOURCC('P', 'N', 'G', ' ') -+#define MMAL_ENCODING_PPM MMAL_FOURCC('P', 'P', 'M', ' ') -+#define MMAL_ENCODING_TGA MMAL_FOURCC('T', 'G', 'A', ' ') -+#define MMAL_ENCODING_BMP MMAL_FOURCC('B', 'M', 'P', ' ') -+ -+#define MMAL_ENCODING_I420 MMAL_FOURCC('I', '4', '2', '0') -+#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S', '4', '2', '0') -+#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y', 'V', '1', '2') -+#define MMAL_ENCODING_I422 MMAL_FOURCC('I', '4', '2', '2') -+#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S', '4', '2', '2') -+#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y', 'U', 'Y', 'V') -+#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y', 'V', 'Y', 'U') -+#define MMAL_ENCODING_UYVY MMAL_FOURCC('U', 'Y', 'V', 'Y') -+#define MMAL_ENCODING_VYUY MMAL_FOURCC('V', 'Y', 'U', 'Y') -+#define MMAL_ENCODING_NV12 MMAL_FOURCC('N', 'V', '1', '2') -+#define MMAL_ENCODING_NV21 MMAL_FOURCC('N', 'V', '2', '1') -+#define MMAL_ENCODING_ARGB MMAL_FOURCC('A', 'R', 'G', 'B') -+#define MMAL_ENCODING_RGBA MMAL_FOURCC('R', 'G', 'B', 'A') -+#define MMAL_ENCODING_ABGR MMAL_FOURCC('A', 'B', 'G', 'R') -+#define MMAL_ENCODING_BGRA MMAL_FOURCC('B', 'G', 'R', 'A') -+#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R', 'G', 'B', '2') -+#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R', 'G', 'B', '3') -+#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R', 'G', 'B', '4') -+#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B', 'G', 'R', '2') -+#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B', 'G', 'R', '3') -+#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B', 'G', 'R', '4') -+ -+/** SAND Video (YUVUV128) format, native format understood by VideoCore. -+ * This format is *not* opaque - if requested you will receive full frames -+ * of YUV_UV video. -+ */ -+#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D') -+ -+/** VideoCore opaque image format, image handles are returned to -+ * the host but not the actual image data. -+ */ -+#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V') -+ -+/** An EGL image handle -+ */ -+#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I') -+ -+/* }@ */ -+ -+/** \name Pre-defined audio encodings */ -+/* @{ */ -+#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'U') -+#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p', 'c', 'm', 'u') -+#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'S') -+#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p', 'c', 'm', 's') -+#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P', 'C', 'M', 'F') -+#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p', 'c', 'm', 'f') -+ -+/* Pre-defined H264 encoding variants */ -+ -+/** ISO 14496-10 Annex B byte stream format */ -+#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0 -+/** ISO 14496-15 AVC stream format */ -+#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1') -+/** Implicitly delineated NAL units without emulation prevention */ -+#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ') -+ -+ -+/** \defgroup MmalColorSpace List of pre-defined video color spaces -+ * This defines a list of common color spaces. This list isn't exhaustive and -+ * is only provided as a convenience to avoid clients having to use FourCC -+ * codes directly. However components are allowed to define and use their own -+ * FourCC codes. -+ */ -+/* @{ */ -+ -+/** Unknown color space */ -+#define MMAL_COLOR_SPACE_UNKNOWN 0 -+/** ITU-R BT.601-5 [SDTV] */ -+#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1') -+/** ITU-R BT.709-3 [HDTV] */ -+#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9') -+/** JPEG JFIF */ -+#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I') -+/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */ -+#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C') -+/** Society of Motion Picture and Television Engineers 240M (1999) */ -+#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0') -+/** ITU-R BT.470-2 System M */ -+#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M') -+/** ITU-R BT.470-2 System BG */ -+#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G') -+/** JPEG JFIF, but with 16..255 luma */ -+#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6') -+/* @} MmalColorSpace List */ -+ -+#endif /* MMAL_ENCODINGS_H */ -diff --git a/drivers/media/platform/bcm2835/mmal-msg-common.h b/drivers/media/platform/bcm2835/mmal-msg-common.h -new file mode 100644 -index 0000000000000000000000000000000000000000..66e8a6edf628565aeb487662b0b503c0c562ac8a ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-msg-common.h -@@ -0,0 +1,50 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+#ifndef MMAL_MSG_COMMON_H -+#define MMAL_MSG_COMMON_H -+ -+enum mmal_msg_status { -+ MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */ -+ MMAL_MSG_STATUS_ENOMEM, /**< Out of memory */ -+ MMAL_MSG_STATUS_ENOSPC, /**< Out of resources other than memory */ -+ MMAL_MSG_STATUS_EINVAL, /**< Argument is invalid */ -+ MMAL_MSG_STATUS_ENOSYS, /**< Function not implemented */ -+ MMAL_MSG_STATUS_ENOENT, /**< No such file or directory */ -+ MMAL_MSG_STATUS_ENXIO, /**< No such device or address */ -+ MMAL_MSG_STATUS_EIO, /**< I/O error */ -+ MMAL_MSG_STATUS_ESPIPE, /**< Illegal seek */ -+ MMAL_MSG_STATUS_ECORRUPT, /**< Data is corrupt \attention */ -+ MMAL_MSG_STATUS_ENOTREADY, /**< Component is not ready */ -+ MMAL_MSG_STATUS_ECONFIG, /**< Component is not configured */ -+ MMAL_MSG_STATUS_EISCONN, /**< Port is already connected */ -+ MMAL_MSG_STATUS_ENOTCONN, /**< Port is disconnected */ -+ MMAL_MSG_STATUS_EAGAIN, /**< Resource temporarily unavailable. */ -+ MMAL_MSG_STATUS_EFAULT, /**< Bad address */ -+}; -+ -+struct mmal_rect { -+ s32 x; /**< x coordinate (from left) */ -+ s32 y; /**< y coordinate (from top) */ -+ s32 width; /**< width */ -+ s32 height; /**< height */ -+}; -+ -+struct mmal_rational { -+ s32 num; /**< Numerator */ -+ s32 den; /**< Denominator */ -+}; -+ -+#endif /* MMAL_MSG_COMMON_H */ -diff --git a/drivers/media/platform/bcm2835/mmal-msg-format.h b/drivers/media/platform/bcm2835/mmal-msg-format.h -new file mode 100644 -index 0000000000000000000000000000000000000000..123d86ef582b0d059d1d5d14ba9add56b7365419 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-msg-format.h -@@ -0,0 +1,81 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+#ifndef MMAL_MSG_FORMAT_H -+#define MMAL_MSG_FORMAT_H -+ -+#include "mmal-msg-common.h" -+ -+/* MMAL_ES_FORMAT_T */ -+ -+ -+struct mmal_audio_format { -+ u32 channels; /**< Number of audio channels */ -+ u32 sample_rate; /**< Sample rate */ -+ -+ u32 bits_per_sample; /**< Bits per sample */ -+ u32 block_align; /**< Size of a block of data */ -+}; -+ -+struct mmal_video_format { -+ u32 width; /**< Width of frame in pixels */ -+ u32 height; /**< Height of frame in rows of pixels */ -+ struct mmal_rect crop; /**< Visible region of the frame */ -+ struct mmal_rational frame_rate; /**< Frame rate */ -+ struct mmal_rational par; /**< Pixel aspect ratio */ -+ -+ /* FourCC specifying the color space of the video stream. See the -+ * \ref MmalColorSpace "pre-defined color spaces" for some examples. -+ */ -+ u32 color_space; -+}; -+ -+struct mmal_subpicture_format { -+ u32 x_offset; -+ u32 y_offset; -+}; -+ -+union mmal_es_specific_format { -+ struct mmal_audio_format audio; -+ struct mmal_video_format video; -+ struct mmal_subpicture_format subpicture; -+}; -+ -+/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */ -+struct mmal_es_format { -+ u32 type; /* enum mmal_es_type */ -+ -+ u32 encoding; /* FourCC specifying encoding of the elementary stream.*/ -+ u32 encoding_variant; /* FourCC specifying the specific -+ * encoding variant of the elementary -+ * stream. -+ */ -+ -+ union mmal_es_specific_format *es; /* TODO: pointers in -+ * message serialisation?!? -+ */ -+ /* Type specific -+ * information for the -+ * elementary stream -+ */ -+ -+ u32 bitrate; /**< Bitrate in bits per second */ -+ u32 flags; /**< Flags describing properties of the elementary stream. */ -+ -+ u32 extradata_size; /**< Size of the codec specific data */ -+ u8 *extradata; /**< Codec specific data */ -+}; -+ -+#endif /* MMAL_MSG_FORMAT_H */ -diff --git a/drivers/media/platform/bcm2835/mmal-msg-port.h b/drivers/media/platform/bcm2835/mmal-msg-port.h -new file mode 100644 -index 0000000000000000000000000000000000000000..a55c1ea2eceb190689910a6a84370f126b1e9cbb ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-msg-port.h -@@ -0,0 +1,107 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+/* MMAL_PORT_TYPE_T */ -+enum mmal_port_type { -+ MMAL_PORT_TYPE_UNKNOWN = 0, /**< Unknown port type */ -+ MMAL_PORT_TYPE_CONTROL, /**< Control port */ -+ MMAL_PORT_TYPE_INPUT, /**< Input port */ -+ MMAL_PORT_TYPE_OUTPUT, /**< Output port */ -+ MMAL_PORT_TYPE_CLOCK, /**< Clock port */ -+}; -+ -+/** The port is pass-through and doesn't need buffer headers allocated */ -+#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01 -+/** The port wants to allocate the buffer payloads. -+ * This signals a preference that payload allocation should be done -+ * on this port for efficiency reasons. */ -+#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02 -+/** The port supports format change events. -+ * This applies to input ports and is used to let the client know -+ * whether the port supports being reconfigured via a format -+ * change event (i.e. without having to disable the port). */ -+#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04 -+ -+/* mmal port structure (MMAL_PORT_T) -+ * -+ * most elements are informational only, the pointer values for -+ * interogation messages are generally provided as additional -+ * strucures within the message. When used to set values only teh -+ * buffer_num, buffer_size and userdata parameters are writable. -+ */ -+struct mmal_port { -+ void *priv; /* Private member used by the framework */ -+ const char *name; /* Port name. Used for debugging purposes (RO) */ -+ -+ u32 type; /* Type of the port (RO) enum mmal_port_type */ -+ u16 index; /* Index of the port in its type list (RO) */ -+ u16 index_all; /* Index of the port in the list of all ports (RO) */ -+ -+ u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */ -+ struct mmal_es_format *format; /* Format of the elementary stream */ -+ -+ u32 buffer_num_min; /* Minimum number of buffers the port -+ * requires (RO). This is set by the -+ * component. -+ */ -+ -+ u32 buffer_size_min; /* Minimum size of buffers the port -+ * requires (RO). This is set by the -+ * component. -+ */ -+ -+ u32 buffer_alignment_min; /* Minimum alignment requirement for -+ * the buffers (RO). A value of -+ * zero means no special alignment -+ * requirements. This is set by the -+ * component. -+ */ -+ -+ u32 buffer_num_recommended; /* Number of buffers the port -+ * recommends for optimal -+ * performance (RO). A value of -+ * zero means no special -+ * recommendation. This is set -+ * by the component. -+ */ -+ -+ u32 buffer_size_recommended; /* Size of buffers the port -+ * recommends for optimal -+ * performance (RO). A value of -+ * zero means no special -+ * recommendation. This is set -+ * by the component. -+ */ -+ -+ u32 buffer_num; /* Actual number of buffers the port will use. -+ * This is set by the client. -+ */ -+ -+ u32 buffer_size; /* Actual maximum size of the buffers that -+ * will be sent to the port. This is set by -+ * the client. -+ */ -+ -+ void *component; /* Component this port belongs to (Read Only) */ -+ -+ void *userdata; /* Field reserved for use by the client */ -+ -+ u32 capabilities; /* Flags describing the capabilities of a -+ * port (RO). Bitwise combination of \ref -+ * portcapabilities "Port capabilities" -+ * values. -+ */ -+ -+}; -diff --git a/drivers/media/platform/bcm2835/mmal-msg.h b/drivers/media/platform/bcm2835/mmal-msg.h -new file mode 100644 -index 0000000000000000000000000000000000000000..67b1076015a54646eb0a3b956afdc97e75d2a39c ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-msg.h -@@ -0,0 +1,404 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+/* all the data structures which serialise the MMAL protocol. note -+ * these are directly mapped onto the recived message data. -+ * -+ * BEWARE: They seem to *assume* pointers are u32 and that there is no -+ * structure padding! -+ * -+ * NOTE: this implementation uses kernel types to ensure sizes. Rather -+ * than assigning values to enums to force their size the -+ * implementation uses fixed size types and not the enums (though the -+ * comments have the actual enum type -+ */ -+ -+#define VC_MMAL_VER 15 -+#define VC_MMAL_MIN_VER 10 -+#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal") -+ -+/* max total message size is 512 bytes */ -+#define MMAL_MSG_MAX_SIZE 512 -+/* with six 32bit header elements max payload is therefore 488 bytes */ -+#define MMAL_MSG_MAX_PAYLOAD 488 -+ -+#include "mmal-msg-common.h" -+#include "mmal-msg-format.h" -+#include "mmal-msg-port.h" -+ -+enum mmal_msg_type { -+ MMAL_MSG_TYPE_QUIT = 1, -+ MMAL_MSG_TYPE_SERVICE_CLOSED, -+ MMAL_MSG_TYPE_GET_VERSION, -+ MMAL_MSG_TYPE_COMPONENT_CREATE, -+ MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */ -+ MMAL_MSG_TYPE_COMPONENT_ENABLE, -+ MMAL_MSG_TYPE_COMPONENT_DISABLE, -+ MMAL_MSG_TYPE_PORT_INFO_GET, -+ MMAL_MSG_TYPE_PORT_INFO_SET, -+ MMAL_MSG_TYPE_PORT_ACTION, /* 10 */ -+ MMAL_MSG_TYPE_BUFFER_FROM_HOST, -+ MMAL_MSG_TYPE_BUFFER_TO_HOST, -+ MMAL_MSG_TYPE_GET_STATS, -+ MMAL_MSG_TYPE_PORT_PARAMETER_SET, -+ MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */ -+ MMAL_MSG_TYPE_EVENT_TO_HOST, -+ MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT, -+ MMAL_MSG_TYPE_OPAQUE_ALLOCATOR, -+ MMAL_MSG_TYPE_CONSUME_MEM, -+ MMAL_MSG_TYPE_LMK, /* 20 */ -+ MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC, -+ MMAL_MSG_TYPE_DRM_GET_LHS32, -+ MMAL_MSG_TYPE_DRM_GET_TIME, -+ MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN, -+ MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */ -+ MMAL_MSG_TYPE_HOST_LOG, -+ MMAL_MSG_TYPE_MSG_LAST -+}; -+ -+/* port action request messages differ depending on the action type */ -+enum mmal_msg_port_action_type { -+ MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0, /* Unkown action */ -+ MMAL_MSG_PORT_ACTION_TYPE_ENABLE, /* Enable a port */ -+ MMAL_MSG_PORT_ACTION_TYPE_DISABLE, /* Disable a port */ -+ MMAL_MSG_PORT_ACTION_TYPE_FLUSH, /* Flush a port */ -+ MMAL_MSG_PORT_ACTION_TYPE_CONNECT, /* Connect ports */ -+ MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, /* Disconnect ports */ -+ MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/ -+}; -+ -+struct mmal_msg_header { -+ u32 magic; -+ u32 type; /** enum mmal_msg_type */ -+ -+ /* Opaque handle to the control service */ -+ struct mmal_control_service *control_service; -+ -+ struct mmal_msg_context *context; /** a u32 per message context */ -+ u32 status; /** The status of the vchiq operation */ -+ u32 padding; -+}; -+ -+/* Send from VC to host to report version */ -+struct mmal_msg_version { -+ u32 flags; -+ u32 major; -+ u32 minor; -+ u32 minimum; -+}; -+ -+/* request to VC to create component */ -+struct mmal_msg_component_create { -+ void *client_component; /* component context */ -+ char name[128]; -+ u32 pid; /* For debug */ -+}; -+ -+/* reply from VC to component creation request */ -+struct mmal_msg_component_create_reply { -+ u32 status; /** enum mmal_msg_status - how does this differ to -+ * the one in the header? -+ */ -+ u32 component_handle; /* VideoCore handle for component */ -+ u32 input_num; /* Number of input ports */ -+ u32 output_num; /* Number of output ports */ -+ u32 clock_num; /* Number of clock ports */ -+}; -+ -+/* request to VC to destroy a component */ -+struct mmal_msg_component_destroy { -+ u32 component_handle; -+}; -+ -+struct mmal_msg_component_destroy_reply { -+ u32 status; /** The component destruction status */ -+}; -+ -+ -+/* request and reply to VC to enable a component */ -+struct mmal_msg_component_enable { -+ u32 component_handle; -+}; -+ -+struct mmal_msg_component_enable_reply { -+ u32 status; /** The component enable status */ -+}; -+ -+ -+/* request and reply to VC to disable a component */ -+struct mmal_msg_component_disable { -+ u32 component_handle; -+}; -+ -+struct mmal_msg_component_disable_reply { -+ u32 status; /** The component disable status */ -+}; -+ -+/* request to VC to get port information */ -+struct mmal_msg_port_info_get { -+ u32 component_handle; /* component handle port is associated with */ -+ u32 port_type; /* enum mmal_msg_port_type */ -+ u32 index; /* port index to query */ -+}; -+ -+/* reply from VC to get port info request */ -+struct mmal_msg_port_info_get_reply { -+ u32 status; /** enum mmal_msg_status */ -+ u32 component_handle; /* component handle port is associated with */ -+ u32 port_type; /* enum mmal_msg_port_type */ -+ u32 port_index; /* port indexed in query */ -+ s32 found; /* unused */ -+ u32 port_handle; /**< Handle to use for this port */ -+ struct mmal_port port; -+ struct mmal_es_format format; /* elementry stream format */ -+ union mmal_es_specific_format es; /* es type specific data */ -+ u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */ -+}; -+ -+/* request to VC to set port information */ -+struct mmal_msg_port_info_set { -+ u32 component_handle; -+ u32 port_type; /* enum mmal_msg_port_type */ -+ u32 port_index; /* port indexed in query */ -+ struct mmal_port port; -+ struct mmal_es_format format; -+ union mmal_es_specific_format es; -+ u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; -+}; -+ -+/* reply from VC to port info set request */ -+struct mmal_msg_port_info_set_reply { -+ u32 status; -+ u32 component_handle; /* component handle port is associated with */ -+ u32 port_type; /* enum mmal_msg_port_type */ -+ u32 index; /* port indexed in query */ -+ s32 found; /* unused */ -+ u32 port_handle; /**< Handle to use for this port */ -+ struct mmal_port port; -+ struct mmal_es_format format; -+ union mmal_es_specific_format es; -+ u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; -+}; -+ -+ -+/* port action requests that take a mmal_port as a parameter */ -+struct mmal_msg_port_action_port { -+ u32 component_handle; -+ u32 port_handle; -+ u32 action; /* enum mmal_msg_port_action_type */ -+ struct mmal_port port; -+}; -+ -+/* port action requests that take handles as a parameter */ -+struct mmal_msg_port_action_handle { -+ u32 component_handle; -+ u32 port_handle; -+ u32 action; /* enum mmal_msg_port_action_type */ -+ u32 connect_component_handle; -+ u32 connect_port_handle; -+}; -+ -+struct mmal_msg_port_action_reply { -+ u32 status; /** The port action operation status */ -+}; -+ -+ -+ -+ -+/* MMAL buffer transfer */ -+ -+/** Size of space reserved in a buffer message for short messages. */ -+#define MMAL_VC_SHORT_DATA 128 -+ -+/** Signals that the current payload is the end of the stream of data */ -+#define MMAL_BUFFER_HEADER_FLAG_EOS (1<<0) -+/** Signals that the start of the current payload starts a frame */ -+#define MMAL_BUFFER_HEADER_FLAG_FRAME_START (1<<1) -+/** Signals that the end of the current payload ends a frame */ -+#define MMAL_BUFFER_HEADER_FLAG_FRAME_END (1<<2) -+/** Signals that the current payload contains only complete frames (>1) */ -+#define MMAL_BUFFER_HEADER_FLAG_FRAME \ -+ (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END) -+/** Signals that the current payload is a keyframe (i.e. self decodable) */ -+#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME (1<<3) -+/** Signals a discontinuity in the stream of data (e.g. after a seek). -+ * Can be used for instance by a decoder to reset its state */ -+#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY (1<<4) -+/** Signals a buffer containing some kind of config data for the component -+ * (e.g. codec config data) */ -+#define MMAL_BUFFER_HEADER_FLAG_CONFIG (1<<5) -+/** Signals an encrypted payload */ -+#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED (1<<6) -+/** Signals a buffer containing side information */ -+#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO (1<<7) -+/** Signals a buffer which is the snapshot/postview image from a stills -+ * capture -+ */ -+#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT (1<<8) -+/** Signals a buffer which contains data known to be corrupted */ -+#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED (1<<9) -+/** Signals that a buffer failed to be transmitted */ -+#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED (1<<10) -+ -+struct mmal_driver_buffer { -+ u32 magic; -+ u32 component_handle; -+ u32 port_handle; -+ void *client_context; -+}; -+ -+/* buffer header */ -+struct mmal_buffer_header { -+ struct mmal_buffer_header *next; /* next header */ -+ void *priv; /* framework private data */ -+ u32 cmd; -+ void *data; -+ u32 alloc_size; -+ u32 length; -+ u32 offset; -+ u32 flags; -+ s64 pts; -+ s64 dts; -+ void *type; -+ void *user_data; -+}; -+ -+struct mmal_buffer_header_type_specific { -+ union { -+ struct { -+ u32 planes; -+ u32 offset[4]; -+ u32 pitch[4]; -+ u32 flags; -+ } video; -+ } u; -+}; -+ -+struct mmal_msg_buffer_from_host { -+ /* The front 32 bytes of the buffer header are copied -+ * back to us in the reply to allow for context. This -+ * area is used to store two mmal_driver_buffer structures to -+ * allow for multiple concurrent service users. -+ */ -+ /* control data */ -+ struct mmal_driver_buffer drvbuf; -+ -+ /* referenced control data for passthrough buffer management */ -+ struct mmal_driver_buffer drvbuf_ref; -+ struct mmal_buffer_header buffer_header; /* buffer header itself */ -+ struct mmal_buffer_header_type_specific buffer_header_type_specific; -+ s32 is_zero_copy; -+ s32 has_reference; -+ -+ /** allows short data to be xfered in control message */ -+ u32 payload_in_message; -+ u8 short_data[MMAL_VC_SHORT_DATA]; -+}; -+ -+ -+/* port parameter setting */ -+ -+#define MMAL_WORKER_PORT_PARAMETER_SPACE 96 -+ -+struct mmal_msg_port_parameter_set { -+ u32 component_handle; /* component */ -+ u32 port_handle; /* port */ -+ u32 id; /* Parameter ID */ -+ u32 size; /* Parameter size */ -+ uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE]; -+}; -+ -+struct mmal_msg_port_parameter_set_reply { -+ u32 status; /** enum mmal_msg_status todo: how does this -+ * differ to the one in the header? -+ */ -+}; -+ -+/* port parameter getting */ -+ -+struct mmal_msg_port_parameter_get { -+ u32 component_handle; /* component */ -+ u32 port_handle; /* port */ -+ u32 id; /* Parameter ID */ -+ u32 size; /* Parameter size */ -+}; -+ -+struct mmal_msg_port_parameter_get_reply { -+ u32 status; /* Status of mmal_port_parameter_get call */ -+ u32 id; /* Parameter ID */ -+ u32 size; /* Parameter size */ -+ uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE]; -+}; -+ -+/* event messages */ -+#define MMAL_WORKER_EVENT_SPACE 256 -+ -+struct mmal_msg_event_to_host { -+ void *client_component; /* component context */ -+ -+ u32 port_type; -+ u32 port_num; -+ -+ u32 cmd; -+ u32 length; -+ u8 data[MMAL_WORKER_EVENT_SPACE]; -+ struct mmal_buffer_header *delayed_buffer; -+}; -+ -+/* all mmal messages are serialised through this structure */ -+struct mmal_msg { -+ /* header */ -+ struct mmal_msg_header h; -+ /* payload */ -+ union { -+ struct mmal_msg_version version; -+ -+ struct mmal_msg_component_create component_create; -+ struct mmal_msg_component_create_reply component_create_reply; -+ -+ struct mmal_msg_component_destroy component_destroy; -+ struct mmal_msg_component_destroy_reply component_destroy_reply; -+ -+ struct mmal_msg_component_enable component_enable; -+ struct mmal_msg_component_enable_reply component_enable_reply; -+ -+ struct mmal_msg_component_disable component_disable; -+ struct mmal_msg_component_disable_reply component_disable_reply; -+ -+ struct mmal_msg_port_info_get port_info_get; -+ struct mmal_msg_port_info_get_reply port_info_get_reply; -+ -+ struct mmal_msg_port_info_set port_info_set; -+ struct mmal_msg_port_info_set_reply port_info_set_reply; -+ -+ struct mmal_msg_port_action_port port_action_port; -+ struct mmal_msg_port_action_handle port_action_handle; -+ struct mmal_msg_port_action_reply port_action_reply; -+ -+ struct mmal_msg_buffer_from_host buffer_from_host; -+ -+ struct mmal_msg_port_parameter_set port_parameter_set; -+ struct mmal_msg_port_parameter_set_reply -+ port_parameter_set_reply; -+ struct mmal_msg_port_parameter_get -+ port_parameter_get; -+ struct mmal_msg_port_parameter_get_reply -+ port_parameter_get_reply; -+ -+ struct mmal_msg_event_to_host event_to_host; -+ -+ u8 payload[MMAL_MSG_MAX_PAYLOAD]; -+ } u; -+}; -diff --git a/drivers/media/platform/bcm2835/mmal-parameters.h b/drivers/media/platform/bcm2835/mmal-parameters.h -new file mode 100644 -index 0000000000000000000000000000000000000000..f6abb5cfa49d58277fddfb40b7ad329518bd397f ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-parameters.h -@@ -0,0 +1,689 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ */ -+ -+/* common parameters */ -+ -+/** @name Parameter groups -+ * Parameters are divided into groups, and then allocated sequentially within -+ * a group using an enum. -+ * @{ -+ */ -+ -+/** Common parameter ID group, used with many types of component. */ -+#define MMAL_PARAMETER_GROUP_COMMON (0<<16) -+/** Camera-specific parameter ID group. */ -+#define MMAL_PARAMETER_GROUP_CAMERA (1<<16) -+/** Video-specific parameter ID group. */ -+#define MMAL_PARAMETER_GROUP_VIDEO (2<<16) -+/** Audio-specific parameter ID group. */ -+#define MMAL_PARAMETER_GROUP_AUDIO (3<<16) -+/** Clock-specific parameter ID group. */ -+#define MMAL_PARAMETER_GROUP_CLOCK (4<<16) -+/** Miracast-specific parameter ID group. */ -+#define MMAL_PARAMETER_GROUP_MIRACAST (5<<16) -+ -+/* Common parameters */ -+enum mmal_parameter_common_type { -+ MMAL_PARAMETER_UNUSED /**< Never a valid parameter ID */ -+ = MMAL_PARAMETER_GROUP_COMMON, -+ MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */ -+ MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */ -+ -+ /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */ -+ MMAL_PARAMETER_CHANGE_EVENT_REQUEST, -+ -+ /** MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_ZERO_COPY, -+ -+ /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */ -+ MMAL_PARAMETER_BUFFER_REQUIREMENTS, -+ -+ MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */ -+ MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */ -+ MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */ -+ MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */ -+ MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */ -+ MMAL_PARAMETER_SYSTEM_TIME, /**< MMAL_PARAMETER_UINT64_T */ -+ MMAL_PARAMETER_NO_IMAGE_PADDING /**< MMAL_PARAMETER_BOOLEAN_T */ -+}; -+ -+/* camera parameters */ -+ -+enum mmal_parameter_camera_type { -+ /* 0 */ -+ /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */ -+ MMAL_PARAMETER_THUMBNAIL_CONFIGURATION -+ = MMAL_PARAMETER_GROUP_CAMERA, -+ MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */ -+ MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */ -+ MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */ -+ MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */ -+ MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */ -+ MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */ -+ MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */ -+ MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */ -+ MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */ -+ MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */ -+ MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */ -+ MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */ -+ MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */ -+ MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */ -+ -+ /* 0x10 */ -+ MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */ -+ MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */ -+ MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */ -+ MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */ -+ MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */ -+ MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */ -+ MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */ -+ MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */ -+ MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */ -+ MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */ -+ MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ -+ /* 0x20 */ -+ MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */ -+ MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */ -+ MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */ -+ MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */ -+ MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */ -+ MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */ -+ MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */ -+ MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */ -+ MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */ -+ MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */ -+ MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */ -+ MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */ -+ MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */ -+ -+ /* 0x30 */ -+ MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ -+ /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */ -+ MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_CAMERA_BURST_CAPTURE, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_CAMERA_MIN_ISO, -+ -+ /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */ -+ MMAL_PARAMETER_CAMERA_USE_CASE, -+ -+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_CAPTURE_STATS_PASS, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_ENABLE_REGISTER_FILE, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL, -+ -+ /** @ref MMAL_PARAMETER_CONFIGFILE_T */ -+ MMAL_PARAMETER_CONFIGFILE_REGISTERS, -+ -+ /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */ -+ MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS, -+ MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */ -+ MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */ -+ MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */ -+ -+ /* 0x40 */ -+ MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_SHUTTER_SPEED, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */ -+}; -+ -+struct mmal_parameter_rational { -+ s32 num; /**< Numerator */ -+ s32 den; /**< Denominator */ -+}; -+ -+enum mmal_parameter_camera_config_timestamp_mode { -+ MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */ -+ MMAL_PARAM_TIMESTAMP_MODE_RAW_STC, /* Use the raw STC value -+ * for the frame timestamp -+ */ -+ MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp -+ * but subtract the -+ * timestamp of the first -+ * frame sent to give a -+ * zero based timestamp. -+ */ -+}; -+ -+struct mmal_parameter_fps_range { -+ /**< Low end of the permitted framerate range */ -+ struct mmal_parameter_rational fps_low; -+ /**< High end of the permitted framerate range */ -+ struct mmal_parameter_rational fps_high; -+}; -+ -+ -+/* camera configuration parameter */ -+struct mmal_parameter_camera_config { -+ /* Parameters for setting up the image pools */ -+ u32 max_stills_w; /* Max size of stills capture */ -+ u32 max_stills_h; -+ u32 stills_yuv422; /* Allow YUV422 stills capture */ -+ u32 one_shot_stills; /* Continuous or one shot stills captures. */ -+ -+ u32 max_preview_video_w; /* Max size of the preview or video -+ * capture frames -+ */ -+ u32 max_preview_video_h; -+ u32 num_preview_video_frames; -+ -+ /** Sets the height of the circular buffer for stills capture. */ -+ u32 stills_capture_circular_buffer_height; -+ -+ /** Allows preview/encode to resume as fast as possible after the stills -+ * input frame has been received, and then processes the still frame in -+ * the background whilst preview/encode has resumed. -+ * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE. -+ */ -+ u32 fast_preview_resume; -+ -+ /** Selects algorithm for timestamping frames if -+ * there is no clock component connected. -+ * enum mmal_parameter_camera_config_timestamp_mode -+ */ -+ s32 use_stc_timestamp; -+}; -+ -+ -+enum mmal_parameter_exposuremode { -+ MMAL_PARAM_EXPOSUREMODE_OFF, -+ MMAL_PARAM_EXPOSUREMODE_AUTO, -+ MMAL_PARAM_EXPOSUREMODE_NIGHT, -+ MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW, -+ MMAL_PARAM_EXPOSUREMODE_BACKLIGHT, -+ MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT, -+ MMAL_PARAM_EXPOSUREMODE_SPORTS, -+ MMAL_PARAM_EXPOSUREMODE_SNOW, -+ MMAL_PARAM_EXPOSUREMODE_BEACH, -+ MMAL_PARAM_EXPOSUREMODE_VERYLONG, -+ MMAL_PARAM_EXPOSUREMODE_FIXEDFPS, -+ MMAL_PARAM_EXPOSUREMODE_ANTISHAKE, -+ MMAL_PARAM_EXPOSUREMODE_FIREWORKS, -+}; -+ -+enum mmal_parameter_exposuremeteringmode { -+ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE, -+ MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT, -+ MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT, -+ MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX, -+}; -+ -+enum mmal_parameter_awbmode { -+ MMAL_PARAM_AWBMODE_OFF, -+ MMAL_PARAM_AWBMODE_AUTO, -+ MMAL_PARAM_AWBMODE_SUNLIGHT, -+ MMAL_PARAM_AWBMODE_CLOUDY, -+ MMAL_PARAM_AWBMODE_SHADE, -+ MMAL_PARAM_AWBMODE_TUNGSTEN, -+ MMAL_PARAM_AWBMODE_FLUORESCENT, -+ MMAL_PARAM_AWBMODE_INCANDESCENT, -+ MMAL_PARAM_AWBMODE_FLASH, -+ MMAL_PARAM_AWBMODE_HORIZON, -+}; -+ -+enum mmal_parameter_imagefx { -+ MMAL_PARAM_IMAGEFX_NONE, -+ MMAL_PARAM_IMAGEFX_NEGATIVE, -+ MMAL_PARAM_IMAGEFX_SOLARIZE, -+ MMAL_PARAM_IMAGEFX_POSTERIZE, -+ MMAL_PARAM_IMAGEFX_WHITEBOARD, -+ MMAL_PARAM_IMAGEFX_BLACKBOARD, -+ MMAL_PARAM_IMAGEFX_SKETCH, -+ MMAL_PARAM_IMAGEFX_DENOISE, -+ MMAL_PARAM_IMAGEFX_EMBOSS, -+ MMAL_PARAM_IMAGEFX_OILPAINT, -+ MMAL_PARAM_IMAGEFX_HATCH, -+ MMAL_PARAM_IMAGEFX_GPEN, -+ MMAL_PARAM_IMAGEFX_PASTEL, -+ MMAL_PARAM_IMAGEFX_WATERCOLOUR, -+ MMAL_PARAM_IMAGEFX_FILM, -+ MMAL_PARAM_IMAGEFX_BLUR, -+ MMAL_PARAM_IMAGEFX_SATURATION, -+ MMAL_PARAM_IMAGEFX_COLOURSWAP, -+ MMAL_PARAM_IMAGEFX_WASHEDOUT, -+ MMAL_PARAM_IMAGEFX_POSTERISE, -+ MMAL_PARAM_IMAGEFX_COLOURPOINT, -+ MMAL_PARAM_IMAGEFX_COLOURBALANCE, -+ MMAL_PARAM_IMAGEFX_CARTOON, -+}; -+ -+enum MMAL_PARAM_FLICKERAVOID_T { -+ MMAL_PARAM_FLICKERAVOID_OFF, -+ MMAL_PARAM_FLICKERAVOID_AUTO, -+ MMAL_PARAM_FLICKERAVOID_50HZ, -+ MMAL_PARAM_FLICKERAVOID_60HZ, -+ MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF -+}; -+ -+struct mmal_parameter_awbgains { -+ struct mmal_parameter_rational r_gain; /**< Red gain */ -+ struct mmal_parameter_rational b_gain; /**< Blue gain */ -+}; -+ -+/** Manner of video rate control */ -+enum mmal_parameter_rate_control_mode { -+ MMAL_VIDEO_RATECONTROL_DEFAULT, -+ MMAL_VIDEO_RATECONTROL_VARIABLE, -+ MMAL_VIDEO_RATECONTROL_CONSTANT, -+ MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES, -+ MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES -+}; -+ -+enum mmal_video_profile { -+ MMAL_VIDEO_PROFILE_H263_BASELINE, -+ MMAL_VIDEO_PROFILE_H263_H320CODING, -+ MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE, -+ MMAL_VIDEO_PROFILE_H263_ISWV2, -+ MMAL_VIDEO_PROFILE_H263_ISWV3, -+ MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION, -+ MMAL_VIDEO_PROFILE_H263_INTERNET, -+ MMAL_VIDEO_PROFILE_H263_INTERLACE, -+ MMAL_VIDEO_PROFILE_H263_HIGHLATENCY, -+ MMAL_VIDEO_PROFILE_MP4V_SIMPLE, -+ MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE, -+ MMAL_VIDEO_PROFILE_MP4V_CORE, -+ MMAL_VIDEO_PROFILE_MP4V_MAIN, -+ MMAL_VIDEO_PROFILE_MP4V_NBIT, -+ MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE, -+ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE, -+ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA, -+ MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED, -+ MMAL_VIDEO_PROFILE_MP4V_HYBRID, -+ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME, -+ MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE, -+ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING, -+ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE, -+ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE, -+ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE, -+ MMAL_VIDEO_PROFILE_H264_BASELINE, -+ MMAL_VIDEO_PROFILE_H264_MAIN, -+ MMAL_VIDEO_PROFILE_H264_EXTENDED, -+ MMAL_VIDEO_PROFILE_H264_HIGH, -+ MMAL_VIDEO_PROFILE_H264_HIGH10, -+ MMAL_VIDEO_PROFILE_H264_HIGH422, -+ MMAL_VIDEO_PROFILE_H264_HIGH444, -+ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, -+ MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF -+}; -+ -+enum mmal_video_level { -+ MMAL_VIDEO_LEVEL_H263_10, -+ MMAL_VIDEO_LEVEL_H263_20, -+ MMAL_VIDEO_LEVEL_H263_30, -+ MMAL_VIDEO_LEVEL_H263_40, -+ MMAL_VIDEO_LEVEL_H263_45, -+ MMAL_VIDEO_LEVEL_H263_50, -+ MMAL_VIDEO_LEVEL_H263_60, -+ MMAL_VIDEO_LEVEL_H263_70, -+ MMAL_VIDEO_LEVEL_MP4V_0, -+ MMAL_VIDEO_LEVEL_MP4V_0b, -+ MMAL_VIDEO_LEVEL_MP4V_1, -+ MMAL_VIDEO_LEVEL_MP4V_2, -+ MMAL_VIDEO_LEVEL_MP4V_3, -+ MMAL_VIDEO_LEVEL_MP4V_4, -+ MMAL_VIDEO_LEVEL_MP4V_4a, -+ MMAL_VIDEO_LEVEL_MP4V_5, -+ MMAL_VIDEO_LEVEL_MP4V_6, -+ MMAL_VIDEO_LEVEL_H264_1, -+ MMAL_VIDEO_LEVEL_H264_1b, -+ MMAL_VIDEO_LEVEL_H264_11, -+ MMAL_VIDEO_LEVEL_H264_12, -+ MMAL_VIDEO_LEVEL_H264_13, -+ MMAL_VIDEO_LEVEL_H264_2, -+ MMAL_VIDEO_LEVEL_H264_21, -+ MMAL_VIDEO_LEVEL_H264_22, -+ MMAL_VIDEO_LEVEL_H264_3, -+ MMAL_VIDEO_LEVEL_H264_31, -+ MMAL_VIDEO_LEVEL_H264_32, -+ MMAL_VIDEO_LEVEL_H264_4, -+ MMAL_VIDEO_LEVEL_H264_41, -+ MMAL_VIDEO_LEVEL_H264_42, -+ MMAL_VIDEO_LEVEL_H264_5, -+ MMAL_VIDEO_LEVEL_H264_51, -+ MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF -+}; -+ -+struct mmal_parameter_video_profile { -+ enum mmal_video_profile profile; -+ enum mmal_video_level level; -+}; -+ -+/* video parameters */ -+ -+enum mmal_parameter_video_type { -+ /** @ref MMAL_DISPLAYREGION_T */ -+ MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ -+ MMAL_PARAMETER_SUPPORTED_PROFILES, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ -+ MMAL_PARAMETER_PROFILE, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_INTRAPERIOD, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */ -+ MMAL_PARAMETER_RATECONTROL, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */ -+ MMAL_PARAMETER_NALUNITFORMAT, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_MINIMISE_FRAGMENTATION, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. -+ * Setting the value to zero resets to the default (one slice per frame). -+ */ -+ MMAL_PARAMETER_MB_ROWS_PER_SLICE, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */ -+ MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */ -+ MMAL_PARAMETER_VIDEO_EEDE_ENABLE, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */ -+ MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */ -+ MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, -+ /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */ -+ MMAL_PARAMETER_VIDEO_INTRA_REFRESH, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. */ -+ MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */ -+ MMAL_PARAMETER_VIDEO_BIT_RATE, -+ -+ /** @ref MMAL_PARAMETER_FRAME_RATE_T */ -+ MMAL_PARAMETER_VIDEO_FRAME_RATE, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL, -+ -+ MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */ -+ /** @ref MMAL_PARAMETER_UINT32_T. -+ * Changing this parameter from the default can reduce frame rate -+ * because image buffers need to be re-pitched. -+ */ -+ MMAL_PARAMETER_VIDEO_ALIGN_HORIZ, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. -+ * Changing this parameter from the default can reduce frame rate -+ * because image buffers need to be re-pitched. -+ */ -+ MMAL_PARAMETER_VIDEO_ALIGN_VERT, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. */ -+ MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, -+ -+ /**< @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_QP_P, -+ -+ /**< @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, -+ -+ /* H264 specific parameters */ -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS, -+ -+ /** @ref MMAL_PARAMETER_UINT32_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */ -+ MMAL_PARAMETER_VIDEO_DRM_INIT_INFO, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, -+ -+ /** @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT, -+ -+ /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */ -+ MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER, -+ -+ /** @ref MMAL_PARAMETER_BYTES_T */ -+ MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3, -+ -+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS, -+ -+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG, -+ -+ /**< @ref MMAL_PARAMETER_BOOLEAN_T */ -+ MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER -+}; -+ -+/** Valid mirror modes */ -+enum mmal_parameter_mirror { -+ MMAL_PARAM_MIRROR_NONE, -+ MMAL_PARAM_MIRROR_VERTICAL, -+ MMAL_PARAM_MIRROR_HORIZONTAL, -+ MMAL_PARAM_MIRROR_BOTH, -+}; -+ -+enum mmal_parameter_displaytransform { -+ MMAL_DISPLAY_ROT0 = 0, -+ MMAL_DISPLAY_MIRROR_ROT0 = 1, -+ MMAL_DISPLAY_MIRROR_ROT180 = 2, -+ MMAL_DISPLAY_ROT180 = 3, -+ MMAL_DISPLAY_MIRROR_ROT90 = 4, -+ MMAL_DISPLAY_ROT270 = 5, -+ MMAL_DISPLAY_ROT90 = 6, -+ MMAL_DISPLAY_MIRROR_ROT270 = 7, -+}; -+ -+enum mmal_parameter_displaymode { -+ MMAL_DISPLAY_MODE_FILL = 0, -+ MMAL_DISPLAY_MODE_LETTERBOX = 1, -+}; -+ -+enum mmal_parameter_displayset { -+ MMAL_DISPLAY_SET_NONE = 0, -+ MMAL_DISPLAY_SET_NUM = 1, -+ MMAL_DISPLAY_SET_FULLSCREEN = 2, -+ MMAL_DISPLAY_SET_TRANSFORM = 4, -+ MMAL_DISPLAY_SET_DEST_RECT = 8, -+ MMAL_DISPLAY_SET_SRC_RECT = 0x10, -+ MMAL_DISPLAY_SET_MODE = 0x20, -+ MMAL_DISPLAY_SET_PIXEL = 0x40, -+ MMAL_DISPLAY_SET_NOASPECT = 0x80, -+ MMAL_DISPLAY_SET_LAYER = 0x100, -+ MMAL_DISPLAY_SET_COPYPROTECT = 0x200, -+ MMAL_DISPLAY_SET_ALPHA = 0x400, -+}; -+ -+struct mmal_parameter_displayregion { -+ /** Bitfield that indicates which fields are set and should be -+ * used. All other fields will maintain their current value. -+ * \ref MMAL_DISPLAYSET_T defines the bits that can be -+ * combined. -+ */ -+ u32 set; -+ -+ /** Describes the display output device, with 0 typically -+ * being a directly connected LCD display. The actual values -+ * will depend on the hardware. Code using hard-wired numbers -+ * (e.g. 2) is certain to fail. -+ */ -+ -+ u32 display_num; -+ /** Indicates that we are using the full device screen area, -+ * rather than a window of the display. If zero, then -+ * dest_rect is used to specify a region of the display to -+ * use. -+ */ -+ -+ s32 fullscreen; -+ /** Indicates any rotation or flipping used to map frames onto -+ * the natural display orientation. -+ */ -+ u32 transform; /* enum mmal_parameter_displaytransform */ -+ -+ /** Where to display the frame within the screen, if -+ * fullscreen is zero. -+ */ -+ struct vchiq_mmal_rect dest_rect; -+ -+ /** Indicates which area of the frame to display. If all -+ * values are zero, the whole frame will be used. -+ */ -+ struct vchiq_mmal_rect src_rect; -+ -+ /** If set to non-zero, indicates that any display scaling -+ * should disregard the aspect ratio of the frame region being -+ * displayed. -+ */ -+ s32 noaspect; -+ -+ /** Indicates how the image should be scaled to fit the -+ * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates -+ * that the image should fill the screen by potentially -+ * cropping the frames. Setting \code mode \endcode to \code -+ * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the -+ * source region should be displayed and black bars added if -+ * necessary. -+ */ -+ u32 mode; /* enum mmal_parameter_displaymode */ -+ -+ /** If non-zero, defines the width of a source pixel relative -+ * to \code pixel_y \endcode. If zero, then pixels default to -+ * being square. -+ */ -+ u32 pixel_x; -+ -+ /** If non-zero, defines the height of a source pixel relative -+ * to \code pixel_x \endcode. If zero, then pixels default to -+ * being square. -+ */ -+ u32 pixel_y; -+ -+ /** Sets the relative depth of the images, with greater values -+ * being in front of smaller values. -+ */ -+ u32 layer; -+ -+ /** Set to non-zero to ensure copy protection is used on -+ * output. -+ */ -+ s32 copyprotect_required; -+ -+ /** Level of opacity of the layer, where zero is fully -+ * transparent and 255 is fully opaque. -+ */ -+ u32 alpha; -+}; -+ -+#define MMAL_MAX_IMAGEFX_PARAMETERS 5 -+ -+struct mmal_parameter_imagefx_parameters { -+ enum mmal_parameter_imagefx effect; -+ u32 num_effect_params; -+ u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; -+}; -+ -+#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4 -+#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2 -+#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16 -+ -+struct mmal_parameter_camera_info_camera_t { -+ u32 port_id; -+ u32 max_width; -+ u32 max_height; -+ u32 lens_present; -+ u8 camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN]; -+}; -+ -+enum mmal_parameter_camera_info_flash_type_t { -+ /* Make values explicit to ensure they match values in config ini */ -+ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0, -+ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1, -+ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2, -+ MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF -+}; -+ -+struct mmal_parameter_camera_info_flash_t { -+ enum mmal_parameter_camera_info_flash_type_t flash_type; -+}; -+ -+struct mmal_parameter_camera_info_t { -+ u32 num_cameras; -+ u32 num_flashes; -+ struct mmal_parameter_camera_info_camera_t -+ cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS]; -+ struct mmal_parameter_camera_info_flash_t -+ flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES]; -+}; -diff --git a/drivers/media/platform/bcm2835/mmal-vchiq.c b/drivers/media/platform/bcm2835/mmal-vchiq.c -new file mode 100644 -index 0000000000000000000000000000000000000000..781322542d5a8295f3d7d5a3eaaf0cac29930c30 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-vchiq.c -@@ -0,0 +1,1916 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ * -+ * V4L2 driver MMAL vchiq interface code -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mmal-common.h" -+#include "mmal-vchiq.h" -+#include "mmal-msg.h" -+ -+#define USE_VCHIQ_ARM -+#include "interface/vchi/vchi.h" -+ -+/* maximum number of components supported */ -+#define VCHIQ_MMAL_MAX_COMPONENTS 4 -+ -+/*#define FULL_MSG_DUMP 1*/ -+ -+#ifdef DEBUG -+static const char *const msg_type_names[] = { -+ "UNKNOWN", -+ "QUIT", -+ "SERVICE_CLOSED", -+ "GET_VERSION", -+ "COMPONENT_CREATE", -+ "COMPONENT_DESTROY", -+ "COMPONENT_ENABLE", -+ "COMPONENT_DISABLE", -+ "PORT_INFO_GET", -+ "PORT_INFO_SET", -+ "PORT_ACTION", -+ "BUFFER_FROM_HOST", -+ "BUFFER_TO_HOST", -+ "GET_STATS", -+ "PORT_PARAMETER_SET", -+ "PORT_PARAMETER_GET", -+ "EVENT_TO_HOST", -+ "GET_CORE_STATS_FOR_PORT", -+ "OPAQUE_ALLOCATOR", -+ "CONSUME_MEM", -+ "LMK", -+ "OPAQUE_ALLOCATOR_DESC", -+ "DRM_GET_LHS32", -+ "DRM_GET_TIME", -+ "BUFFER_FROM_HOST_ZEROLEN", -+ "PORT_FLUSH", -+ "HOST_LOG", -+}; -+#endif -+ -+static const char *const port_action_type_names[] = { -+ "UNKNOWN", -+ "ENABLE", -+ "DISABLE", -+ "FLUSH", -+ "CONNECT", -+ "DISCONNECT", -+ "SET_REQUIREMENTS", -+}; -+ -+#if defined(DEBUG) -+#if defined(FULL_MSG_DUMP) -+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \ -+ do { \ -+ pr_debug(TITLE" type:%s(%d) length:%d\n", \ -+ msg_type_names[(MSG)->h.type], \ -+ (MSG)->h.type, (MSG_LEN)); \ -+ print_hex_dump(KERN_DEBUG, "<h.type], \ -+ (MSG)->h.type, (MSG_LEN)); \ -+ } -+#endif -+#else -+#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) -+#endif -+ -+/* normal message context */ -+struct mmal_msg_context { -+ union { -+ struct { -+ /* work struct for defered callback - must come first */ -+ struct work_struct work; -+ /* mmal instance */ -+ struct vchiq_mmal_instance *instance; -+ /* mmal port */ -+ struct vchiq_mmal_port *port; -+ /* actual buffer used to store bulk reply */ -+ struct mmal_buffer *buffer; -+ /* amount of buffer used */ -+ unsigned long buffer_used; -+ /* MMAL buffer flags */ -+ u32 mmal_flags; -+ /* Presentation and Decode timestamps */ -+ s64 pts; -+ s64 dts; -+ -+ int status; /* context status */ -+ -+ } bulk; /* bulk data */ -+ -+ struct { -+ /* message handle to release */ -+ VCHI_HELD_MSG_T msg_handle; -+ /* pointer to received message */ -+ struct mmal_msg *msg; -+ /* received message length */ -+ u32 msg_len; -+ /* completion upon reply */ -+ struct completion cmplt; -+ } sync; /* synchronous response */ -+ } u; -+ -+}; -+ -+struct vchiq_mmal_instance { -+ VCHI_SERVICE_HANDLE_T handle; -+ -+ /* ensure serialised access to service */ -+ struct mutex vchiq_mutex; -+ -+ /* ensure serialised access to bulk operations */ -+ struct mutex bulk_mutex; -+ -+ /* vmalloc page to receive scratch bulk xfers into */ -+ void *bulk_scratch; -+ -+ /* component to use next */ -+ int component_idx; -+ struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS]; -+}; -+ -+static struct mmal_msg_context *get_msg_context(struct vchiq_mmal_instance -+ *instance) -+{ -+ struct mmal_msg_context *msg_context; -+ -+ /* todo: should this be allocated from a pool to avoid kmalloc */ -+ msg_context = kmalloc(sizeof(*msg_context), GFP_KERNEL); -+ memset(msg_context, 0, sizeof(*msg_context)); -+ -+ return msg_context; -+} -+ -+static void release_msg_context(struct mmal_msg_context *msg_context) -+{ -+ kfree(msg_context); -+} -+ -+/* deals with receipt of event to host message */ -+static void event_to_host_cb(struct vchiq_mmal_instance *instance, -+ struct mmal_msg *msg, u32 msg_len) -+{ -+ pr_debug("unhandled event\n"); -+ pr_debug("component:%p port type:%d num:%d cmd:0x%x length:%d\n", -+ msg->u.event_to_host.client_component, -+ msg->u.event_to_host.port_type, -+ msg->u.event_to_host.port_num, -+ msg->u.event_to_host.cmd, msg->u.event_to_host.length); -+} -+ -+/* workqueue scheduled callback -+ * -+ * we do this because it is important we do not call any other vchiq -+ * sync calls from witin the message delivery thread -+ */ -+static void buffer_work_cb(struct work_struct *work) -+{ -+ struct mmal_msg_context *msg_context = (struct mmal_msg_context *)work; -+ -+ msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance, -+ msg_context->u.bulk.port, -+ msg_context->u.bulk.status, -+ msg_context->u.bulk.buffer, -+ msg_context->u.bulk.buffer_used, -+ msg_context->u.bulk.mmal_flags, -+ msg_context->u.bulk.dts, -+ msg_context->u.bulk.pts); -+ -+ /* release message context */ -+ release_msg_context(msg_context); -+} -+ -+/* enqueue a bulk receive for a given message context */ -+static int bulk_receive(struct vchiq_mmal_instance *instance, -+ struct mmal_msg *msg, -+ struct mmal_msg_context *msg_context) -+{ -+ unsigned long rd_len; -+ unsigned long flags = 0; -+ int ret; -+ -+ /* bulk mutex stops other bulk operations while we have a -+ * receive in progress - released in callback -+ */ -+ ret = mutex_lock_interruptible(&instance->bulk_mutex); -+ if (ret != 0) -+ return ret; -+ -+ rd_len = msg->u.buffer_from_host.buffer_header.length; -+ -+ /* take buffer from queue */ -+ spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags); -+ if (list_empty(&msg_context->u.bulk.port->buffers)) { -+ spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); -+ pr_err("buffer list empty trying to submit bulk receive\n"); -+ -+ /* todo: this is a serious error, we should never have -+ * commited a buffer_to_host operation to the mmal -+ * port without the buffer to back it up (underflow -+ * handling) and there is no obvious way to deal with -+ * this - how is the mmal servie going to react when -+ * we fail to do the xfer and reschedule a buffer when -+ * it arrives? perhaps a starved flag to indicate a -+ * waiting bulk receive? -+ */ -+ -+ mutex_unlock(&instance->bulk_mutex); -+ -+ return -EINVAL; -+ } -+ -+ msg_context->u.bulk.buffer = -+ list_entry(msg_context->u.bulk.port->buffers.next, -+ struct mmal_buffer, list); -+ list_del(&msg_context->u.bulk.buffer->list); -+ -+ spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); -+ -+ /* ensure we do not overrun the available buffer */ -+ if (rd_len > msg_context->u.bulk.buffer->buffer_size) { -+ rd_len = msg_context->u.bulk.buffer->buffer_size; -+ pr_warn("short read as not enough receive buffer space\n"); -+ /* todo: is this the correct response, what happens to -+ * the rest of the message data? -+ */ -+ } -+ -+ /* store length */ -+ msg_context->u.bulk.buffer_used = rd_len; -+ msg_context->u.bulk.mmal_flags = -+ msg->u.buffer_from_host.buffer_header.flags; -+ msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts; -+ msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts; -+ -+ // only need to flush L1 cache here, as VCHIQ takes care of the L2 -+ // cache. -+ __cpuc_flush_dcache_area(msg_context->u.bulk.buffer->buffer, rd_len); -+ -+ /* queue the bulk submission */ -+ vchi_service_use(instance->handle); -+ ret = vchi_bulk_queue_receive(instance->handle, -+ msg_context->u.bulk.buffer->buffer, -+ /* Actual receive needs to be a multiple -+ * of 4 bytes -+ */ -+ (rd_len + 3) & ~3, -+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, -+ msg_context); -+ -+ vchi_service_release(instance->handle); -+ -+ if (ret != 0) { -+ /* callback will not be clearing the mutex */ -+ mutex_unlock(&instance->bulk_mutex); -+ } -+ -+ return ret; -+} -+ -+/* enque a dummy bulk receive for a given message context */ -+static int dummy_bulk_receive(struct vchiq_mmal_instance *instance, -+ struct mmal_msg_context *msg_context) -+{ -+ int ret; -+ -+ /* bulk mutex stops other bulk operations while we have a -+ * receive in progress - released in callback -+ */ -+ ret = mutex_lock_interruptible(&instance->bulk_mutex); -+ if (ret != 0) -+ return ret; -+ -+ /* zero length indicates this was a dummy transfer */ -+ msg_context->u.bulk.buffer_used = 0; -+ -+ /* queue the bulk submission */ -+ vchi_service_use(instance->handle); -+ -+ ret = vchi_bulk_queue_receive(instance->handle, -+ instance->bulk_scratch, -+ 8, -+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE | -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, -+ msg_context); -+ -+ vchi_service_release(instance->handle); -+ -+ if (ret != 0) { -+ /* callback will not be clearing the mutex */ -+ mutex_unlock(&instance->bulk_mutex); -+ } -+ -+ return ret; -+} -+ -+/* data in message, memcpy from packet into output buffer */ -+static int inline_receive(struct vchiq_mmal_instance *instance, -+ struct mmal_msg *msg, -+ struct mmal_msg_context *msg_context) -+{ -+ unsigned long flags = 0; -+ -+ /* take buffer from queue */ -+ spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags); -+ if (list_empty(&msg_context->u.bulk.port->buffers)) { -+ spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); -+ pr_err("buffer list empty trying to receive inline\n"); -+ -+ /* todo: this is a serious error, we should never have -+ * commited a buffer_to_host operation to the mmal -+ * port without the buffer to back it up (with -+ * underflow handling) and there is no obvious way to -+ * deal with this. Less bad than the bulk case as we -+ * can just drop this on the floor but...unhelpful -+ */ -+ return -EINVAL; -+ } -+ -+ msg_context->u.bulk.buffer = -+ list_entry(msg_context->u.bulk.port->buffers.next, -+ struct mmal_buffer, list); -+ list_del(&msg_context->u.bulk.buffer->list); -+ -+ spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags); -+ -+ memcpy(msg_context->u.bulk.buffer->buffer, -+ msg->u.buffer_from_host.short_data, -+ msg->u.buffer_from_host.payload_in_message); -+ -+ msg_context->u.bulk.buffer_used = -+ msg->u.buffer_from_host.payload_in_message; -+ -+ return 0; -+} -+ -+/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */ -+static int -+buffer_from_host(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, struct mmal_buffer *buf) -+{ -+ struct mmal_msg_context *msg_context; -+ struct mmal_msg m; -+ int ret; -+ -+ pr_debug("instance:%p buffer:%p\n", instance->handle, buf); -+ -+ /* bulk mutex stops other bulk operations while we -+ * have a receive in progress -+ */ -+ if (mutex_lock_interruptible(&instance->bulk_mutex)) -+ return -EINTR; -+ -+ /* get context */ -+ msg_context = get_msg_context(instance); -+ if (msg_context == NULL) -+ return -ENOMEM; -+ -+ /* store bulk message context for when data arrives */ -+ msg_context->u.bulk.instance = instance; -+ msg_context->u.bulk.port = port; -+ msg_context->u.bulk.buffer = NULL; /* not valid until bulk xfer */ -+ msg_context->u.bulk.buffer_used = 0; -+ -+ /* initialise work structure ready to schedule callback */ -+ INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb); -+ -+ /* prep the buffer from host message */ -+ memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */ -+ -+ m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST; -+ m.h.magic = MMAL_MAGIC; -+ m.h.context = msg_context; -+ m.h.status = 0; -+ -+ /* drvbuf is our private data passed back */ -+ m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC; -+ m.u.buffer_from_host.drvbuf.component_handle = port->component->handle; -+ m.u.buffer_from_host.drvbuf.port_handle = port->handle; -+ m.u.buffer_from_host.drvbuf.client_context = msg_context; -+ -+ /* buffer header */ -+ m.u.buffer_from_host.buffer_header.cmd = 0; -+ m.u.buffer_from_host.buffer_header.data = buf->buffer; -+ m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size; -+ m.u.buffer_from_host.buffer_header.length = 0; /* nothing used yet */ -+ m.u.buffer_from_host.buffer_header.offset = 0; /* no offset */ -+ m.u.buffer_from_host.buffer_header.flags = 0; /* no flags */ -+ m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN; -+ m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN; -+ -+ /* clear buffer type sepecific data */ -+ memset(&m.u.buffer_from_host.buffer_header_type_specific, 0, -+ sizeof(m.u.buffer_from_host.buffer_header_type_specific)); -+ -+ /* no payload in message */ -+ m.u.buffer_from_host.payload_in_message = 0; -+ -+ vchi_service_use(instance->handle); -+ -+ ret = vchi_msg_queue(instance->handle, &m, -+ sizeof(struct mmal_msg_header) + -+ sizeof(m.u.buffer_from_host), -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (ret != 0) { -+ release_msg_context(msg_context); -+ /* todo: is this correct error value? */ -+ } -+ -+ vchi_service_release(instance->handle); -+ -+ mutex_unlock(&instance->bulk_mutex); -+ -+ return ret; -+} -+ -+/* submit a buffer to the mmal sevice -+ * -+ * the buffer_from_host uses size data from the ports next available -+ * mmal_buffer and deals with there being no buffer available by -+ * incrementing the underflow for later -+ */ -+static int port_buffer_from_host(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ struct mmal_buffer *buf; -+ unsigned long flags = 0; -+ -+ if (!port->enabled) -+ return -EINVAL; -+ -+ /* peek buffer from queue */ -+ spin_lock_irqsave(&port->slock, flags); -+ if (list_empty(&port->buffers)) { -+ port->buffer_underflow++; -+ spin_unlock_irqrestore(&port->slock, flags); -+ return -ENOSPC; -+ } -+ -+ buf = list_entry(port->buffers.next, struct mmal_buffer, list); -+ -+ spin_unlock_irqrestore(&port->slock, flags); -+ -+ /* issue buffer to mmal service */ -+ ret = buffer_from_host(instance, port, buf); -+ if (ret) { -+ pr_err("adding buffer header failed\n"); -+ /* todo: how should this be dealt with */ -+ } -+ -+ return ret; -+} -+ -+/* deals with receipt of buffer to host message */ -+static void buffer_to_host_cb(struct vchiq_mmal_instance *instance, -+ struct mmal_msg *msg, u32 msg_len) -+{ -+ struct mmal_msg_context *msg_context; -+ -+ pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n", -+ instance, msg, msg_len); -+ -+ if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) { -+ msg_context = msg->u.buffer_from_host.drvbuf.client_context; -+ } else { -+ pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n"); -+ return; -+ } -+ -+ if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) { -+ /* message reception had an error */ -+ pr_warn("error %d in reply\n", msg->h.status); -+ -+ msg_context->u.bulk.status = msg->h.status; -+ -+ } else if (msg->u.buffer_from_host.buffer_header.length == 0) { -+ /* empty buffer */ -+ if (msg->u.buffer_from_host.buffer_header.flags & -+ MMAL_BUFFER_HEADER_FLAG_EOS) { -+ msg_context->u.bulk.status = -+ dummy_bulk_receive(instance, msg_context); -+ if (msg_context->u.bulk.status == 0) -+ return; /* successful bulk submission, bulk -+ * completion will trigger callback -+ */ -+ } else { -+ /* do callback with empty buffer - not EOS though */ -+ msg_context->u.bulk.status = 0; -+ msg_context->u.bulk.buffer_used = 0; -+ } -+ } else if (msg->u.buffer_from_host.payload_in_message == 0) { -+ /* data is not in message, queue a bulk receive */ -+ msg_context->u.bulk.status = -+ bulk_receive(instance, msg, msg_context); -+ if (msg_context->u.bulk.status == 0) -+ return; /* successful bulk submission, bulk -+ * completion will trigger callback -+ */ -+ -+ /* failed to submit buffer, this will end badly */ -+ pr_err("error %d on bulk submission\n", -+ msg_context->u.bulk.status); -+ -+ } else if (msg->u.buffer_from_host.payload_in_message <= -+ MMAL_VC_SHORT_DATA) { -+ /* data payload within message */ -+ msg_context->u.bulk.status = inline_receive(instance, msg, -+ msg_context); -+ } else { -+ pr_err("message with invalid short payload\n"); -+ -+ /* signal error */ -+ msg_context->u.bulk.status = -EINVAL; -+ msg_context->u.bulk.buffer_used = -+ msg->u.buffer_from_host.payload_in_message; -+ } -+ -+ /* replace the buffer header */ -+ port_buffer_from_host(instance, msg_context->u.bulk.port); -+ -+ /* schedule the port callback */ -+ schedule_work(&msg_context->u.bulk.work); -+} -+ -+static void bulk_receive_cb(struct vchiq_mmal_instance *instance, -+ struct mmal_msg_context *msg_context) -+{ -+ /* bulk receive operation complete */ -+ mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex); -+ -+ /* replace the buffer header */ -+ port_buffer_from_host(msg_context->u.bulk.instance, -+ msg_context->u.bulk.port); -+ -+ msg_context->u.bulk.status = 0; -+ -+ /* schedule the port callback */ -+ schedule_work(&msg_context->u.bulk.work); -+} -+ -+static void bulk_abort_cb(struct vchiq_mmal_instance *instance, -+ struct mmal_msg_context *msg_context) -+{ -+ pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context); -+ -+ /* bulk receive operation complete */ -+ mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex); -+ -+ /* replace the buffer header */ -+ port_buffer_from_host(msg_context->u.bulk.instance, -+ msg_context->u.bulk.port); -+ -+ msg_context->u.bulk.status = -EINTR; -+ -+ schedule_work(&msg_context->u.bulk.work); -+} -+ -+/* incoming event service callback */ -+static void service_callback(void *param, -+ const VCHI_CALLBACK_REASON_T reason, -+ void *bulk_ctx) -+{ -+ struct vchiq_mmal_instance *instance = param; -+ int status; -+ u32 msg_len; -+ struct mmal_msg *msg; -+ VCHI_HELD_MSG_T msg_handle; -+ -+ if (!instance) { -+ pr_err("Message callback passed NULL instance\n"); -+ return; -+ } -+ -+ switch (reason) { -+ case VCHI_CALLBACK_MSG_AVAILABLE: -+ status = vchi_msg_hold(instance->handle, (void **)&msg, -+ &msg_len, VCHI_FLAGS_NONE, &msg_handle); -+ if (status) { -+ pr_err("Unable to dequeue a message (%d)\n", status); -+ break; -+ } -+ -+ DBG_DUMP_MSG(msg, msg_len, "<<< reply message"); -+ -+ /* handling is different for buffer messages */ -+ switch (msg->h.type) { -+ -+ case MMAL_MSG_TYPE_BUFFER_FROM_HOST: -+ vchi_held_msg_release(&msg_handle); -+ break; -+ -+ case MMAL_MSG_TYPE_EVENT_TO_HOST: -+ event_to_host_cb(instance, msg, msg_len); -+ vchi_held_msg_release(&msg_handle); -+ -+ break; -+ -+ case MMAL_MSG_TYPE_BUFFER_TO_HOST: -+ buffer_to_host_cb(instance, msg, msg_len); -+ vchi_held_msg_release(&msg_handle); -+ break; -+ -+ default: -+ /* messages dependant on header context to complete */ -+ -+ /* todo: the msg.context really ought to be sanity -+ * checked before we just use it, afaict it comes back -+ * and is used raw from the videocore. Perhaps it -+ * should be verified the address lies in the kernel -+ * address space. -+ */ -+ if (msg->h.context == NULL) { -+ pr_err("received message context was null!\n"); -+ vchi_held_msg_release(&msg_handle); -+ break; -+ } -+ -+ /* fill in context values */ -+ msg->h.context->u.sync.msg_handle = msg_handle; -+ msg->h.context->u.sync.msg = msg; -+ msg->h.context->u.sync.msg_len = msg_len; -+ -+ /* todo: should this check (completion_done() -+ * == 1) for no one waiting? or do we need a -+ * flag to tell us the completion has been -+ * interrupted so we can free the message and -+ * its context. This probably also solves the -+ * message arriving after interruption todo -+ * below -+ */ -+ -+ /* complete message so caller knows it happened */ -+ complete(&msg->h.context->u.sync.cmplt); -+ break; -+ } -+ -+ break; -+ -+ case VCHI_CALLBACK_BULK_RECEIVED: -+ bulk_receive_cb(instance, bulk_ctx); -+ break; -+ -+ case VCHI_CALLBACK_BULK_RECEIVE_ABORTED: -+ bulk_abort_cb(instance, bulk_ctx); -+ break; -+ -+ case VCHI_CALLBACK_SERVICE_CLOSED: -+ /* TODO: consider if this requires action if received when -+ * driver is not explicitly closing the service -+ */ -+ break; -+ -+ default: -+ pr_err("Received unhandled message reason %d\n", reason); -+ break; -+ } -+} -+ -+static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, -+ struct mmal_msg *msg, -+ unsigned int payload_len, -+ struct mmal_msg **msg_out, -+ VCHI_HELD_MSG_T *msg_handle_out) -+{ -+ struct mmal_msg_context msg_context; -+ int ret; -+ -+ /* payload size must not cause message to exceed max size */ -+ if (payload_len > -+ (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) { -+ pr_err("payload length %d exceeds max:%d\n", payload_len, -+ (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))); -+ return -EINVAL; -+ } -+ -+ init_completion(&msg_context.u.sync.cmplt); -+ -+ msg->h.magic = MMAL_MAGIC; -+ msg->h.context = &msg_context; -+ msg->h.status = 0; -+ -+ DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len), -+ ">>> sync message"); -+ -+ vchi_service_use(instance->handle); -+ -+ ret = vchi_msg_queue(instance->handle, -+ msg, -+ sizeof(struct mmal_msg_header) + payload_len, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ vchi_service_release(instance->handle); -+ -+ if (ret) { -+ pr_err("error %d queuing message\n", ret); -+ return ret; -+ } -+ -+ ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, 3*HZ); -+ if (ret <= 0) { -+ pr_err("error %d waiting for sync completion\n", ret); -+ if (ret == 0) -+ ret = -ETIME; -+ /* todo: what happens if the message arrives after aborting */ -+ return ret; -+ } -+ -+ *msg_out = msg_context.u.sync.msg; -+ *msg_handle_out = msg_context.u.sync.msg_handle; -+ -+ return 0; -+} -+ -+static void dump_port_info(struct vchiq_mmal_port *port) -+{ -+ pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled); -+ -+ pr_debug("buffer minimum num:%d size:%d align:%d\n", -+ port->minimum_buffer.num, -+ port->minimum_buffer.size, port->minimum_buffer.alignment); -+ -+ pr_debug("buffer recommended num:%d size:%d align:%d\n", -+ port->recommended_buffer.num, -+ port->recommended_buffer.size, -+ port->recommended_buffer.alignment); -+ -+ pr_debug("buffer current values num:%d size:%d align:%d\n", -+ port->current_buffer.num, -+ port->current_buffer.size, port->current_buffer.alignment); -+ -+ pr_debug("elementry stream: type:%d encoding:0x%x varient:0x%x\n", -+ port->format.type, -+ port->format.encoding, port->format.encoding_variant); -+ -+ pr_debug(" bitrate:%d flags:0x%x\n", -+ port->format.bitrate, port->format.flags); -+ -+ if (port->format.type == MMAL_ES_TYPE_VIDEO) { -+ pr_debug -+ ("es video format: width:%d height:%d colourspace:0x%x\n", -+ port->es.video.width, port->es.video.height, -+ port->es.video.color_space); -+ -+ pr_debug(" : crop xywh %d,%d,%d,%d\n", -+ port->es.video.crop.x, -+ port->es.video.crop.y, -+ port->es.video.crop.width, port->es.video.crop.height); -+ pr_debug(" : framerate %d/%d aspect %d/%d\n", -+ port->es.video.frame_rate.num, -+ port->es.video.frame_rate.den, -+ port->es.video.par.num, port->es.video.par.den); -+ } -+} -+ -+static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p) -+{ -+ -+ /* todo do readonly fields need setting at all? */ -+ p->type = port->type; -+ p->index = port->index; -+ p->index_all = 0; -+ p->is_enabled = port->enabled; -+ p->buffer_num_min = port->minimum_buffer.num; -+ p->buffer_size_min = port->minimum_buffer.size; -+ p->buffer_alignment_min = port->minimum_buffer.alignment; -+ p->buffer_num_recommended = port->recommended_buffer.num; -+ p->buffer_size_recommended = port->recommended_buffer.size; -+ -+ /* only three writable fields in a port */ -+ p->buffer_num = port->current_buffer.num; -+ p->buffer_size = port->current_buffer.size; -+ p->userdata = port; -+} -+ -+static int port_info_set(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ pr_debug("setting port info port %p\n", port); -+ if (!port) -+ return -1; -+ dump_port_info(port); -+ -+ m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET; -+ -+ m.u.port_info_set.component_handle = port->component->handle; -+ m.u.port_info_set.port_type = port->type; -+ m.u.port_info_set.port_index = port->index; -+ -+ port_to_mmal_msg(port, &m.u.port_info_set.port); -+ -+ /* elementry stream format setup */ -+ m.u.port_info_set.format.type = port->format.type; -+ m.u.port_info_set.format.encoding = port->format.encoding; -+ m.u.port_info_set.format.encoding_variant = -+ port->format.encoding_variant; -+ m.u.port_info_set.format.bitrate = port->format.bitrate; -+ m.u.port_info_set.format.flags = port->format.flags; -+ -+ memcpy(&m.u.port_info_set.es, &port->es, -+ sizeof(union mmal_es_specific_format)); -+ -+ m.u.port_info_set.format.extradata_size = port->format.extradata_size; -+ memcpy(&m.u.port_info_set.extradata, port->format.extradata, -+ port->format.extradata_size); -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.port_info_set), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ /* return operation status */ -+ ret = -rmsg->u.port_info_get_reply.status; -+ -+ pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret, -+ port->component->handle, port->handle); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+ -+} -+ -+/* use port info get message to retrive port information */ -+static int port_info_get(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ /* port info time */ -+ m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET; -+ m.u.port_info_get.component_handle = port->component->handle; -+ m.u.port_info_get.port_type = port->type; -+ m.u.port_info_get.index = port->index; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.port_info_get), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ /* return operation status */ -+ ret = -rmsg->u.port_info_get_reply.status; -+ if (ret != MMAL_MSG_STATUS_SUCCESS) -+ goto release_msg; -+ -+ if (rmsg->u.port_info_get_reply.port.is_enabled == 0) -+ port->enabled = false; -+ else -+ port->enabled = true; -+ -+ /* copy the values out of the message */ -+ port->handle = rmsg->u.port_info_get_reply.port_handle; -+ -+ /* port type and index cached to use on port info set becuase -+ * it does not use a port handle -+ */ -+ port->type = rmsg->u.port_info_get_reply.port_type; -+ port->index = rmsg->u.port_info_get_reply.port_index; -+ -+ port->minimum_buffer.num = -+ rmsg->u.port_info_get_reply.port.buffer_num_min; -+ port->minimum_buffer.size = -+ rmsg->u.port_info_get_reply.port.buffer_size_min; -+ port->minimum_buffer.alignment = -+ rmsg->u.port_info_get_reply.port.buffer_alignment_min; -+ -+ port->recommended_buffer.alignment = -+ rmsg->u.port_info_get_reply.port.buffer_alignment_min; -+ port->recommended_buffer.num = -+ rmsg->u.port_info_get_reply.port.buffer_num_recommended; -+ -+ port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num; -+ port->current_buffer.size = -+ rmsg->u.port_info_get_reply.port.buffer_size; -+ -+ /* stream format */ -+ port->format.type = rmsg->u.port_info_get_reply.format.type; -+ port->format.encoding = rmsg->u.port_info_get_reply.format.encoding; -+ port->format.encoding_variant = -+ rmsg->u.port_info_get_reply.format.encoding_variant; -+ port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate; -+ port->format.flags = rmsg->u.port_info_get_reply.format.flags; -+ -+ /* elementry stream format */ -+ memcpy(&port->es, -+ &rmsg->u.port_info_get_reply.es, -+ sizeof(union mmal_es_specific_format)); -+ port->format.es = &port->es; -+ -+ port->format.extradata_size = -+ rmsg->u.port_info_get_reply.format.extradata_size; -+ memcpy(port->format.extradata, -+ rmsg->u.port_info_get_reply.extradata, -+ port->format.extradata_size); -+ -+ pr_debug("received port info\n"); -+ dump_port_info(port); -+ -+release_msg: -+ -+ pr_debug("%s:result:%d component:0x%x port:%d\n", -+ __func__, ret, port->component->handle, port->handle); -+ -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* create comonent on vc */ -+static int create_component(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component, -+ const char *name) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ /* build component create message */ -+ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE; -+ m.u.component_create.client_component = component; -+ strncpy(m.u.component_create.name, name, -+ sizeof(m.u.component_create.name)); -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.component_create), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != m.h.type) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.component_create_reply.status; -+ if (ret != MMAL_MSG_STATUS_SUCCESS) -+ goto release_msg; -+ -+ /* a valid component response received */ -+ component->handle = rmsg->u.component_create_reply.component_handle; -+ component->inputs = rmsg->u.component_create_reply.input_num; -+ component->outputs = rmsg->u.component_create_reply.output_num; -+ component->clocks = rmsg->u.component_create_reply.clock_num; -+ -+ pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n", -+ component->handle, -+ component->inputs, component->outputs, component->clocks); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* destroys a component on vc */ -+static int destroy_component(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY; -+ m.u.component_destroy.component_handle = component->handle; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.component_destroy), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != m.h.type) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.component_destroy_reply.status; -+ -+release_msg: -+ -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* enable a component on vc */ -+static int enable_component(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE; -+ m.u.component_enable.component_handle = component->handle; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.component_enable), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != m.h.type) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.component_enable_reply.status; -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* disable a component on vc */ -+static int disable_component(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE; -+ m.u.component_disable.component_handle = component->handle; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.component_disable), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != m.h.type) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.component_disable_reply.status; -+ -+release_msg: -+ -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* get version of mmal implementation */ -+static int get_version(struct vchiq_mmal_instance *instance, -+ u32 *major_out, u32 *minor_out) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_GET_VERSION; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.version), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != m.h.type) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ *major_out = rmsg->u.version.major; -+ *minor_out = rmsg->u.version.minor; -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* do a port action with a port as a parameter */ -+static int port_action_port(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ enum mmal_msg_port_action_type action_type) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_PORT_ACTION; -+ m.u.port_action_port.component_handle = port->component->handle; -+ m.u.port_action_port.port_handle = port->handle; -+ m.u.port_action_port.action = action_type; -+ -+ port_to_mmal_msg(port, &m.u.port_action_port.port); -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.port_action_port), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.port_action_reply.status; -+ -+ pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n", -+ __func__, -+ ret, port->component->handle, port->handle, -+ port_action_type_names[action_type], action_type); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* do a port action with handles as parameters */ -+static int port_action_handle(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ enum mmal_msg_port_action_type action_type, -+ u32 connect_component_handle, -+ u32 connect_port_handle) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_PORT_ACTION; -+ -+ m.u.port_action_handle.component_handle = port->component->handle; -+ m.u.port_action_handle.port_handle = port->handle; -+ m.u.port_action_handle.action = action_type; -+ -+ m.u.port_action_handle.connect_component_handle = -+ connect_component_handle; -+ m.u.port_action_handle.connect_port_handle = connect_port_handle; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(m.u.port_action_handle), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.port_action_reply.status; -+ -+ pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \ -+ " connect component:0x%x connect port:%d\n", -+ __func__, -+ ret, port->component->handle, port->handle, -+ port_action_type_names[action_type], -+ action_type, connect_component_handle, connect_port_handle); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+static int port_parameter_set(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter_id, void *value, u32 value_size) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET; -+ -+ m.u.port_parameter_set.component_handle = port->component->handle; -+ m.u.port_parameter_set.port_handle = port->handle; -+ m.u.port_parameter_set.id = parameter_id; -+ m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size; -+ memcpy(&m.u.port_parameter_set.value, value, value_size); -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ (4 * sizeof(u32)) + value_size, -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) { -+ /* got an unexpected message type in reply */ -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.port_parameter_set_reply.status; -+ -+ pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", -+ __func__, -+ ret, port->component->handle, port->handle, parameter_id); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+static int port_parameter_get(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter_id, void *value, u32 *value_size) -+{ -+ int ret; -+ struct mmal_msg m; -+ struct mmal_msg *rmsg; -+ VCHI_HELD_MSG_T rmsg_handle; -+ -+ m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET; -+ -+ m.u.port_parameter_get.component_handle = port->component->handle; -+ m.u.port_parameter_get.port_handle = port->handle; -+ m.u.port_parameter_get.id = parameter_id; -+ m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size; -+ -+ ret = send_synchronous_mmal_msg(instance, &m, -+ sizeof(struct -+ mmal_msg_port_parameter_get), -+ &rmsg, &rmsg_handle); -+ if (ret) -+ return ret; -+ -+ if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) { -+ /* got an unexpected message type in reply */ -+ pr_err("Incorrect reply type %d\n", rmsg->h.type); -+ ret = -EINVAL; -+ goto release_msg; -+ } -+ -+ ret = -rmsg->u.port_parameter_get_reply.status; -+ if (ret) { -+ /* Copy only as much as we have space for -+ * but report true size of parameter -+ */ -+ memcpy(value, &rmsg->u.port_parameter_get_reply.value, -+ *value_size); -+ *value_size = rmsg->u.port_parameter_get_reply.size; -+ } else -+ memcpy(value, &rmsg->u.port_parameter_get_reply.value, -+ rmsg->u.port_parameter_get_reply.size); -+ -+ pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, -+ ret, port->component->handle, port->handle, parameter_id); -+ -+release_msg: -+ vchi_held_msg_release(&rmsg_handle); -+ -+ return ret; -+} -+ -+/* disables a port and drains buffers from it */ -+static int port_disable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ struct list_head *q, *buf_head; -+ unsigned long flags = 0; -+ -+ if (!port->enabled) -+ return 0; -+ -+ port->enabled = false; -+ -+ ret = port_action_port(instance, port, -+ MMAL_MSG_PORT_ACTION_TYPE_DISABLE); -+ if (ret == 0) { -+ -+ /* drain all queued buffers on port */ -+ spin_lock_irqsave(&port->slock, flags); -+ -+ list_for_each_safe(buf_head, q, &port->buffers) { -+ struct mmal_buffer *mmalbuf; -+ mmalbuf = list_entry(buf_head, struct mmal_buffer, -+ list); -+ list_del(buf_head); -+ if (port->buffer_cb) -+ port->buffer_cb(instance, -+ port, 0, mmalbuf, 0, 0, -+ MMAL_TIME_UNKNOWN, -+ MMAL_TIME_UNKNOWN); -+ } -+ -+ spin_unlock_irqrestore(&port->slock, flags); -+ -+ ret = port_info_get(instance, port); -+ } -+ -+ return ret; -+} -+ -+/* enable a port */ -+static int port_enable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ unsigned int hdr_count; -+ struct list_head *buf_head; -+ int ret; -+ -+ if (port->enabled) -+ return 0; -+ -+ /* ensure there are enough buffers queued to cover the buffer headers */ -+ if (port->buffer_cb != NULL) { -+ hdr_count = 0; -+ list_for_each(buf_head, &port->buffers) { -+ hdr_count++; -+ } -+ if (hdr_count < port->current_buffer.num) -+ return -ENOSPC; -+ } -+ -+ ret = port_action_port(instance, port, -+ MMAL_MSG_PORT_ACTION_TYPE_ENABLE); -+ if (ret) -+ goto done; -+ -+ port->enabled = true; -+ -+ if (port->buffer_cb) { -+ /* send buffer headers to videocore */ -+ hdr_count = 1; -+ list_for_each(buf_head, &port->buffers) { -+ struct mmal_buffer *mmalbuf; -+ mmalbuf = list_entry(buf_head, struct mmal_buffer, -+ list); -+ ret = buffer_from_host(instance, port, mmalbuf); -+ if (ret) -+ goto done; -+ -+ hdr_count++; -+ if (hdr_count > port->current_buffer.num) -+ break; -+ } -+ } -+ -+ ret = port_info_get(instance, port); -+ -+done: -+ return ret; -+} -+ -+/* ------------------------------------------------------------------ -+ * Exported API -+ *------------------------------------------------------------------*/ -+ -+int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ ret = port_info_set(instance, port); -+ if (ret) -+ goto release_unlock; -+ -+ /* read what has actually been set */ -+ ret = port_info_get(instance, port); -+ -+release_unlock: -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+ -+} -+ -+int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter, void *value, u32 value_size) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ ret = port_parameter_set(instance, port, parameter, value, value_size); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter, void *value, u32 *value_size) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ ret = port_parameter_get(instance, port, parameter, value, value_size); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+/* enable a port -+ * -+ * enables a port and queues buffers for satisfying callbacks if we -+ * provide a callback handler -+ */ -+int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ vchiq_mmal_buffer_cb buffer_cb) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ /* already enabled - noop */ -+ if (port->enabled) { -+ ret = 0; -+ goto unlock; -+ } -+ -+ port->buffer_cb = buffer_cb; -+ -+ ret = port_enable(instance, port); -+ -+unlock: -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ if (!port->enabled) { -+ mutex_unlock(&instance->vchiq_mutex); -+ return 0; -+ } -+ -+ ret = port_disable(instance, port); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+/* ports will be connected in a tunneled manner so data buffers -+ * are not handled by client. -+ */ -+int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *src, -+ struct vchiq_mmal_port *dst) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ /* disconnect ports if connected */ -+ if (src->connected != NULL) { -+ ret = port_disable(instance, src); -+ if (ret) { -+ pr_err("failed disabling src port(%d)\n", ret); -+ goto release_unlock; -+ } -+ -+ /* do not need to disable the destination port as they -+ * are connected and it is done automatically -+ */ -+ -+ ret = port_action_handle(instance, src, -+ MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, -+ src->connected->component->handle, -+ src->connected->handle); -+ if (ret < 0) { -+ pr_err("failed disconnecting src port\n"); -+ goto release_unlock; -+ } -+ src->connected->enabled = false; -+ src->connected = NULL; -+ } -+ -+ if (dst == NULL) { -+ /* do not make new connection */ -+ ret = 0; -+ pr_debug("not making new connection\n"); -+ goto release_unlock; -+ } -+ -+ /* copy src port format to dst */ -+ dst->format.encoding = src->format.encoding; -+ dst->es.video.width = src->es.video.width; -+ dst->es.video.height = src->es.video.height; -+ dst->es.video.crop.x = src->es.video.crop.x; -+ dst->es.video.crop.y = src->es.video.crop.y; -+ dst->es.video.crop.width = src->es.video.crop.width; -+ dst->es.video.crop.height = src->es.video.crop.height; -+ dst->es.video.frame_rate.num = src->es.video.frame_rate.num; -+ dst->es.video.frame_rate.den = src->es.video.frame_rate.den; -+ -+ /* set new format */ -+ ret = port_info_set(instance, dst); -+ if (ret) { -+ pr_debug("setting port info failed\n"); -+ goto release_unlock; -+ } -+ -+ /* read what has actually been set */ -+ ret = port_info_get(instance, dst); -+ if (ret) { -+ pr_debug("read back port info failed\n"); -+ goto release_unlock; -+ } -+ -+ /* connect two ports together */ -+ ret = port_action_handle(instance, src, -+ MMAL_MSG_PORT_ACTION_TYPE_CONNECT, -+ dst->component->handle, dst->handle); -+ if (ret < 0) { -+ pr_debug("connecting port %d:%d to %d:%d failed\n", -+ src->component->handle, src->handle, -+ dst->component->handle, dst->handle); -+ goto release_unlock; -+ } -+ src->connected = dst; -+ -+release_unlock: -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ struct mmal_buffer *buffer) -+{ -+ unsigned long flags = 0; -+ -+ spin_lock_irqsave(&port->slock, flags); -+ list_add_tail(&buffer->list, &port->buffers); -+ spin_unlock_irqrestore(&port->slock, flags); -+ -+ /* the port previously underflowed because it was missing a -+ * mmal_buffer which has just been added, submit that buffer -+ * to the mmal service. -+ */ -+ if (port->buffer_underflow) { -+ port_buffer_from_host(instance, port); -+ port->buffer_underflow--; -+ } -+ -+ return 0; -+} -+ -+/* Initialise a mmal component and its ports -+ * -+ */ -+int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, -+ const char *name, -+ struct vchiq_mmal_component **component_out) -+{ -+ int ret; -+ int idx; /* port index */ -+ struct vchiq_mmal_component *component; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) { -+ ret = -EINVAL; /* todo is this correct error? */ -+ goto unlock; -+ } -+ -+ component = &instance->component[instance->component_idx]; -+ -+ ret = create_component(instance, component, name); -+ if (ret < 0) -+ goto unlock; -+ -+ /* ports info needs gathering */ -+ component->control.type = MMAL_PORT_TYPE_CONTROL; -+ component->control.index = 0; -+ component->control.component = component; -+ spin_lock_init(&component->control.slock); -+ INIT_LIST_HEAD(&component->control.buffers); -+ ret = port_info_get(instance, &component->control); -+ if (ret < 0) -+ goto release_component; -+ -+ for (idx = 0; idx < component->inputs; idx++) { -+ component->input[idx].type = MMAL_PORT_TYPE_INPUT; -+ component->input[idx].index = idx; -+ component->input[idx].component = component; -+ spin_lock_init(&component->input[idx].slock); -+ INIT_LIST_HEAD(&component->input[idx].buffers); -+ ret = port_info_get(instance, &component->input[idx]); -+ if (ret < 0) -+ goto release_component; -+ } -+ -+ for (idx = 0; idx < component->outputs; idx++) { -+ component->output[idx].type = MMAL_PORT_TYPE_OUTPUT; -+ component->output[idx].index = idx; -+ component->output[idx].component = component; -+ spin_lock_init(&component->output[idx].slock); -+ INIT_LIST_HEAD(&component->output[idx].buffers); -+ ret = port_info_get(instance, &component->output[idx]); -+ if (ret < 0) -+ goto release_component; -+ } -+ -+ for (idx = 0; idx < component->clocks; idx++) { -+ component->clock[idx].type = MMAL_PORT_TYPE_CLOCK; -+ component->clock[idx].index = idx; -+ component->clock[idx].component = component; -+ spin_lock_init(&component->clock[idx].slock); -+ INIT_LIST_HEAD(&component->clock[idx].buffers); -+ ret = port_info_get(instance, &component->clock[idx]); -+ if (ret < 0) -+ goto release_component; -+ } -+ -+ instance->component_idx++; -+ -+ *component_out = component; -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return 0; -+ -+release_component: -+ destroy_component(instance, component); -+unlock: -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+/* -+ * cause a mmal component to be destroyed -+ */ -+int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ if (component->enabled) -+ ret = disable_component(instance, component); -+ -+ ret = destroy_component(instance, component); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+/* -+ * cause a mmal component to be enabled -+ */ -+int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ if (component->enabled) { -+ mutex_unlock(&instance->vchiq_mutex); -+ return 0; -+ } -+ -+ ret = enable_component(instance, component); -+ if (ret == 0) -+ component->enabled = true; -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+/* -+ * cause a mmal component to be enabled -+ */ -+int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ if (!component->enabled) { -+ mutex_unlock(&instance->vchiq_mutex); -+ return 0; -+ } -+ -+ ret = disable_component(instance, component); -+ if (ret == 0) -+ component->enabled = false; -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+int vchiq_mmal_version(struct vchiq_mmal_instance *instance, -+ u32 *major_out, u32 *minor_out) -+{ -+ int ret; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ ret = get_version(instance, major_out, minor_out); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ return ret; -+} -+ -+int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) -+{ -+ int status = 0; -+ -+ if (instance == NULL) -+ return -EINVAL; -+ -+ if (mutex_lock_interruptible(&instance->vchiq_mutex)) -+ return -EINTR; -+ -+ vchi_service_use(instance->handle); -+ -+ status = vchi_service_close(instance->handle); -+ if (status != 0) -+ pr_err("mmal-vchiq: VCHIQ close failed"); -+ -+ mutex_unlock(&instance->vchiq_mutex); -+ -+ vfree(instance->bulk_scratch); -+ -+ kfree(instance); -+ -+ return status; -+} -+ -+int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) -+{ -+ int status; -+ struct vchiq_mmal_instance *instance; -+ static VCHI_CONNECTION_T *vchi_connection; -+ static VCHI_INSTANCE_T vchi_instance; -+ SERVICE_CREATION_T params = { -+ VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER), -+ VC_MMAL_SERVER_NAME, -+ vchi_connection, -+ 0, /* rx fifo size (unused) */ -+ 0, /* tx fifo size (unused) */ -+ service_callback, -+ NULL, /* service callback parameter */ -+ 1, /* unaligned bulk receives */ -+ 1, /* unaligned bulk transmits */ -+ 0 /* want crc check on bulk transfers */ -+ }; -+ -+ /* compile time checks to ensure structure size as they are -+ * directly (de)serialised from memory. -+ */ -+ -+ /* ensure the header structure has packed to the correct size */ -+ BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24); -+ -+ /* ensure message structure does not exceed maximum length */ -+ BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE); -+ -+ /* mmal port struct is correct size */ -+ BUILD_BUG_ON(sizeof(struct mmal_port) != 64); -+ -+ /* create a vchi instance */ -+ status = vchi_initialise(&vchi_instance); -+ if (status) { -+ pr_err("Failed to initialise VCHI instance (status=%d)\n", -+ status); -+ return -EIO; -+ } -+ -+ status = vchi_connect(NULL, 0, vchi_instance); -+ if (status) { -+ pr_err("Failed to connect VCHI instance (status=%d)\n", status); -+ return -EIO; -+ } -+ -+ instance = kmalloc(sizeof(*instance), GFP_KERNEL); -+ memset(instance, 0, sizeof(*instance)); -+ -+ mutex_init(&instance->vchiq_mutex); -+ mutex_init(&instance->bulk_mutex); -+ -+ instance->bulk_scratch = vmalloc(PAGE_SIZE); -+ -+ params.callback_param = instance; -+ -+ status = vchi_service_open(vchi_instance, ¶ms, &instance->handle); -+ if (status) { -+ pr_err("Failed to open VCHI service connection (status=%d)\n", -+ status); -+ goto err_close_services; -+ } -+ -+ vchi_service_release(instance->handle); -+ -+ *out_instance = instance; -+ -+ return 0; -+ -+err_close_services: -+ -+ vchi_service_close(instance->handle); -+ vfree(instance->bulk_scratch); -+ kfree(instance); -+ return -ENODEV; -+} -diff --git a/drivers/media/platform/bcm2835/mmal-vchiq.h b/drivers/media/platform/bcm2835/mmal-vchiq.h -new file mode 100644 -index 0000000000000000000000000000000000000000..9d1d11e4a53e510c04a416d92d195a7df15012d5 ---- /dev/null -+++ b/drivers/media/platform/bcm2835/mmal-vchiq.h -@@ -0,0 +1,178 @@ -+/* -+ * Broadcom BM2835 V4L2 driver -+ * -+ * Copyright © 2013 Raspberry Pi (Trading) Ltd. -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive -+ * for more details. -+ * -+ * Authors: Vincent Sanders -+ * Dave Stevenson -+ * Simon Mellor -+ * Luke Diamand -+ * -+ * MMAL interface to VCHIQ message passing -+ */ -+ -+#ifndef MMAL_VCHIQ_H -+#define MMAL_VCHIQ_H -+ -+#include "mmal-msg-format.h" -+ -+#define MAX_PORT_COUNT 4 -+ -+/* Maximum size of the format extradata. */ -+#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128 -+ -+struct vchiq_mmal_instance; -+ -+enum vchiq_mmal_es_type { -+ MMAL_ES_TYPE_UNKNOWN, /**< Unknown elementary stream type */ -+ MMAL_ES_TYPE_CONTROL, /**< Elementary stream of control commands */ -+ MMAL_ES_TYPE_AUDIO, /**< Audio elementary stream */ -+ MMAL_ES_TYPE_VIDEO, /**< Video elementary stream */ -+ MMAL_ES_TYPE_SUBPICTURE /**< Sub-picture elementary stream */ -+}; -+ -+/* rectangle, used lots so it gets its own struct */ -+struct vchiq_mmal_rect { -+ s32 x; -+ s32 y; -+ s32 width; -+ s32 height; -+}; -+ -+struct vchiq_mmal_port_buffer { -+ unsigned int num; /* number of buffers */ -+ u32 size; /* size of buffers */ -+ u32 alignment; /* alignment of buffers */ -+}; -+ -+struct vchiq_mmal_port; -+ -+typedef void (*vchiq_mmal_buffer_cb)( -+ struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ int status, struct mmal_buffer *buffer, -+ unsigned long length, u32 mmal_flags, s64 dts, s64 pts); -+ -+struct vchiq_mmal_port { -+ bool enabled; -+ u32 handle; -+ u32 type; /* port type, cached to use on port info set */ -+ u32 index; /* port index, cached to use on port info set */ -+ -+ /* component port belongs to, allows simple deref */ -+ struct vchiq_mmal_component *component; -+ -+ struct vchiq_mmal_port *connected; /* port conencted to */ -+ -+ /* buffer info */ -+ struct vchiq_mmal_port_buffer minimum_buffer; -+ struct vchiq_mmal_port_buffer recommended_buffer; -+ struct vchiq_mmal_port_buffer current_buffer; -+ -+ /* stream format */ -+ struct mmal_es_format format; -+ /* elementry stream format */ -+ union mmal_es_specific_format es; -+ -+ /* data buffers to fill */ -+ struct list_head buffers; -+ /* lock to serialise adding and removing buffers from list */ -+ spinlock_t slock; -+ /* count of how many buffer header refils have failed because -+ * there was no buffer to satisfy them -+ */ -+ int buffer_underflow; -+ /* callback on buffer completion */ -+ vchiq_mmal_buffer_cb buffer_cb; -+ /* callback context */ -+ void *cb_ctx; -+}; -+ -+struct vchiq_mmal_component { -+ bool enabled; -+ u32 handle; /* VideoCore handle for component */ -+ u32 inputs; /* Number of input ports */ -+ u32 outputs; /* Number of output ports */ -+ u32 clocks; /* Number of clock ports */ -+ struct vchiq_mmal_port control; /* control port */ -+ struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */ -+ struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */ -+ struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */ -+}; -+ -+ -+int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance); -+int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance); -+ -+/* Initialise a mmal component and its ports -+* -+*/ -+int vchiq_mmal_component_init( -+ struct vchiq_mmal_instance *instance, -+ const char *name, -+ struct vchiq_mmal_component **component_out); -+ -+int vchiq_mmal_component_finalise( -+ struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component); -+ -+int vchiq_mmal_component_enable( -+ struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component); -+ -+int vchiq_mmal_component_disable( -+ struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_component *component); -+ -+ -+ -+/* enable a mmal port -+ * -+ * enables a port and if a buffer callback provided enque buffer -+ * headers as apropriate for the port. -+ */ -+int vchiq_mmal_port_enable( -+ struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ vchiq_mmal_buffer_cb buffer_cb); -+ -+/* disable a port -+ * -+ * disable a port will dequeue any pending buffers -+ */ -+int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port); -+ -+ -+int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter, -+ void *value, -+ u32 value_size); -+ -+int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ u32 parameter, -+ void *value, -+ u32 *value_size); -+ -+int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port); -+ -+int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *src, -+ struct vchiq_mmal_port *dst); -+ -+int vchiq_mmal_version(struct vchiq_mmal_instance *instance, -+ u32 *major_out, -+ u32 *minor_out); -+ -+int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, -+ struct vchiq_mmal_port *port, -+ struct mmal_buffer *buf); -+ -+#endif /* MMAL_VCHIQ_H */ - -From effc2a027af54dc168df1904669f6be64ed78f26 Mon Sep 17 00:00:00 2001 +From 25e0dc791a0d0019588d8018960ffa4e871c4fbe Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 11 May 2015 09:00:42 +0100 -Subject: [PATCH 049/216] scripts: Add mkknlimg and knlinfo scripts from tools +Subject: [PATCH 055/150] scripts: Add mkknlimg and knlinfo scripts from tools repo The Raspberry Pi firmware looks for a trailer on the kernel image to @@ -93714,2864 +82438,10 @@ index 0000000000000000000000000000000000000000..60206de7fa9a49bd027c635306674a29 + return $trailer; +} -From 53e15f300d983d30bc77e70b6c38775b863264a6 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 10 Aug 2015 09:49:15 +0100 -Subject: [PATCH 050/216] scripts/dtc: Update to upstream version 1.4.1 - -Includes the new localfixups format. - -Signed-off-by: Phil Elwell - -scripts/dtc: Fix UMR causing corrupt dtbo overlay files - -struct fixup_entry is allocated from the heap but it's member -local_fixup_generated was never initialized. This lead to -corrupted dtbo files. - -Fix this by initializing local_fixup_generated to false. - -Signed-off-by: Matthias Reichl - -scripts/dtc: Only emit local fixups for overlays - -Signed-off-by: Phil Elwell ---- - scripts/dtc/checks.c | 106 +++++- - scripts/dtc/dtc-lexer.l | 5 + - scripts/dtc/dtc-lexer.lex.c_shipped | 537 +++++++++++++------------- - scripts/dtc/dtc-parser.tab.c_shipped | 714 ++++++++++++++++++----------------- - scripts/dtc/dtc-parser.tab.h_shipped | 46 +-- - scripts/dtc/dtc-parser.y | 22 +- - scripts/dtc/dtc.c | 9 +- - scripts/dtc/dtc.h | 40 ++ - scripts/dtc/flattree.c | 202 ++++++++++ - scripts/dtc/version_gen.h | 2 +- - 10 files changed, 1029 insertions(+), 654 deletions(-) - -diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c -index 386f9563313f713f896236814de35811d145d121..2164d8fe5f98f123bbf74aa25e69891b31bd8c64 100644 ---- a/scripts/dtc/checks.c -+++ b/scripts/dtc/checks.c -@@ -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; -+ struct fixup *f, **fp; -+ struct fixup_entry *fe, **fep; - struct node *refnode; - cell_t phandle; - -@@ -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) { -- FAIL(c, "Reference to non-existent node or label \"%s\"\n", -- m->ref); -+ if (!dt->is_plugin) { -+ FAIL(c, "Reference to non-existent node or label \"%s\"\n", -+ m->ref); -+ continue; -+ } -+ -+ /* allocate fixup entry */ -+ fe = xmalloc(sizeof(*fe)); -+ -+ fe->node = node; -+ fe->prop = prop; -+ fe->offset = m->offset; -+ fe->next = NULL; -+ -+ /* search for an already existing fixup */ -+ for_each_fixup(dt, f) -+ if (strcmp(f->ref, m->ref) == 0) -+ break; -+ -+ /* no fixup found, add new */ -+ if (f == NULL) { -+ f = xmalloc(sizeof(*f)); -+ f->ref = m->ref; -+ f->entries = NULL; -+ f->next = NULL; -+ -+ /* add it to the tree */ -+ fp = &dt->fixups; -+ while (*fp) -+ fp = &(*fp)->next; -+ *fp = f; -+ } -+ -+ /* and now append fixup entry */ -+ fep = &f->entries; -+ while (*fep) -+ fep = &(*fep)->next; -+ *fep = fe; -+ -+ /* mark the entry as unresolved */ -+ *((cell_t *)(prop->val.val + m->offset)) = -+ cpu_to_fdt32(0xdeadbeef); - continue; - } - -+ /* if it's a local reference, we need to record it */ -+ if (symbol_fixup_support && dt->is_plugin) { -+ -+ /* allocate a new local fixup entry */ -+ fe = xmalloc(sizeof(*fe)); -+ -+ fe->node = node; -+ fe->prop = prop; -+ fe->offset = m->offset; -+ fe->next = NULL; -+ fe->local_fixup_generated = false; -+ -+ /* append it to the local fixups */ -+ fep = &dt->local_fixups; -+ while (*fep) -+ fep = &(*fep)->next; -+ *fep = fe; -+ } -+ - phandle = get_node_phandle(dt, refnode); - *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); - } -@@ -676,6 +737,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c, - } - TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); - -+static void check_auto_label_phandles(struct check *c, struct node *dt, -+ struct node *node) -+{ -+ struct label *l; -+ struct symbol *s, **sp; -+ int has_label; -+ -+ if (!symbol_fixup_support) -+ return; -+ -+ has_label = 0; -+ for_each_label(node->labels, l) { -+ has_label = 1; -+ break; -+ } -+ -+ if (!has_label) -+ return; -+ -+ /* force allocation of a phandle for this node */ -+ (void)get_node_phandle(dt, node); -+ -+ /* add the symbol */ -+ for_each_label(node->labels, l) { -+ -+ s = xmalloc(sizeof(*s)); -+ s->label = l; -+ s->node = node; -+ s->next = NULL; -+ -+ /* add it to the symbols list */ -+ sp = &dt->symbols; -+ while (*sp) -+ sp = &((*sp)->next); -+ *sp = s; -+ } -+} -+NODE_WARNING(auto_label_phandles, NULL); -+ - static struct check *check_table[] = { - &duplicate_node_names, &duplicate_property_names, - &node_name_chars, &node_name_format, &property_name_chars, -@@ -696,6 +796,8 @@ static struct check *check_table[] = { - &avoid_default_addr_size, - &obsolete_chosen_interrupt_controller, - -+ &auto_label_phandles, -+ - &always_fail, - }; - -diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l -index 790fbf6cf2d75349780a5c849cdb9cdb697f5019..40bbc87d0f1dcaafd7275670cc678b970397f232 100644 ---- a/scripts/dtc/dtc-lexer.l -+++ b/scripts/dtc/dtc-lexer.l -@@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...); - return DT_V1; - } - -+<*>"/plugin/" { -+ DPRINT("Keyword: /plugin/\n"); -+ return DT_PLUGIN; -+ } -+ - <*>"/memreserve/" { - DPRINT("Keyword: /memreserve/\n"); - BEGIN_DEFAULT(); -diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped -index ba525c2f9fc28f596452999eaa2a66116446dc58..15185255fafdbebf805ad2bb2c63f0fdef4c8776 100644 ---- a/scripts/dtc/dtc-lexer.lex.c_shipped -+++ b/scripts/dtc/dtc-lexer.lex.c_shipped -@@ -9,7 +9,7 @@ - #define FLEX_SCANNER - #define YY_FLEX_MAJOR_VERSION 2 - #define YY_FLEX_MINOR_VERSION 5 --#define YY_FLEX_SUBMINOR_VERSION 39 -+#define YY_FLEX_SUBMINOR_VERSION 35 - #if YY_FLEX_SUBMINOR_VERSION > 0 - #define FLEX_BETA - #endif -@@ -162,12 +162,7 @@ typedef unsigned int flex_uint32_t; - typedef struct yy_buffer_state *YY_BUFFER_STATE; - #endif - --#ifndef YY_TYPEDEF_YY_SIZE_T --#define YY_TYPEDEF_YY_SIZE_T --typedef size_t yy_size_t; --#endif -- --extern yy_size_t yyleng; -+extern int yyleng; - - extern FILE *yyin, *yyout; - -@@ -176,7 +171,6 @@ extern FILE *yyin, *yyout; - #define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) -- #define YY_LINENO_REWIND_TO(ptr) - - /* Return all but the first "n" matched characters back to the input stream. */ - #define yyless(n) \ -@@ -194,6 +188,11 @@ extern FILE *yyin, *yyout; - - #define unput(c) yyunput( c, (yytext_ptr) ) - -+#ifndef YY_TYPEDEF_YY_SIZE_T -+#define YY_TYPEDEF_YY_SIZE_T -+typedef size_t yy_size_t; -+#endif -+ - #ifndef YY_STRUCT_YY_BUFFER_STATE - #define YY_STRUCT_YY_BUFFER_STATE - struct yy_buffer_state -@@ -211,7 +210,7 @@ struct yy_buffer_state - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ -- yy_size_t yy_n_chars; -+ int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to -@@ -281,8 +280,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ - - /* yy_hold_char holds the character lost when yytext is formed. */ - static char yy_hold_char; --static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ --yy_size_t yyleng; -+static int yy_n_chars; /* number of characters read into yy_ch_buf */ -+int yyleng; - - /* Points to current character in buffer. */ - static char *yy_c_buf_p = (char *) 0; -@@ -310,7 +309,7 @@ static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); - - YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); - YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); --YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); -+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); - - void *yyalloc (yy_size_t ); - void *yyrealloc (void *,yy_size_t ); -@@ -342,7 +341,7 @@ void yyfree (void * ); - - /* Begin user sect3 */ - --#define yywrap() 1 -+#define yywrap(n) 1 - #define YY_SKIP_YYWRAP - - typedef unsigned char YY_CHAR; -@@ -373,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[] ); - *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; - --#define YY_NUM_RULES 30 --#define YY_END_OF_BUFFER 31 -+#define YY_NUM_RULES 31 -+#define YY_END_OF_BUFFER 32 - /* This struct is not used in this scanner, - but its presence is necessary. */ - struct yy_trans_info -@@ -382,25 +381,26 @@ struct yy_trans_info - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; --static yyconst flex_int16_t yy_accept[159] = -+static yyconst flex_int16_t yy_accept[166] = - { 0, -- 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, -- 18, 18, 29, 29, 29, 29, 29, 29, 29, 29, -- 29, 29, 29, 29, 29, 29, 15, 16, 16, 29, -- 16, 10, 10, 18, 26, 0, 3, 0, 27, 12, -- 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, -- 21, 23, 25, 24, 22, 0, 9, 28, 0, 0, -- 0, 14, 14, 16, 16, 16, 10, 10, 10, 0, -- 12, 0, 11, 0, 0, 0, 20, 0, 0, 0, -- 0, 0, 0, 0, 0, 16, 10, 10, 10, 0, -- 13, 19, 0, 0, 0, 0, 0, 0, 0, 0, -- -- 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 16, 6, 0, 0, 0, 0, 0, 0, 2, -- 0, 0, 0, 0, 0, 0, 0, 0, 4, 17, -- 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- 5, 8, 0, 0, 0, 0, 7, 0 -+ 0, 0, 0, 0, 0, 0, 0, 0, 32, 30, -+ 19, 19, 30, 30, 30, 30, 30, 30, 30, 30, -+ 30, 30, 30, 30, 30, 30, 16, 17, 17, 30, -+ 17, 11, 11, 19, 27, 0, 3, 0, 28, 13, -+ 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, -+ 0, 22, 24, 26, 25, 23, 0, 10, 29, 0, -+ 0, 0, 15, 15, 17, 17, 17, 11, 11, 11, -+ 0, 13, 0, 12, 0, 0, 0, 21, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 17, 11, 11, -+ 11, 0, 14, 20, 0, 0, 0, 0, 0, 0, -+ -+ 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 17, 7, 0, 0, 0, -+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 4, 18, 0, 0, 5, 2, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 1, 0, 0, 0, 0, 6, 9, 0, -+ 0, 0, 0, 8, 0 - } ; - - static yyconst flex_int32_t yy_ec[256] = -@@ -416,9 +416,9 @@ static yyconst flex_int32_t yy_ec[256] = - 22, 22, 22, 22, 24, 22, 22, 25, 22, 22, - 1, 26, 27, 1, 22, 1, 21, 28, 29, 30, - -- 31, 21, 22, 22, 32, 22, 22, 33, 34, 35, -- 36, 37, 22, 38, 39, 40, 41, 42, 22, 25, -- 43, 22, 44, 45, 46, 1, 1, 1, 1, 1, -+ 31, 21, 32, 22, 33, 22, 22, 34, 35, 36, -+ 37, 38, 22, 39, 40, 41, 42, 43, 22, 25, -+ 44, 22, 45, 46, 47, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -@@ -435,163 +435,165 @@ static yyconst flex_int32_t yy_ec[256] = - 1, 1, 1, 1, 1 - } ; - --static yyconst flex_int32_t yy_meta[47] = -+static yyconst flex_int32_t yy_meta[48] = - { 0, - 1, 1, 1, 1, 1, 1, 2, 3, 1, 2, - 2, 2, 4, 5, 5, 5, 6, 1, 1, 1, - 7, 8, 8, 8, 8, 1, 1, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, -- 8, 8, 8, 3, 1, 4 -+ 8, 8, 8, 8, 3, 1, 4 - } ; - --static yyconst flex_int16_t yy_base[173] = -+static yyconst flex_int16_t yy_base[180] = - { 0, -- 0, 383, 34, 382, 65, 381, 37, 105, 387, 391, -- 54, 111, 367, 110, 109, 109, 112, 41, 366, 104, -- 367, 338, 124, 117, 0, 144, 391, 0, 121, 0, -- 135, 155, 140, 179, 391, 160, 391, 379, 391, 0, -- 368, 141, 391, 167, 370, 376, 346, 103, 342, 345, -- 391, 391, 391, 391, 391, 358, 391, 391, 175, 342, -- 338, 391, 355, 0, 185, 339, 184, 347, 346, 0, -- 0, 322, 175, 357, 175, 363, 352, 324, 330, 323, -- 332, 326, 201, 324, 329, 322, 391, 333, 181, 309, -- 391, 341, 340, 313, 320, 338, 178, 311, 146, 317, -- -- 314, 315, 335, 331, 303, 300, 309, 299, 308, 188, -- 336, 335, 391, 305, 320, 281, 283, 271, 203, 288, -- 281, 271, 266, 264, 245, 242, 208, 104, 391, 391, -- 244, 218, 204, 219, 206, 224, 201, 212, 204, 229, -- 215, 208, 207, 200, 219, 391, 233, 221, 200, 181, -- 391, 391, 149, 122, 86, 41, 391, 391, 245, 251, -- 259, 263, 267, 273, 280, 284, 292, 300, 304, 310, -- 318, 326 -+ 0, 393, 35, 392, 66, 391, 38, 107, 397, 401, -+ 55, 113, 377, 112, 111, 111, 114, 42, 376, 106, -+ 377, 347, 126, 120, 0, 147, 401, 0, 124, 0, -+ 137, 158, 170, 163, 401, 153, 401, 389, 401, 0, -+ 378, 120, 401, 131, 380, 386, 355, 139, 351, 355, -+ 351, 401, 401, 401, 401, 401, 367, 401, 401, 185, -+ 350, 346, 401, 364, 0, 185, 347, 189, 356, 355, -+ 0, 0, 330, 180, 366, 141, 372, 361, 332, 338, -+ 331, 341, 334, 326, 205, 331, 337, 329, 401, 341, -+ 167, 316, 401, 349, 348, 320, 328, 346, 180, 318, -+ -+ 324, 209, 324, 320, 322, 342, 338, 309, 306, 315, -+ 305, 315, 312, 192, 342, 341, 401, 293, 306, 282, -+ 268, 252, 255, 203, 285, 282, 272, 268, 252, 233, -+ 232, 239, 208, 107, 401, 401, 238, 211, 401, 211, -+ 212, 208, 228, 203, 215, 207, 233, 222, 212, 211, -+ 203, 227, 401, 237, 225, 204, 185, 401, 401, 149, -+ 128, 88, 42, 401, 401, 253, 259, 267, 271, 275, -+ 281, 288, 292, 300, 308, 312, 318, 326, 334 - } ; - --static yyconst flex_int16_t yy_def[173] = -+static yyconst flex_int16_t yy_def[180] = - { 0, -- 158, 1, 1, 3, 158, 5, 1, 1, 158, 158, -- 158, 158, 158, 159, 160, 161, 158, 158, 158, 158, -- 162, 158, 158, 158, 163, 162, 158, 164, 165, 164, -- 164, 158, 158, 158, 158, 159, 158, 159, 158, 166, -- 158, 161, 158, 161, 167, 168, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 162, 158, 158, 158, 158, -- 158, 158, 162, 164, 165, 164, 158, 158, 158, 169, -- 166, 170, 161, 167, 167, 168, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 164, 158, 158, 169, 170, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- -- 158, 164, 158, 158, 158, 158, 158, 158, 158, 171, -- 158, 164, 158, 158, 158, 158, 158, 158, 171, 158, -- 171, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 172, 158, 158, 158, 172, 158, 172, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 0, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158 -+ 165, 1, 1, 3, 165, 5, 1, 1, 165, 165, -+ 165, 165, 165, 166, 167, 168, 165, 165, 165, 165, -+ 169, 165, 165, 165, 170, 169, 165, 171, 172, 171, -+ 171, 165, 165, 165, 165, 166, 165, 166, 165, 173, -+ 165, 168, 165, 168, 174, 175, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 169, 165, 165, 165, -+ 165, 165, 165, 169, 171, 172, 171, 165, 165, 165, -+ 176, 173, 177, 168, 174, 174, 175, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 171, 165, 165, -+ 176, 177, 165, 165, 165, 165, 165, 165, 165, 165, -+ -+ 165, 165, 165, 165, 171, 165, 165, 165, 165, 165, -+ 165, 165, 165, 178, 165, 171, 165, 165, 165, 165, -+ 165, 165, 165, 178, 165, 178, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 179, 165, 165, -+ 165, 179, 165, 179, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 0, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165 - } ; - --static yyconst flex_int16_t yy_nxt[438] = -+static yyconst flex_int16_t yy_nxt[449] = - { 0, - 10, 11, 12, 11, 13, 14, 10, 15, 16, 10, - 10, 10, 17, 10, 10, 10, 10, 18, 19, 20, - 21, 21, 21, 21, 21, 10, 10, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -- 21, 21, 21, 10, 22, 10, 24, 25, 25, 25, -- 32, 33, 33, 157, 26, 34, 34, 34, 51, 52, -- 27, 26, 26, 26, 26, 10, 11, 12, 11, 13, -- 14, 28, 15, 16, 28, 28, 28, 24, 28, 28, -- 28, 10, 18, 19, 20, 29, 29, 29, 29, 29, -- 30, 10, 29, 29, 29, 29, 29, 29, 29, 29, -- -- 29, 29, 29, 29, 29, 29, 29, 29, 10, 22, -- 10, 23, 34, 34, 34, 37, 39, 43, 32, 33, -- 33, 45, 54, 55, 46, 59, 45, 64, 156, 46, -- 64, 64, 64, 79, 44, 38, 59, 57, 134, 47, -- 135, 48, 80, 49, 47, 50, 48, 99, 61, 43, -- 50, 110, 41, 67, 67, 67, 60, 63, 63, 63, -- 57, 155, 68, 69, 63, 37, 44, 66, 67, 67, -- 67, 63, 63, 63, 63, 73, 59, 68, 69, 70, -- 34, 34, 34, 43, 75, 38, 154, 92, 83, 83, -- 83, 64, 44, 120, 64, 64, 64, 67, 67, 67, -- -- 44, 57, 99, 68, 69, 107, 68, 69, 120, 127, -- 108, 153, 152, 121, 83, 83, 83, 133, 133, 133, -- 146, 133, 133, 133, 146, 140, 140, 140, 121, 141, -- 140, 140, 140, 151, 141, 158, 150, 149, 148, 144, -- 147, 143, 142, 139, 147, 36, 36, 36, 36, 36, -- 36, 36, 36, 40, 138, 137, 136, 40, 40, 42, -- 42, 42, 42, 42, 42, 42, 42, 56, 56, 56, -- 56, 62, 132, 62, 64, 131, 130, 64, 129, 64, -- 64, 65, 128, 158, 65, 65, 65, 65, 71, 127, -- 71, 71, 74, 74, 74, 74, 74, 74, 74, 74, -- -- 76, 76, 76, 76, 76, 76, 76, 76, 89, 126, -- 89, 90, 125, 90, 90, 124, 90, 90, 119, 119, -- 119, 119, 119, 119, 119, 119, 145, 145, 145, 145, -- 145, 145, 145, 145, 123, 122, 59, 59, 118, 117, -- 116, 115, 114, 113, 45, 112, 108, 111, 109, 106, -- 105, 104, 46, 103, 91, 87, 102, 101, 100, 98, -- 97, 96, 95, 94, 93, 77, 75, 91, 88, 87, -- 86, 57, 85, 84, 57, 82, 81, 78, 77, 75, -- 72, 158, 58, 57, 53, 35, 158, 31, 23, 23, -- 9, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158 -+ 21, 21, 21, 21, 10, 22, 10, 24, 25, 25, -+ 25, 32, 33, 33, 164, 26, 34, 34, 34, 52, -+ 53, 27, 26, 26, 26, 26, 10, 11, 12, 11, -+ 13, 14, 28, 15, 16, 28, 28, 28, 24, 28, -+ 28, 28, 10, 18, 19, 20, 29, 29, 29, 29, -+ 29, 30, 10, 29, 29, 29, 29, 29, 29, 29, -+ -+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -+ 10, 22, 10, 23, 34, 34, 34, 37, 39, 43, -+ 32, 33, 33, 45, 55, 56, 46, 60, 43, 45, -+ 65, 163, 46, 65, 65, 65, 44, 38, 60, 74, -+ 58, 47, 141, 48, 142, 44, 49, 47, 50, 48, -+ 76, 51, 62, 94, 50, 41, 44, 51, 37, 61, -+ 64, 64, 64, 58, 34, 34, 34, 64, 162, 80, -+ 67, 68, 68, 68, 64, 64, 64, 64, 38, 81, -+ 69, 70, 71, 68, 68, 68, 60, 161, 43, 69, -+ 70, 65, 69, 70, 65, 65, 65, 125, 85, 85, -+ -+ 85, 58, 68, 68, 68, 44, 102, 110, 125, 133, -+ 102, 69, 70, 111, 114, 160, 159, 126, 85, 85, -+ 85, 140, 140, 140, 140, 140, 140, 153, 126, 147, -+ 147, 147, 153, 148, 147, 147, 147, 158, 148, 165, -+ 157, 156, 155, 151, 150, 149, 146, 154, 145, 144, -+ 143, 139, 154, 36, 36, 36, 36, 36, 36, 36, -+ 36, 40, 138, 137, 136, 40, 40, 42, 42, 42, -+ 42, 42, 42, 42, 42, 57, 57, 57, 57, 63, -+ 135, 63, 65, 134, 165, 65, 133, 65, 65, 66, -+ 132, 131, 66, 66, 66, 66, 72, 130, 72, 72, -+ -+ 75, 75, 75, 75, 75, 75, 75, 75, 77, 77, -+ 77, 77, 77, 77, 77, 77, 91, 129, 91, 92, -+ 128, 92, 92, 127, 92, 92, 124, 124, 124, 124, -+ 124, 124, 124, 124, 152, 152, 152, 152, 152, 152, -+ 152, 152, 60, 60, 123, 122, 121, 120, 119, 118, -+ 117, 45, 116, 111, 115, 113, 112, 109, 108, 107, -+ 46, 106, 93, 89, 105, 104, 103, 101, 100, 99, -+ 98, 97, 96, 95, 78, 76, 93, 90, 89, 88, -+ 58, 87, 86, 58, 84, 83, 82, 79, 78, 76, -+ 73, 165, 59, 58, 54, 35, 165, 31, 23, 23, -+ -+ 9, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165 - } ; - --static yyconst flex_int16_t yy_chk[438] = -+static yyconst flex_int16_t yy_chk[449] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, -- 7, 7, 7, 156, 3, 11, 11, 11, 18, 18, -- 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, -+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, -+ 3, 7, 7, 7, 163, 3, 11, 11, 11, 18, -+ 18, 3, 3, 3, 3, 3, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -- 5, 8, 12, 12, 12, 14, 15, 16, 8, 8, -- 8, 17, 20, 20, 17, 23, 24, 29, 155, 24, -- 29, 29, 29, 48, 16, 14, 31, 29, 128, 17, -- 128, 17, 48, 17, 24, 17, 24, 99, 24, 42, -- 24, 99, 15, 33, 33, 33, 23, 26, 26, 26, -- 26, 154, 33, 33, 26, 36, 42, 31, 32, 32, -- 32, 26, 26, 26, 26, 44, 59, 32, 32, 32, -- 34, 34, 34, 73, 75, 36, 153, 75, 59, 59, -- 59, 65, 44, 110, 65, 65, 65, 67, 67, 67, -- -- 73, 65, 83, 89, 89, 97, 67, 67, 119, 127, -- 97, 150, 149, 110, 83, 83, 83, 133, 133, 133, -- 141, 127, 127, 127, 145, 136, 136, 136, 119, 136, -- 140, 140, 140, 148, 140, 147, 144, 143, 142, 139, -- 141, 138, 137, 135, 145, 159, 159, 159, 159, 159, -- 159, 159, 159, 160, 134, 132, 131, 160, 160, 161, -- 161, 161, 161, 161, 161, 161, 161, 162, 162, 162, -- 162, 163, 126, 163, 164, 125, 124, 164, 123, 164, -- 164, 165, 122, 121, 165, 165, 165, 165, 166, 120, -- 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, -- -- 168, 168, 168, 168, 168, 168, 168, 168, 169, 118, -- 169, 170, 117, 170, 170, 116, 170, 170, 171, 171, -- 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, -- 172, 172, 172, 172, 115, 114, 112, 111, 109, 108, -- 107, 106, 105, 104, 103, 102, 101, 100, 98, 96, -- 95, 94, 93, 92, 90, 88, 86, 85, 84, 82, -- 81, 80, 79, 78, 77, 76, 74, 72, 69, 68, -- 66, 63, 61, 60, 56, 50, 49, 47, 46, 45, -+ 5, 5, 5, 8, 12, 12, 12, 14, 15, 16, -+ 8, 8, 8, 17, 20, 20, 17, 23, 42, 24, -+ 29, 162, 24, 29, 29, 29, 16, 14, 31, 44, -+ 29, 17, 134, 17, 134, 42, 17, 24, 17, 24, -+ 76, 17, 24, 76, 24, 15, 44, 24, 36, 23, -+ 26, 26, 26, 26, 34, 34, 34, 26, 161, 48, -+ 31, 32, 32, 32, 26, 26, 26, 26, 36, 48, -+ 32, 32, 32, 33, 33, 33, 60, 160, 74, 91, -+ 91, 66, 33, 33, 66, 66, 66, 114, 60, 60, -+ -+ 60, 66, 68, 68, 68, 74, 85, 99, 124, 133, -+ 102, 68, 68, 99, 102, 157, 156, 114, 85, 85, -+ 85, 133, 133, 133, 140, 140, 140, 148, 124, 143, -+ 143, 143, 152, 143, 147, 147, 147, 155, 147, 154, -+ 151, 150, 149, 146, 145, 144, 142, 148, 141, 138, -+ 137, 132, 152, 166, 166, 166, 166, 166, 166, 166, -+ 166, 167, 131, 130, 129, 167, 167, 168, 168, 168, -+ 168, 168, 168, 168, 168, 169, 169, 169, 169, 170, -+ 128, 170, 171, 127, 126, 171, 125, 171, 171, 172, -+ 123, 122, 172, 172, 172, 172, 173, 121, 173, 173, -+ -+ 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, -+ 175, 175, 175, 175, 175, 175, 176, 120, 176, 177, -+ 119, 177, 177, 118, 177, 177, 178, 178, 178, 178, -+ 178, 178, 178, 178, 179, 179, 179, 179, 179, 179, -+ 179, 179, 116, 115, 113, 112, 111, 110, 109, 108, -+ 107, 106, 105, 104, 103, 101, 100, 98, 97, 96, -+ 95, 94, 92, 90, 88, 87, 86, 84, 83, 82, -+ 81, 80, 79, 78, 77, 75, 73, 70, 69, 67, -+ 64, 62, 61, 57, 51, 50, 49, 47, 46, 45, - 41, 38, 22, 21, 19, 13, 9, 6, 4, 2, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, - -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, -- 158, 158, 158, 158, 158, 158, 158 -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, -+ 165, 165, 165, 165, 165, 165, 165, 165 - } ; - - static yy_state_type yy_last_accepting_state; -@@ -662,7 +664,7 @@ static int dts_version = 1; - static void push_input_file(const char *filename); - static bool pop_input_file(void); - static void lexical_error(const char *fmt, ...); --#line 666 "dtc-lexer.lex.c" -+#line 668 "dtc-lexer.lex.c" - - #define INITIAL 0 - #define BYTESTRING 1 -@@ -704,7 +706,7 @@ FILE *yyget_out (void ); - - void yyset_out (FILE * out_str ); - --yy_size_t yyget_leng (void ); -+int yyget_leng (void ); - - char *yyget_text (void ); - -@@ -853,6 +855,10 @@ YY_DECL - register char *yy_cp, *yy_bp; - register int yy_act; - -+#line 68 "dtc-lexer.l" -+ -+#line 861 "dtc-lexer.lex.c" -+ - if ( !(yy_init) ) - { - (yy_init) = 1; -@@ -879,11 +885,6 @@ YY_DECL - yy_load_buffer_state( ); - } - -- { --#line 68 "dtc-lexer.l" -- --#line 886 "dtc-lexer.lex.c" -- - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = (yy_c_buf_p); -@@ -901,7 +902,7 @@ YY_DECL - yy_match: - do - { -- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; -+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - (yy_last_accepting_state) = yy_current_state; -@@ -910,13 +911,13 @@ yy_match: - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 159 ) -+ if ( yy_current_state >= 166 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } -- while ( yy_current_state != 158 ); -+ while ( yy_current_state != 165 ); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); - -@@ -951,39 +952,31 @@ case 2: - YY_RULE_SETUP - #line 75 "dtc-lexer.l" - { -- char *line, *fnstart, *fnend; -- struct data fn; -+ char *line, *tmp, *fn; - /* skip text before line # */ - line = yytext; - while (!isdigit((unsigned char)*line)) - line++; -- -- /* regexp ensures that first and list " -- * in the whole yytext are those at -- * beginning and end of the filename string */ -- fnstart = memchr(yytext, '"', yyleng); -- for (fnend = yytext + yyleng - 1; -- *fnend != '"'; fnend--) -- ; -- assert(fnstart && fnend && (fnend > fnstart)); -- -- fn = data_copy_escape_string(fnstart + 1, -- fnend - fnstart - 1); -- -- /* Don't allow nuls in filenames */ -- if (memchr(fn.val, '\0', fn.len - 1)) -- lexical_error("nul in line number directive"); -- -+ /* skip digits in line # */ -+ tmp = line; -+ while (!isspace((unsigned char)*tmp)) -+ tmp++; -+ /* "NULL"-terminate line # */ -+ *tmp = '\0'; -+ /* start of filename */ -+ fn = strchr(tmp + 1, '"') + 1; -+ /* strip trailing " from filename */ -+ tmp = strchr(fn, '"'); -+ *tmp = 0; - /* -1 since #line is the number of the next line */ -- srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); -- data_free(fn); -+ srcpos_set_line(xstrdup(fn), atoi(line) - 1); - } - YY_BREAK - case YY_STATE_EOF(INITIAL): - case YY_STATE_EOF(BYTESTRING): - case YY_STATE_EOF(PROPNODENAME): - case YY_STATE_EOF(V1): --#line 104 "dtc-lexer.l" -+#line 96 "dtc-lexer.l" - { - if (!pop_input_file()) { - yyterminate(); -@@ -993,7 +986,7 @@ case YY_STATE_EOF(V1): - case 3: - /* rule 3 can match eol */ - YY_RULE_SETUP --#line 110 "dtc-lexer.l" -+#line 102 "dtc-lexer.l" - { - DPRINT("String: %s\n", yytext); - yylval.data = data_copy_escape_string(yytext+1, -@@ -1003,7 +996,7 @@ YY_RULE_SETUP - YY_BREAK - case 4: - YY_RULE_SETUP --#line 117 "dtc-lexer.l" -+#line 109 "dtc-lexer.l" - { - DPRINT("Keyword: /dts-v1/\n"); - dts_version = 1; -@@ -1013,25 +1006,33 @@ YY_RULE_SETUP - YY_BREAK - case 5: - YY_RULE_SETUP --#line 124 "dtc-lexer.l" -+#line 116 "dtc-lexer.l" -+{ -+ DPRINT("Keyword: /plugin/\n"); -+ return DT_PLUGIN; -+ } -+ YY_BREAK -+case 6: -+YY_RULE_SETUP -+#line 121 "dtc-lexer.l" - { - DPRINT("Keyword: /memreserve/\n"); - BEGIN_DEFAULT(); - return DT_MEMRESERVE; - } - YY_BREAK --case 6: -+case 7: - YY_RULE_SETUP --#line 130 "dtc-lexer.l" -+#line 127 "dtc-lexer.l" - { - DPRINT("Keyword: /bits/\n"); - BEGIN_DEFAULT(); - return DT_BITS; - } - YY_BREAK --case 7: -+case 8: - YY_RULE_SETUP --#line 136 "dtc-lexer.l" -+#line 133 "dtc-lexer.l" - { - DPRINT("Keyword: /delete-property/\n"); - DPRINT("\n"); -@@ -1039,9 +1040,9 @@ YY_RULE_SETUP - return DT_DEL_PROP; - } - YY_BREAK --case 8: -+case 9: - YY_RULE_SETUP --#line 143 "dtc-lexer.l" -+#line 140 "dtc-lexer.l" - { - DPRINT("Keyword: /delete-node/\n"); - DPRINT("\n"); -@@ -1049,9 +1050,9 @@ YY_RULE_SETUP - return DT_DEL_NODE; - } - YY_BREAK --case 9: -+case 10: - YY_RULE_SETUP --#line 150 "dtc-lexer.l" -+#line 147 "dtc-lexer.l" - { - DPRINT("Label: %s\n", yytext); - yylval.labelref = xstrdup(yytext); -@@ -1059,9 +1060,9 @@ YY_RULE_SETUP - return DT_LABEL; - } - YY_BREAK --case 10: -+case 11: - YY_RULE_SETUP --#line 157 "dtc-lexer.l" -+#line 154 "dtc-lexer.l" - { - char *e; - DPRINT("Integer Literal: '%s'\n", yytext); -@@ -1069,10 +1070,7 @@ YY_RULE_SETUP - errno = 0; - yylval.integer = strtoull(yytext, &e, 0); - -- if (*e && e[strspn(e, "UL")]) { -- lexical_error("Bad integer literal '%s'", -- yytext); -- } -+ assert(!(*e) || !e[strspn(e, "UL")]); - - if (errno == ERANGE) - lexical_error("Integer literal '%s' out of range", -@@ -1084,10 +1082,10 @@ YY_RULE_SETUP - return DT_LITERAL; - } - YY_BREAK --case 11: --/* rule 11 can match eol */ -+case 12: -+/* rule 12 can match eol */ - YY_RULE_SETUP --#line 179 "dtc-lexer.l" -+#line 173 "dtc-lexer.l" - { - struct data d; - DPRINT("Character literal: %s\n", yytext); -@@ -1109,18 +1107,18 @@ YY_RULE_SETUP - return DT_CHAR_LITERAL; - } - YY_BREAK --case 12: -+case 13: - YY_RULE_SETUP --#line 200 "dtc-lexer.l" -+#line 194 "dtc-lexer.l" - { /* label reference */ - DPRINT("Ref: %s\n", yytext+1); - yylval.labelref = xstrdup(yytext+1); - return DT_REF; - } - YY_BREAK --case 13: -+case 14: - YY_RULE_SETUP --#line 206 "dtc-lexer.l" -+#line 200 "dtc-lexer.l" - { /* new-style path reference */ - yytext[yyleng-1] = '\0'; - DPRINT("Ref: %s\n", yytext+2); -@@ -1128,27 +1126,27 @@ YY_RULE_SETUP - return DT_REF; - } - YY_BREAK --case 14: -+case 15: - YY_RULE_SETUP --#line 213 "dtc-lexer.l" -+#line 207 "dtc-lexer.l" - { - yylval.byte = strtol(yytext, NULL, 16); - DPRINT("Byte: %02x\n", (int)yylval.byte); - return DT_BYTE; - } - YY_BREAK --case 15: -+case 16: - YY_RULE_SETUP --#line 219 "dtc-lexer.l" -+#line 213 "dtc-lexer.l" - { - DPRINT("/BYTESTRING\n"); - BEGIN_DEFAULT(); - return ']'; - } - YY_BREAK --case 16: -+case 17: - YY_RULE_SETUP --#line 225 "dtc-lexer.l" -+#line 219 "dtc-lexer.l" - { - DPRINT("PropNodeName: %s\n", yytext); - yylval.propnodename = xstrdup((yytext[0] == '\\') ? -@@ -1157,75 +1155,75 @@ YY_RULE_SETUP - return DT_PROPNODENAME; - } - YY_BREAK --case 17: -+case 18: - YY_RULE_SETUP --#line 233 "dtc-lexer.l" -+#line 227 "dtc-lexer.l" - { - DPRINT("Binary Include\n"); - return DT_INCBIN; - } - YY_BREAK --case 18: --/* rule 18 can match eol */ --YY_RULE_SETUP --#line 238 "dtc-lexer.l" --/* eat whitespace */ -- YY_BREAK - case 19: - /* rule 19 can match eol */ - YY_RULE_SETUP --#line 239 "dtc-lexer.l" --/* eat C-style comments */ -+#line 232 "dtc-lexer.l" -+/* eat whitespace */ - YY_BREAK - case 20: - /* rule 20 can match eol */ - YY_RULE_SETUP --#line 240 "dtc-lexer.l" --/* eat C++-style comments */ -+#line 233 "dtc-lexer.l" -+/* eat C-style comments */ - YY_BREAK - case 21: -+/* rule 21 can match eol */ - YY_RULE_SETUP --#line 242 "dtc-lexer.l" --{ return DT_LSHIFT; }; -+#line 234 "dtc-lexer.l" -+/* eat C++-style comments */ - YY_BREAK - case 22: - YY_RULE_SETUP --#line 243 "dtc-lexer.l" --{ return DT_RSHIFT; }; -+#line 236 "dtc-lexer.l" -+{ return DT_LSHIFT; }; - YY_BREAK - case 23: - YY_RULE_SETUP --#line 244 "dtc-lexer.l" --{ return DT_LE; }; -+#line 237 "dtc-lexer.l" -+{ return DT_RSHIFT; }; - YY_BREAK - case 24: - YY_RULE_SETUP --#line 245 "dtc-lexer.l" --{ return DT_GE; }; -+#line 238 "dtc-lexer.l" -+{ return DT_LE; }; - YY_BREAK - case 25: - YY_RULE_SETUP --#line 246 "dtc-lexer.l" --{ return DT_EQ; }; -+#line 239 "dtc-lexer.l" -+{ return DT_GE; }; - YY_BREAK - case 26: - YY_RULE_SETUP --#line 247 "dtc-lexer.l" --{ return DT_NE; }; -+#line 240 "dtc-lexer.l" -+{ return DT_EQ; }; - YY_BREAK - case 27: - YY_RULE_SETUP --#line 248 "dtc-lexer.l" --{ return DT_AND; }; -+#line 241 "dtc-lexer.l" -+{ return DT_NE; }; - YY_BREAK - case 28: - YY_RULE_SETUP --#line 249 "dtc-lexer.l" --{ return DT_OR; }; -+#line 242 "dtc-lexer.l" -+{ return DT_AND; }; - YY_BREAK - case 29: - YY_RULE_SETUP --#line 251 "dtc-lexer.l" -+#line 243 "dtc-lexer.l" -+{ return DT_OR; }; -+ YY_BREAK -+case 30: -+YY_RULE_SETUP -+#line 245 "dtc-lexer.l" - { - DPRINT("Char: %c (\\x%02x)\n", yytext[0], - (unsigned)yytext[0]); -@@ -1241,12 +1239,12 @@ YY_RULE_SETUP - return yytext[0]; - } - YY_BREAK --case 30: -+case 31: - YY_RULE_SETUP --#line 266 "dtc-lexer.l" -+#line 260 "dtc-lexer.l" - ECHO; - YY_BREAK --#line 1250 "dtc-lexer.lex.c" -+#line 1248 "dtc-lexer.lex.c" - - case YY_END_OF_BUFFER: - { -@@ -1376,7 +1374,6 @@ ECHO; - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ -- } /* end of user's declarations */ - } /* end of yylex */ - - /* yy_get_next_buffer - try to read in a new buffer -@@ -1432,21 +1429,21 @@ static int yy_get_next_buffer (void) - - else - { -- yy_size_t num_to_read = -+ int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ - - /* just a shorter name for the current buffer */ -- YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; -+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; - - int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { -- yy_size_t new_size = b->yy_buf_size * 2; -+ int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; -@@ -1477,7 +1474,7 @@ static int yy_get_next_buffer (void) - - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), -- (yy_n_chars), num_to_read ); -+ (yy_n_chars), (size_t) num_to_read ); - - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } -@@ -1539,7 +1536,7 @@ static int yy_get_next_buffer (void) - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 159 ) -+ if ( yy_current_state >= 166 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -@@ -1567,13 +1564,13 @@ static int yy_get_next_buffer (void) - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; -- if ( yy_current_state >= 159 ) -+ if ( yy_current_state >= 166 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; -- yy_is_jam = (yy_current_state == 158); -+ yy_is_jam = (yy_current_state == 165); - -- return yy_is_jam ? 0 : yy_current_state; -+ return yy_is_jam ? 0 : yy_current_state; - } - - #ifndef YY_NO_INPUT -@@ -1600,7 +1597,7 @@ static int yy_get_next_buffer (void) - - else - { /* need more input */ -- yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); -+ int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); - - switch ( yy_get_next_buffer( ) ) -@@ -1874,7 +1871,7 @@ void yypop_buffer_state (void) - */ - static void yyensure_buffer_stack (void) - { -- yy_size_t num_to_alloc; -+ int num_to_alloc; - - if (!(yy_buffer_stack)) { - -@@ -1971,12 +1968,12 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) - * - * @return the newly allocated buffer state object. - */ --YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) -+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; -- yy_size_t i; -+ int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; -@@ -2058,7 +2055,7 @@ FILE *yyget_out (void) - /** Get the length of the current token. - * - */ --yy_size_t yyget_leng (void) -+int yyget_leng (void) - { - return yyleng; - } -@@ -2206,7 +2203,7 @@ void yyfree (void * ptr ) - - #define YYTABLES_NAME "yytables" - --#line 265 "dtc-lexer.l" -+#line 260 "dtc-lexer.l" - - - -diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped -index 31cec50a12650a254a639a6a291ce74f07a0e2c2..844c4628962d0e3e2860edf1315bec4e21b7a810 100644 ---- a/scripts/dtc/dtc-parser.tab.c_shipped -+++ b/scripts/dtc/dtc-parser.tab.c_shipped -@@ -65,6 +65,7 @@ - #line 20 "dtc-parser.y" /* yacc.c:339 */ - - #include -+#include - - #include "dtc.h" - #include "srcpos.h" -@@ -80,7 +81,7 @@ extern void yyerror(char const *s); - extern struct boot_info *the_boot_info; - extern bool treesource_error; - --#line 84 "dtc-parser.tab.c" /* yacc.c:339 */ -+#line 85 "dtc-parser.tab.c" /* yacc.c:339 */ - - # ifndef YY_NULLPTR - # if defined __cplusplus && 201103L <= __cplusplus -@@ -116,26 +117,27 @@ extern int yydebug; - enum yytokentype - { - DT_V1 = 258, -- DT_MEMRESERVE = 259, -- DT_LSHIFT = 260, -- DT_RSHIFT = 261, -- DT_LE = 262, -- DT_GE = 263, -- DT_EQ = 264, -- DT_NE = 265, -- DT_AND = 266, -- DT_OR = 267, -- DT_BITS = 268, -- DT_DEL_PROP = 269, -- DT_DEL_NODE = 270, -- DT_PROPNODENAME = 271, -- DT_LITERAL = 272, -- DT_CHAR_LITERAL = 273, -- DT_BYTE = 274, -- DT_STRING = 275, -- DT_LABEL = 276, -- DT_REF = 277, -- DT_INCBIN = 278 -+ DT_PLUGIN = 259, -+ DT_MEMRESERVE = 260, -+ DT_LSHIFT = 261, -+ DT_RSHIFT = 262, -+ DT_LE = 263, -+ DT_GE = 264, -+ DT_EQ = 265, -+ DT_NE = 266, -+ DT_AND = 267, -+ DT_OR = 268, -+ DT_BITS = 269, -+ DT_DEL_PROP = 270, -+ DT_DEL_NODE = 271, -+ DT_PROPNODENAME = 272, -+ DT_LITERAL = 273, -+ DT_CHAR_LITERAL = 274, -+ DT_BYTE = 275, -+ DT_STRING = 276, -+ DT_LABEL = 277, -+ DT_REF = 278, -+ DT_INCBIN = 279 - }; - #endif - -@@ -144,7 +146,7 @@ extern int yydebug; - typedef union YYSTYPE YYSTYPE; - union YYSTYPE - { --#line 38 "dtc-parser.y" /* yacc.c:355 */ -+#line 39 "dtc-parser.y" /* yacc.c:355 */ - - char *propnodename; - char *labelref; -@@ -162,8 +164,9 @@ union YYSTYPE - struct node *nodelist; - struct reserve_info *re; - uint64_t integer; -+ bool is_plugin; - --#line 167 "dtc-parser.tab.c" /* yacc.c:355 */ -+#line 170 "dtc-parser.tab.c" /* yacc.c:355 */ - }; - # define YYSTYPE_IS_TRIVIAL 1 - # define YYSTYPE_IS_DECLARED 1 -@@ -192,7 +195,7 @@ int yyparse (void); - - /* Copy the second part of user declarations. */ - --#line 196 "dtc-parser.tab.c" /* yacc.c:358 */ -+#line 199 "dtc-parser.tab.c" /* yacc.c:358 */ - - #ifdef short - # undef short -@@ -439,18 +442,18 @@ union yyalloc - #define YYLAST 136 - - /* YYNTOKENS -- Number of terminals. */ --#define YYNTOKENS 47 -+#define YYNTOKENS 48 - /* YYNNTS -- Number of nonterminals. */ --#define YYNNTS 28 -+#define YYNNTS 29 - /* YYNRULES -- Number of rules. */ --#define YYNRULES 80 -+#define YYNRULES 82 - /* YYNSTATES -- Number of states. */ --#define YYNSTATES 144 -+#define YYNSTATES 147 - - /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned - by yylex, with out-of-bounds checking. */ - #define YYUNDEFTOK 2 --#define YYMAXUTOK 278 -+#define YYMAXUTOK 279 - - #define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -@@ -462,16 +465,16 @@ static const yytype_uint8 yytranslate[] = - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -- 2, 2, 2, 46, 2, 2, 2, 44, 40, 2, -- 32, 34, 43, 41, 33, 42, 2, 25, 2, 2, -- 2, 2, 2, 2, 2, 2, 2, 2, 37, 24, -- 35, 28, 29, 36, 2, 2, 2, 2, 2, 2, -+ 2, 2, 2, 47, 2, 2, 2, 45, 41, 2, -+ 33, 35, 44, 42, 34, 43, 2, 26, 2, 2, -+ 2, 2, 2, 2, 2, 2, 2, 2, 38, 25, -+ 36, 29, 30, 37, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -- 2, 30, 2, 31, 39, 2, 2, 2, 2, 2, -+ 2, 31, 2, 32, 40, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -- 2, 2, 2, 26, 38, 27, 45, 2, 2, 2, -+ 2, 2, 2, 27, 39, 28, 46, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -@@ -486,22 +489,22 @@ static const yytype_uint8 yytranslate[] = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -- 15, 16, 17, 18, 19, 20, 21, 22, 23 -+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 - }; - - #if YYDEBUG - /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ - static const yytype_uint16 yyrline[] = - { -- 0, 104, 104, 113, 116, 123, 127, 135, 139, 144, -- 155, 165, 180, 188, 191, 198, 202, 206, 210, 218, -- 222, 226, 230, 234, 250, 260, 268, 271, 275, 282, -- 298, 303, 322, 336, 343, 344, 345, 352, 356, 357, -- 361, 362, 366, 367, 371, 372, 376, 377, 381, 382, -- 386, 387, 388, 392, 393, 394, 395, 396, 400, 401, -- 402, 406, 407, 408, 412, 413, 422, 431, 435, 436, -- 437, 438, 443, 446, 450, 458, 461, 465, 473, 477, -- 481 -+ 0, 108, 108, 118, 121, 129, 132, 139, 143, 151, -+ 155, 160, 171, 181, 196, 204, 207, 214, 218, 222, -+ 226, 234, 238, 242, 246, 250, 266, 276, 284, 287, -+ 291, 298, 314, 319, 338, 352, 359, 360, 361, 368, -+ 372, 373, 377, 378, 382, 383, 387, 388, 392, 393, -+ 397, 398, 402, 403, 404, 408, 409, 410, 411, 412, -+ 416, 417, 418, 422, 423, 424, 428, 429, 430, 431, -+ 435, 436, 437, 438, 443, 446, 450, 458, 461, 465, -+ 473, 477, 481 - }; - #endif - -@@ -510,19 +513,19 @@ static const yytype_uint16 yyrline[] = - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ - static const char *const yytname[] = - { -- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT", -- "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR", -- "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL", -- "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", -- "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", "']'", -- "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", "'+'", -- "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile", -- "memreserves", "memreserve", "devicetree", "nodedef", "proplist", -- "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim", -- "integer_expr", "integer_trinary", "integer_or", "integer_and", -- "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq", -- "integer_rela", "integer_shift", "integer_add", "integer_mul", -- "integer_unary", "bytestring", "subnodes", "subnode", YY_NULLPTR -+ "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE", -+ "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", -+ "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", -+ "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", -+ "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", -+ "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", -+ "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile", -+ "plugindecl", "memreserves", "memreserve", "devicetree", "nodedef", -+ "proplist", "propdef", "propdata", "propdataprefix", "arrayprefix", -+ "integer_prim", "integer_expr", "integer_trinary", "integer_or", -+ "integer_and", "integer_bitor", "integer_bitxor", "integer_bitand", -+ "integer_eq", "integer_rela", "integer_shift", "integer_add", -+ "integer_mul", "integer_unary", "bytestring", "subnodes", "subnode", YY_NULLPTR - }; - #endif - -@@ -533,16 +536,16 @@ static const yytype_uint16 yytoknum[] = - { - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, -- 275, 276, 277, 278, 59, 47, 123, 125, 61, 62, -- 91, 93, 40, 44, 41, 60, 63, 58, 124, 94, -- 38, 43, 45, 42, 37, 126, 33 -+ 275, 276, 277, 278, 279, 59, 47, 123, 125, 61, -+ 62, 91, 93, 40, 44, 41, 60, 63, 58, 124, -+ 94, 38, 43, 45, 42, 37, 126, 33 - }; - # endif - --#define YYPACT_NINF -81 -+#define YYPACT_NINF -84 - - #define yypact_value_is_default(Yystate) \ -- (!!((Yystate) == (-81))) -+ (!!((Yystate) == (-84))) - - #define YYTABLE_NINF -1 - -@@ -553,21 +556,21 @@ static const yytype_uint16 yytoknum[] = - STATE-NUM. */ - static const yytype_int8 yypact[] = - { -- 16, -11, 21, 10, -81, 25, 10, 19, 10, -81, -- -81, -9, 25, -81, 2, 51, -81, -9, -9, -9, -- -81, 1, -81, -6, 50, 14, 28, 29, 36, 3, -- 58, 44, -3, -81, 47, -81, -81, 65, 68, 2, -- 2, -81, -81, -81, -81, -9, -9, -9, -9, -9, -- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -- -9, -9, -9, -9, -81, 63, 69, 2, -81, -81, -- 50, 57, 14, 28, 29, 36, 3, 3, 58, 58, -- 58, 58, 44, 44, -3, -3, -81, -81, -81, 79, -- 80, -8, 63, -81, 72, 63, -81, -81, -9, 76, -- 77, -81, -81, -81, -81, -81, 78, -81, -81, -81, -- -81, -81, 35, 4, -81, -81, -81, -81, 86, -81, -- -81, -81, 73, -81, -81, 33, 71, 84, 39, -81, -- -81, -81, -81, -81, 41, -81, -81, -81, 25, -81, -- 74, 25, 75, -81 -+ 15, -12, 35, 42, -84, 27, 9, -84, 24, 9, -+ 43, 9, -84, -84, -10, 24, -84, 60, 44, -84, -+ -10, -10, -10, -84, 55, -84, -7, 52, 53, 51, -+ 54, 10, 2, 38, 37, -4, -84, 68, -84, -84, -+ 71, 73, 60, 60, -84, -84, -84, -84, -10, -10, -+ -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, -+ -10, -10, -10, -10, -10, -10, -10, -84, 56, 72, -+ 60, -84, -84, 52, 61, 53, 51, 54, 10, 2, -+ 2, 38, 38, 38, 38, 37, 37, -4, -4, -84, -+ -84, -84, 81, 83, 34, 56, -84, 74, 56, -84, -+ -84, -10, 76, 78, -84, -84, -84, -84, -84, 79, -+ -84, -84, -84, -84, -84, -6, 3, -84, -84, -84, -+ -84, 87, -84, -84, -84, 75, -84, -84, 32, 70, -+ 86, 36, -84, -84, -84, -84, -84, 47, -84, -84, -+ -84, 24, -84, 77, 24, 80, -84 - }; - - /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. -@@ -575,37 +578,37 @@ static const yytype_int8 yypact[] = - means the default is an error. */ - static const yytype_uint8 yydefact[] = - { -- 0, 0, 0, 3, 1, 0, 0, 0, 3, 34, -- 35, 0, 0, 6, 0, 2, 4, 0, 0, 0, -- 68, 0, 37, 38, 40, 42, 44, 46, 48, 50, -- 53, 60, 63, 67, 0, 13, 7, 0, 0, 0, -- 0, 69, 70, 71, 36, 0, 0, 0, 0, 0, -+ 0, 0, 0, 3, 1, 0, 5, 4, 0, 0, -+ 0, 5, 36, 37, 0, 0, 8, 0, 2, 6, -+ 0, 0, 0, 70, 0, 39, 40, 42, 44, 46, -+ 48, 50, 52, 55, 62, 65, 69, 0, 15, 9, -+ 0, 0, 0, 0, 71, 72, 73, 38, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 5, 75, 0, 0, 10, 8, -- 41, 0, 43, 45, 47, 49, 51, 52, 56, 57, -- 55, 54, 58, 59, 61, 62, 65, 64, 66, 0, -- 0, 0, 0, 14, 0, 75, 11, 9, 0, 0, -- 0, 16, 26, 78, 18, 80, 0, 77, 76, 39, -- 17, 79, 0, 0, 12, 25, 15, 27, 0, 19, -- 28, 22, 0, 72, 30, 0, 0, 0, 0, 33, -- 32, 20, 31, 29, 0, 73, 74, 21, 0, 24, -- 0, 0, 0, 23 -+ 0, 0, 0, 0, 0, 0, 0, 7, 77, 0, -+ 0, 12, 10, 43, 0, 45, 47, 49, 51, 53, -+ 54, 58, 59, 57, 56, 60, 61, 63, 64, 67, -+ 66, 68, 0, 0, 0, 0, 16, 0, 77, 13, -+ 11, 0, 0, 0, 18, 28, 80, 20, 82, 0, -+ 79, 78, 41, 19, 81, 0, 0, 14, 27, 17, -+ 29, 0, 21, 30, 24, 0, 74, 32, 0, 0, -+ 0, 0, 35, 34, 22, 33, 31, 0, 75, 76, -+ 23, 0, 26, 0, 0, 0, 25 - }; - - /* YYPGOTO[NTERM-NUM]. */ - static const yytype_int8 yypgoto[] = - { -- -81, -81, 100, 104, -81, -38, -81, -80, -81, -81, -- -81, -5, 66, 13, -81, 70, 67, 81, 64, 82, -- 37, 27, 34, 38, -14, -81, 22, 24 -+ -84, -84, -84, 98, 101, -84, -41, -84, -83, -84, -+ -84, -84, -8, 63, 12, -84, 66, 67, 65, 69, -+ 82, 29, 18, 25, 26, -17, -84, 20, 28 - }; - - /* YYDEFGOTO[NTERM-NUM]. */ - static const yytype_int16 yydefgoto[] = - { -- -1, 2, 7, 8, 15, 36, 65, 93, 112, 113, -- 125, 20, 21, 22, 23, 24, 25, 26, 27, 28, -- 29, 30, 31, 32, 33, 128, 94, 95 -+ -1, 2, 6, 10, 11, 18, 39, 68, 96, 115, -+ 116, 128, 23, 24, 25, 26, 27, 28, 29, 30, -+ 31, 32, 33, 34, 35, 36, 131, 97, 98 - }; - - /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If -@@ -613,87 +616,87 @@ static const yytype_int16 yydefgoto[] = - number is the opposite. If YYTABLE_NINF, syntax error. */ - static const yytype_uint8 yytable[] = - { -- 12, 68, 69, 41, 42, 43, 45, 34, 9, 10, -- 53, 54, 104, 3, 5, 107, 101, 118, 35, 1, -- 102, 4, 61, 11, 119, 120, 121, 122, 35, 97, -- 46, 6, 55, 17, 123, 44, 18, 19, 56, 124, -- 62, 63, 9, 10, 14, 51, 52, 86, 87, 88, -- 9, 10, 48, 103, 129, 130, 115, 11, 135, 116, -- 136, 47, 131, 57, 58, 11, 37, 49, 117, 50, -- 137, 64, 38, 39, 138, 139, 40, 89, 90, 91, -- 78, 79, 80, 81, 92, 59, 60, 66, 76, 77, -- 67, 82, 83, 96, 98, 99, 100, 84, 85, 106, -- 110, 111, 114, 126, 134, 127, 133, 141, 16, 143, -- 13, 109, 71, 74, 72, 70, 105, 108, 0, 0, -- 132, 0, 0, 0, 0, 0, 0, 0, 0, 73, -- 0, 0, 75, 140, 0, 0, 142 -+ 15, 71, 72, 44, 45, 46, 48, 37, 12, 13, -+ 56, 57, 107, 3, 8, 110, 118, 121, 1, 119, -+ 54, 55, 64, 14, 122, 123, 124, 125, 120, 100, -+ 49, 9, 58, 20, 126, 4, 21, 22, 59, 127, -+ 65, 66, 12, 13, 60, 61, 5, 89, 90, 91, -+ 12, 13, 7, 106, 132, 133, 138, 14, 139, 104, -+ 40, 38, 134, 105, 50, 14, 41, 42, 140, 17, -+ 43, 92, 93, 94, 81, 82, 83, 84, 95, 62, -+ 63, 141, 142, 79, 80, 85, 86, 38, 87, 88, -+ 47, 52, 51, 67, 69, 53, 70, 99, 102, 101, -+ 103, 113, 109, 114, 117, 129, 136, 137, 130, 19, -+ 16, 144, 74, 112, 73, 146, 76, 75, 111, 0, -+ 135, 77, 0, 108, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 143, 0, 78, 145 - }; - - static const yytype_int16 yycheck[] = - { -- 5, 39, 40, 17, 18, 19, 12, 12, 17, 18, -- 7, 8, 92, 24, 4, 95, 24, 13, 26, 3, -- 28, 0, 25, 32, 20, 21, 22, 23, 26, 67, -- 36, 21, 29, 42, 30, 34, 45, 46, 35, 35, -- 43, 44, 17, 18, 25, 9, 10, 61, 62, 63, -- 17, 18, 38, 91, 21, 22, 21, 32, 19, 24, -- 21, 11, 29, 5, 6, 32, 15, 39, 33, 40, -- 31, 24, 21, 22, 33, 34, 25, 14, 15, 16, -- 53, 54, 55, 56, 21, 41, 42, 22, 51, 52, -- 22, 57, 58, 24, 37, 16, 16, 59, 60, 27, -- 24, 24, 24, 17, 20, 32, 35, 33, 8, 34, -- 6, 98, 46, 49, 47, 45, 92, 95, -1, -1, -- 125, -1, -1, -1, -1, -1, -1, -1, -1, 48, -- -1, -1, 50, 138, -1, -1, 141 -+ 8, 42, 43, 20, 21, 22, 13, 15, 18, 19, -+ 8, 9, 95, 25, 5, 98, 22, 14, 3, 25, -+ 10, 11, 26, 33, 21, 22, 23, 24, 34, 70, -+ 37, 22, 30, 43, 31, 0, 46, 47, 36, 36, -+ 44, 45, 18, 19, 6, 7, 4, 64, 65, 66, -+ 18, 19, 25, 94, 22, 23, 20, 33, 22, 25, -+ 16, 27, 30, 29, 12, 33, 22, 23, 32, 26, -+ 26, 15, 16, 17, 56, 57, 58, 59, 22, 42, -+ 43, 34, 35, 54, 55, 60, 61, 27, 62, 63, -+ 35, 40, 39, 25, 23, 41, 23, 25, 17, 38, -+ 17, 25, 28, 25, 25, 18, 36, 21, 33, 11, -+ 9, 34, 49, 101, 48, 35, 51, 50, 98, -1, -+ 128, 52, -1, 95, -1, -1, -1, -1, -1, -1, -+ -1, -1, -1, 141, -1, 53, 144 - }; - - /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ - static const yytype_uint8 yystos[] = - { -- 0, 3, 48, 24, 0, 4, 21, 49, 50, 17, -- 18, 32, 58, 50, 25, 51, 49, 42, 45, 46, -- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, -- 68, 69, 70, 71, 58, 26, 52, 15, 21, 22, -- 25, 71, 71, 71, 34, 12, 36, 11, 38, 39, -- 40, 9, 10, 7, 8, 29, 35, 5, 6, 41, -- 42, 25, 43, 44, 24, 53, 22, 22, 52, 52, -- 62, 59, 63, 64, 65, 66, 67, 67, 68, 68, -- 68, 68, 69, 69, 70, 70, 71, 71, 71, 14, -- 15, 16, 21, 54, 73, 74, 24, 52, 37, 16, -- 16, 24, 28, 52, 54, 74, 27, 54, 73, 60, -- 24, 24, 55, 56, 24, 21, 24, 33, 13, 20, -- 21, 22, 23, 30, 35, 57, 17, 32, 72, 21, -- 22, 29, 58, 35, 20, 19, 21, 31, 33, 34, -- 58, 33, 58, 34 -+ 0, 3, 49, 25, 0, 4, 50, 25, 5, 22, -+ 51, 52, 18, 19, 33, 60, 52, 26, 53, 51, -+ 43, 46, 47, 60, 61, 62, 63, 64, 65, 66, -+ 67, 68, 69, 70, 71, 72, 73, 60, 27, 54, -+ 16, 22, 23, 26, 73, 73, 73, 35, 13, 37, -+ 12, 39, 40, 41, 10, 11, 8, 9, 30, 36, -+ 6, 7, 42, 43, 26, 44, 45, 25, 55, 23, -+ 23, 54, 54, 64, 61, 65, 66, 67, 68, 69, -+ 69, 70, 70, 70, 70, 71, 71, 72, 72, 73, -+ 73, 73, 15, 16, 17, 22, 56, 75, 76, 25, -+ 54, 38, 17, 17, 25, 29, 54, 56, 76, 28, -+ 56, 75, 62, 25, 25, 57, 58, 25, 22, 25, -+ 34, 14, 21, 22, 23, 24, 31, 36, 59, 18, -+ 33, 74, 22, 23, 30, 60, 36, 21, 20, 22, -+ 32, 34, 35, 60, 34, 60, 35 - }; - - /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ - static const yytype_uint8 yyr1[] = - { -- 0, 47, 48, 49, 49, 50, 50, 51, 51, 51, -- 51, 51, 52, 53, 53, 54, 54, 54, 54, 55, -- 55, 55, 55, 55, 55, 55, 56, 56, 56, 57, -- 57, 57, 57, 57, 58, 58, 58, 59, 60, 60, -- 61, 61, 62, 62, 63, 63, 64, 64, 65, 65, -- 66, 66, 66, 67, 67, 67, 67, 67, 68, 68, -- 68, 69, 69, 69, 70, 70, 70, 70, 71, 71, -- 71, 71, 72, 72, 72, 73, 73, 73, 74, 74, -- 74 -+ 0, 48, 49, 50, 50, 51, 51, 52, 52, 53, -+ 53, 53, 53, 53, 54, 55, 55, 56, 56, 56, -+ 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, -+ 58, 59, 59, 59, 59, 59, 60, 60, 60, 61, -+ 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, -+ 67, 67, 68, 68, 68, 69, 69, 69, 69, 69, -+ 70, 70, 70, 71, 71, 71, 72, 72, 72, 72, -+ 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, -+ 76, 76, 76 - }; - - /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ - static const yytype_uint8 yyr2[] = - { -- 0, 2, 4, 0, 2, 4, 2, 2, 3, 4, -- 3, 4, 5, 0, 2, 4, 2, 3, 2, 2, -- 3, 4, 2, 9, 5, 2, 0, 2, 2, 3, -- 1, 2, 2, 2, 1, 1, 3, 1, 1, 5, -- 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, -- 1, 3, 3, 1, 3, 3, 3, 3, 3, 3, -- 1, 3, 3, 1, 3, 3, 3, 1, 1, 2, -- 2, 2, 0, 2, 2, 0, 2, 2, 2, 3, -- 2 -+ 0, 2, 5, 0, 2, 0, 2, 4, 2, 2, -+ 3, 4, 3, 4, 5, 0, 2, 4, 2, 3, -+ 2, 2, 3, 4, 2, 9, 5, 2, 0, 2, -+ 2, 3, 1, 2, 2, 2, 1, 1, 3, 1, -+ 1, 5, 1, 3, 1, 3, 1, 3, 1, 3, -+ 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, -+ 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, -+ 1, 2, 2, 2, 0, 2, 2, 0, 2, 2, -+ 2, 3, 2 - }; - - -@@ -1463,65 +1466,82 @@ yyreduce: - switch (yyn) - { - case 2: --#line 105 "dtc-parser.y" /* yacc.c:1646 */ -+#line 109 "dtc-parser.y" /* yacc.c:1646 */ - { -+ (yyvsp[0].node)->is_plugin = (yyvsp[-2].is_plugin); - the_boot_info = build_boot_info((yyvsp[-1].re), (yyvsp[0].node), - guess_boot_cpuid((yyvsp[0].node))); - } --#line 1472 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1476 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - - case 3: --#line 113 "dtc-parser.y" /* yacc.c:1646 */ -+#line 118 "dtc-parser.y" /* yacc.c:1646 */ - { -- (yyval.re) = NULL; -+ (yyval.is_plugin) = false; - } --#line 1480 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1484 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - - case 4: --#line 117 "dtc-parser.y" /* yacc.c:1646 */ -+#line 122 "dtc-parser.y" /* yacc.c:1646 */ - { -- (yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re)); -+ (yyval.is_plugin) = true; - } --#line 1488 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1492 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - - case 5: --#line 124 "dtc-parser.y" /* yacc.c:1646 */ -+#line 129 "dtc-parser.y" /* yacc.c:1646 */ - { -- (yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer)); -+ (yyval.re) = NULL; - } --#line 1496 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1500 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - - case 6: --#line 128 "dtc-parser.y" /* yacc.c:1646 */ -+#line 133 "dtc-parser.y" /* yacc.c:1646 */ -+ { -+ (yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re)); -+ } -+#line 1508 "dtc-parser.tab.c" /* yacc.c:1646 */ -+ break; -+ -+ case 7: -+#line 140 "dtc-parser.y" /* yacc.c:1646 */ -+ { -+ (yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer)); -+ } -+#line 1516 "dtc-parser.tab.c" /* yacc.c:1646 */ -+ break; -+ -+ case 8: -+#line 144 "dtc-parser.y" /* yacc.c:1646 */ - { - add_label(&(yyvsp[0].re)->labels, (yyvsp[-1].labelref)); - (yyval.re) = (yyvsp[0].re); - } --#line 1505 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1525 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 7: --#line 136 "dtc-parser.y" /* yacc.c:1646 */ -+ case 9: -+#line 152 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.node) = name_node((yyvsp[0].node), ""); - } --#line 1513 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1533 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 8: --#line 140 "dtc-parser.y" /* yacc.c:1646 */ -+ case 10: -+#line 156 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.node) = merge_nodes((yyvsp[-2].node), (yyvsp[0].node)); - } --#line 1521 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1541 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 9: --#line 145 "dtc-parser.y" /* yacc.c:1646 */ -+ case 11: -+#line 161 "dtc-parser.y" /* yacc.c:1646 */ - { - struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); - -@@ -1532,11 +1552,11 @@ yyreduce: - ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); - (yyval.node) = (yyvsp[-3].node); - } --#line 1536 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1556 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 10: --#line 156 "dtc-parser.y" /* yacc.c:1646 */ -+ case 12: -+#line 172 "dtc-parser.y" /* yacc.c:1646 */ - { - struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref)); - -@@ -1546,11 +1566,11 @@ yyreduce: - ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); - (yyval.node) = (yyvsp[-2].node); - } --#line 1550 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1570 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 11: --#line 166 "dtc-parser.y" /* yacc.c:1646 */ -+ case 13: -+#line 182 "dtc-parser.y" /* yacc.c:1646 */ - { - struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); - -@@ -1562,100 +1582,100 @@ yyreduce: - - (yyval.node) = (yyvsp[-3].node); - } --#line 1566 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1586 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 12: --#line 181 "dtc-parser.y" /* yacc.c:1646 */ -+ case 14: -+#line 197 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist)); - } --#line 1574 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1594 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 13: --#line 188 "dtc-parser.y" /* yacc.c:1646 */ -+ case 15: -+#line 204 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.proplist) = NULL; - } --#line 1582 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1602 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 14: --#line 192 "dtc-parser.y" /* yacc.c:1646 */ -+ case 16: -+#line 208 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist)); - } --#line 1590 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1610 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 15: --#line 199 "dtc-parser.y" /* yacc.c:1646 */ -+ case 17: -+#line 215 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data)); - } --#line 1598 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1618 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 16: --#line 203 "dtc-parser.y" /* yacc.c:1646 */ -+ case 18: -+#line 219 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data); - } --#line 1606 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1626 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 17: --#line 207 "dtc-parser.y" /* yacc.c:1646 */ -+ case 19: -+#line 223 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.prop) = build_property_delete((yyvsp[-1].propnodename)); - } --#line 1614 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1634 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 18: --#line 211 "dtc-parser.y" /* yacc.c:1646 */ -+ case 20: -+#line 227 "dtc-parser.y" /* yacc.c:1646 */ - { - add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref)); - (yyval.prop) = (yyvsp[0].prop); - } --#line 1623 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1643 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 19: --#line 219 "dtc-parser.y" /* yacc.c:1646 */ -+ case 21: -+#line 235 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data)); - } --#line 1631 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1651 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 20: --#line 223 "dtc-parser.y" /* yacc.c:1646 */ -+ case 22: -+#line 239 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data); - } --#line 1639 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1659 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 21: --#line 227 "dtc-parser.y" /* yacc.c:1646 */ -+ case 23: -+#line 243 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data)); - } --#line 1647 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1667 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 22: --#line 231 "dtc-parser.y" /* yacc.c:1646 */ -+ case 24: -+#line 247 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref)); - } --#line 1655 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1675 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 23: --#line 235 "dtc-parser.y" /* yacc.c:1646 */ -+ case 25: -+#line 251 "dtc-parser.y" /* yacc.c:1646 */ - { - FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL); - struct data d; -@@ -1671,11 +1691,11 @@ yyreduce: - (yyval.data) = data_merge((yyvsp[-8].data), d); - fclose(f); - } --#line 1675 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1695 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 24: --#line 251 "dtc-parser.y" /* yacc.c:1646 */ -+ case 26: -+#line 267 "dtc-parser.y" /* yacc.c:1646 */ - { - FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL); - struct data d = empty_data; -@@ -1685,43 +1705,43 @@ yyreduce: - (yyval.data) = data_merge((yyvsp[-4].data), d); - fclose(f); - } --#line 1689 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1709 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 25: --#line 261 "dtc-parser.y" /* yacc.c:1646 */ -+ case 27: -+#line 277 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); - } --#line 1697 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1717 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 26: --#line 268 "dtc-parser.y" /* yacc.c:1646 */ -+ case 28: -+#line 284 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = empty_data; - } --#line 1705 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1725 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 27: --#line 272 "dtc-parser.y" /* yacc.c:1646 */ -+ case 29: -+#line 288 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = (yyvsp[-1].data); - } --#line 1713 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1733 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 28: --#line 276 "dtc-parser.y" /* yacc.c:1646 */ -+ case 30: -+#line 292 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); - } --#line 1721 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1741 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 29: --#line 283 "dtc-parser.y" /* yacc.c:1646 */ -+ case 31: -+#line 299 "dtc-parser.y" /* yacc.c:1646 */ - { - unsigned long long bits; - -@@ -1737,20 +1757,20 @@ yyreduce: - (yyval.array).data = empty_data; - (yyval.array).bits = bits; - } --#line 1741 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1761 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 30: --#line 299 "dtc-parser.y" /* yacc.c:1646 */ -+ case 32: -+#line 315 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.array).data = empty_data; - (yyval.array).bits = 32; - } --#line 1750 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1770 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 31: --#line 304 "dtc-parser.y" /* yacc.c:1646 */ -+ case 33: -+#line 320 "dtc-parser.y" /* yacc.c:1646 */ - { - if ((yyvsp[-1].array).bits < 64) { - uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1; -@@ -1769,11 +1789,11 @@ yyreduce: - - (yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits); - } --#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1793 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 32: --#line 323 "dtc-parser.y" /* yacc.c:1646 */ -+ case 34: -+#line 339 "dtc-parser.y" /* yacc.c:1646 */ - { - uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits); - -@@ -1787,247 +1807,233 @@ yyreduce: - - (yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits); - } --#line 1791 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1811 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 33: --#line 337 "dtc-parser.y" /* yacc.c:1646 */ -+ case 35: -+#line 353 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref)); - } --#line 1799 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1819 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 36: --#line 346 "dtc-parser.y" /* yacc.c:1646 */ -+ case 38: -+#line 362 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.integer) = (yyvsp[-1].integer); - } --#line 1807 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1827 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 39: --#line 357 "dtc-parser.y" /* yacc.c:1646 */ -+ case 41: -+#line 373 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); } --#line 1813 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1833 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 41: --#line 362 "dtc-parser.y" /* yacc.c:1646 */ -+ case 43: -+#line 378 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); } --#line 1819 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1839 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 43: --#line 367 "dtc-parser.y" /* yacc.c:1646 */ -+ case 45: -+#line 383 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); } --#line 1825 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1845 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 45: --#line 372 "dtc-parser.y" /* yacc.c:1646 */ -+ case 47: -+#line 388 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); } --#line 1831 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1851 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 47: --#line 377 "dtc-parser.y" /* yacc.c:1646 */ -+ case 49: -+#line 393 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); } --#line 1837 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1857 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 49: --#line 382 "dtc-parser.y" /* yacc.c:1646 */ -+ case 51: -+#line 398 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); } --#line 1843 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1863 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 51: --#line 387 "dtc-parser.y" /* yacc.c:1646 */ -+ case 53: -+#line 403 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); } --#line 1849 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1869 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 52: --#line 388 "dtc-parser.y" /* yacc.c:1646 */ -+ case 54: -+#line 404 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); } --#line 1855 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1875 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 54: --#line 393 "dtc-parser.y" /* yacc.c:1646 */ -+ case 56: -+#line 409 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); } --#line 1861 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1881 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 55: --#line 394 "dtc-parser.y" /* yacc.c:1646 */ -+ case 57: -+#line 410 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); } --#line 1867 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1887 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 56: --#line 395 "dtc-parser.y" /* yacc.c:1646 */ -+ case 58: -+#line 411 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); } --#line 1873 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1893 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 57: --#line 396 "dtc-parser.y" /* yacc.c:1646 */ -+ case 59: -+#line 412 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); } --#line 1879 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1899 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 58: --#line 400 "dtc-parser.y" /* yacc.c:1646 */ -+ case 60: -+#line 416 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); } --#line 1885 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1905 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 59: --#line 401 "dtc-parser.y" /* yacc.c:1646 */ -+ case 61: -+#line 417 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); } --#line 1891 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1911 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 61: --#line 406 "dtc-parser.y" /* yacc.c:1646 */ -+ case 63: -+#line 422 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); } --#line 1897 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1917 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 62: --#line 407 "dtc-parser.y" /* yacc.c:1646 */ -+ case 64: -+#line 423 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); } --#line 1903 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1923 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 64: --#line 412 "dtc-parser.y" /* yacc.c:1646 */ -+ case 66: -+#line 428 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); } --#line 1909 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1929 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 65: --#line 414 "dtc-parser.y" /* yacc.c:1646 */ -- { -- if ((yyvsp[0].integer) != 0) { -- (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); -- } else { -- ERROR(&(yyloc), "Division by zero"); -- (yyval.integer) = 0; -- } -- } --#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */ -+ case 67: -+#line 429 "dtc-parser.y" /* yacc.c:1646 */ -+ { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); } -+#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 66: --#line 423 "dtc-parser.y" /* yacc.c:1646 */ -- { -- if ((yyvsp[0].integer) != 0) { -- (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); -- } else { -- ERROR(&(yyloc), "Division by zero"); -- (yyval.integer) = 0; -- } -- } --#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */ -+ case 68: -+#line 430 "dtc-parser.y" /* yacc.c:1646 */ -+ { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); } -+#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 69: -+ case 71: - #line 436 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = -(yyvsp[0].integer); } --#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 70: -+ case 72: - #line 437 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = ~(yyvsp[0].integer); } --#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 71: -+ case 73: - #line 438 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = !(yyvsp[0].integer); } --#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1959 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 72: -+ case 74: - #line 443 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = empty_data; - } --#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1967 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 73: -+ case 75: - #line 447 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte)); - } --#line 1969 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1975 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 74: -+ case 76: - #line 451 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); - } --#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1983 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 75: -+ case 77: - #line 458 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.nodelist) = NULL; - } --#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1991 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 76: -+ case 78: - #line 462 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist)); - } --#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 1999 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 77: -+ case 79: - #line 466 "dtc-parser.y" /* yacc.c:1646 */ - { - ERROR(&(yylsp[0]), "Properties must precede subnodes"); - YYERROR; - } --#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 2008 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 78: -+ case 80: - #line 474 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename)); - } --#line 2010 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 2016 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 79: -+ case 81: - #line 478 "dtc-parser.y" /* yacc.c:1646 */ - { - (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename)); - } --#line 2018 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 2024 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - -- case 80: -+ case 82: - #line 482 "dtc-parser.y" /* yacc.c:1646 */ - { - add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref)); - (yyval.node) = (yyvsp[0].node); - } --#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 2033 "dtc-parser.tab.c" /* yacc.c:1646 */ - break; - - --#line 2031 "dtc-parser.tab.c" /* yacc.c:1646 */ -+#line 2037 "dtc-parser.tab.c" /* yacc.c:1646 */ - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires -diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped -index 30867c688300e38333877360e3b05475d5b4a2a3..276d0788f8581bf1970ec8ef9c29b1981b4fe252 100644 ---- a/scripts/dtc/dtc-parser.tab.h_shipped -+++ b/scripts/dtc/dtc-parser.tab.h_shipped -@@ -46,26 +46,27 @@ extern int yydebug; - enum yytokentype - { - DT_V1 = 258, -- DT_MEMRESERVE = 259, -- DT_LSHIFT = 260, -- DT_RSHIFT = 261, -- DT_LE = 262, -- DT_GE = 263, -- DT_EQ = 264, -- DT_NE = 265, -- DT_AND = 266, -- DT_OR = 267, -- DT_BITS = 268, -- DT_DEL_PROP = 269, -- DT_DEL_NODE = 270, -- DT_PROPNODENAME = 271, -- DT_LITERAL = 272, -- DT_CHAR_LITERAL = 273, -- DT_BYTE = 274, -- DT_STRING = 275, -- DT_LABEL = 276, -- DT_REF = 277, -- DT_INCBIN = 278 -+ DT_PLUGIN = 259, -+ DT_MEMRESERVE = 260, -+ DT_LSHIFT = 261, -+ DT_RSHIFT = 262, -+ DT_LE = 263, -+ DT_GE = 264, -+ DT_EQ = 265, -+ DT_NE = 266, -+ DT_AND = 267, -+ DT_OR = 268, -+ DT_BITS = 269, -+ DT_DEL_PROP = 270, -+ DT_DEL_NODE = 271, -+ DT_PROPNODENAME = 272, -+ DT_LITERAL = 273, -+ DT_CHAR_LITERAL = 274, -+ DT_BYTE = 275, -+ DT_STRING = 276, -+ DT_LABEL = 277, -+ DT_REF = 278, -+ DT_INCBIN = 279 - }; - #endif - -@@ -74,7 +75,7 @@ extern int yydebug; - typedef union YYSTYPE YYSTYPE; - union YYSTYPE - { --#line 38 "dtc-parser.y" /* yacc.c:1909 */ -+#line 39 "dtc-parser.y" /* yacc.c:1909 */ - - char *propnodename; - char *labelref; -@@ -92,8 +93,9 @@ union YYSTYPE - struct node *nodelist; - struct reserve_info *re; - uint64_t integer; -+ bool is_plugin; - --#line 97 "dtc-parser.tab.h" /* yacc.c:1909 */ -+#line 99 "dtc-parser.tab.h" /* yacc.c:1909 */ - }; - # define YYSTYPE_IS_TRIVIAL 1 - # define YYSTYPE_IS_DECLARED 1 -diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y -index 000873f070fdcf3e4a11618cbfefdccb0d8e6cf9..bd67bacd543db130cc547ce7b6238ee168a62f19 100644 ---- a/scripts/dtc/dtc-parser.y -+++ b/scripts/dtc/dtc-parser.y -@@ -19,6 +19,7 @@ - */ - %{ - #include -+#include - - #include "dtc.h" - #include "srcpos.h" -@@ -52,9 +53,11 @@ extern bool treesource_error; - struct node *nodelist; - struct reserve_info *re; - uint64_t integer; -+ bool is_plugin; - } - - %token DT_V1 -+%token DT_PLUGIN - %token DT_MEMRESERVE - %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR - %token DT_BITS -@@ -71,6 +74,7 @@ extern bool treesource_error; - - %type propdata - %type propdataprefix -+%type plugindecl - %type memreserve - %type memreserves - %type arrayprefix -@@ -101,10 +105,22 @@ extern bool treesource_error; - %% - - sourcefile: -- DT_V1 ';' memreserves devicetree -+ DT_V1 ';' plugindecl memreserves devicetree - { -- the_boot_info = build_boot_info($3, $4, -- guess_boot_cpuid($4)); -+ $5->is_plugin = $3; -+ the_boot_info = build_boot_info($4, $5, -+ guess_boot_cpuid($5)); -+ } -+ ; -+ -+plugindecl: -+ /* empty */ -+ { -+ $$ = false; -+ } -+ | DT_PLUGIN ';' -+ { -+ $$ = true; - } - ; - -diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c -index 5fa23c406266e1ec58b9184cc81d381233f8f967..1f8c2852bf14ddad4b1312d7a81eceac947acdfe 100644 ---- a/scripts/dtc/dtc.c -+++ b/scripts/dtc/dtc.c -@@ -31,6 +31,7 @@ int reservenum; /* Number of memory reservation slots */ - int minsize; /* Minimum blob size */ - int padsize; /* Additional padding to blob */ - int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ -+int symbol_fixup_support = 0; - - static void fill_fullpaths(struct node *tree, const char *prefix) - { -@@ -53,7 +54,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) - #define FDT_VERSION(version) _FDT_VERSION(version) - #define _FDT_VERSION(version) #version - static const char usage_synopsis[] = "dtc [options] "; --static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; -+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:@hv"; - static struct option const usage_long_opts[] = { - {"quiet", no_argument, NULL, 'q'}, - {"in-format", a_argument, NULL, 'I'}, -@@ -71,6 +72,7 @@ static struct option const usage_long_opts[] = { - {"phandle", a_argument, NULL, 'H'}, - {"warning", a_argument, NULL, 'W'}, - {"error", a_argument, NULL, 'E'}, -+ {"symbols", no_argument, NULL, '@'}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'v'}, - {NULL, no_argument, NULL, 0x0}, -@@ -101,6 +103,7 @@ static const char * const usage_opts_help[] = { - "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", - "\n\tEnable/disable warnings (prefix with \"no-\")", - "\n\tEnable/disable errors (prefix with \"no-\")", -+ "\n\tEnable symbols/fixup support", - "\n\tPrint this help and exit", - "\n\tPrint version and exit", - NULL, -@@ -233,7 +236,9 @@ int main(int argc, char *argv[]) - case 'E': - parse_checks_option(false, true, optarg); - break; -- -+ case '@': -+ symbol_fixup_support = 1; -+ break; - case 'h': - usage(NULL); - default: -diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h -index 56212c8df660396b1d9bf6752e1121990e0789ab..f163b22b14b806b637c9fe996efd02762d182e1d 100644 ---- a/scripts/dtc/dtc.h -+++ b/scripts/dtc/dtc.h -@@ -54,6 +54,7 @@ extern int reservenum; /* Number of memory reservation slots */ - extern int minsize; /* Minimum blob size */ - extern int padsize; /* Additional padding to blob */ - extern int phandle_format; /* Use linux,phandle or phandle properties */ -+extern int symbol_fixup_support;/* enable symbols & fixup support */ - - #define PHANDLE_LEGACY 0x1 - #define PHANDLE_EPAPR 0x2 -@@ -132,6 +133,26 @@ struct label { - struct label *next; - }; - -+struct fixup_entry { -+ int offset; -+ struct node *node; -+ struct property *prop; -+ struct fixup_entry *next; -+ bool local_fixup_generated; -+}; -+ -+struct fixup { -+ char *ref; -+ struct fixup_entry *entries; -+ struct fixup *next; -+}; -+ -+struct symbol { -+ struct label *label; -+ struct node *node; -+ struct symbol *next; -+}; -+ - struct property { - bool deleted; - char *name; -@@ -158,6 +179,13 @@ struct node { - int addr_cells, size_cells; - - struct label *labels; -+ -+ struct symbol *symbols; -+ struct fixup_entry *local_fixups; -+ bool emit_local_fixup_node; -+ -+ bool is_plugin; -+ struct fixup *fixups; - }; - - #define for_each_label_withdel(l0, l) \ -@@ -181,6 +209,18 @@ struct node { - for_each_child_withdel(n, c) \ - if (!(c)->deleted) - -+#define for_each_fixup(n, f) \ -+ for ((f) = (n)->fixups; (f); (f) = (f)->next) -+ -+#define for_each_fixup_entry(f, fe) \ -+ for ((fe) = (f)->entries; (fe); (fe) = (fe)->next) -+ -+#define for_each_symbol(n, s) \ -+ for ((s) = (n)->symbols; (s); (s) = (s)->next) -+ -+#define for_each_local_fixup_entry(n, fe) \ -+ for ((fe) = (n)->local_fixups; (fe); (fe) = (fe)->next) -+ - void add_label(struct label **labels, char *label); - void delete_labels(struct label **labels); - -diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c -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) - return i; - } - -+static void emit_local_fixups(struct node *tree, struct emitter *emit, -+ void *etarget, struct data *strbuf, struct version_info *vi, -+ struct node *node) -+{ -+ struct fixup_entry *fe, *fen; -+ struct node *child; -+ int nameoff, count; -+ cell_t *buf; -+ struct data d; -+ -+ if (node->emit_local_fixup_node) { -+ -+ /* emit the external fixups (do not emit /) */ -+ if (node != tree) { -+ emit->beginnode(etarget, NULL); -+ emit->string(etarget, node->name, 0); -+ emit->align(etarget, sizeof(cell_t)); -+ } -+ -+ for_each_local_fixup_entry(tree, fe) { -+ if (fe->node != node || fe->local_fixup_generated) -+ continue; -+ -+ /* count the number of fixup entries */ -+ count = 0; -+ for_each_local_fixup_entry(tree, fen) { -+ if (fen->prop != fe->prop) -+ continue; -+ fen->local_fixup_generated = true; -+ count++; -+ } -+ -+ /* allocate buffer */ -+ buf = xmalloc(count * sizeof(cell_t)); -+ -+ /* collect all the offsets in buffer */ -+ count = 0; -+ for_each_local_fixup_entry(tree, fen) { -+ if (fen->prop != fe->prop) -+ continue; -+ fen->local_fixup_generated = true; -+ buf[count++] = cpu_to_fdt32(fen->offset); -+ } -+ d = empty_data; -+ d.len = count * sizeof(cell_t); -+ d.val = (char *)buf; -+ -+ nameoff = stringtable_insert(strbuf, fe->prop->name); -+ emit->property(etarget, fe->prop->labels); -+ emit->cell(etarget, count * sizeof(cell_t)); -+ emit->cell(etarget, nameoff); -+ -+ if ((vi->flags & FTF_VARALIGN) && -+ (count * sizeof(cell_t)) >= 8) -+ emit->align(etarget, 8); -+ -+ emit->data(etarget, d); -+ emit->align(etarget, sizeof(cell_t)); -+ -+ free(buf); -+ } -+ } -+ -+ for_each_child(node, child) -+ emit_local_fixups(tree, emit, etarget, strbuf, vi, child); -+ -+ if (node->emit_local_fixup_node && node != tree) -+ emit->endnode(etarget, tree->labels); -+} -+ -+static void emit_symbols_node(struct node *tree, struct emitter *emit, -+ void *etarget, struct data *strbuf, -+ struct version_info *vi) -+{ -+ struct symbol *sym; -+ int nameoff, vallen; -+ -+ /* do nothing if no symbols */ -+ if (!tree->symbols) -+ return; -+ -+ emit->beginnode(etarget, NULL); -+ emit->string(etarget, "__symbols__", 0); -+ emit->align(etarget, sizeof(cell_t)); -+ -+ for_each_symbol(tree, sym) { -+ -+ vallen = strlen(sym->node->fullpath); -+ -+ nameoff = stringtable_insert(strbuf, sym->label->label); -+ -+ emit->property(etarget, NULL); -+ emit->cell(etarget, vallen + 1); -+ emit->cell(etarget, nameoff); -+ -+ if ((vi->flags & FTF_VARALIGN) && vallen >= 8) -+ emit->align(etarget, 8); -+ -+ emit->string(etarget, sym->node->fullpath, -+ strlen(sym->node->fullpath)); -+ emit->align(etarget, sizeof(cell_t)); -+ } -+ -+ emit->endnode(etarget, NULL); -+} -+ -+static void emit_local_fixups_node(struct node *tree, struct emitter *emit, -+ void *etarget, struct data *strbuf, -+ struct version_info *vi) -+{ -+ struct fixup_entry *fe; -+ struct node *node; -+ -+ /* do nothing if no local fixups */ -+ if (!tree->local_fixups) -+ return; -+ -+ /* mark all nodes that need a local fixup generated (and parents) */ -+ for_each_local_fixup_entry(tree, fe) { -+ node = fe->node; -+ while (node != NULL && !node->emit_local_fixup_node) { -+ node->emit_local_fixup_node = true; -+ node = node->parent; -+ } -+ } -+ -+ /* emit the local fixups node now */ -+ emit->beginnode(etarget, NULL); -+ emit->string(etarget, "__local_fixups__", 0); -+ emit->align(etarget, sizeof(cell_t)); -+ -+ emit_local_fixups(tree, emit, etarget, strbuf, vi, tree); -+ -+ emit->endnode(etarget, tree->labels); -+} -+ -+static void emit_fixups_node(struct node *tree, struct emitter *emit, -+ void *etarget, struct data *strbuf, -+ struct version_info *vi) -+{ -+ struct fixup *f; -+ struct fixup_entry *fe; -+ char *name, *s; -+ const char *fullpath; -+ int namesz, nameoff, vallen; -+ -+ /* do nothing if no fixups */ -+ if (!tree->fixups) -+ return; -+ -+ /* emit the external fixups */ -+ emit->beginnode(etarget, NULL); -+ emit->string(etarget, "__fixups__", 0); -+ emit->align(etarget, sizeof(cell_t)); -+ -+ for_each_fixup(tree, f) { -+ -+ namesz = 0; -+ for_each_fixup_entry(f, fe) { -+ fullpath = fe->node->fullpath; -+ if (fullpath[0] == '\0') -+ fullpath = "/"; -+ namesz += strlen(fullpath) + 1; -+ namesz += strlen(fe->prop->name) + 1; -+ namesz += 32; /* space for : + '\0' */ -+ } -+ -+ name = xmalloc(namesz); -+ -+ s = name; -+ for_each_fixup_entry(f, fe) { -+ fullpath = fe->node->fullpath; -+ if (fullpath[0] == '\0') -+ fullpath = "/"; -+ snprintf(s, name + namesz - s, "%s:%s:%d", fullpath, -+ fe->prop->name, fe->offset); -+ s += strlen(s) + 1; -+ } -+ -+ nameoff = stringtable_insert(strbuf, f->ref); -+ vallen = s - name - 1; -+ -+ emit->property(etarget, NULL); -+ emit->cell(etarget, vallen + 1); -+ emit->cell(etarget, nameoff); -+ -+ if ((vi->flags & FTF_VARALIGN) && vallen >= 8) -+ emit->align(etarget, 8); -+ -+ emit->string(etarget, name, vallen); -+ emit->align(etarget, sizeof(cell_t)); -+ -+ free(name); -+ } -+ -+ emit->endnode(etarget, tree->labels); -+} -+ - static void flatten_tree(struct node *tree, struct emitter *emit, - void *etarget, struct data *strbuf, - struct version_info *vi) -@@ -310,6 +508,10 @@ static void flatten_tree(struct node *tree, struct emitter *emit, - flatten_tree(child, emit, etarget, strbuf, vi); - } - -+ emit_symbols_node(tree, emit, etarget, strbuf, vi); -+ emit_local_fixups_node(tree, emit, etarget, strbuf, vi); -+ emit_fixups_node(tree, emit, etarget, strbuf, vi); -+ - emit->endnode(etarget, tree->labels); - } - -diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h -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-g53bf130b" -+#define DTC_VERSION "DTC 1.4.1-g25efc119" - -From 27d75d314a4c5b5acbb75bb6d58a50213da5d90c Mon Sep 17 00:00:00 2001 +From 67d0ae429b8998ff33a858f118934bb4b49a8254 Mon Sep 17 00:00:00 2001 From: notro Date: Wed, 9 Jul 2014 14:46:08 +0200 -Subject: [PATCH 051/216] BCM2708: Add core Device Tree support +Subject: [PATCH 056/150] BCM2708: Add core Device Tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -96755,75 +82625,84 @@ Signed-off-by: Khem Raj --- arch/arm/Makefile | 2 + arch/arm/boot/.gitignore | 2 +- - arch/arm/boot/dts/Makefile | 19 + - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 156 +++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 146 +++ - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 105 ++ + arch/arm/boot/dts/Makefile | 20 + + arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 197 +++ + arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 157 +++ + arch/arm/boot/dts/bcm2708-rpi-b.dts | 147 ++ + arch/arm/boot/dts/bcm2708-rpi-cm.dts | 110 ++ arch/arm/boot/dts/bcm2708-rpi-cm.dtsi | 50 + - arch/arm/boot/dts/bcm2708-rpi.dtsi | 109 ++ + arch/arm/boot/dts/bcm2708-rpi.dtsi | 113 ++ arch/arm/boot/dts/bcm2708.dtsi | 16 + - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 156 +++ + arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 157 +++ arch/arm/boot/dts/bcm2709.dtsi | 22 + - arch/arm/boot/dts/bcm270x.dtsi | 141 ++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 203 +++ - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 155 +++ - arch/arm/boot/dts/bcm2710.dtsi | 155 +++ - arch/arm/boot/dts/overlays/Makefile | 105 ++ - arch/arm/boot/dts/overlays/README | 1368 ++++++++++++++++++++ - .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 53 + + arch/arm/boot/dts/bcm270x.dtsi | 157 +++ + arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 226 +++ + arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 167 +++ + arch/arm/boot/dts/bcm2710.dtsi | 148 ++ + arch/arm/boot/dts/bcm283x.dtsi | 1 + + arch/arm/boot/dts/overlays/Makefile | 114 ++ + arch/arm/boot/dts/overlays/README | 1458 ++++++++++++++++++++ + .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 40 + + .../boot/dts/overlays/adau7002-simple-overlay.dts | 52 + arch/arm/boot/dts/overlays/ads1015-overlay.dts | 98 ++ + arch/arm/boot/dts/overlays/ads1115-overlay.dts | 103 ++ arch/arm/boot/dts/overlays/ads7846-overlay.dts | 89 ++ - .../dts/overlays/akkordion-iqdacplus-overlay.dts | 46 + + .../dts/overlays/akkordion-iqdacplus-overlay.dts | 49 + .../allo-piano-dac-pcm512x-audio-overlay.dts | 54 + arch/arm/boot/dts/overlays/at86rf233-overlay.dts | 57 + + .../dts/overlays/audioinjector-addons-overlay.dts | 50 + .../audioinjector-wm8731-audio-overlay.dts | 39 + arch/arm/boot/dts/overlays/audremap-overlay.dts | 19 + .../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 + + .../dts/overlays/dionaudio-loco-v2-overlay.dts | 49 + arch/arm/boot/dts/overlays/dpi18-overlay.dts | 31 + 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 + .../boot/dts/overlays/enc28j60-spi2-overlay.dts | 47 + + arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 70 + 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 + - .../dts/overlays/hifiberry-dacplus-overlay.dts | 56 + - .../boot/dts/overlays/hifiberry-digi-overlay.dts | 39 + - .../dts/overlays/hifiberry-digi-pro-overlay.dts | 41 + + .../dts/overlays/hifiberry-dacplus-overlay.dts | 59 + + .../boot/dts/overlays/hifiberry-digi-overlay.dts | 41 + + .../dts/overlays/hifiberry-digi-pro-overlay.dts | 43 + arch/arm/boot/dts/overlays/hy28a-overlay.dts | 93 ++ - arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 +++ + arch/arm/boot/dts/overlays/hy28b-overlay.dts | 148 ++ arch/arm/boot/dts/overlays/i2c-bcm2708-overlay.dts | 13 + 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 | 83 ++ - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 34 + + arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 41 + .../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/iqaudio-dac-overlay.dts | 43 + - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 46 + + arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 46 + + .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 49 + .../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 + + .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 46 + + .../boot/dts/overlays/justboom-digi-overlay.dts | 41 + arch/arm/boot/dts/overlays/lirc-rpi-overlay.dts | 57 + arch/arm/boot/dts/overlays/mcp23017-overlay.dts | 54 + - arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 732 +++++++++++ - .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 73 ++ - .../arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 73 ++ + arch/arm/boot/dts/overlays/mcp23s17-overlay.dts | 732 ++++++++++ + .../arm/boot/dts/overlays/mcp2515-can0-overlay.dts | 73 + + .../arm/boot/dts/overlays/mcp2515-can1-overlay.dts | 73 + + arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 205 +++ arch/arm/boot/dts/overlays/midi-uart0-overlay.dts | 36 + arch/arm/boot/dts/overlays/mmc-overlay.dts | 38 + 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-disable-wifi-overlay.dts | 13 + .../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/pisound-overlay.dts | 114 ++ + arch/arm/boot/dts/overlays/pisound-overlay.dts | 120 ++ arch/arm/boot/dts/overlays/pitft22-overlay.dts | 69 + .../dts/overlays/pitft28-capacitive-overlay.dts | 91 ++ .../dts/overlays/pitft28-resistive-overlay.dts | 121 ++ @@ -96832,14 +82711,15 @@ Signed-off-by: Khem Raj arch/arm/boot/dts/overlays/pwm-2chan-overlay.dts | 47 + arch/arm/boot/dts/overlays/pwm-overlay.dts | 43 + arch/arm/boot/dts/overlays/qca7000-overlay.dts | 52 + - arch/arm/boot/dts/overlays/raspidac3-overlay.dts | 45 + + arch/arm/boot/dts/overlays/raspidac3-overlay.dts | 49 + .../boot/dts/overlays/rpi-backlight-overlay.dts | 21 + + .../dts/overlays/rpi-cirrus-wm5102-overlay.dts | 146 ++ arch/arm/boot/dts/overlays/rpi-dac-overlay.dts | 34 + arch/arm/boot/dts/overlays/rpi-display-overlay.dts | 89 ++ arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts | 17 + 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 ++ + .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 49 + .../boot/dts/overlays/sc16is750-i2c-overlay.dts | 37 + .../boot/dts/overlays/sc16is752-spi1-overlay.dts | 61 + arch/arm/boot/dts/overlays/sdhost-overlay.dts | 32 + @@ -96851,6 +82731,7 @@ Signed-off-by: Khem Raj 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-cs-overlay.dts | 29 + 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 + @@ -96858,17 +82739,18 @@ Signed-off-by: Khem Raj arch/arm/boot/dts/overlays/spi2-1cs-overlay.dts | 57 + arch/arm/boot/dts/overlays/spi2-2cs-overlay.dts | 69 + arch/arm/boot/dts/overlays/spi2-3cs-overlay.dts | 81 ++ - arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 ++++ + arch/arm/boot/dts/overlays/tinylcd35-overlay.dts | 224 +++ arch/arm/boot/dts/overlays/uart1-overlay.dts | 38 + .../arm/boot/dts/overlays/vc4-fkms-v3d-overlay.dts | 89 ++ - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 136 ++ + arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 151 ++ 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 + scripts/Makefile.dtbinst | 10 +- scripts/Makefile.lib | 11 + - 115 files changed, 8979 insertions(+), 4 deletions(-) + 126 files changed, 10058 insertions(+), 4 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm2708-rpi-0-w.dts 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 100644 arch/arm/boot/dts/bcm2708-rpi-cm.dts @@ -96884,22 +82766,27 @@ Signed-off-by: Khem Raj 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/adau7002-simple-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/ads1015-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/ads1115-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/allo-piano-dac-pcm512x-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/at86rf233-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/audremap-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/dionaudio-loco-v2-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/dpi18-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 create mode 100644 arch/arm/boot/dts/overlays/enc28j60-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/enc28j60-spi2-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-ir-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/hifiberry-amp-overlay.dts @@ -96928,11 +82815,13 @@ Signed-off-by: Khem Raj create mode 100644 arch/arm/boot/dts/overlays/mcp23s17-overlay.dts create mode 100755 arch/arm/boot/dts/overlays/mcp2515-can0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mcp2515-can1-overlay.dts + create mode 100755 arch/arm/boot/dts/overlays/mcp3008-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/midi-uart0-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mmc-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/mz61581-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pi3-act-led-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pi3-disable-bt-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/piscreen2r-overlay.dts @@ -96947,6 +82836,7 @@ Signed-off-by: Khem Raj create mode 100644 arch/arm/boot/dts/overlays/qca7000-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/raspidac3-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-backlight-overlay.dts + create mode 100644 arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-dac-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-display-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/rpi-ft5406-overlay.dts @@ -96964,6 +82854,7 @@ Signed-off-by: Khem Raj 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-cs-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 @@ -97004,16 +82895,17 @@ index 3c79f85975aaa26c7c2e353fefc54d71d89bc5bf..eaaeb17e5986e5f7178b2851169444ac -*.dtb +*.dtb* diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 01d178a2009f598f133e890a46c3e3e99efcc63c..0263d6172d3af40668c02535a4f8dce022f3a93d 100644 +index 011808490fed73ee3bc676f96449411119983b0d..35b4276d46354ce02af6456b619e51803ff8232f 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile -@@ -1,5 +1,13 @@ +@@ -1,5 +1,14 @@ ifeq ($(CONFIG_OF),y) +dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2708-rpi-b.dtb \ + bcm2708-rpi-b-plus.dtb \ + bcm2708-rpi-cm.dtb \ ++ bcm2708-rpi-0-w.dtb \ + bcm2709-rpi-2-b.dtb \ + bcm2710-rpi-3-b.dtb \ + bcm2710-rpi-cm3.dtb @@ -97021,9 +82913,9 @@ index 01d178a2009f598f133e890a46c3e3e99efcc63c..0263d6172d3af40668c02535a4f8dce0 dtb-$(CONFIG_ARCH_ALPINE) += \ alpine-db.dtb dtb-$(CONFIG_MACH_ARTPEC6) += \ -@@ -984,10 +992,21 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \ - dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb +@@ -1010,10 +1019,21 @@ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \ + aspeed-bmc-opp-romulus.dtb \ aspeed-ast2500-evb.dtb + +targets += dtbs dtbs_install @@ -97043,17 +82935,221 @@ index 01d178a2009f598f133e890a46c3e3e99efcc63c..0263d6172d3af40668c02535a4f8dce0 + DTC_FLAGS ?= -@ -H epapr + dts-dirs += overlays +endif -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +diff --git a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts new file mode 100644 -index 0000000000000000000000000000000000000000..360da5c928dc5599b0d2a9055728087604c6b189 +index 0000000000000000000000000000000000000000..db0f99ddf2f46e83827d56e21c4846dd0b414c63 --- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -0,0 +1,156 @@ ++++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts +@@ -0,0 +1,197 @@ +/dts-v1/; + +#include "bcm2708.dtsi" + +/ { ++ model = "Raspberry Pi Zero W"; ++}; ++ ++&gpio { ++ sdhost_pins: sdhost_pins { ++ brcm,pins = <48 49 50 51 52 53>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ spi0_pins: spi0_pins { ++ brcm,pins = <9 10 11>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ spi0_cs_pins: spi0_cs_pins { ++ brcm,pins = <8 7>; ++ brcm,function = <1>; /* output */ ++ }; ++ ++ i2c0_pins: i2c0 { ++ brcm,pins = <0 1>; ++ brcm,function = <4>; ++ }; ++ ++ i2c1_pins: i2c1 { ++ brcm,pins = <2 3>; ++ brcm,function = <4>; ++ }; ++ ++ i2s_pins: i2s { ++ brcm,pins = <18 19 20 21>; ++ brcm,function = <4>; /* alt0 */ ++ }; ++ ++ sdio_pins: sdio_pins { ++ brcm,pins = <34 35 36 37 38 39>; ++ brcm,function = <7>; /* ALT3 = SD1 */ ++ brcm,pull = <0 2 2 2 2 2>; ++ }; ++ ++ bt_pins: bt_pins { ++ brcm,pins = <43>; ++ brcm,function = <4>; /* alt0:GPCLK2 */ ++ brcm,pull = <0>; /* none */ ++ }; ++ ++ uart0_pins: uart0_pins { ++ brcm,pins = <30 31 32 33>; ++ brcm,function = <7>; /* alt3=UART0 */ ++ brcm,pull = <2 0 0 2>; /* up none none up */ ++ }; ++ ++ uart1_pins: uart1_pins { ++ brcm,pins; ++ brcm,function; ++ brcm,pull; ++ }; ++ ++ audio_pins: audio_pins { ++ brcm,pins = <>; ++ brcm,function = <>; ++ }; ++}; ++ ++&sdhost { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdhost_pins>; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&mmc { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdio_pins>; ++ non-removable; ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&fb { ++ status = "okay"; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins &bt_pins>; ++ status = "okay"; ++}; ++ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>; ++ status = "okay"; ++}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0{ ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++ ++ spidev1: spidev@1{ ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <500000>; ++ }; ++}; ++ ++&i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++&i2c2 { ++ clock-frequency = <100000>; ++}; ++ ++&i2s { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s_pins>; ++}; ++ ++&random { ++ status = "okay"; ++}; ++ ++&leds { ++ act_led: act { ++ label = "led0"; ++ linux,default-trigger = "mmc0"; ++ gpios = <&gpio 47 0>; ++ }; ++}; ++ ++&hdmi { ++ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++}; ++ ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ ++/ { ++ chosen { ++ bootargs = "8250.nr_uarts=1"; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ uart0 = <&uart0>,"status"; ++ uart1 = <&uart1>,"status"; ++ i2s = <&i2s>,"status"; ++ spi = <&spi0>,"status"; ++ i2c0 = <&i2c0>,"status"; ++ i2c1 = <&i2c1>,"status"; ++ i2c2_iknowwhatimdoing = <&i2c2>,"status"; ++ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; ++ i2c2_baudrate = <&i2c2>,"clock-frequency:0"; ++ ++ act_led_gpio = <&act_led>,"gpios:4"; ++ act_led_activelow = <&act_led>,"gpios:8"; ++ act_led_trigger = <&act_led>,"linux,default-trigger"; ++ ++ audio = <&audio>,"status"; ++ watchdog = <&watchdog>,"status"; ++ random = <&random>,"status"; ++ sd_overclock = <&sdhost>,"brcm,overclock-50:0"; ++ sd_force_pio = <&sdhost>,"brcm,force-pio?"; ++ sd_pio_limit = <&sdhost>,"brcm,pio-limit:0"; ++ sd_debug = <&sdhost>,"brcm,debug"; ++ }; ++}; +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..0b66ac9f25a5f7ae51f3d0666cfcb908f85e1d24 +--- /dev/null ++++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts +@@ -0,0 +1,157 @@ ++/dts-v1/; ++ ++#include "bcm2708.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" ++ ++/ { + model = "Raspberry Pi Model B+"; +}; + @@ -97207,13 +83303,14 @@ index 0000000000000000000000000000000000000000..360da5c928dc5599b0d2a90557280876 +}; 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..9c49659ab246bce0656f3514f3b924bc4826b421 +index 0000000000000000000000000000000000000000..e99e9d999e4142060c41eb47b93c8ac70a30f384 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -0,0 +1,146 @@ +@@ -0,0 +1,147 @@ +/dts-v1/; + +#include "bcm2708.dtsi" ++#include "bcm283x-rpi-smsc9512.dtsi" + +/ { + model = "Raspberry Pi Model B"; @@ -97359,10 +83456,10 @@ index 0000000000000000000000000000000000000000..9c49659ab246bce0656f3514f3b924bc +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts new file mode 100644 -index 0000000000000000000000000000000000000000..eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3 +index 0000000000000000000000000000000000000000..10be69972bd1440f574e35d515f3d6a0505fd869 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -0,0 +1,105 @@ +@@ -0,0 +1,110 @@ +/dts-v1/; + +#include "bcm2708-rpi-cm.dtsi" @@ -97450,6 +83547,11 @@ index 0000000000000000000000000000000000000000..eb8662f0d222b4c0a9a2bcb8bccb13e8 + pinctrl-0 = <&i2s_pins>; +}; + ++&audio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&audio_pins>; ++}; ++ +&hdmi { + hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; +}; @@ -97526,10 +83628,10 @@ index 0000000000000000000000000000000000000000..d33d462b4090e4a4f967a37212918b9c +}; diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..055090ace687b94e4d25de65d1b8fbf7f730be9e +index 0000000000000000000000000000000000000000..ef14e9ac6cd2092efb1681682dd2d3c52b8abfd5 --- /dev/null +++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -0,0 +1,109 @@ +@@ -0,0 +1,113 @@ +/* Downstream version of bcm2835-rpi.dtsi */ + +#include @@ -97639,6 +83741,10 @@ index 0000000000000000000000000000000000000000..055090ace687b94e4d25de65d1b8fbf7 +&usb { + power-domains = <&power RPI_POWER_DOMAIN_USB>; +}; ++ ++&clocks { ++ firmware = <&firmware>; ++}; diff --git a/arch/arm/boot/dts/bcm2708.dtsi b/arch/arm/boot/dts/bcm2708.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..0f72bd90c591a2e8752d7437fa7e8c6308bd8c3f @@ -97663,13 +83769,14 @@ index 0000000000000000000000000000000000000000..0f72bd90c591a2e8752d7437fa7e8c63 +}; 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..19c83823420fc3cc20a01d07091100cb8720ff4d +index 0000000000000000000000000000000000000000..20674f250af922e9f9a43e3e8b13aee42e3930be --- /dev/null +++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -0,0 +1,156 @@ +@@ -0,0 +1,157 @@ +/dts-v1/; + +#include "bcm2709.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" + +/ { + model = "Raspberry Pi 2 Model B"; @@ -97853,10 +83960,10 @@ index 0000000000000000000000000000000000000000..343437db94820bb75a9b81e8bc6ecf6f +}; diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..a46cb4a8b1419edd95e0e07c18b0f373222dc2bf +index 0000000000000000000000000000000000000000..36d853715f2379e1952ce3d3be58dd670e305159 --- /dev/null +++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -0,0 +1,141 @@ +@@ -0,0 +1,157 @@ +/* Downstream bcm283x.dtsi diff */ +#include "dt-bindings/power/raspberrypi-power.h" + @@ -97997,13 +84104,29 @@ index 0000000000000000000000000000000000000000..a46cb4a8b1419edd95e0e07c18b0f373 + status = "disabled"; + }; + }; ++ ++ vdd_5v0_reg: fixedregulator_5v0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "5v0"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ vdd_3v3_reg: fixedregulator_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; +}; 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..12764a3495b2372ffaf47e32ea0d21326ca83686 +index 0000000000000000000000000000000000000000..616cfd5c7094596b497101e8feca25e25e77c3e8 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -0,0 +1,203 @@ +@@ -0,0 +1,226 @@ +/dts-v1/; + +#ifdef RPI364 @@ -98011,6 +84134,7 @@ index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d2132 +#endif + +#include "bcm2710.dtsi" ++#include "bcm283x-rpi-smsc9514.dtsi" + +/ { + model = "Raspberry Pi 3 Model B"; @@ -98101,6 +84225,14 @@ index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d2132 + firmware = <&firmware>; + status = "okay"; + }; ++ ++ expgpio: expgpio { ++ compatible = "brcm,bcm2835-expgpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; +}; + +&fb { @@ -98168,6 +84300,16 @@ index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d2132 + linux,default-trigger = "mmc0"; + gpios = <&virtgpio 0 0>; + }; ++ ++ pwr_led: pwr { ++ label = "led1"; ++ linux,default-trigger = "input"; ++ gpios = <&expgpio 7 GPIO_ACTIVE_LOW>; ++ }; ++}; ++ ++&hdmi { ++ hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>; +}; + +&audio { @@ -98198,6 +84340,10 @@ index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d2132 + act_led_activelow = <&act_led>,"gpios:8"; + act_led_trigger = <&act_led>,"linux,default-trigger"; + ++ pwr_led_gpio = <&pwr_led>,"gpios:4"; ++ pwr_led_activelow = <&pwr_led>,"gpios:8"; ++ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; ++ + audio = <&audio>,"status"; + watchdog = <&watchdog>,"status"; + random = <&random>,"status"; @@ -98209,10 +84355,10 @@ index 0000000000000000000000000000000000000000..12764a3495b2372ffaf47e32ea0d2132 +}; diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts new file mode 100644 -index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a571fe6123 +index 0000000000000000000000000000000000000000..fe402e84cdda884583336422289ac8b3cc12fb28 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -0,0 +1,155 @@ +@@ -0,0 +1,167 @@ +/dts-v1/; + +#include "bcm2710.dtsi" @@ -98221,6 +84367,10 @@ index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a5 + model = "Raspberry Pi Compute Module 3"; +}; + ++&uart0 { ++ status = "okay"; ++}; ++ +&gpio { + sdhost_pins: sdhost_pins { + brcm,pins = <48 49 50 51 52 53>; @@ -98276,6 +84426,14 @@ index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a5 + firmware = <&firmware>; + status = "okay"; + }; ++ ++ expgpio: expgpio { ++ compatible = "brcm,bcm2835-expgpio"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; +}; + +&fb { @@ -98334,7 +84492,7 @@ index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a5 +}; + +&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; ++ hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>; +}; + +&audio { @@ -98370,10 +84528,10 @@ index 0000000000000000000000000000000000000000..41874c25a84226c0e4af92ec4059e0a5 +}; diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi new file mode 100644 -index 0000000000000000000000000000000000000000..f6def5d7e5d622cf09e8f87332c7374fe28da08b +index 0000000000000000000000000000000000000000..3e134a1208610b90e2d0fc22f03c6e9f372bfcd7 --- /dev/null +++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -0,0 +1,155 @@ +@@ -0,0 +1,148 @@ +#include "bcm283x.dtsi" +#include "bcm270x.dtsi" +#include "bcm2708-rpi.dtsi" @@ -98522,39 +84680,49 @@ index 0000000000000000000000000000000000000000..f6def5d7e5d622cf09e8f87332c7374f + interrupts = <8>; +}; + -+#ifdef RPI364 -+&usb { -+ compatible = "brcm,bcm2835-usb"; -+ reg = <0x7e980000 0x10000>; -+ interrupts = <1 9>; -+}; -+#endif +diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi +index a3106aa446c6906108c90952cd39520ff195ef79..72cb9dc60ca9ad9aa2813972a299c50dcea7cd89 100644 +--- a/arch/arm/boot/dts/bcm283x.dtsi ++++ b/arch/arm/boot/dts/bcm283x.dtsi +@@ -366,6 +366,7 @@ + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; + }; + + i2c0: i2c@7e205000 { diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile new file mode 100644 -index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d6266315273 +index 0000000000000000000000000000000000000000..0f7340799fb465ba1fb5aaa1e970cbf6295d75c4 --- /dev/null +++ b/arch/arm/boot/dts/overlays/Makefile -@@ -0,0 +1,105 @@ +@@ -0,0 +1,114 @@ +# Overlays for the Raspberry Pi platform + +dtbo-$(CONFIG_ARCH_BCM2835) += \ + adau1977-adc.dtbo \ ++ adau7002-simple.dtbo \ + ads1015.dtbo \ ++ ads1115.dtbo \ + ads7846.dtbo \ + akkordion-iqdacplus.dtbo \ + allo-piano-dac-pcm512x-audio.dtbo \ + at86rf233.dtbo \ ++ audioinjector-addons.dtbo \ + audioinjector-wm8731-audio.dtbo \ + audremap.dtbo \ + bmp085_i2c-sensor.dtbo \ + dht11.dtbo \ + dionaudio-loco.dtbo \ ++ dionaudio-loco-v2.dtbo \ + dpi18.dtbo \ + dpi24.dtbo \ + dwc-otg.dtbo \ + dwc2.dtbo \ + enc28j60.dtbo \ + enc28j60-spi2.dtbo \ ++ fe-pi-audio.dtbo \ + gpio-ir.dtbo \ + gpio-poweroff.dtbo \ + hifiberry-amp.dtbo \ @@ -98583,11 +84751,13 @@ index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d62 + mcp23s17.dtbo \ + mcp2515-can0.dtbo \ + mcp2515-can1.dtbo \ ++ mcp3008.dtbo \ + midi-uart0.dtbo \ + mmc.dtbo \ + mz61581.dtbo \ + pi3-act-led.dtbo \ + pi3-disable-bt.dtbo \ ++ pi3-disable-wifi.dtbo \ + pi3-miniuart-bt.dtbo \ + piscreen.dtbo \ + piscreen2r.dtbo \ @@ -98602,6 +84772,7 @@ index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d62 + qca7000.dtbo \ + raspidac3.dtbo \ + rpi-backlight.dtbo \ ++ rpi-cirrus-wm5102.dtbo \ + rpi-dac.dtbo \ + rpi-display.dtbo \ + rpi-ft5406.dtbo \ @@ -98619,6 +84790,7 @@ index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d62 + smi-nand.dtbo \ + spi-gpio35-39.dtbo \ + spi-rtc.dtbo \ ++ spi0-cs.dtbo \ + spi0-hw-cs.dtbo \ + spi1-1cs.dtbo \ + spi1-2cs.dtbo \ @@ -98642,10 +84814,10 @@ index 0000000000000000000000000000000000000000..11dba31712840a9e4b91acd4565c2d62 +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..81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd +index 0000000000000000000000000000000000000000..c1883bba938290f03826026651c764cfd4ac278b --- /dev/null +++ b/arch/arm/boot/dts/overlays/README -@@ -0,0 +1,1368 @@ +@@ -0,0 +1,1458 @@ +Introduction +============ + @@ -98816,6 +84988,12 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +Params: + + ++Name: adau7002-simple ++Info: Overlay for the activation of ADAU7002 stereo PDM to I2S converter. ++Load: dtoverlay=adau7002-simple,= ++Params: card-name Override the default, "adau7002", card name. ++ ++ +Name: ads1015 +Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C +Load: dtoverlay=ads1015,= @@ -98838,6 +85016,28 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + http://www.ti.com/lit/ds/symlink/ads1015.pdf + + ++Name: ads1115 ++Info: Texas Instruments ADS1115 ADC ++Load: dtoverlay=ads1115,[=] ++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. ++ 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=7 sets 860 sps) ++ cha_gain Set the gain of the Programmable Gain ++ Amplifier for this channel. (Default 1 sets the ++ full scale of the channel to 4.096 Volts) ++ ++ Channel 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/ads1115.pdf ++ ++ +Name: ads7846 +Info: ADS7846 Touch controller +Load: dtoverlay=ads7846,= @@ -98915,6 +85115,12 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + arrays (0=+0pF, 15=+4.5pF, default 15) + + ++Name: audioinjector-addons ++Info: Configures the audioinjector.net audio add on soundcards ++Load: dtoverlay=audioinjector-addons ++Params: ++ ++ +Name: audioinjector-wm8731-audio +Info: Configures the audioinjector.net audio add on soundcard +Load: dtoverlay=audioinjector-wm8731-audio @@ -98950,6 +85156,25 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +Params: + + ++Name: dionaudio-loco-v2 ++Info: Configures the Dion Audio LOCO-V2 DAC-AMP ++Load: dtoverlay=dionaudio-loco-v2,= ++Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec ++ Digital volume control. Enable with ++ "dtoverlay=hifiberry-dacplus,24db_digital_gain" ++ (The default behaviour is that the Digital ++ volume control is limited to a maximum of ++ 0dB. ie. it can attenuate but not provide ++ gain. For most users, this will be desired ++ as it will prevent clipping. By appending ++ the 24dB_digital_gain parameter, the Digital ++ volume control will allow up to 24dB of ++ gain. If this parameter is enabled, it is the ++ responsibility of the user to ensure that ++ the Digital volume control is set to a value ++ that does not result in clipping/distortion!) ++ ++ +Name: dpi18 +Info: Overlay for a generic 18-bit DPI display + This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output @@ -99006,6 +85231,12 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + speed SPI bus speed (default 12000000) + + ++Name: fe-pi-audio ++Info: Configures the Fe-Pi Audio Sound Card ++Load: dtoverlay=fe-pi-audio ++Params: ++ ++ +Name: gpio-ir +Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- + based gpio_ir_recv driver maps received keys directly to a @@ -99197,6 +85428,9 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + + bmp280 Select the Bosch sensortronic BMP280 + ++ si7020 Select the Silicon Labs Si7013/20/21 humidity/ ++ temperature sensor ++ + +Name: i2c0-bcm2708 +Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations @@ -99381,6 +85615,15 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + interrupt GPIO for interrupt signal + + ++Name: mcp3008 ++Info: Configures MCP3008 A/D converters ++ For devices on spi1 or spi2, the interfaces should be enabled ++ with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. ++Load: dtoverlay=mcp3008,[=] ++Params: spi--present boolean, configure device at spi, cs ++ spi--speed integer, set the spi bus speed for this device ++ ++ +Name: midi-uart0 +Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets + 31.25kbaud, the frequency required for MIDI @@ -99445,6 +85688,12 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +Params: + + ++Name: pi3-disable-wifi ++Info: Disable Pi3 onboard WiFi ++Load: dtoverlay=pi3-disable-wifi ++Params: ++ ++ +Name: pi3-miniuart-bt +Info: Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore + UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum @@ -99619,6 +85868,12 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +Params: + + ++Name: rpi-cirrus-wm5102 ++Info: Configures the Cirrus Logic Audio Card ++Load: dtoverlay=rpi-cirrus-wm5102 ++Params: ++ ++ +Name: rpi-dac +Info: Configures the RPi DAC audio card +Load: dtoverlay=rpi-dac @@ -99777,7 +86032,7 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 + + +Name: spi-gpio35-39 -+Info: move SPI function block to GPIO 35 to 39 ++Info: Move SPI function block to GPIO 35 to 39 +Load: dtoverlay=spi-gpio35-39 +Params: + @@ -99788,6 +86043,13 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +Params: pcf2123 Select the PCF2123 device + + ++Name: spi0-cs ++Info: Allows the (software) CS pins for SPI0 to be changed ++Load: dtoverlay=spi0-cs,= ++Params: cs0_pin GPIO pin for CS0 (default 8) ++ cs1_pin GPIO pin for CS1 (default 7) ++ ++ +Name: spi0-hw-cs +Info: Re-enables hardware CS/CE (chip selects) for SPI0 +Load: dtoverlay=spi0-hw-cs @@ -100016,10 +86278,10 @@ index 0000000000000000000000000000000000000000..81d991803be335e5a1bc3bb0a8c7a2c9 +http://www.raspberrypi.org/documentation/configuration/device-tree.md diff --git a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c65130dde6 +index 0000000000000000000000000000000000000000..1aaca71c1b677e414ada9a3f94e60e5e2cf30815 --- /dev/null +++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -@@ -0,0 +1,53 @@ +@@ -0,0 +1,40 @@ +// Definitions for ADAU1977 ADC +/dts-v1/; +/plugin/; @@ -100028,19 +86290,6 @@ index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c6 + compatible = "brcm,bcm2708"; + + fragment@0 { -+ target = <&soc>; -+ -+ __overlay__ { -+ codec_supply: fixedregulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "AVDD"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { + target = <&i2c>; + + __overlay__ { @@ -100052,19 +86301,19 @@ index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c6 + compatible = "adi,adau1977"; + reg = <0x11>; + reset-gpios = <&gpio 5 0>; -+ AVDD-supply = <&codec_supply>; ++ AVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; + -+ fragment@2 { ++ fragment@1 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + -+ fragment@3 { ++ fragment@2 { + target = <&sound>; + __overlay__ { + compatible = "adi,adau1977-adc"; @@ -100073,6 +86322,64 @@ index 0000000000000000000000000000000000000000..24fcd58fd1dc61d97a77def3d5d1f7c6 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..e67e6625d7967abc92cf00cb604d4c12fd76b377 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts +@@ -0,0 +1,52 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ adau7002_codec: adau7002-codec { ++ #sound-dai-cells = <0>; ++ compatible = "adi,adau7002"; ++/* IOVDD-supply = <&supply>;*/ ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ sound_overlay: __overlay__ { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "adau7002"; ++ simple-audio-card,bitclock-slave = <&dailink0_slave>; ++ simple-audio-card,frame-slave = <&dailink0_slave>; ++ simple-audio-card,widgets = ++ "Microphone", "Microphone Jack"; ++ simple-audio-card,routing = ++ "PDM_DAT", "Microphone Jack"; ++ status = "okay"; ++ simple-audio-card,cpu { ++ sound-dai = <&i2s>; ++ }; ++ dailink0_slave: simple-audio-card,codec { ++ sound-dai = <&adau7002_codec>; ++ }; ++ }; ++ }; ++ ++ ++ __overrides__ { ++ card-name = <&sound_overlay>,"simple-audio-card,name"; ++ }; ++}; 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 @@ -100177,6 +86484,115 @@ index 0000000000000000000000000000000000000000..02b9de46299bae8f22e1a665a482c0cb + }; + +}; +diff --git a/arch/arm/boot/dts/overlays/ads1115-overlay.dts b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..7c16a1af3172d14e1a976b1776b9f1677278beed +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts +@@ -0,0 +1,103 @@ ++/* ++ * TI ADS1115 multi-channel ADC overlay ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ads1115: ads1115 { ++ compatible = "ti,ads1115"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x48>; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_a: channel_a { ++ reg = <4>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_b: channel_b { ++ reg = <5>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_c: channel_c { ++ reg = <6>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "i2c_arm/ads1115"; ++ __dormant__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ channel_d: channel_d { ++ reg = <7>; ++ ti,gain = <1>; ++ ti,datarate = <7>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ addr = <&ads1115>,"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 @@ -100274,10 +86690,10 @@ index 0000000000000000000000000000000000000000..edf2dc9d5d5f6830508edabf2d04c42d +}; diff --git a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..208849d5c39274ed0aa557f63a19430a451a95f5 +index 0000000000000000000000000000000000000000..241d03b9b79ef5e833cc28819003946a9eb319fd --- /dev/null +++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -@@ -0,0 +1,46 @@ +@@ -0,0 +1,49 @@ +// Definitions for Digital Dreamtime Akkordion using IQaudIO DAC+ or DACZero +/dts-v1/; +/plugin/; @@ -100303,6 +86719,9 @@ index 0000000000000000000000000000000000000000..208849d5c39274ed0aa557f63a19430a + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -100447,6 +86866,62 @@ index 0000000000000000000000000000000000000000..880c7539d496fb10672ee573f7c51b8a + trim = <&lowpan0>, "xtal-trim.0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..dbf2f3cacc2e6bf5b7116fbadd97f2781580a79c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts +@@ -0,0 +1,50 @@ ++// Definitions for audioinjector.net audio add on soundcard ++/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"; ++ ++ cs42448: cs42448@48 { ++ #sound-dai-cells = <0>; ++ compatible = "cirrus,cs42448"; ++ reg = <0x48>; ++ clocks = <&cs42448_mclk>; ++ clock-names = "mclk"; ++ status = "okay"; ++ }; ++ ++ cs42448_mclk: codec-mclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <49152000>; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "ai,audioinjector-octo-soundcard"; ++ mult-gpios = <&gpio 27 0>, <&gpio 22 0>, <&gpio 23 0>, ++ <&gpio 24 0>; ++ i2s-controller = <&i2s>; ++ codec = <&cs42448>; ++ status = "okay"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts b/arch/arm/boot/dts/overlays/audioinjector-wm8731-audio-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..4ed66577fa1d59e7b167ffdfd5a3f0de066cded2 @@ -100636,6 +87111,61 @@ index 0000000000000000000000000000000000000000..3930f412bca4454c6673fb19859e607b + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..a1af93de30119734e8d14cbd454589d365a3ba10 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts +@@ -0,0 +1,49 @@ ++/* ++ * Definitions for Dion Audio LOCO-V2 DAC-AMP ++ * eg. dtoverlay=dionaudio-loco-v2 ++ * ++ * PCM5242 DAC (in software mode) and TPA3255 AMP. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&sound>; ++ frag0: __overlay__ { ++ compatible = "dionaudio,dionaudio-loco-v2"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ pcm5122@4c { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5122"; ++ reg = <0x4d>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ 24db_digital_gain = <&frag0>,"dionaudio,24db_digital_gain?"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/dpi18-overlay.dts b/arch/arm/boot/dts/overlays/dpi18-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..8098d5e28a71ffbc717db5c6b88305d2ba6e3175 @@ -100883,6 +87413,82 @@ index 0000000000000000000000000000000000000000..946c9d2107a83335b11f094e75945a50 + speed = <ð1>, "spi-max-frequency:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..81a07ed5a8c7594e65f0df2176418cac57a7910c +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts +@@ -0,0 +1,70 @@ ++// Definitions for Fe-Pi Audio ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&clocks>; ++ __overlay__ { ++ sgtl5000_mclk: sgtl5000_mclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <12288000>; ++ clock-output-names = "sgtl5000-mclk"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&soc>; ++ __overlay__ { ++ reg_1v8: reg_1v8@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&i2c1>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ sgtl5000@0a { ++ #sound-dai-cells = <0>; ++ compatible = "fepi,sgtl5000"; ++ reg = <0x0a>; ++ clocks = <&sgtl5000_mclk>; ++ micbias-resistor-k-ohms = <2>; ++ micbias-voltage-m-volts = <3000>; ++ VDDA-supply = <&vdd_3v3_reg>; ++ VDDIO-supply = <&vdd_3v3_reg>; ++ VDDD-supply = <®_1v8>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "fe-pi,fe-pi-audio"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; 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..af5baf7ddc92be7a59ad3d5f9a9fefba915bed05 @@ -101060,10 +87666,10 @@ index 0000000000000000000000000000000000000000..0b74fdc6e0f640967a5681b28360e33b +}; diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..2f078d4747ccfdc5172e24b18ce65454f1219b9d +index 0000000000000000000000000000000000000000..b4dc99633b9d409565c0443de378a4460c7a966a --- /dev/null +++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -@@ -0,0 +1,56 @@ +@@ -0,0 +1,59 @@ +// Definitions for HiFiBerry DAC+ +/dts-v1/; +/plugin/; @@ -101100,6 +87706,9 @@ index 0000000000000000000000000000000000000000..2f078d4747ccfdc5172e24b18ce65454 + compatible = "ti,pcm5122"; + reg = <0x4d>; + clocks = <&dacpro_osc>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -101122,10 +87731,10 @@ index 0000000000000000000000000000000000000000..2f078d4747ccfdc5172e24b18ce65454 +}; diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..f5e41f48ba4fed92194ff5a63d13c70bb2d1c091 +index 0000000000000000000000000000000000000000..64cb1e00343b57e3d7dee864416e558dc3163117 --- /dev/null +++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -@@ -0,0 +1,39 @@ +@@ -0,0 +1,41 @@ +// Definitions for HiFiBerry Digi +/dts-v1/; +/plugin/; @@ -101151,6 +87760,8 @@ index 0000000000000000000000000000000000000000..f5e41f48ba4fed92194ff5a63d13c70b + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -101167,10 +87778,10 @@ index 0000000000000000000000000000000000000000..f5e41f48ba4fed92194ff5a63d13c70b +}; diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..2a26d9cfffb0f3d7958eb3756ca7c4ba28400e1c +index 0000000000000000000000000000000000000000..d02479ca4a25c3b2da75fe737fd457b1882c20b1 --- /dev/null +++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -@@ -0,0 +1,41 @@ +@@ -0,0 +1,43 @@ +// Definitions for HiFiBerry Digi Pro +/dts-v1/; +/plugin/; @@ -101196,6 +87807,8 @@ index 0000000000000000000000000000000000000000..2a26d9cfffb0f3d7958eb3756ca7c4ba + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -101801,42 +88414,49 @@ index 0000000000000000000000000000000000000000..1efcf0b712c9c5c19210545002ac1f09 +}; diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..f6d134c095af2398fc55ae7d2b0e86456c30627c +index 0000000000000000000000000000000000000000..31bda8da4cb6a56bfe493a81b918900995fb0589 --- /dev/null +++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -0,0 +1,34 @@ -+// Definitions for a few digital barometric pressure and temperature sensors +@@ -0,0 +1,41 @@ ++// Definitions for I2C based sensors using the Industrial IO interface. +/dts-v1/; +/plugin/; + +/ { -+ compatible = "brcm,bcm2708"; ++ compatible = "brcm,bcm2708"; + -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; + -+ bmp085: bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "disable"; -+ }; ++ bmp085: bmp085@77 { ++ compatible = "bosch,bmp085"; ++ reg = <0x77>; ++ default-oversampling = <3>; ++ status = "disable"; ++ }; + -+ bmp280: bmp280@76 { -+ compatible = "bosch,bmp280"; -+ reg = <0x76>; -+ status = "disable"; -+ }; -+ }; -+ }; ++ bmp280: bmp280@76 { ++ compatible = "bosch,bmp280"; ++ reg = <0x76>; ++ status = "disable"; ++ }; ++ ++ si7020: si7020@40 { ++ compatible = "si7020"; ++ reg = <0x40>; ++ status = "disable"; ++ }; ++ }; ++ }; + + __overrides__ { + bmp085 = <&bmp085>,"status"; + bmp280 = <&bmp280>,"status"; ++ si7020 = <&si7020>,"status"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts b/arch/arm/boot/dts/overlays/i2c0-bcm2708-overlay.dts @@ -101975,10 +88595,10 @@ index 0000000000000000000000000000000000000000..30c356d6070cc3b1dfd1d5a07dc10213 +}; diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..0d35c85382bb5766b3eeb9de1bd4a94621229e4b +index 0000000000000000000000000000000000000000..f16586f05971f69b928200d212015982e388ce96 --- /dev/null +++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +// Definitions for IQaudIO DAC +/dts-v1/; +/plugin/; @@ -102004,6 +88624,9 @@ index 0000000000000000000000000000000000000000..0d35c85382bb5766b3eeb9de1bd4a946 + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -102024,10 +88647,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..d4bad8742a985e2f15eed19ca52ef283a74fefb9 +index 0000000000000000000000000000000000000000..4dcf17515f95589addd5194cf825be813d1e0c98 --- /dev/null +++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -0,0 +1,46 @@ +@@ -0,0 +1,49 @@ +// Definitions for IQaudIO DAC+ +/dts-v1/; +/plugin/; @@ -102053,6 +88676,9 @@ index 0000000000000000000000000000000000000000..d4bad8742a985e2f15eed19ca52ef283 + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -102076,7 +88702,7 @@ index 0000000000000000000000000000000000000000..d4bad8742a985e2f15eed19ca52ef283 +}; 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 +index 0000000000000000000000000000000000000000..b86e1e5edc89fb78fd1ab8482bfff6c7ec4ec9f5 --- /dev/null +++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts @@ -0,0 +1,47 @@ @@ -102106,8 +88732,8 @@ index 0000000000000000000000000000000000000000..da4fbfdfdbbbcf2505b9eb4789ddb779 + compatible = "wlf,wm8804"; + reg = <0x3b>; + status = "okay"; -+ // DVDD-supply = <®_3v3>; -+ // PVDD-supply = <®_3v3>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ PVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; @@ -102129,10 +88755,10 @@ index 0000000000000000000000000000000000000000..da4fbfdfdbbbcf2505b9eb4789ddb779 +}; diff --git a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..312632ad376d5b8c8ff1dbf31fa03d0d18181d94 +index 0000000000000000000000000000000000000000..2b8dba0c231b20ac7660152356a06abeacc83c2d --- /dev/null +++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -@@ -0,0 +1,43 @@ +@@ -0,0 +1,46 @@ +// Definitions for JustBoom DAC +/dts-v1/; +/plugin/; @@ -102158,6 +88784,9 @@ index 0000000000000000000000000000000000000000..312632ad376d5b8c8ff1dbf31fa03d0d + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4d>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -102178,10 +88807,10 @@ index 0000000000000000000000000000000000000000..312632ad376d5b8c8ff1dbf31fa03d0d +}; diff --git a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..cbbede9a541166ba257122918081982016e0b7eb +index 0000000000000000000000000000000000000000..1212e3ff591b6071604ee4a519c89ec50ac95d00 --- /dev/null +++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -@@ -0,0 +1,39 @@ +@@ -0,0 +1,41 @@ +// Definitions for JustBoom Digi +/dts-v1/; +/plugin/; @@ -102207,6 +88836,8 @@ index 0000000000000000000000000000000000000000..cbbede9a541166ba2571229180819820 + #sound-dai-cells = <0>; + compatible = "wlf,wm8804"; + reg = <0x3b>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -103240,6 +89871,217 @@ index 0000000000000000000000000000000000000000..67bd0d9bdaa2ff767d284010a69ecfe3 + interrupt = <&can1_pins>,"brcm,pins:0",<&can1>,"interrupts:0"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts +new file mode 100755 +index 0000000000000000000000000000000000000000..06bf4264959c380d8a9f90f74e7803972d399b2a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts +@@ -0,0 +1,205 @@ ++/* ++ * Device tree overlay for Microchip mcp3008 10-Bit A/D Converters ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spidev0>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev1>; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "spi1/spidev@0"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@3 { ++ target-path = "spi1/spidev@1"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "spi1/spidev@2"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@5 { ++ target-path = "spi2/spidev@0"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@6 { ++ target-path = "spi2/spidev@1"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@7 { ++ target-path = "spi2/spidev@2"; ++ __dormant__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@8 { ++ target = <&spi0>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_00: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@9 { ++ target = <&spi0>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_01: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@10 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_10: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@11 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_11: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@12 { ++ target = <&spi1>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_12: mcp3008@2 { ++ compatible = "mcp3008"; ++ reg = <2>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@13 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_20: mcp3008@0 { ++ compatible = "mcp3008"; ++ reg = <0>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@14 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_21: mcp3008@1 { ++ compatible = "mcp3008"; ++ reg = <1>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ fragment@15 { ++ target = <&spi2>; ++ __dormant__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ mcp3008_22: mcp3008@2 { ++ compatible = "mcp3008"; ++ reg = <2>; ++ spi-max-frequency = <1600000>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ spi0-0-present = <0>, "+0+8"; ++ spi0-1-present = <0>, "+1+9"; ++ spi1-0-present = <0>, "+2+10"; ++ spi1-1-present = <0>, "+3+11"; ++ spi1-2-present = <0>, "+4+12"; ++ spi2-0-present = <0>, "+5+13"; ++ spi2-1-present = <0>, "+6+14"; ++ spi2-2-present = <0>, "+7+15"; ++ spi0-0-speed = <&mcp3008_00>, "spi-max-frequency:0"; ++ spi0-1-speed = <&mcp3008_01>, "spi-max-frequency:0"; ++ spi1-0-speed = <&mcp3008_10>, "spi-max-frequency:0"; ++ spi1-1-speed = <&mcp3008_11>, "spi-max-frequency:0"; ++ spi1-2-speed = <&mcp3008_12>, "spi-max-frequency:0"; ++ spi2-0-speed = <&mcp3008_20>, "spi-max-frequency:0"; ++ spi2-1-speed = <&mcp3008_21>, "spi-max-frequency:0"; ++ spi2-2-speed = <&mcp3008_22>, "spi-max-frequency:0"; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts b/arch/arm/boot/dts/overlays/midi-uart0-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..565af7cf79d761877be3bd06191f31aabf9e1e9b @@ -103534,6 +90376,25 @@ index 0000000000000000000000000000000000000000..87cf345f9641e62c5ed496c238333716 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..017199554bf2f4e381efcc7bb71e750c210343e0 +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts +@@ -0,0 +1,13 @@ ++/dts-v1/; ++/plugin/; ++ ++/{ ++ compatible = "brcm,bcm2708"; ++ ++ fragment@0 { ++ target = <&mmc>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++}; diff --git a/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts b/arch/arm/boot/dts/overlays/pi3-miniuart-bt-overlay.dts new file mode 100644 index 0000000000000000000000000000000000000000..18f77453c38dbbf33f3726a5b4cce15b9f20f390 @@ -103826,10 +90687,10 @@ index 0000000000000000000000000000000000000000..9c0bed893057b9129c8f16b0b695b85b + diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae26019055 +index 0000000000000000000000000000000000000000..5197e656a3d741d14bd9dd6c812b4b93be1419a2 --- /dev/null +++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts -@@ -0,0 +1,114 @@ +@@ -0,0 +1,120 @@ +/* + * pisound Linux kernel module. + * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound @@ -103858,6 +90719,54 @@ index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae + compatible = "brcm,bcm2708"; + + fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spidev0>; ++ __overlay__ { ++ status = "disabled"; ++ }; ++ }; ++ ++ fragment@2 { ++ target = <&spidev1>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pisound_spi: pisound_spi@0{ ++ compatible = "blokaslabs,pisound-spi"; ++ reg = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target-path = "/"; ++ __overlay__ { ++ pcm5102a-codec { ++ #sound-dai-cells = <0>; ++ compatible = "ti,pcm5102a"; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@5 { + target = <&sound>; + __overlay__ { + compatible = "blokaslabs,pisound"; @@ -103881,7 +90790,7 @@ index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae + }; + }; + -+ fragment@1 { ++ fragment@6 { + target = <&gpio>; + __overlay__ { + pinctrl-names = "default"; @@ -103895,54 +90804,12 @@ index 0000000000000000000000000000000000000000..7cdfc29ba4fbffd3216376677922e7ae + }; + }; + -+ fragment@2 { ++ fragment@7 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; -+ -+ fragment@3 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&spi0>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pisound_spi: pisound_spi@0{ -+ compatible = "blokaslabs,pisound-spi"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ spi-max-frequency = <1000000>; -+ }; -+ }; -+ }; +}; diff --git a/arch/arm/boot/dts/overlays/pitft22-overlay.dts b/arch/arm/boot/dts/overlays/pitft22-overlay.dts new file mode 100644 @@ -104573,10 +91440,10 @@ index 0000000000000000000000000000000000000000..b4e601396c4955b9e5de3a639d9afd74 +}; diff --git a/arch/arm/boot/dts/overlays/raspidac3-overlay.dts b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..2fac57ca179fcf114655ea91dbef419c16aceb79 +index 0000000000000000000000000000000000000000..2c3c97813f22c94eff6da2193aff0920ac7c39b1 --- /dev/null +++ b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -@@ -0,0 +1,45 @@ +@@ -0,0 +1,49 @@ +// Definitions for RaspiDACv3 +/dts-v1/; +/plugin/; @@ -104602,12 +91469,16 @@ index 0000000000000000000000000000000000000000..2fac57ca179fcf114655ea91dbef419c + #sound-dai-cells = <0>; + compatible = "ti,pcm5122"; + reg = <0x4c>; ++ AVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + + tpa6130a2: tpa6130a2@60 { + compatible = "ti,tpa6130a2"; + reg = <0x60>; ++ Vdd-supply = <&vdd_3v3_reg>; + status = "okay"; + }; + }; @@ -104649,6 +91520,158 @@ index 0000000000000000000000000000000000000000..c021d02bb75ff5ceb5c5066d00e4bca9 + }; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..cf85f0af224067cf58053a143664f0716d5ce71a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts +@@ -0,0 +1,146 @@ ++// Definitions for the Cirrus Logic Audio Card ++/dts-v1/; ++/plugin/; ++#include ++#include ++#include ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&i2s>; ++ __overlay__ { ++ status = "okay"; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&gpio>; ++ __overlay__ { ++ wlf_pins: wlf_pins { ++ brcm,pins = <17 22 27 8>; ++ brcm,function = < ++ BCM2835_FSEL_GPIO_OUT ++ BCM2835_FSEL_GPIO_OUT ++ BCM2835_FSEL_GPIO_IN ++ BCM2835_FSEL_GPIO_OUT ++ >; ++ }; ++ }; ++ }; ++ ++ fragment@2 { ++ target-path = "/"; ++ __overlay__ { ++ rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "RPi-Cirrus 1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ fragment@3 { ++ target = <&spi0>; ++ __overlay__ { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ spidev@0{ ++ status = "disabled"; ++ }; ++ ++ spidev@1{ ++ status = "disabled"; ++ }; ++ ++ wm5102@1{ ++ compatible = "wlf,wm5102"; ++ reg = <1>; ++ ++ spi-max-frequency = <500000>; ++ ++ interrupt-parent = <&gpio>; ++ interrupts = <27 8>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ LDOVDD-supply = <&rpi_cirrus_reg_1v8>; ++ AVDD-supply = <&rpi_cirrus_reg_1v8>; ++ DBVDD1-supply = <&rpi_cirrus_reg_1v8>; ++ DBVDD2-supply = <&vdd_3v3_reg>; ++ DBVDD3-supply = <&vdd_3v3_reg>; ++ CPVDD-supply = <&rpi_cirrus_reg_1v8>; ++ SPKVDDL-supply = <&vdd_5v0_reg>; ++ SPKVDDR-supply = <&vdd_5v0_reg>; ++ DCVDD-supply = <&arizona_ldo1>; ++ ++ wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>; ++ wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>; ++ wlf,gpio-defaults = < ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ ARIZONA_GP_DEFAULT ++ >; ++ wlf,micd-configs = <0 1 0>; ++ wlf,dmic-ref = < ++ ARIZONA_DMIC_MICVDD ++ ARIZONA_DMIC_MICBIAS2 ++ ARIZONA_DMIC_MICVDD ++ ARIZONA_DMIC_MICVDD ++ >; ++ wlf,inmode = < ++ ARIZONA_INMODE_DIFF ++ ARIZONA_INMODE_DMIC ++ ARIZONA_INMODE_SE ++ ARIZONA_INMODE_DIFF ++ >; ++ status = "okay"; ++ ++ arizona_ldo1: ldo1 { ++ regulator-name = "LDO1"; ++ // default constraints as in ++ // arizona-ldo1.c ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ }; ++ }; ++ }; ++ ++ fragment@4 { ++ target = <&i2c1>; ++ __overlay__ { ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wm8804@3b { ++ compatible = "wlf,wm8804"; ++ reg = <0x3b>; ++ status = "okay"; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; ++ wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ }; ++ ++ fragment@5 { ++ target = <&sound>; ++ __overlay__ { ++ compatible = "wlf,rpi-cirrus"; ++ i2s-controller = <&i2s>; ++ status = "okay"; ++ }; ++ }; ++}; 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..a442c8f0ec01b7503f32e070683a984e895f5668 @@ -104907,10 +91930,10 @@ index 0000000000000000000000000000000000000000..27153240e1be595ae07c7ec74db16155 +}; diff --git a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts new file mode 100644 -index 0000000000000000000000000000000000000000..16b1247bfa618ff85936ddf78c3aea58075eaa67 +index 0000000000000000000000000000000000000000..f8d48233e28c7c18509b4a95692f6aff29ea33fd --- /dev/null +++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -@@ -0,0 +1,81 @@ +@@ -0,0 +1,49 @@ +// Definitions for RRA DigiDAC1 Audio card +/dts-v1/; +/plugin/; @@ -104919,45 +91942,13 @@ index 0000000000000000000000000000000000000000..16b1247bfa618ff85936ddf78c3aea58 + compatible = "brcm,bcm2708"; + + fragment@0 { -+ target-path = "/"; -+ __overlay__ { -+ aliases { -+ ldo0 = &ldo0; -+ ldo1 = &ldo1; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "/soc"; -+ __overlay__ { -+ -+ ldo1: ldo1 { -+ compatible = "regulator-fixed"; -+ regulator-name = "DC_5V"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ ldo0: ldo0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "DC_3V3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ fragment@2 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + -+ fragment@3 { ++ fragment@1 { + target = <&i2c1>; + __overlay__ { + #address-cells = <1>; @@ -104969,21 +91960,21 @@ index 0000000000000000000000000000000000000000..16b1247bfa618ff85936ddf78c3aea58 + compatible = "wlf,wm8804"; + reg = <0x3b>; + status = "okay"; -+ PVDD-supply = <&ldo0>; -+ DVDD-supply = <&ldo0>; ++ PVDD-supply = <&vdd_3v3_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + }; + + wm8742: wm8741@1a { + compatible = "wlf,wm8741"; + reg = <0x1a>; + status = "okay"; -+ AVDD-supply = <&ldo1>; -+ DVDD-supply = <&ldo0>; ++ AVDD-supply = <&vdd_5v0_reg>; ++ DVDD-supply = <&vdd_3v3_reg>; + }; + }; + }; + -+ fragment@4 { ++ fragment@2 { + target = <&sound>; + __overlay__ { + compatible = "rra,digidac1-soundcard"; @@ -105471,6 +92462,41 @@ index 0000000000000000000000000000000000000000..88d1800d63c9f6727b46d4e590c8e96c + pcf2123 = <0>, "=0=1"; + }; +}; +diff --git a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..7f79029d043c04d7496c7c3480450c691dc9a5cb +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts +@@ -0,0 +1,29 @@ ++/dts-v1/; ++/plugin/; ++ ++ ++/ { ++ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0_cs_pins>; ++ frag0: __overlay__ { ++ brcm,pins = <8 7>; ++ }; ++ }; ++ ++ fragment@1 { ++ target = <&spi0>; ++ frag1: __overlay__ { ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ status = "okay"; ++ }; ++ }; ++ ++ __overrides__ { ++ cs0_pin = <&frag0>,"brcm,pins:0", ++ <&frag1>,"cs-gpios:4"; ++ cs1_pin = <&frag0>,"brcm,pins:4", ++ <&frag1>,"cs-gpios:16"; ++ }; ++}; 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 @@ -106324,10 +93350,10 @@ index 0000000000000000000000000000000000000000..95a595a35cb4fbb707bf4b18161f6a46 +}; 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..4f1cc20f90dc6780f74e08ebee00e5a1a6062c85 +index 0000000000000000000000000000000000000000..fb45c6456b181b047d6cff8784f7696eb75da3c7 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -0,0 +1,136 @@ +@@ -0,0 +1,151 @@ +/* + * vc4-kms-v3d-overlay.dts + */ @@ -106335,6 +93361,8 @@ index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1 +/dts-v1/; +/plugin/; + ++#include ++ +/ { + compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; + @@ -106456,6 +93484,19 @@ index 0000000000000000000000000000000000000000..4f1cc20f90dc6780f74e08ebee00e5a1 + }; + }; + ++ ++ fragment@16 { ++ target = <&clocks>; ++ __overlay__ { ++ claim-clocks = < ++ BCM2835_PLLD_DSI0 ++ BCM2835_PLLD_DSI1 ++ BCM2835_PLLH_AUX ++ BCM2835_PLLH_PIX ++ >; ++ }; ++ }; ++ + __overrides__ { + cma-256 = <0>,"+0-1-2-3-4"; + cma-192 = <0>,"-0+1-2-3-4"; @@ -106677,7 +93718,7 @@ index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..ad8dc1c93d04bc929b551c5a47f67d24 .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib -index 0a07f9014944ed92a8e2e42983ae43be60b3e471..1967878a843461c3ff1f473b9a030eb01b7c726e 100644 +index 7234e61e7ce370a775ec6981b391b6d102a01770..1b53cd59e4875d388e4974a3399d5f07df880280 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -312,6 +312,17 @@ cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ @@ -106699,10 +93740,10 @@ index 0a07f9014944ed92a8e2e42983ae43be60b3e471..1967878a843461c3ff1f473b9a030eb0 # Bzip2 -From 9a227b7a8606564e1af28361e8ff04517f5ab0d9 Mon Sep 17 00:00:00 2001 +From bb58274a2b2b00ffe65d2521dbfdd61b76074da1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 Feb 2015 13:50:57 +0000 -Subject: [PATCH 052/216] BCM270x_DT: Add pwr_led, and the required "input" +Subject: [PATCH 057/150] BCM270x_DT: Add pwr_led, and the required "input" trigger The "input" trigger makes the associated GPIO an input. This is to support @@ -106732,7 +93773,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 d400dcaf4d296444967065e98812c210c48a192d..6a27a693034825de2897bb7b338b60cc10c9e59f 100644 +index 066fc75907299cc4ecd83bdf83f155c52e87cfb0..934cdb1d7bc7f12a4fb06a5c458ad76727c7b7c7 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -50,8 +50,15 @@ static void gpio_led_set(struct led_classdev *led_cdev, @@ -106864,13 +93905,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 569cb531094c20a9aa2db478aaa6f348d2afd7f4..aca292f4b0932f61b5bd864251fd05b945497ed4 100644 +index 38c0bd7ca1074af234d516275791d05f945ce1f0..2f026646d24bad617c73aa79db30c9aa1f2b0424 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h -@@ -46,6 +46,9 @@ struct led_classdev { - #define LED_DEV_CAP_FLASH (1 << 18) +@@ -49,6 +49,9 @@ struct led_classdev { #define LED_HW_PLUGGABLE (1 << 19) #define LED_PANIC_INDICATOR (1 << 20) + #define LED_BRIGHT_HW_CHANGED (1 << 21) + /* Additions for Raspberry Pi PWR LED */ +#define SET_GPIO_INPUT (1 << 30) +#define SET_GPIO_OUTPUT (1 << 31) @@ -106878,10 +93919,10 @@ index 569cb531094c20a9aa2db478aaa6f348d2afd7f4..aca292f4b0932f61b5bd864251fd05b9 /* set_brightness_work / blink_timer flags, atomic, private. */ unsigned long work_flags; -From 618bc22e91cca6e00d634bb251386980b6f21362 Mon Sep 17 00:00:00 2001 +From 19b0f43669b73b6a011edb71ce88eaab3b1d93ee Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 053/216] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 058/150] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -107035,7 +94076,7 @@ index 37f60813fe1dd95d9f5f725c07ec2e75c09857bf..53c5a0bdadb4be9251affdabed663058 dev_dbg(info->device, "Unknown ioctl 0x%x\n", cmd); return -ENOTTY; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c -index 76c1ad96fb37d4f07bbde6462f54825f566acbac..7bf48e478c056fcd745026902961506d5826615d 100644 +index 069fe7960df1cedd17c3f7119d2ab6a6989e46c1..2577fca6a93954a499d8b2f94e6a70967874ded2 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1084,6 +1084,31 @@ fb_blank(struct fb_info *info, int blank) @@ -107133,10 +94174,10 @@ index fb795c3b3c178ad3cd7c9e9e4547ffd492bac181..703fa8a70574323abe2fb32599254582 __u32 dx; /* screen-relative */ __u32 dy; -From 5843c3f304dbb45f920aea328f5c92860d0bbf9e Mon Sep 17 00:00:00 2001 +From 3f80968f502506472c21fb2a2fbf291ec9a05297 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 054/216] Speed up console framebuffer imageblit function +Subject: [PATCH 059/150] 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 @@ -107345,10 +94386,10 @@ index a2bb276a8b2463eee98eb237c4647bc00cd93601..436494fba15abecb400ef28688466faf start_index, pitch_index); } else -From a54202aff650c7afbee2de94bc3e341efff34eb9 Mon Sep 17 00:00:00 2001 +From 70a3c50a638d2ef7bac56c6e89684625b8c9d78d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 055/216] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 060/150] 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 @@ -107514,10 +94555,10 @@ index a373ae69d9f6ef8a5925dbd5004cd5e9b8fc5c05..080e5976e2a6b75965ed753ddf29648c } diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h -index 129895f562b06630b464f2579dc9e5bdc105f35e..737a75b594c69716eae8d37479a40031b3045494 100644 +index 758a7a6322e983d527c1f26e4262a5f853b877bc..a36f5becf27b8b07b22a0ab28d1edb9bb9ff4ac4 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h -@@ -173,6 +173,12 @@ struct w1_bus_master +@@ -166,6 +166,12 @@ struct w1_bus_master u8 (*set_pullup)(void *, int); @@ -107531,10 +94572,10 @@ index 129895f562b06630b464f2579dc9e5bdc105f35e..737a75b594c69716eae8d37479a40031 u8, w1_slave_found_callback); }; diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c -index 20f766afa4c7d7b8116565687541f84184fe61f4..c4fbdb1f25e961f9f7bacbac7b52a6d74cabaf12 100644 +index 2cae7b29bb5fb5b72803b9d82d65d636b130bacc..ad0779966ab207972e64be4b2d8eaf17204870f5 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c -@@ -122,6 +122,20 @@ int w1_add_master_device(struct w1_bus_master *master) +@@ -116,6 +116,20 @@ int w1_add_master_device(struct w1_bus_master *master) return(-EINVAL); } @@ -107556,10 +94597,10 @@ 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 f4bc8c100a01b1f04a62ebca2528c51c05f40520..77527e37c7e749754cd3dc2241cdcb64f178166c 100644 +index de8bebc278967552222d025dc143054af040a8af..ffb8184a33f6b4e932379aae19db8952b6d7c488 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) +@@ -127,10 +127,22 @@ static void w1_pre_write(struct w1_master *dev) static void w1_post_write(struct w1_master *dev) { if (dev->pullup_duration) { @@ -107598,63 +94639,10 @@ index d58594a3232492e33f1dd4babd3798b03e0f0203..feae94256256316fd9d850c3d83325af unsigned int ext_pullup_enable_pin; unsigned int pullup_duration; -From d5b0ab4b3de905efb12c1e6f192301c3e6334fa1 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 18 Dec 2013 22:16:19 +0000 -Subject: [PATCH 056/216] config: Enable CONFIG_MEMCG, but leave it disabled - (due to memory cost). Enable with cgroup_enable=memory. - ---- - kernel/cgroup.c | 24 +++++++++++++++++++++++- - 1 file changed, 23 insertions(+), 1 deletion(-) - -diff --git a/kernel/cgroup.c b/kernel/cgroup.c -index 36672b678cce657d43b3a40c4feafc7f4845a516..0324faee0d849a1ccfd8999b1d52b074d89f8804 100644 ---- a/kernel/cgroup.c -+++ b/kernel/cgroup.c -@@ -5632,7 +5632,7 @@ int __init cgroup_init_early(void) - return 0; - } - --static u16 cgroup_disable_mask __initdata; -+static u16 cgroup_disable_mask __initdata = 1<<0; - - /** - * cgroup_init - cgroup initialization -@@ -6169,6 +6169,28 @@ static int __init cgroup_no_v1(char *str) - } - __setup("cgroup_no_v1=", cgroup_no_v1); - -+static int __init cgroup_enable(char *str) -+{ -+ struct cgroup_subsys *ss; -+ char *token; -+ int i; -+ -+ while ((token = strsep(&str, ",")) != NULL) { -+ if (!*token) -+ continue; -+ -+ for_each_subsys(ss, i) { -+ if (strcmp(token, ss->name) && -+ strcmp(token, ss->legacy_name)) -+ continue; -+ -+ cgroup_disable_mask &= ~(1 << i); -+ } -+ } -+ return 1; -+} -+__setup("cgroup_enable=", cgroup_enable); -+ - /** - * css_tryget_online_from_dir - get corresponding css from a cgroup dentry - * @dentry: directory dentry of interest - -From 11d7a34d5bebb128f80e2149c7072c290a1ad809 Mon Sep 17 00:00:00 2001 +From e4163aac85eb2d5aa1bf0b4b9afbfbfe2db7c8c6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 14 Jul 2014 22:02:09 +0100 -Subject: [PATCH 057/216] hid: Reduce default mouse polling interval to 60Hz +Subject: [PATCH 061/150] hid: Reduce default mouse polling interval to 60Hz Reduces overhead when using X --- @@ -107662,10 +94650,10 @@ Reduces overhead when using X 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c -index 333108ef18cf2f3f94ee3816b2ba6522017295b6..da0ee3beeeed3a223ea6859f52a81e99e3e2efbd 100644 +index 961bc6fdd2d908835fa9a07d169a4746fb44189d..c595188a1156a27aa79f111d81636b6d134ed6b2 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c -@@ -49,7 +49,7 @@ +@@ -48,7 +48,7 @@ * Module parameters. */ @@ -107674,7 +94662,7 @@ index 333108ef18cf2f3f94ee3816b2ba6522017295b6..da0ee3beeeed3a223ea6859f52a81e99 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) +@@ -1082,8 +1082,12 @@ static int usbhid_start(struct hid_device *hid) } /* Change the polling interval of mice. */ @@ -107690,10 +94678,10 @@ index 333108ef18cf2f3f94ee3816b2ba6522017295b6..da0ee3beeeed3a223ea6859f52a81e99 ret = -ENOMEM; if (usb_endpoint_dir_in(endpoint)) { -From 51413c15f6566971786541fb95c8b0255245cd5c Mon Sep 17 00:00:00 2001 +From 89bf0e2488d1b059a2e6ff9fc64c8ab00fef7f43 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Tue, 12 May 2015 14:47:56 +0100 -Subject: [PATCH 058/216] rpi-ft5406: Add touchscreen driver for pi LCD display +Subject: [PATCH 062/150] 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 @@ -107711,10 +94699,10 @@ Signed-off-by: Gerhard de Clercq create mode 100644 drivers/input/touchscreen/rpi-ft5406.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig -index efca0133e266b84439bed072f86b6d4c3e147ece..0bf78ff1ae888a1afe3825aab5316f365ef96bfe 100644 +index 03359977765156edb0f8d00c04d51e8921358ef9..60504f240239901a50dc024ec46f7cdba8bebc79 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig -@@ -638,6 +638,13 @@ config TOUCHSCREEN_EDT_FT5X06 +@@ -626,6 +626,13 @@ config TOUCHSCREEN_EDT_FT5X06 To compile this driver as a module, choose M here: the module will be called edt-ft5x06. @@ -107729,7 +94717,7 @@ index efca0133e266b84439bed072f86b6d4c3e147ece..0bf78ff1ae888a1afe3825aab5316f36 tristate "Renesas MIGO-R touchscreen" depends on (SH_MIGOR || COMPILE_TEST) && I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile -index 81b86451782d4479147fbb1a8c70cdc0f6f08eac..f720bc30ada9c2b5907228e852e3955ce9f48c12 100644 +index b622e53441376a7261fe42b1f82598b0aeb3126a..09db22757c88f89619929cc01e79e46c9a577550 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o @@ -108051,10 +95039,10 @@ index 30fb37fe175df604a738258a2a632bca3bfff33f..4a3d79d3b48eb483a4e4bf498f617515 RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From fec27d28df003251ba7af0d36d8c9297eb498978 Mon Sep 17 00:00:00 2001 +From 12dbdcc2fc0f3a2a190f7a96fd32e3cae2b06fbe Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 28 Nov 2016 16:50:04 +0000 -Subject: [PATCH 059/216] Improve __copy_to_user and __copy_from_user +Subject: [PATCH 063/150] Improve __copy_to_user and __copy_from_user performance Provide a __copy_from_user that uses memcpy. On BCM2708, use @@ -109629,10 +96617,10 @@ index 333dc3c2e5ffbb2c5ab8fcfb6115b6162643cf20..46b787a6474ffa857da9b663948863ec bool "Broadcom BCM63xx DSL SoC" depends on ARCH_MULTI_V7 -From 684fbdfad75c8375dcae993744ce68f7c88ad53d Mon Sep 17 00:00:00 2001 +From 0db5a9c2c3f24c992b0a8b09c4f9875aff9e8706 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 25 Jun 2015 12:16:11 +0100 -Subject: [PATCH 060/216] gpio-poweroff: Allow it to work on Raspberry Pi +Subject: [PATCH 064/150] 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 @@ -109667,10 +96655,10 @@ index be3d81ff51cc3f510d85e4eed7a52960e51e7bc1..a030ae9fb1fca325061c093696e82186 "%s: pm_power_off function already registered", __func__); -From 77ecfd9e772af6016a40e7c8949a3c971edc15a3 Mon Sep 17 00:00:00 2001 +From dadaf95138bf3fd42d3028f94b006143132c0191 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 14 Jul 2015 14:32:47 +0100 -Subject: [PATCH 061/216] mfd: Add Raspberry Pi Sense HAT core driver +Subject: [PATCH 065/150] mfd: Add Raspberry Pi Sense HAT core driver --- drivers/input/joystick/Kconfig | 8 + @@ -109880,7 +96868,7 @@ index 0000000000000000000000000000000000000000..6a416769065d2198344792eb02d8e38d +MODULE_AUTHOR("Serge Schneider "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index 4ce3b6f118304048c0fb4d0db7c1d4da7463e8e7..ea2865fec057ffa3b8d1208a6824315a9fd486c6 100644 +index 55ecdfb74d317a3a5a7943a7d93a1cf37dd1fecb..6279545f979ca5e1461f24b21b49482db2c92583 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -10,6 +10,14 @@ config MFD_CORE @@ -109899,13 +96887,13 @@ index 4ce3b6f118304048c0fb4d0db7c1d4da7463e8e7..ea2865fec057ffa3b8d1208a6824315a tristate "AMD CS5535 and CS5536 southbridge core functions" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index dda4d4f73ad743b7cdde1f085dd494c0a1701656..e092a40ceda5b599bf13383147adea6b75a83aa9 100644 +index 31ce07611a6fcbc9854a642587a559ee5d591059..2fae93a57832d636166d689f9a1de444648600f2 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -212,3 +212,4 @@ obj-$(CONFIG_MFD_MT6397) += mt6397-core.o - - obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o +@@ -215,3 +215,4 @@ obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o obj-$(CONFIG_MFD_SUN4I_GPADC) += sun4i-gpadc.o + + obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o +obj-$(CONFIG_MFD_RPISENSE_CORE) += rpisense-core.o diff --git a/drivers/mfd/rpisense-core.c b/drivers/mfd/rpisense-core.c new file mode 100644 @@ -110071,10 +97059,10 @@ index 0000000000000000000000000000000000000000..eea9312dc96a496ce846b0c5a83e6e4f +MODULE_LICENSE("GPL"); + diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig -index 0ff4f80531e013f028ca4d05559c5464f8cfa5ef..2cd45bce38120d076d6a19804443557862978d4b 100644 +index 2fae1676fafc16900d56622e3eef887e27b01eed..b49ef60bb304f3379a29eb8268ebc3a32829d557 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig -@@ -2504,3 +2504,16 @@ config FB_SM712 +@@ -2512,3 +2512,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 . @@ -110535,10 +97523,10 @@ index 0000000000000000000000000000000000000000..56196dc2af10e464a1e3f98b028dca1c + +#endif -From 608514a433fde4cfcf263b8585fa27dc75786699 Mon Sep 17 00:00:00 2001 +From 879ce76fe0a8184a9db36e7092544ab3d5b1b9e6 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Fri, 22 Nov 2013 19:19:08 +0100 -Subject: [PATCH 062/216] ASoC: Add support for HifiBerry DAC +Subject: [PATCH 066/150] ASoC: Add support for HifiBerry DAC This adds a machine driver for the HifiBerry DAC. It is a sound card that can @@ -110584,7 +97572,7 @@ index fc739d0078842680802389500dea19334da8fb7b..be80079de3cefbd52f4b78db20ee9a5d +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..45f2b770ad9e67728ca599a7445d6ae9a01c0c29 +index 0000000000000000000000000000000000000000..ee9f133953544629282631e5ef3f73fec857a7c5 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dac.c @@ -0,0 +1,124 @@ @@ -110680,7 +97668,7 @@ index 0000000000000000000000000000000000000000..45f2b770ad9e67728ca599a7445d6ae9 + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; @@ -110713,10 +97701,10 @@ index 0000000000000000000000000000000000000000..45f2b770ad9e67728ca599a7445d6ae9 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC"); +MODULE_LICENSE("GPL v2"); -From 112ef7d324ba961481fc21fb580841d54d49518f Mon Sep 17 00:00:00 2001 +From 7e921e79cd61712157fc89f006c0a4abfa540696 Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 25 Jan 2016 15:48:59 +0000 -Subject: [PATCH 063/216] ASoC: Add support for Rpi-DAC +Subject: [PATCH 067/150] ASoC: Add support for Rpi-DAC --- sound/soc/bcm/Kconfig | 7 +++ @@ -110758,7 +97746,7 @@ index be80079de3cefbd52f4b78db20ee9a5d554b04c6..09501910f8152b8d516e098433339b5f +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 +index 0000000000000000000000000000000000000000..38224467cbab7d5be3be731e73e2cf787cd9908a --- /dev/null +++ b/sound/soc/bcm/rpi-dac.c @@ -0,0 +1,119 @@ @@ -110849,7 +97837,7 @@ index 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1 + } + + ret = snd_soc_register_card(&snd_rpi_rpi_dac); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; @@ -110882,10 +97870,10 @@ index 0000000000000000000000000000000000000000..59dc89ecabc082c0a1ed8adacdc4f0f1 +MODULE_DESCRIPTION("ASoC Driver for RPi-DAC"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 9e1718a8cb1ce20a0fd68e2cbe797653b39aadeb..35fdfb508505699618dc9d35c941707dcd2a2b20 100644 +index e49e9da7f1f6e41028a0ca832e76e7dce0bc1c01..17b431dc7ea27b1938a1cfe8949e450933ba83e7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -101,6 +101,7 @@ config SND_SOC_ALL_CODECS +@@ -102,6 +102,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 @@ -110893,7 +97881,7 @@ index 9e1718a8cb1ce20a0fd68e2cbe797653b39aadeb..35fdfb508505699618dc9d35c941707d select SND_SOC_PCM3008 select SND_SOC_PCM3168A_I2C if I2C select SND_SOC_PCM3168A_SPI if SPI_MASTER -@@ -709,6 +710,10 @@ config SND_SOC_RT5616 +@@ -712,6 +713,10 @@ config SND_SOC_RT5616 tristate "Realtek RT5616 CODEC" depends on I2C @@ -110905,10 +97893,10 @@ index 9e1718a8cb1ce20a0fd68e2cbe797653b39aadeb..35fdfb508505699618dc9d35c941707d tristate "Realtek ALC5631/RT5631 CODEC" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 7e1dad79610b39a6d5b83865c7022f09d53d3705..3aea6cd7e2d08e72961640860b375059f41c789e 100644 +index 1796cb987e712c78b0fe8f3aa8ec71177256b5b2..4dd919b509d11511807a3c3307ca9b472309c810 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -97,6 +97,7 @@ snd-soc-pcm1681-objs := pcm1681.o +@@ -98,6 +98,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 @@ -110916,7 +97904,7 @@ index 7e1dad79610b39a6d5b83865c7022f09d53d3705..3aea6cd7e2d08e72961640860b375059 snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm3168a-objs := pcm3168a.o snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o -@@ -333,6 +334,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o +@@ -335,6 +336,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 @@ -111000,10 +97988,10 @@ index 0000000000000000000000000000000000000000..afe1b419582aa40c4b2729d242bb13cd +MODULE_AUTHOR("Florian Meier "); +MODULE_LICENSE("GPL v2"); -From a2dea67a42aa4e9e41cc66d18cbb6b249e6d7766 Mon Sep 17 00:00:00 2001 +From 1e09cfdb073d536b57e5dc774d0e4141f26dcffa Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:41:23 +0100 -Subject: [PATCH 064/216] ASoC: wm8804: Implement MCLK configuration options, +Subject: [PATCH 068/150] 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 @@ -111052,10 +98040,10 @@ index af95d648265b3e92e345101542b332aee35191d4..513f56ba132929662802d15cdc653af3 .component_driver = { .dapm_widgets = wm8804_dapm_widgets, -From 8a025e1b920a0e0cc780d6aeab6485daf740830e Mon Sep 17 00:00:00 2001 +From 52195477c717b4447a30950e0ecadb6e5b023fe8 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Wed, 15 Jan 2014 21:42:08 +0100 -Subject: [PATCH 065/216] ASoC: BCM:Add support for HiFiBerry Digi. Driver is +Subject: [PATCH 069/150] ASoC: BCM:Add support for HiFiBerry Digi. Driver is based on the patched WM8804 driver. Signed-off-by: Daniel Matuschek @@ -111118,7 +98106,7 @@ index 09501910f8152b8d516e098433339b5fc2640d0f..862f00fb43bfb0b8dc75d577df47ea4e 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..19dc953b7227ba86123fc7a2ba654499e0c581c5 +index 0000000000000000000000000000000000000000..7620dd02de40b6d644ff038b445d375d8f632def --- /dev/null +++ b/sound/soc/bcm/hifiberry_digi.c @@ -0,0 +1,276 @@ @@ -111366,7 +98354,7 @@ index 0000000000000000000000000000000000000000..19dc953b7227ba86123fc7a2ba654499 + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; @@ -111399,10 +98387,10 @@ index 0000000000000000000000000000000000000000..19dc953b7227ba86123fc7a2ba654499 +MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi"); +MODULE_LICENSE("GPL v2"); -From fb7a95741f1ee401c903e6fe464b159c26912e7e Mon Sep 17 00:00:00 2001 +From 9167d661cd7dfffc95466047de1da73649acef65 Mon Sep 17 00:00:00 2001 From: Gordon Garrity Date: Sat, 8 Mar 2014 16:56:57 +0000 -Subject: [PATCH 066/216] Add IQaudIO Sound Card support for Raspberry Pi +Subject: [PATCH 070/150] Add IQaudIO Sound Card support for Raspberry Pi Set a limit of 0dB on Digital Volume Control @@ -111458,8 +98446,8 @@ 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(+) + sound/soc/bcm/iqaudio-dac.c | 239 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 248 insertions(+) create mode 100644 sound/soc/bcm/iqaudio-dac.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig @@ -111493,10 +98481,10 @@ index 862f00fb43bfb0b8dc75d577df47ea4e8336d00a..fcac518ca9b46ab2074fc859b8d2f1ff +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 +index 0000000000000000000000000000000000000000..1ee4097c846376666775272ed692ca330881b0cb --- /dev/null +++ b/sound/soc/bcm/iqaudio-dac.c -@@ -0,0 +1,234 @@ +@@ -0,0 +1,239 @@ +/* + * ASoC Driver for IQaudIO DAC + * @@ -111575,7 +98563,11 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 +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; @@ -111692,8 +98684,9 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 + + ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); + if (ret) { -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, ++ "snd_soc_register_card() failed: %d\n", ret); + return ret; + } + @@ -111732,37 +98725,10 @@ index 0000000000000000000000000000000000000000..4e8e6dec14bcf4a1ff286c43742d4097 +MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC"); +MODULE_LICENSE("GPL v2"); -From 6498223e6ee8ba37f138fffff3b4fa97ec1dd8ff Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 25 Jul 2016 17:06:50 +0100 -Subject: [PATCH 067/216] 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; - -From 473352a93bdf7df862701175dea6ca4a85554ecb Mon Sep 17 00:00:00 2001 +From 301e8327c483088177bceb0321009ec323859493 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 10:06:56 +0200 -Subject: [PATCH 068/216] Added support for HiFiBerry DAC+ +Subject: [PATCH 071/150] 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. @@ -111799,7 +98765,7 @@ Signed-off-by: DigitalDreamtime create mode 100644 sound/soc/bcm/hifiberry_dacplus.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 925081ec14c04935e1eb17bf2709640c7ae3ae10..2b6fcd8abf79da77aa85fdc53512aafd09f836cb 100644 +index 92c12b86c2e86f2022faeb434bb961f2410faa3e..c901caf8988417053d19916172cf8eb8468a59fd 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o @@ -112014,7 +98980,7 @@ index fcac518ca9b46ab2074fc859b8d2f1ff850ebc19..203afc03167acbcad15e836209956bc5 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..bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266 +index 0000000000000000000000000000000000000000..b7b401cbe2b0d510d8b12d2dda6d5ff1fff42eb0 --- /dev/null +++ b/sound/soc/bcm/hifiberry_dacplus.c @@ -0,0 +1,359 @@ @@ -112344,7 +99310,7 @@ index 0000000000000000000000000000000000000000..bdc35e7e6bc12dc1cf04f5ffad8f9ab4 + } + + ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + @@ -112392,10 +99358,10 @@ index 72b19e62f6267698aea45d2410d616d91c1825cb..c6839ef6e16754ed9de2698507b8986a dev_err(dev, "No LRCLK?\n"); return -EINVAL; -From e8c40361dcb29854097af5e752acf68051dcf0a5 Mon Sep 17 00:00:00 2001 +From f11eecb7b64146142b5ec4743eff96ad07deb6c4 Mon Sep 17 00:00:00 2001 From: Daniel Matuschek Date: Mon, 4 Aug 2014 11:09:58 +0200 -Subject: [PATCH 069/216] Added driver for HiFiBerry Amp amplifier add-on board +Subject: [PATCH 072/150] 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. @@ -112413,12 +99379,12 @@ Some code to load the driver based on device-tree-overlays was missing. This is --- sound/soc/bcm/Kconfig | 7 + sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/hifiberry_amp.c | 129 +++++++++++++++ + sound/soc/bcm/hifiberry_amp.c | 128 +++++++++++++++ sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tas5713.c | 371 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tas5713.h | 210 ++++++++++++++++++++++++ - 7 files changed, 725 insertions(+) + 7 files changed, 724 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 @@ -112442,29 +99408,30 @@ index 3580a12f865975e920ff86697849b137b41bae62..f650f1522d6ef1e02d87345fea01bb14 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 203afc03167acbcad15e836209956bc5ab151157..a4838e2cf8e93c9285836f95f4151daea33e1bd1 100644 +index 203afc03167acbcad15e836209956bc5ab151157..8ffe0725ba10307b5636a252b6bb8d61ecfe2591 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -12,11 +12,13 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o +@@ -9,12 +9,14 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o + obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o + + # BCM2708 Machine Support ++snd-soc-hifiberry-amp-objs := hifiberry_amp.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_AMP) += snd-soc-hifiberry-amp.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..d17c29780507dc31c50f1d567ff5cea7c8241ff5 +index 0000000000000000000000000000000000000000..221c6c38e6465ffe5d5ad77fa80a0b146d0b6841 --- /dev/null +++ b/sound/soc/bcm/hifiberry_amp.c -@@ -0,0 +1,129 @@ +@@ -0,0 +1,128 @@ +/* + * ASoC Driver for HifiBerry AMP + * @@ -112563,9 +99530,8 @@ index 0000000000000000000000000000000000000000..d17c29780507dc31c50f1d567ff5cea7 + + ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); + -+ if (ret != 0) { ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ } + + return ret; +} @@ -112595,10 +99561,10 @@ index 0000000000000000000000000000000000000000..d17c29780507dc31c50f1d567ff5cea7 +MODULE_DESCRIPTION("ASoC driver for HiFiBerry-AMP"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index 35fdfb508505699618dc9d35c941707dcd2a2b20..cd02edde708f860ba90ef7892339ef311c898746 100644 +index 17b431dc7ea27b1938a1cfe8949e450933ba83e7..55812b0b884cf4fc4e86680b11fedd11c863db7a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -143,6 +143,7 @@ config SND_SOC_ALL_CODECS +@@ -144,6 +144,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 @@ -112606,7 +99572,7 @@ index 35fdfb508505699618dc9d35c941707dcd2a2b20..cd02edde708f860ba90ef7892339ef31 select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC31XX if I2C select SND_SOC_TLV320AIC32X4_I2C if I2C -@@ -844,6 +845,9 @@ config SND_SOC_TFA9879 +@@ -847,6 +848,9 @@ config SND_SOC_TFA9879 tristate "NXP Semiconductors TFA9879 amplifier" depends on I2C @@ -112617,10 +99583,10 @@ index 35fdfb508505699618dc9d35c941707dcd2a2b20..cd02edde708f860ba90ef7892339ef31 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile -index 3aea6cd7e2d08e72961640860b375059f41c789e..1f5a6b7f6c52c9464637c028773653cdadae43ab 100644 +index 4dd919b509d11511807a3c3307ca9b472309c810..c675785b3e8d5987f3f7d7aef0bb4b31fbee81e4 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile -@@ -149,6 +149,7 @@ snd-soc-tas5086-objs := tas5086.o +@@ -150,6 +150,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 @@ -112628,7 +99594,7 @@ index 3aea6cd7e2d08e72961640860b375059f41c789e..1f5a6b7f6c52c9464637c028773653cd snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -@@ -375,6 +376,7 @@ obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o +@@ -377,6 +378,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 @@ -113230,10 +100196,10 @@ index 0000000000000000000000000000000000000000..8f019e04898754d2f87e9630137be9e8 + +#endif /* _TAS5713_H */ -From 1846b303b886215d812d2031a606337d297885d6 Mon Sep 17 00:00:00 2001 +From a6100cc973f3a03a8f5ca3ee907a42f9a1bc8517 Mon Sep 17 00:00:00 2001 From: Ryan Coe Date: Sat, 31 Jan 2015 18:25:49 -0700 -Subject: [PATCH 070/216] Update ds1307 driver for device-tree support +Subject: [PATCH 073/150] Update ds1307 driver for device-tree support Signed-off-by: Ryan Coe --- @@ -113260,10 +100226,10 @@ index 4ad97be480430babc3321075f2739114eaad8f04..2ac1c265dc9cea56a5949eb537949a1f .driver = { .name = "rtc-ds1307", -From 8093e25f9c51491cf1a627c7002756c9f6de84dd Mon Sep 17 00:00:00 2001 +From 89ce5a9ebf767d4fdec28695b9a7414bfa347258 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 25 Mar 2015 09:26:17 +0100 -Subject: [PATCH 071/216] Add driver for rpi-proto +Subject: [PATCH 074/150] 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 @@ -113278,8 +100244,8 @@ 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(+) + sound/soc/bcm/rpi-proto.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 162 insertions(+) create mode 100644 sound/soc/bcm/rpi-proto.c diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig @@ -113301,29 +100267,29 @@ index f650f1522d6ef1e02d87345fea01bb1458693423..3cb799da4687e10cd1cfe9258e109b9f 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 a4838e2cf8e93c9285836f95f4151daea33e1bd1..680d1b6d5e16819094fbfaa6c42b458267b54819 100644 +index 8ffe0725ba10307b5636a252b6bb8d61ecfe2591..5793c83cf2f53a831f5f49bb46b5bd4515d711a7 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -14,6 +14,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o +@@ -14,6 +14,7 @@ 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-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 -@@ -21,4 +22,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 +@@ -21,4 +22,5 @@ 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_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 +index 0000000000000000000000000000000000000000..fadbfade100228aaafabb0d3bdf35c01f8d10485 --- /dev/null +++ b/sound/soc/bcm/rpi-proto.c -@@ -0,0 +1,154 @@ +@@ -0,0 +1,153 @@ +/* + * ASoC driver for PROTO AudioCODEC (with a WM8731) + * connected to a Raspberry Pi @@ -113443,10 +100409,9 @@ index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed67 + } + + ret = snd_soc_register_card(&snd_rpi_proto); -+ if (ret) { ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); -+ } + + return ret; +} @@ -113479,10 +100444,10 @@ index 0000000000000000000000000000000000000000..9db678e885efd63d84d60a098a84ed67 +MODULE_DESCRIPTION("ASoC Driver for Raspberry Pi connected to PROTO board (WM8731)"); +MODULE_LICENSE("GPL"); -From e35cad3cabb1465c425a3364bff8c003ca728abb Mon Sep 17 00:00:00 2001 +From b56677c7d2f69587c080bb827e912c94e0317622 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Mon, 24 Aug 2015 16:03:47 +0100 -Subject: [PATCH 072/216] RaspiDAC3 support +Subject: [PATCH 075/150] RaspiDAC3 support Signed-off-by: Jan Grulich @@ -113516,25 +100481,25 @@ index 3cb799da4687e10cd1cfe9258e109b9fcf701c4c..a1b6a78182c9c3698df90e6c8ddaf100 + help + Say Y or M if you want to add support for RaspiDAC Rev.3x. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 680d1b6d5e16819094fbfaa6c42b458267b54819..18253b39addf831780fefe85578e72007c0d51d9 100644 +index 5793c83cf2f53a831f5f49bb46b5bd4515d711a7..c078798106818e3a23f4fbb8068c9ff143b8a2c7 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-hifiberry-amp-objs := hifiberry_amp.o +@@ -16,6 +16,7 @@ snd-soc-hifiberry-digi-objs := hifiberry_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-raspidac3-objs := raspidac3.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.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 -@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -24,3 +25,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o obj-$(CONFIG_SND_BCM2708_SOC_RPI_PROTO) += snd-soc-rpi-proto.o obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_RASPIDAC3) += snd-soc-raspidac3.o diff --git a/sound/soc/bcm/raspidac3.c b/sound/soc/bcm/raspidac3.c new file mode 100644 -index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d15468c1a470a +index 0000000000000000000000000000000000000000..ad2b5b89bc8213dc2e277306ef50d6e32448759c --- /dev/null +++ b/sound/soc/bcm/raspidac3.c @@ -0,0 +1,186 @@ @@ -113689,7 +100654,7 @@ index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d1546 + } + + ret = snd_soc_register_card(&snd_rpi_raspidac3); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + @@ -113725,10 +100690,10 @@ index 0000000000000000000000000000000000000000..dd9eeea2af0382307f437e6db09d1546 +MODULE_DESCRIPTION("ASoC Driver for RaspiDAC Rev.3x"); +MODULE_LICENSE("GPL v2"); -From 1adef94dd6050960cb25b3110be1b92d645a9e92 Mon Sep 17 00:00:00 2001 +From fda8de87fe56328e0c2db342aba4d22141b3d6ab Mon Sep 17 00:00:00 2001 From: Aaron Shaw Date: Thu, 7 Apr 2016 21:26:21 +0100 -Subject: [PATCH 073/216] Add Support for JustBoom Audio boards +Subject: [PATCH 076/150] Add Support for JustBoom Audio boards justboom-dac: Adjust for ALSA API change @@ -113739,9 +100704,9 @@ Signed-off-by: Phil Elwell --- 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(+) + sound/soc/bcm/justboom-dac.c | 163 +++++++++++++++++++++++++++++++ + sound/soc/bcm/justboom-digi.c | 216 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 397 insertions(+) create mode 100644 sound/soc/bcm/justboom-dac.c create mode 100644 sound/soc/bcm/justboom-digi.c @@ -113771,33 +100736,33 @@ index a1b6a78182c9c3698df90e6c8ddaf1003bf01f91..c9c2f702a1ea5548eff093cc84dcc1de 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 18253b39addf831780fefe85578e72007c0d51d9..dbc45d892277bd0b4c0f82e57f0b782e770cddfd 100644 +index c078798106818e3a23f4fbb8068c9ff143b8a2c7..94f5a29386d4e164be428f35d98b007f79dad663 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -12,6 +12,8 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o +@@ -13,6 +13,8 @@ snd-soc-hifiberry-amp-objs := hifiberry_amp.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-justboom-dac-objs := justboom-dac.o +snd-soc-justboom-digi-objs := justboom-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 -@@ -21,6 +23,8 @@ snd-soc-raspidac3-objs := raspidac3.o + snd-soc-iqaudio-dac-objs := iqaudio-dac.o +@@ -22,6 +24,8 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.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_JUSTBOOM_DAC) += snd-soc-justboom-dac.o +obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-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/justboom-dac.c b/sound/soc/bcm/justboom-dac.c new file mode 100644 -index 0000000000000000000000000000000000000000..8fd50dbe681508a2cfe8fdde1c9fedbe9a507fa7 +index 0000000000000000000000000000000000000000..9bab6cf063d3d450d96b4ee2196a7384e071cbdb --- /dev/null +++ b/sound/soc/bcm/justboom-dac.c -@@ -0,0 +1,162 @@ +@@ -0,0 +1,163 @@ +/* + * ASoC Driver for JustBoom DAC Raspberry Pi HAT Sound Card + * @@ -113898,6 +100863,7 @@ index 0000000000000000000000000000000000000000..8fd50dbe681508a2cfe8fdde1c9fedbe +/* audio machine driver */ +static struct snd_soc_card snd_rpi_justboom_dac = { + .name = "snd_rpi_justboom_dac", ++ .driver_name = "JustBoomDac", + .owner = THIS_MODULE, + .dai_link = snd_rpi_justboom_dac_dai, + .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), @@ -113927,7 +100893,7 @@ index 0000000000000000000000000000000000000000..8fd50dbe681508a2cfe8fdde1c9fedbe + } + + ret = snd_soc_register_card(&snd_rpi_justboom_dac); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + @@ -113962,10 +100928,10 @@ index 0000000000000000000000000000000000000000..8fd50dbe681508a2cfe8fdde1c9fedbe +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/bcm/justboom-digi.c b/sound/soc/bcm/justboom-digi.c new file mode 100644 -index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bbec59417b +index 0000000000000000000000000000000000000000..909cf8928f2f4313982316f9c5b8a709c1d47ab8 --- /dev/null +++ b/sound/soc/bcm/justboom-digi.c -@@ -0,0 +1,215 @@ +@@ -0,0 +1,216 @@ +/* + * ASoC Driver for JustBoom Raspberry Pi Digi HAT Sound Card + * @@ -114122,6 +101088,7 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +/* audio machine driver */ +static struct snd_soc_card snd_rpi_justboom_digi = { + .name = "snd_rpi_justboom_digi", ++ .driver_name = "JustBoomDigi", + .owner = THIS_MODULE, + .dai_link = snd_rpi_justboom_digi_dai, + .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), @@ -114148,7 +101115,7 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb + } + + ret = snd_soc_register_card(&snd_rpi_justboom_digi); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + @@ -114182,10 +101149,10 @@ index 0000000000000000000000000000000000000000..91acb666380faa3c0deb2230f8a0f8bb +MODULE_DESCRIPTION("ASoC Driver for JustBoom PI Digi HAT Sound Card"); +MODULE_LICENSE("GPL v2"); -From 9ccd257ea97b462c5f62a64b278db583ce76b9b2 Mon Sep 17 00:00:00 2001 +From 19304e17350389cf286834b934fb0a16e234db67 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Tue, 3 May 2016 22:10:59 -0400 -Subject: [PATCH 074/216] ARM: adau1977-adc: Add basic machine driver for +Subject: [PATCH 077/150] ARM: adau1977-adc: Add basic machine driver for adau1977 codec driver. This commit adds basic support for the codec usage including: Device tree overlay, @@ -114216,7 +101183,7 @@ index c9c2f702a1ea5548eff093cc84dcc1de2f8724ad..72b86dad16b3dd440e5919308a5312fb + help + Say Y or M if you want to add support for ADAU1977 ADC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index dbc45d892277bd0b4c0f82e57f0b782e770cddfd..2b3d1987ea449713b18f60cae3f6edcbd2bcff08 100644 +index 94f5a29386d4e164be428f35d98b007f79dad663..8c20ce506f2b0d653be39ceb9224503a0ef63c39 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -9,6 +9,7 @@ snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o @@ -114224,20 +101191,20 @@ index dbc45d892277bd0b4c0f82e57f0b782e770cddfd..2b3d1987ea449713b18f60cae3f6edcb # BCM2708 Machine Support +snd-soc-adau1977-adc-objs := adau1977-adc.o + snd-soc-hifiberry-amp-objs := hifiberry_amp.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 @@ -20,6 +21,7 @@ snd-soc-rpi-proto-objs := rpi-proto.o snd-soc-iqaudio-dac-objs := iqaudio-dac.o snd-soc-raspidac3-objs := raspidac3.o +obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.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 diff --git a/sound/soc/bcm/adau1977-adc.c b/sound/soc/bcm/adau1977-adc.c new file mode 100644 -index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d2434b0e1 +index 0000000000000000000000000000000000000000..f3d7e5db7bb912e1d7ca6f8e8d42df5f59c9edb8 --- /dev/null +++ b/sound/soc/bcm/adau1977-adc.c @@ -0,0 +1,125 @@ @@ -114333,7 +101300,7 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d + } + + ret = snd_soc_register_card(&snd_adau1977_adc); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); + + return ret; @@ -114367,10 +101334,10 @@ index 0000000000000000000000000000000000000000..6e2ee027926ee63c89222f75ceb89e3d +MODULE_DESCRIPTION("ASoC Driver for ADAU1977 ADC"); +MODULE_LICENSE("GPL v2"); -From 3feaa9ddfd2dd1b9758dea1cf560bf0403ba65af Mon Sep 17 00:00:00 2001 +From 9c11e69322957bbf2493eb225fa9e758462979e6 Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 16 May 2016 21:36:31 +1000 -Subject: [PATCH 075/216] New AudioInjector.net Pi soundcard with low jitter +Subject: [PATCH 078/150] 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. @@ -114404,7 +101371,7 @@ index 72b86dad16b3dd440e5919308a5312fbb72e8703..7ebfa8261a69d31a5add15ae03399dc6 + help + Say Y or M if you want to add support for audioinjector.net Pi Hat diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 2b3d1987ea449713b18f60cae3f6edcbd2bcff08..e61b0f6c7ccee06dfa763d2abbb667707184febc 100644 +index 8c20ce506f2b0d653be39ceb9224503a0ef63c39..4d4189b6d0c57645c5ec19554f1e77d4ccc716d6 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -20,6 +20,7 @@ snd-soc-rpi-dac-objs := rpi-dac.o @@ -114414,7 +101381,7 @@ index 2b3d1987ea449713b18f60cae3f6edcbd2bcff08..e61b0f6c7ccee06dfa763d2abbb66770 +snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-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 + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o @@ -32,3 +33,5 @@ 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 @@ -114621,10 +101588,10 @@ index 0000000000000000000000000000000000000000..ef54e0f07ea03f59e9957b5d98f3e7fd +MODULE_ALIAS("platform:audioinjector-pi-soundcard"); + -From 6b160217d6221e65d9bb2dd95f9e906facc4bb08 Mon Sep 17 00:00:00 2001 +From 00bf028d6bde5775143388b29684a94a3fcd3cb8 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Thu, 30 Jun 2016 18:38:42 +0100 -Subject: [PATCH 076/216] Add IQAudIO Digi WM8804 board support +Subject: [PATCH 079/150] Add IQAudIO Digi WM8804 board support Support IQAudIO Digi board with iqaudio_digi machine driver and iqaudio-digi-wm8804-audio overlay. @@ -114659,10 +101626,10 @@ index 7ebfa8261a69d31a5add15ae03399dc6d8872581..ebc2b3d7b0bd4a1126adbc1315120fe5 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 e61b0f6c7ccee06dfa763d2abbb667707184febc..c4f2579b173c1232096c177f2e557a5337e2e97e 100644 +index 4d4189b6d0c57645c5ec19554f1e77d4ccc716d6..ee41d6bbdbbda2913aba143a59b4953e800bdb3c 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile -@@ -19,6 +19,7 @@ snd-soc-hifiberry-amp-objs := hifiberry_amp.o +@@ -19,6 +19,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 @@ -114670,7 +101637,7 @@ index e61b0f6c7ccee06dfa763d2abbb667707184febc..c4f2579b173c1232096c177f2e557a53 snd-soc-raspidac3-objs := raspidac3.o snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o -@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -32,6 +33,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 @@ -114680,7 +101647,7 @@ index e61b0f6c7ccee06dfa763d2abbb667707184febc..c4f2579b173c1232096c177f2e557a53 diff --git a/sound/soc/bcm/iqaudio_digi.c b/sound/soc/bcm/iqaudio_digi.c new file mode 100644 -index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e7816319639e39d65 +index 0000000000000000000000000000000000000000..33aa2be8a43a12a12cfb5d844dd9732c2393d510 --- /dev/null +++ b/sound/soc/bcm/iqaudio_digi.c @@ -0,0 +1,239 @@ @@ -114890,7 +101857,7 @@ index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e78163196 + } + + ret = snd_soc_register_card(card); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + @@ -114924,10 +101891,10 @@ index 0000000000000000000000000000000000000000..9b6e829bcb5b1762a853775e78163196 +MODULE_DESCRIPTION("ASoC Driver for IQAudIO WM8804 Digi"); +MODULE_LICENSE("GPL v2"); -From a9e7524758d1da36d56d3c1ee271b0ce713a53a9 Mon Sep 17 00:00:00 2001 +From c232845bec8b96e703a5fa4df769a7eeb043d5e9 Mon Sep 17 00:00:00 2001 From: escalator2015 Date: Tue, 24 May 2016 16:20:09 +0100 -Subject: [PATCH 077/216] New driver for RRA DigiDAC1 soundcard using WM8741 + +Subject: [PATCH 080/150] New driver for RRA DigiDAC1 soundcard using WM8741 + WM8804 --- @@ -114954,7 +101921,7 @@ index ebc2b3d7b0bd4a1126adbc1315120fe5c6aca413..c09de7aac7b448ad3af1b50f25ec56f6 + 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 c4f2579b173c1232096c177f2e557a5337e2e97e..290cfff1f982faba7b0089f04536ca82b319b919 100644 +index ee41d6bbdbbda2913aba143a59b4953e800bdb3c..855f4dbe574fcb725b0309710611fa381e1e29d6 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -22,6 +22,7 @@ snd-soc-iqaudio-dac-objs := iqaudio-dac.o @@ -114964,7 +101931,7 @@ index c4f2579b173c1232096c177f2e557a5337e2e97e..290cfff1f982faba7b0089f04536ca82 +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 + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o @@ -36,4 +37,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 @@ -114973,7 +101940,7 @@ index c4f2579b173c1232096c177f2e557a5337e2e97e..290cfff1f982faba7b0089f04536ca82 diff --git a/sound/soc/bcm/digidac1-soundcard.c b/sound/soc/bcm/digidac1-soundcard.c new file mode 100644 -index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0b151f1f3 +index 0000000000000000000000000000000000000000..f200688bb4ae32b90a0ced555aed94b0add0ac8a --- /dev/null +++ b/sound/soc/bcm/digidac1-soundcard.c @@ -0,0 +1,422 @@ @@ -115366,9 +102333,9 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 + } + + ret = snd_soc_register_card(&digidac1_soundcard); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -+ ret); ++ ret); + + return ret; +} @@ -115400,10 +102367,10 @@ index 0000000000000000000000000000000000000000..446796e7e4c14a7d95b2f2a01211d9a0 +MODULE_DESCRIPTION("ASoC Driver for RRA DigiDAC1"); +MODULE_LICENSE("GPL v2"); -From 4d105b66dd0e5b4b8787f2c7f53224b1671e43d6 Mon Sep 17 00:00:00 2001 +From 87b7e9ed0dcb29a656cab2edc17c650d9fa1f709 Mon Sep 17 00:00:00 2001 From: DigitalDreamtime Date: Sat, 2 Jul 2016 16:26:19 +0100 -Subject: [PATCH 078/216] Add support for Dion Audio LOCO DAC-AMP HAT +Subject: [PATCH 081/150] Add support for Dion Audio LOCO DAC-AMP HAT Using dedicated machine driver and pcm5102a codec driver. @@ -115431,7 +102398,7 @@ index c09de7aac7b448ad3af1b50f25ec56f682f872b7..aac9120b0865ce63b6c851dbe3917f55 + 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 290cfff1f982faba7b0089f04536ca82b319b919..3d09653b2e9eafc1d82f4b8349646fa174c86877 100644 +index 855f4dbe574fcb725b0309710611fa381e1e29d6..fca9d682bbd2e7821ae01aefc7a5a94e0880a41e 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -23,6 +23,7 @@ snd-soc-iqaudio-digi-objs := iqaudio_digi.o @@ -115441,7 +102408,7 @@ index 290cfff1f982faba7b0089f04536ca82b319b919..3d09653b2e9eafc1d82f4b8349646fa1 +snd-soc-dionaudio-loco-objs := dionaudio_loco.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 + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o @@ -38,4 +39,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 @@ -115450,7 +102417,7 @@ index 290cfff1f982faba7b0089f04536ca82b319b919..3d09653b2e9eafc1d82f4b8349646fa1 +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 +index 0000000000000000000000000000000000000000..65e03741d349a2dc5bd91f69855ea952d9cf87a2 --- /dev/null +++ b/sound/soc/bcm/dionaudio_loco.c @@ -0,0 +1,121 @@ @@ -115542,7 +102509,7 @@ index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98 + } + + ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", + ret); + @@ -115576,10 +102543,10 @@ index 0000000000000000000000000000000000000000..89e65317512bc774453ac8d0d5b0ff98 +MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO"); +MODULE_LICENSE("GPL v2"); -From 4a86ff8bc24b711cd7316e273fe5f211323a687d Mon Sep 17 00:00:00 2001 +From fe2aefea2964c92668d7b70130fed4e2ccbd6537 Mon Sep 17 00:00:00 2001 From: Clive Messer Date: Mon, 19 Sep 2016 14:01:04 +0100 -Subject: [PATCH 079/216] Allo Piano DAC boards: Initial 2 channel (stereo) +Subject: [PATCH 082/150] Allo Piano DAC boards: Initial 2 channel (stereo) support (#1645) Add initial 2 channel (stereo) support for Allo Piano DAC (2.0/2.1) boards, @@ -115619,7 +102586,7 @@ index aac9120b0865ce63b6c851dbe3917f5548b9a539..b600cfb98ac9baa21b3c6f09eff05149 + help + Say Y or M if you want to add support for Allo Piano DAC. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 3d09653b2e9eafc1d82f4b8349646fa174c86877..7d70655c226c1ecd59ee60aae4508699ee9d10ae 100644 +index fca9d682bbd2e7821ae01aefc7a5a94e0880a41e..64f007f8ba38276a42e0bd8db92544db9412544b 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -24,6 +24,7 @@ snd-soc-raspidac3-objs := raspidac3.o @@ -115629,7 +102596,7 @@ index 3d09653b2e9eafc1d82f4b8349646fa174c86877..7d70655c226c1ecd59ee60aae4508699 +snd-soc-allo-piano-dac-objs := allo-piano-dac.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 + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o @@ -40,3 +41,4 @@ 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 @@ -115637,7 +102604,7 @@ index 3d09653b2e9eafc1d82f4b8349646fa174c86877..7d70655c226c1ecd59ee60aae4508699 +obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o diff --git a/sound/soc/bcm/allo-piano-dac.c b/sound/soc/bcm/allo-piano-dac.c new file mode 100644 -index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99ecd7e4cf +index 0000000000000000000000000000000000000000..eaf50fb6dbca1970ae1c6f8662088b0f1573fecb --- /dev/null +++ b/sound/soc/bcm/allo-piano-dac.c @@ -0,0 +1,144 @@ @@ -115752,7 +102719,7 @@ index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99 + } + + ret = snd_soc_register_card(&snd_allo_piano_dac); -+ if (ret) ++ if (ret && ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "snd_soc_register_card() failed: %d\n", ret); + @@ -115786,30 +102753,40 @@ index 0000000000000000000000000000000000000000..8e8e62e5a36a279b425ed4655cfbac99 +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC"); +MODULE_LICENSE("GPL v2"); -From f7163c1dd4e2f7b4b23bf5de7c50740f3b0aedc0 Mon Sep 17 00:00:00 2001 +From 8a499717a13372304fd7a0368cff9c0c888384fb Mon Sep 17 00:00:00 2001 From: gtrainavicius Date: Sun, 23 Oct 2016 12:06:53 +0300 -Subject: [PATCH 080/216] Support for Blokas Labs pisound board +Subject: [PATCH 083/150] Support for Blokas Labs pisound board Pisound dynamic overlay (#1760) Restructuring pisound-overlay.dts, so it can be loaded and unloaded dynamically using dtoverlay. Print a logline when the kernel module is removed. + +pisound improvements: + +* Added a writable sysfs object to enable scripts / user space software +to blink MIDI activity LEDs for variable duration. +* Improved hw_param constraints setting. +* Added compatibility with S16_LE sample format. +* Exposed some simple placeholder volume controls, so the card appears +in volumealsa widget. + +Signed-off-by: Giedrius Trainavicius --- - .../devicetree/bindings/vendor-prefixes.txt | 1 + - arch/arm/boot/dts/overlays/pisound-overlay.dts | 94 +- - sound/soc/bcm/Kconfig | 6 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/pisound.c | 989 +++++++++++++++++++++ - 5 files changed, 1048 insertions(+), 44 deletions(-) + .../devicetree/bindings/vendor-prefixes.txt | 1 + + sound/soc/bcm/Kconfig | 6 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/pisound.c | 1123 ++++++++++++++++++++ + 4 files changed, 1132 insertions(+) create mode 100644 sound/soc/bcm/pisound.c diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt -index 16d3b5e7f5d1f52d1bf3c5f98220ba4f09b99b8f..596ea7815668327e3171fb8f53af428a953554dc 100644 +index ec0bfb9bbebd42c828a3b4978db070924275f609..6b6b0b13c361b9cd0df0a9aea86366bd92c520cf 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt -@@ -43,6 +43,7 @@ avago Avago Technologies +@@ -44,6 +44,7 @@ avia avia semiconductor avic Shanghai AVIC Optoelectronics Co., Ltd. axentia Axentia Technologies AB axis Axis Communications AB @@ -115817,128 +102794,6 @@ index 16d3b5e7f5d1f52d1bf3c5f98220ba4f09b99b8f..596ea7815668327e3171fb8f53af428a boe BOE Technology Group Co., Ltd. bosch Bosch Sensortec GmbH boundary Boundary Devices Inc. -diff --git a/arch/arm/boot/dts/overlays/pisound-overlay.dts b/arch/arm/boot/dts/overlays/pisound-overlay.dts -index 7cdfc29ba4fbffd3216376677922e7ae26019055..5197e656a3d741d14bd9dd6c812b4b93be1419a2 100644 ---- a/arch/arm/boot/dts/overlays/pisound-overlay.dts -+++ b/arch/arm/boot/dts/overlays/pisound-overlay.dts -@@ -26,6 +26,54 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spidev0>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&spidev1>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ pisound_spi: pisound_spi@0{ -+ compatible = "blokaslabs,pisound-spi"; -+ reg = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins>; -+ spi-max-frequency = <1000000>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "/"; -+ __overlay__ { -+ pcm5102a-codec { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5102a"; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@5 { - target = <&sound>; - __overlay__ { - compatible = "blokaslabs,pisound"; -@@ -49,7 +97,7 @@ - }; - }; - -- fragment@1 { -+ fragment@6 { - target = <&gpio>; - __overlay__ { - pinctrl-names = "default"; -@@ -63,52 +111,10 @@ - }; - }; - -- fragment@2 { -+ fragment@7 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; -- -- fragment@3 { -- target-path = "/"; -- __overlay__ { -- pcm5102a-codec { -- #sound-dai-cells = <0>; -- compatible = "ti,pcm5102a"; -- status = "okay"; -- }; -- }; -- }; -- -- fragment@4 { -- target = <&spi0>; -- __overlay__ { -- status = "okay"; -- -- spidev@0{ -- status = "disabled"; -- }; -- -- spidev@1{ -- status = "okay"; -- }; -- }; -- }; -- -- fragment@5 { -- target = <&spi0>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- -- pisound_spi: pisound_spi@0{ -- compatible = "blokaslabs,pisound-spi"; -- reg = <0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&spi0_pins>; -- spi-max-frequency = <1000000>; -- }; -- }; -- }; - }; diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig index b600cfb98ac9baa21b3c6f09eff05149f14fda0a..ff4284a0000fd8dc58deb9e50be1422fd7ad6e65 100644 --- a/sound/soc/bcm/Kconfig @@ -115954,7 +102809,7 @@ index b600cfb98ac9baa21b3c6f09eff05149f14fda0a..ff4284a0000fd8dc58deb9e50be1422f + help + Say Y or M if you want to add support for Blokas Labs pisound. diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 7d70655c226c1ecd59ee60aae4508699ee9d10ae..222a7583891f632cc2297f49aa1a58ee46507875 100644 +index 64f007f8ba38276a42e0bd8db92544db9412544b..bb1df438540193652ec5464e8bc51f636a1b844e 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -25,6 +25,7 @@ snd-soc-audioinjector-pi-soundcard-objs := audioinjector-pi-soundcard.o @@ -115964,7 +102819,7 @@ index 7d70655c226c1ecd59ee60aae4508699ee9d10ae..222a7583891f632cc2297f49aa1a58ee +snd-soc-pisound-objs := pisound.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 + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o @@ -42,3 +43,4 @@ obj-$(CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD) += snd-soc-audioinjector-pi-soundca obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o @@ -115972,10 +102827,10 @@ index 7d70655c226c1ecd59ee60aae4508699ee9d10ae..222a7583891f632cc2297f49aa1a58ee +obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c new file mode 100644 -index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb2310b3b94d0 +index 0000000000000000000000000000000000000000..06ff1e53dc9d860946965b6303577762f958fae2 --- /dev/null +++ b/sound/soc/bcm/pisound.c -@@ -0,0 +1,989 @@ +@@ -0,0 +1,1123 @@ +/* + * pisound Linux kernel module. + * Copyright (C) 2016 Vilniaus Blokas UAB, http://blokas.io/pisound @@ -116014,6 +102869,7 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 +#include +#include +#include ++#include + +static int pisnd_spi_init(struct device *dev); +static void pisnd_spi_uninit(void); @@ -116192,6 +103048,9 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 +static char g_id[25]; +static char g_version[5]; + ++static uint8_t g_ledFlashDuration; ++static bool g_ledFlashDurationChanged; ++ +DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); +DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); + @@ -116374,8 +103233,13 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + val = 0; + tx = 0; + -+ if (kfifo_get(&spi_fifo_out, &val)) ++ if (g_ledFlashDurationChanged) { ++ tx = 0xf000 | g_ledFlashDuration; ++ g_ledFlashDuration = 0; ++ g_ledFlashDurationChanged = false; ++ } else if (kfifo_get(&spi_fifo_out, &val)) { + tx = 0x0f00 | val; ++ } + + rx = spi_transfer16(tx); + @@ -116388,6 +103252,7 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + } while (rx != 0 + || !kfifo_is_empty(&spi_fifo_out) + || pisnd_spi_has_more() ++ || g_ledFlashDurationChanged + ); + + if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) @@ -116547,7 +103412,7 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + } + + /* Flash the LEDs. */ -+ spi_transfer16(0xf000); ++ spi_transfer16(0xf008); + + ret = pisnd_spi_gpio_irq_init(dev); + if (ret < 0) { @@ -116588,6 +103453,14 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + pisnd_spi_gpio_uninit(); +} + ++static void pisnd_spi_flash_leds(uint8_t duration) ++{ ++ g_ledFlashDuration = duration; ++ g_ledFlashDurationChanged = true; ++ printd("schedule from spi_flash_leds\n"); ++ pisnd_schedule_process(TASK_PROCESS); ++} ++ +static void pisnd_spi_send(uint8_t val) +{ + kfifo_put(&spi_fifo_out, val); @@ -116636,6 +103509,83 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + {}, +}; + ++enum { ++ SWITCH = 0, ++ VOLUME = 1, ++}; ++ ++static int pisnd_ctl_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ if (kcontrol->private_value == SWITCH) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = 1; ++ return 0; ++ } else if (kcontrol->private_value == VOLUME) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = 100; ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++static int pisnd_ctl_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ if (kcontrol->private_value == SWITCH) { ++ ucontrol->value.integer.value[0] = 1; ++ return 0; ++ } else if (kcontrol->private_value == VOLUME) { ++ ucontrol->value.integer.value[0] = 100; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static struct snd_kcontrol_new pisnd_ctl[] = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Switch", ++ .index = 0, ++ .private_value = SWITCH, ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .info = pisnd_ctl_info, ++ .get = pisnd_ctl_get, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Volume", ++ .index = 0, ++ .private_value = VOLUME, ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .info = pisnd_ctl_info, ++ .get = pisnd_ctl_get, ++ }, ++}; ++ ++static int pisnd_ctl_init(struct snd_card *card) ++{ ++ int err, i; ++ ++ for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) { ++ err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL)); ++ if (err < 0) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int pisnd_ctl_uninit(void) ++{ ++ return 0; ++} ++ +static struct gpio_desc *osr0, *osr1, *osr2; +static struct gpio_desc *reset; +static struct gpio_desc *button; @@ -116645,6 +103595,14 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + struct snd_pcm_hw_params *params + ) +{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ ++ /* pisound runs on fixed 32 clock counts per channel, ++ * as generated by the master ADC. ++ */ ++ snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); ++ + printd("rate = %d\n", params_rate(params)); + printd("ch = %d\n", params_channels(params)); + printd("bits = %u\n", @@ -116689,16 +103647,6 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + .mask = 0, +}; + -+static unsigned int sample_bits[] = { -+ 24, 32 -+}; -+ -+static struct snd_pcm_hw_constraint_list constraints_sample_bits = { -+ .count = ARRAY_SIZE(sample_bits), -+ .list = sample_bits, -+ .mask = 0, -+}; -+ +static int pisnd_startup(struct snd_pcm_substream *substream) +{ + int err = snd_pcm_hw_constraint_list( @@ -116711,11 +103659,21 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + if (err < 0) + return err; + -+ err = snd_pcm_hw_constraint_list( ++ err = snd_pcm_hw_constraint_single( + substream->runtime, -+ 0, -+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -+ &constraints_sample_bits ++ SNDRV_PCM_HW_PARAM_CHANNELS, ++ 2 ++ ); ++ ++ if (err < 0) ++ return err; ++ ++ err = snd_pcm_hw_constraint_mask64( ++ substream->runtime, ++ SNDRV_PCM_HW_PARAM_FORMAT, ++ SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE + ); + + if (err < 0) @@ -116749,14 +103707,23 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 +{ + int err = pisnd_midi_init(card->snd_card); + -+ if (err < 0) ++ if (err < 0) { + printe("pisnd_midi_init failed: %d\n", err); ++ return err; ++ } + -+ return err; ++ err = pisnd_ctl_init(card->snd_card); ++ if (err < 0) { ++ printe("pisnd_ctl_init failed: %d\n", err); ++ return err; ++ } ++ ++ return 0; +} + +static int pisnd_card_remove(struct snd_soc_card *card) +{ ++ pisnd_ctl_uninit(); + pisnd_midi_uninit(); + return 0; +} @@ -116848,17 +103815,38 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + return sprintf(buf, "%s\n", pisnd_spi_get_version()); +} + ++static ssize_t pisnd_led_store( ++ struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, ++ size_t length ++ ) ++{ ++ uint32_t timeout; ++ int err; ++ ++ err = kstrtou32(buf, 10, &timeout); ++ ++ if (err == 0 && timeout <= 255) ++ pisnd_spi_flash_leds(timeout); ++ ++ return length; ++} ++ +static struct kobj_attribute pisnd_serial_attribute = -+ __ATTR(serial, 0644, pisnd_serial_show, NULL); ++ __ATTR(serial, 0444, pisnd_serial_show, NULL); +static struct kobj_attribute pisnd_id_attribute = -+ __ATTR(id, 0644, pisnd_id_show, NULL); ++ __ATTR(id, 0444, pisnd_id_show, NULL); +static struct kobj_attribute pisnd_version_attribute = -+ __ATTR(version, 0644, pisnd_version_show, NULL); ++ __ATTR(version, 0444, pisnd_version_show, NULL); ++static struct kobj_attribute pisnd_led_attribute = ++ __ATTR(led, 0644, NULL, pisnd_led_store); + +static struct attribute *attrs[] = { + &pisnd_serial_attribute.attr, + &pisnd_id_attribute.attr, + &pisnd_version_attribute.attr, ++ &pisnd_led_attribute.attr, + NULL +}; + @@ -116921,7 +103909,8 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 + ret = snd_soc_register_card(&pisnd_card); + + if (ret < 0) { -+ printe("snd_soc_register_card() failed: %d\n", ret); ++ if (ret != -EPROBE_DEFER) ++ printe("snd_soc_register_card() failed: %d\n", ret); + pisnd_uninit_gpio(); + kobject_put(pisnd_kobj); + pisnd_spi_uninit(); @@ -116966,10 +103955,1835 @@ index 0000000000000000000000000000000000000000..4b8545487d06e4ea70073a5d063fb231 +MODULE_DESCRIPTION("ASoC Driver for pisound, http://blokas.io/pisound"); +MODULE_LICENSE("GPL v2"); -From a0af1a9da13398a7a5a6c2377b379d40a38987d2 Mon Sep 17 00:00:00 2001 +From d292bce15d11c21458b30b2b4e4eaa992a33c653 Mon Sep 17 00:00:00 2001 +From: Matthias Reichl +Date: Sun, 22 Jan 2017 12:49:37 +0100 +Subject: [PATCH 084/150] ASoC: Add driver for Cirrus Logic Audio Card + +Note: due to problems with deferred probing of regulators +the following softdep should be added to a modprobe.d file + +softdep arizona-spi pre: arizona-ldo1 + +Signed-off-by: Matthias Reichl +--- + sound/soc/bcm/Kconfig | 9 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/rpi-cirrus.c | 1003 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 1014 insertions(+) + create mode 100644 sound/soc/bcm/rpi-cirrus.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index ff4284a0000fd8dc58deb9e50be1422fd7ad6e65..c0489e591b9b8c8da004ca9e300e97f1a21e5ce1 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -46,6 +46,15 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP + help + Say Y or M if you want to add support for the HifiBerry Amp amplifier board. + ++config SND_BCM2708_SOC_RPI_CIRRUS ++ tristate "Support for Cirrus Logic Audio Card" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_WM5102 ++ select SND_SOC_WM8804 ++ help ++ Say Y or M if you want to add support for the Wolfson and ++ Cirrus Logic audio cards. ++ + 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 bb1df438540193652ec5464e8bc51f636a1b844e..84c2b20ce2e51b525797ee58de95734ee7847e15 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o + snd-soc-hifiberry-digi-objs := hifiberry_digi.o + snd-soc-justboom-dac-objs := justboom-dac.o + snd-soc-justboom-digi-objs := justboom-digi.o ++snd-soc-rpi-cirrus-objs := rpi-cirrus.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 +@@ -34,6 +35,7 @@ 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_JUSTBOOM_DAC) += snd-soc-justboom-dac.o + obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o ++obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.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-cirrus.c b/sound/soc/bcm/rpi-cirrus.c +new file mode 100644 +index 0000000000000000000000000000000000000000..ac8651ddff7bd3701dffe22c7fb88352f912dff3 +--- /dev/null ++++ b/sound/soc/bcm/rpi-cirrus.c +@@ -0,0 +1,1003 @@ ++/* ++ * ASoC machine driver for Cirrus Logic Audio Card ++ * (with WM5102 and WM8804 codecs) ++ * ++ * Copyright 2015-2017 Matthias Reichl ++ * ++ * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../codecs/wm5102.h" ++#include "../codecs/wm8804.h" ++ ++#define WM8804_CLKOUT_HZ 12000000 ++ ++#define RPI_CIRRUS_DEFAULT_RATE 44100 ++#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */ ++#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */ ++ ++static inline unsigned int calc_sysclk(unsigned int rate) ++{ ++ return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1; ++} ++ ++enum { ++ DAI_WM5102 = 0, ++ DAI_WM8804, ++}; ++ ++struct rpi_cirrus_priv { ++ /* mutex for synchronzing FLL1 access with DAPM */ ++ struct mutex lock; ++ unsigned int card_rate; ++ int sync_path_enable; ++ int fll1_freq; /* negative means RefClock in spdif rx case */ ++ ++ /* track hw params/free for substreams */ ++ unsigned int params_set; ++ unsigned int min_rate_idx, max_rate_idx; ++ unsigned char iec958_status[4]; ++}; ++ ++/* helper functions */ ++static inline struct snd_soc_pcm_runtime *get_wm5102_runtime( ++ struct snd_soc_card *card) { ++ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name); ++} ++ ++static inline struct snd_soc_pcm_runtime *get_wm8804_runtime( ++ struct snd_soc_card *card) { ++ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name); ++} ++ ++ ++struct rate_info { ++ unsigned int value; ++ char *text; ++}; ++ ++static struct rate_info min_rates[] = { ++ { 0, "off"}, ++ { 32000, "32kHz"}, ++ { 44100, "44.1kHz"} ++}; ++ ++#define NUM_MIN_RATES ARRAY_SIZE(min_rates) ++ ++static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_MIN_RATES; ++ ++ if (uinfo->value.enumerated.item >= NUM_MIN_RATES) ++ uinfo->value.enumerated.item = NUM_MIN_RATES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ min_rates[uinfo->value.enumerated.item].text); ++ return 0; ++} ++ ++static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ ++ ucontrol->value.enumerated.item[0] = priv->min_rate_idx; ++ return 0; ++} ++ ++static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int changed = 0; ++ ++ if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) { ++ changed = 1; ++ priv->min_rate_idx = ucontrol->value.enumerated.item[0]; ++ } ++ ++ return changed; ++} ++ ++static struct rate_info max_rates[] = { ++ { 0, "off"}, ++ { 48000, "48kHz"}, ++ { 96000, "96kHz"} ++}; ++ ++#define NUM_MAX_RATES ARRAY_SIZE(max_rates) ++ ++static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_MAX_RATES; ++ if (uinfo->value.enumerated.item >= NUM_MAX_RATES) ++ uinfo->value.enumerated.item = NUM_MAX_RATES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ max_rates[uinfo->value.enumerated.item].text); ++ return 0; ++} ++ ++static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ ++ ucontrol->value.enumerated.item[0] = priv->max_rate_idx; ++ return 0; ++} ++ ++static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int changed = 0; ++ ++ if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) { ++ changed = 1; ++ priv->max_rate_idx = ucontrol->value.enumerated.item[0]; ++ } ++ ++ return changed; ++} ++ ++static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; ++ uinfo->count = 1; ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ int i; ++ ++ for (i = 0; i < 4; i++) ++ ucontrol->value.iec958.status[i] = priv->iec958_status[i]; ++ ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned char *stat = priv->iec958_status; ++ unsigned char *ctrl_stat = ucontrol->value.iec958.status; ++ unsigned int mask; ++ int i, changed = 0; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ if ((ctrl_stat[i] & mask) != (stat[i] & mask)) { ++ changed = 1; ++ stat[i] = ctrl_stat[i] & mask; ++ snd_soc_update_bits(wm8804_codec, ++ WM8804_SPDTX1 + i, mask, stat[i]); ++ } ++ } ++ ++ return changed; ++} ++ ++static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ ucontrol->value.iec958.status[0] = 0xff; ++ ucontrol->value.iec958.status[1] = 0xff; ++ ucontrol->value.iec958.status[2] = 0xff; ++ ucontrol->value.iec958.status[3] = 0x3f; ++ ++ return 0; ++} ++ ++static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ unsigned int mask; ++ int i; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ ucontrol->value.iec958.status[i] = ++ snd_soc_read(wm8804_codec, WM8804_RXCHAN1 + i) & mask; ++ } ++ ++ return 0; ++} ++ ++#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \ ++{ \ ++ .access = SNDRV_CTL_ELEM_ACCESS_READ \ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \ ++ desc " Flag", \ ++ .info = snd_ctl_boolean_mono_info, \ ++ .get = rpi_cirrus_spdif_status_flag_get, \ ++ .private_value = \ ++ (bit) | ((reg) << 8) | ((invert) << 16) \ ++} ++ ++static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ ++ unsigned int bit = kcontrol->private_value & 0xff; ++ unsigned int reg = (kcontrol->private_value >> 8) & 0xff; ++ unsigned int invert = (kcontrol->private_value >> 16) & 0xff; ++ ++ bool flag = snd_soc_read(wm8804_codec, reg) & (1 << bit); ++ ++ ucontrol->value.integer.value[0] = invert ? !flag : flag; ++ ++ return 0; ++} ++ ++static const char * const recovered_frequency_texts[] = { ++ "176.4/192 kHz", ++ "88.2/96 kHz", ++ "44.1/48 kHz", ++ "32 kHz" ++}; ++ ++#define NUM_RECOVERED_FREQUENCIES \ ++ ARRAY_SIZE(recovered_frequency_texts) ++ ++static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; ++ uinfo->count = 1; ++ uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES; ++ if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES) ++ uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1; ++ strcpy(uinfo->value.enumerated.name, ++ recovered_frequency_texts[uinfo->value.enumerated.item]); ++ return 0; ++} ++ ++static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); ++ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; ++ ++ ucontrol->value.enumerated.item[0] = ++ (snd_soc_read(wm8804_codec, WM8804_SPDSTAT) >> 4) & 0x03; ++ return 0; ++} ++ ++static const struct snd_kcontrol_new rpi_cirrus_controls[] = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Min Sample Rate", ++ .info = rpi_cirrus_min_rate_info, ++ .get = rpi_cirrus_min_rate_get, ++ .put = rpi_cirrus_min_rate_put, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "Max Sample Rate", ++ .info = rpi_cirrus_max_rate_info, ++ .get = rpi_cirrus_max_rate_get, ++ .put = rpi_cirrus_max_rate_put, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_playback_get, ++ .put = rpi_cirrus_spdif_playback_put, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_capture_get, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), ++ .info = rpi_cirrus_spdif_info, ++ .get = rpi_cirrus_spdif_mask_get, ++ }, ++ { ++ .access = SNDRV_CTL_ELEM_ACCESS_READ ++ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) ++ "Recovered Frequency", ++ .info = rpi_cirrus_recovered_frequency_info, ++ .get = rpi_cirrus_recovered_frequency_get, ++ }, ++ SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1), ++ SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0), ++ SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1), ++ SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0), ++ SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1), ++ SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0), ++ SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0), ++}; ++ ++static const char * const linein_micbias_texts[] = { ++ "off", "on", ++}; ++ ++static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum, ++ linein_micbias_texts); ++ ++static const struct snd_kcontrol_new linein_micbias_mux = ++ SOC_DAPM_ENUM("Route", linein_micbias_enum); ++ ++static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event); ++ ++const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = { ++ SND_SOC_DAPM_MIC("DMIC", NULL), ++ SND_SOC_DAPM_MIC("Headset Mic", NULL), ++ SND_SOC_DAPM_INPUT("Line Input"), ++ SND_SOC_DAPM_MIC("Line Input with Micbias", NULL), ++ SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0, ++ &linein_micbias_mux), ++ SND_SOC_DAPM_INPUT("dummy SPDIF in"), ++ SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0, ++ rpi_cirrus_spdif_rx_enable_event, ++ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), ++ SND_SOC_DAPM_INPUT("Dummy Input"), ++ SND_SOC_DAPM_OUTPUT("Dummy Output"), ++}; ++ ++const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = { ++ { "IN1L", NULL, "Headset Mic" }, ++ { "IN1R", NULL, "Headset Mic" }, ++ { "Headset Mic", NULL, "MICBIAS1" }, ++ ++ { "IN2L", NULL, "DMIC" }, ++ { "IN2R", NULL, "DMIC" }, ++ { "DMIC", NULL, "MICBIAS2" }, ++ ++ { "IN3L", NULL, "Line Input Micbias" }, ++ { "IN3R", NULL, "Line Input Micbias" }, ++ ++ { "Line Input Micbias", "off", "Line Input" }, ++ { "Line Input Micbias", "on", "Line Input with Micbias" }, ++ ++ /* Make sure MICVDD is enabled, otherwise we get noise */ ++ { "Line Input", NULL, "MICVDD" }, ++ { "Line Input with Micbias", NULL, "MICBIAS3" }, ++ ++ /* Dummy routes to check whether SPDIF RX is enabled or not */ ++ {"dummy SPDIFRX", NULL, "dummy SPDIF in"}, ++ {"AIFTX", NULL, "dummy SPDIFRX"}, ++ ++ /* ++ * Dummy routes to keep wm5102 from staying off on ++ * playback/capture if all mixers are off. ++ */ ++ { "Dummy Output", NULL, "AIF1RX1" }, ++ { "Dummy Output", NULL, "AIF1RX2" }, ++ { "AIF1TX1", NULL, "Dummy Input" }, ++ { "AIF1TX2", NULL, "Dummy Input" }, ++}; ++ ++static int rpi_cirrus_clear_flls(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec) { ++ ++ int ret1, ret2; ++ ++ ret1 = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); ++ ret2 = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0); ++ ++ if (ret1) { ++ dev_warn(card->dev, ++ "setting FLL1 to zero failed: %d\n", ret1); ++ return ret1; ++ } ++ if (ret2) { ++ dev_warn(card->dev, ++ "setting FLL1_REFCLK to zero failed: %d\n", ret2); ++ return ret2; ++ } ++ return 0; ++} ++ ++static int rpi_cirrus_set_fll(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec, unsigned int clk_freq) ++{ ++ int ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ++ ARIZONA_CLK_SRC_MCLK1, ++ WM8804_CLKOUT_HZ, ++ clk_freq); ++ if (ret) ++ dev_err(card->dev, "Failed to set FLL1 to %d: %d\n", ++ clk_freq, ret); ++ ++ usleep_range(1000, 2000); ++ return ret; ++} ++ ++static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card, ++ struct snd_soc_codec *wm5102_codec, ++ unsigned int clk_freq, unsigned int aif2_freq) ++{ ++ int ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1_REFCLK, ++ ARIZONA_CLK_SRC_MCLK1, ++ WM8804_CLKOUT_HZ, ++ clk_freq); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set FLL1_REFCLK to %d: %d\n", ++ clk_freq, ret); ++ return ret; ++ } ++ ++ ret = snd_soc_codec_set_pll(wm5102_codec, ++ WM5102_FLL1, ++ ARIZONA_CLK_SRC_AIF2BCLK, ++ aif2_freq, clk_freq); ++ if (ret) ++ dev_err(card->dev, ++ "Failed to set FLL1 with Sync Clock %d to %d: %d\n", ++ aif2_freq, clk_freq, ret); ++ ++ usleep_range(1000, 2000); ++ return ret; ++} ++ ++static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, ++ struct snd_kcontrol *kcontrol, int event) ++{ ++ struct snd_soc_card *card = w->dapm->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_codec *wm5102_codec = get_wm5102_runtime(card)->codec; ++ ++ unsigned int clk_freq, aif2_freq; ++ int ret = 0; ++ ++ switch (event) { ++ case SND_SOC_DAPM_POST_PMU: ++ mutex_lock(&priv->lock); ++ ++ /* Enable sync path in case of SPDIF capture use case */ ++ ++ clk_freq = calc_sysclk(priv->card_rate); ++ aif2_freq = 64 * priv->card_rate; ++ ++ dev_dbg(card->dev, ++ "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n", ++ clk_freq, aif2_freq); ++ ++ ret = rpi_cirrus_clear_flls(card, wm5102_codec); ++ if (ret) { ++ dev_err(card->dev, "spdif_rx: failed to clear FLLs\n"); ++ goto out; ++ } ++ ++ ret = rpi_cirrus_set_fll_refclk(card, wm5102_codec, ++ clk_freq, aif2_freq); ++ ++ if (ret) { ++ dev_err(card->dev, "spdif_rx: failed to set FLLs\n"); ++ goto out; ++ } ++ ++ /* set to negative to indicate we're doing spdif rx */ ++ priv->fll1_freq = -clk_freq; ++ priv->sync_path_enable = 1; ++ break; ++ ++ case SND_SOC_DAPM_POST_PMD: ++ mutex_lock(&priv->lock); ++ priv->sync_path_enable = 0; ++ break; ++ ++ default: ++ return 0; ++ } ++ ++out: ++ mutex_unlock(&priv->lock); ++ return ret; ++} ++ ++static int rpi_cirrus_set_bias_level(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, ++ enum snd_soc_bias_level level) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; ++ ++ int ret = 0; ++ unsigned int clk_freq; ++ ++ if (dapm->dev != wm5102_runtime->codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_PREPARE: ++ if (dapm->bias_level == SND_SOC_BIAS_ON) ++ break; ++ ++ mutex_lock(&priv->lock); ++ ++ if (!priv->sync_path_enable) { ++ clk_freq = calc_sysclk(priv->card_rate); ++ ++ dev_dbg(card->dev, ++ "set_bias: changing FLL1 from %d to %d\n", ++ priv->fll1_freq, clk_freq); ++ ++ ret = rpi_cirrus_set_fll(card, wm5102_codec, clk_freq); ++ if (ret) ++ dev_err(card->dev, ++ "set_bias: Failed to set FLL1\n"); ++ else ++ priv->fll1_freq = clk_freq; ++ } ++ mutex_unlock(&priv->lock); ++ break; ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, ++ enum snd_soc_bias_level level) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; ++ ++ if (dapm->dev != wm5102_runtime->codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_STANDBY: ++ mutex_lock(&priv->lock); ++ ++ dev_dbg(card->dev, ++ "set_bias_post: changing FLL1 from %d to off\n", ++ priv->fll1_freq); ++ ++ if (rpi_cirrus_clear_flls(card, wm5102_codec)) ++ dev_err(card->dev, ++ "set_bias_post: failed to clear FLLs\n"); ++ else ++ priv->fll1_freq = 0; ++ ++ mutex_unlock(&priv->lock); ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card, ++ struct snd_soc_dai *wm8804_dai, unsigned int rate) ++{ ++ int ret; ++ ++ /* use 256fs */ ++ unsigned int clk_freq = rate * 256; ++ ++ ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0, ++ WM8804_CLKOUT_HZ, clk_freq); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret); ++ return ret; ++ } ++ ++ /* Set MCLK as PLL Output */ ++ ret = snd_soc_dai_set_sysclk(wm8804_dai, ++ WM8804_TX_CLKSRC_PLL, clk_freq, 0); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set MCLK as PLL Output: %d\n", ret); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int rpi_cirrus_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned int min_rate = min_rates[priv->min_rate_idx].value; ++ unsigned int max_rate = max_rates[priv->max_rate_idx].value; ++ ++ if (min_rate || max_rate) { ++ if (max_rate == 0) ++ max_rate = UINT_MAX; ++ ++ dev_dbg(card->dev, ++ "startup: limiting rate to %u-%u\n", ++ min_rate, max_rate); ++ ++ snd_pcm_hw_constraint_minmax(substream->runtime, ++ SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate); ++ } ++ ++ return 0; ++} ++ ++static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = { ++ .formats = SNDRV_PCM_FMTBIT_S24_LE, ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = RPI_CIRRUS_DEFAULT_RATE, ++ .rate_max = RPI_CIRRUS_DEFAULT_RATE, ++}; ++ ++static int rpi_cirrus_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_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_dai *bcm_i2s_dai = rtd->cpu_dai; ++ struct snd_soc_codec *wm5102_codec = rtd->codec; ++ struct snd_soc_dai *wm8804_dai = get_wm8804_runtime(card)->codec_dai; ++ ++ int ret; ++ ++ unsigned int width = snd_pcm_format_physical_width( ++ params_format(params)); ++ unsigned int rate = params_rate(params); ++ unsigned int clk_freq = calc_sysclk(rate); ++ ++ mutex_lock(&priv->lock); ++ ++ dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate); ++ ++ ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width); ++ if (ret) { ++ dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret); ++ goto out; ++ } ++ ++ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03, 2, width); ++ if (ret) { ++ dev_err(card->dev, "set_tdm_slot failed: %d\n", ret); ++ goto out; ++ } ++ ++ /* WM8804 supports sample rates from 32k only */ ++ if (rate >= 32000) { ++ ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate); ++ if (ret) ++ goto out; ++ } ++ ++ ret = snd_soc_codec_set_sysclk(wm5102_codec, ++ ARIZONA_CLK_SYSCLK, ++ ARIZONA_CLK_SRC_FLL1, ++ clk_freq, ++ SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret); ++ goto out; ++ } ++ ++ if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) { ++ dev_dbg(card->dev, ++ "hw_params: changing FLL1 from %d to %d\n", ++ priv->fll1_freq, clk_freq); ++ ++ if (rpi_cirrus_clear_flls(card, wm5102_codec)) { ++ dev_err(card->dev, "hw_params: failed to clear FLLs\n"); ++ goto out; ++ } ++ ++ if (rpi_cirrus_set_fll(card, wm5102_codec, clk_freq)) { ++ dev_err(card->dev, "hw_params: failed to set FLL\n"); ++ goto out; ++ } ++ ++ priv->fll1_freq = clk_freq; ++ } ++ ++ priv->card_rate = rate; ++ rpi_cirrus_dai_link2_params.rate_min = rate; ++ rpi_cirrus_dai_link2_params.rate_max = rate; ++ ++ priv->params_set |= 1 << substream->stream; ++ ++out: ++ mutex_unlock(&priv->lock); ++ ++ return ret; ++} ++ ++static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_codec *wm5102_codec = rtd->codec; ++ int ret; ++ unsigned int old_params_set = priv->params_set; ++ ++ priv->params_set &= ~(1 << substream->stream); ++ ++ /* disable sysclk if this was the last open stream */ ++ if (priv->params_set == 0 && old_params_set) { ++ dev_dbg(card->dev, ++ "hw_free: Setting SYSCLK to Zero\n"); ++ ++ ret = snd_soc_codec_set_sysclk(wm5102_codec, ++ ARIZONA_CLK_SYSCLK, ++ ARIZONA_CLK_SRC_FLL1, ++ 0, ++ SND_SOC_CLOCK_IN); ++ if (ret) ++ dev_err(card->dev, ++ "hw_free: Failed to set SYSCLK to Zero: %d\n", ++ ret); ++ } ++ return 0; ++} ++ ++static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ int ret; ++ ++ /* no 32kHz input, derive it from sysclk if needed */ ++ snd_soc_update_bits(codec, ++ ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2); ++ ++ if (rpi_cirrus_clear_flls(rtd->card, codec)) ++ dev_warn(rtd->card->dev, ++ "init_wm5102: failed to clear FLLs\n"); ++ ++ ret = snd_soc_codec_set_sysclk(codec, ++ ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1, ++ 0, SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(rtd->card->dev, ++ "Failed to set SYSCLK to Zero: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_codec *codec = rtd->codec; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_card *card = rtd->card; ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ unsigned int mask; ++ int i, ret; ++ ++ for (i = 0; i < 4; i++) { ++ mask = (i == 3) ? 0x3f : 0xff; ++ priv->iec958_status[i] = ++ snd_soc_read(codec, WM8804_SPDTX1 + i) & mask; ++ } ++ ++ /* Setup for 256fs */ ++ ret = snd_soc_dai_set_clkdiv(codec_dai, ++ WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS); ++ if (ret) { ++ dev_err(card->dev, ++ "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n", ++ ret); ++ return ret; ++ } ++ ++ /* Output OSC on CLKOUT */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, ++ WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0); ++ if (ret) ++ dev_err(card->dev, ++ "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n", ++ ret); ++ ++ /* Init PLL with default samplerate */ ++ ret = rpi_cirrus_set_wm8804_pll(card, codec_dai, ++ RPI_CIRRUS_DEFAULT_RATE); ++ if (ret) ++ dev_err(card->dev, ++ "init_wm8804: Failed to setup PLL for %dHz: %d\n", ++ RPI_CIRRUS_DEFAULT_RATE, ret); ++ ++ return ret; ++} ++ ++static struct snd_soc_ops rpi_cirrus_ops = { ++ .startup = rpi_cirrus_startup, ++ .hw_params = rpi_cirrus_hw_params, ++ .hw_free = rpi_cirrus_hw_free, ++}; ++ ++static struct snd_soc_dai_link rpi_cirrus_dai[] = { ++ [DAI_WM5102] = { ++ .name = "WM5102", ++ .stream_name = "WM5102 AiFi", ++ .codec_dai_name = "wm5102-aif1", ++ .codec_name = "wm5102-codec", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &rpi_cirrus_ops, ++ .init = rpi_cirrus_init_wm5102, ++ }, ++ [DAI_WM8804] = { ++ .name = "WM5102 SPDIF", ++ .stream_name = "SPDIF Tx/Rx", ++ .cpu_dai_name = "wm5102-aif2", ++ .codec_dai_name = "wm8804-spdif", ++ .codec_name = "wm8804.1-003b", ++ .dai_fmt = SND_SOC_DAIFMT_I2S ++ | SND_SOC_DAIFMT_NB_NF ++ | SND_SOC_DAIFMT_CBM_CFM, ++ .ignore_suspend = 1, ++ .params = &rpi_cirrus_dai_link2_params, ++ .init = rpi_cirrus_init_wm8804, ++ }, ++}; ++ ++ ++static int rpi_cirrus_late_probe(struct snd_soc_card *card) ++{ ++ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); ++ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); ++ struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card); ++ int ret; ++ ++ dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n", ++ priv->iec958_status[0], ++ priv->iec958_status[1], ++ priv->iec958_status[2], ++ priv->iec958_status[3]); ++ ++ ret = snd_soc_dai_set_sysclk( ++ wm5102_runtime->codec_dai, ARIZONA_CLK_SYSCLK, 0, 0); ++ if (ret) { ++ dev_err(card->dev, ++ "Failed to set WM5102 codec dai clk domain: %d\n", ret); ++ return ret; ++ } ++ ++ ret = snd_soc_dai_set_sysclk( ++ wm8804_runtime->cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0); ++ if (ret) ++ dev_err(card->dev, ++ "Failed to set WM8804 codec dai clk domain: %d\n", ret); ++ ++ return ret; ++} ++ ++/* audio machine driver */ ++static struct snd_soc_card rpi_cirrus_card = { ++ .name = "RPi-Cirrus", ++ .driver_name = "RPiCirrus", ++ .owner = THIS_MODULE, ++ .dai_link = rpi_cirrus_dai, ++ .num_links = ARRAY_SIZE(rpi_cirrus_dai), ++ .late_probe = rpi_cirrus_late_probe, ++ .controls = rpi_cirrus_controls, ++ .num_controls = ARRAY_SIZE(rpi_cirrus_controls), ++ .dapm_widgets = rpi_cirrus_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets), ++ .dapm_routes = rpi_cirrus_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes), ++ .set_bias_level = rpi_cirrus_set_bias_level, ++ .set_bias_level_post = rpi_cirrus_set_bias_level_post, ++}; ++ ++static int rpi_cirrus_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct rpi_cirrus_priv *priv; ++ struct device_node *i2s_node; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->min_rate_idx = 1; /* min samplerate 32kHz */ ++ priv->card_rate = RPI_CIRRUS_DEFAULT_RATE; ++ ++ mutex_init(&priv->lock); ++ ++ snd_soc_card_set_drvdata(&rpi_cirrus_card, priv); ++ ++ if (!pdev->dev.of_node) ++ return -ENODEV; ++ ++ i2s_node = of_parse_phandle( ++ pdev->dev.of_node, "i2s-controller", 0); ++ if (!i2s_node) { ++ dev_err(&pdev->dev, "i2s-controller missing in DT\n"); ++ return -ENODEV; ++ } ++ ++ rpi_cirrus_dai[DAI_WM5102].cpu_of_node = i2s_node; ++ rpi_cirrus_dai[DAI_WM5102].platform_of_node = i2s_node; ++ ++ rpi_cirrus_card.dev = &pdev->dev; ++ ++ ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card); ++ if (ret) { ++ if (ret == -EPROBE_DEFER) ++ dev_dbg(&pdev->dev, ++ "register card requested probe deferral\n"); ++ else ++ dev_err(&pdev->dev, ++ "Failed to register card: %d\n", ret); ++ } ++ ++ return ret; ++} ++ ++static const struct of_device_id rpi_cirrus_of_match[] = { ++ { .compatible = "wlf,rpi-cirrus", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match); ++ ++static struct platform_driver rpi_cirrus_driver = { ++ .driver = { ++ .name = "snd-rpi-cirrus", ++ .of_match_table = of_match_ptr(rpi_cirrus_of_match), ++ }, ++ .probe = rpi_cirrus_probe, ++}; ++ ++module_platform_driver(rpi_cirrus_driver); ++ ++MODULE_AUTHOR("Matthias Reichl "); ++MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card"); ++MODULE_LICENSE("GPL"); + +From b4da1986d0050504f716cfad4489d5dcef68dafd Mon Sep 17 00:00:00 2001 +From: Miquel +Date: Fri, 24 Feb 2017 20:51:06 +0100 +Subject: [PATCH 085/150] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT + +Signed-off-by: Miquel Blauw +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/dionaudio_loco-v2.c | 140 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 149 insertions(+) + create mode 100644 sound/soc/bcm/dionaudio_loco-v2.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index c0489e591b9b8c8da004ca9e300e97f1a21e5ce1..3e1ee13ef8ec31849e29e551026ba427f8e44fe6 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -134,6 +134,13 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO + help + Say Y or M if you want to add support for Dion Audio LOCO. + ++config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2 ++ tristate "Support for Dion Audio LOCO-V2 DAC-AMP" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_PCM5122 ++ help ++ Say Y or M if you want to add support for Dion Audio LOCO-V2. ++ + config SND_BCM2708_SOC_ALLO_PIANO_DAC + tristate "Support for Allo Piano DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 84c2b20ce2e51b525797ee58de95734ee7847e15..4d8adf691021a974310589e92e599924811f22cb 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -25,6 +25,7 @@ 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 ++snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o + snd-soc-allo-piano-dac-objs := allo-piano-dac.o + snd-soc-pisound-objs := pisound.o + +@@ -44,5 +45,6 @@ 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 + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o ++obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o + obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o + obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o +diff --git a/sound/soc/bcm/dionaudio_loco-v2.c b/sound/soc/bcm/dionaudio_loco-v2.c +new file mode 100644 +index 0000000000000000000000000000000000000000..a009c49477972a9832175d86f201b0357a08f7c0 +--- /dev/null ++++ b/sound/soc/bcm/dionaudio_loco-v2.c +@@ -0,0 +1,140 @@ ++/* ++ * ASoC Driver for Dion Audio LOCO-V2 DAC-AMP ++ * ++ * Author: Miquel Blauw ++ * Copyright 2017 ++ * ++ * 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. ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++static bool digital_gain_0db_limit = true; ++ ++static int snd_rpi_dionaudio_loco_v2_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_dionaudio_loco_v2_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_dionaudio_loco_v2_ops = { ++ .hw_params = snd_rpi_dionaudio_loco_v2_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_rpi_dionaudio_loco_v2_dai[] = { ++{ ++ .name = "DionAudio LOCO-V2", ++ .stream_name = "DionAudio LOCO-V2 DAC-AMP", ++ .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_dionaudio_loco_v2_ops, ++ .init = snd_rpi_dionaudio_loco_v2_init, ++},}; ++ ++/* audio machine driver */ ++static struct snd_soc_card snd_rpi_dionaudio_loco_v2 = { ++ .name = "Dion Audio LOCO-V2", ++ .dai_link = snd_rpi_dionaudio_loco_v2_dai, ++ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_v2_dai), ++}; ++ ++static int snd_rpi_dionaudio_loco_v2_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ ++ snd_rpi_dionaudio_loco_v2.dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = ++ &snd_rpi_dionaudio_loco_v2_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, "dionaudio,24db_digital_gain"); ++ } ++ ++ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco_v2); ++ if (ret) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ++ ret); ++ ++ return ret; ++} ++ ++static int snd_rpi_dionaudio_loco_v2_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco_v2); ++} ++ ++static const struct of_device_id dionaudio_of_match[] = { ++ { .compatible = "dionaudio,dionaudio-loco-v2", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, dionaudio_of_match); ++ ++static struct platform_driver snd_rpi_dionaudio_loco_v2_driver = { ++ .driver = { ++ .name = "snd-rpi-dionaudio-loco-v2", ++ .owner = THIS_MODULE, ++ .of_match_table = dionaudio_of_match, ++ }, ++ .probe = snd_rpi_dionaudio_loco_v2_probe, ++ .remove = snd_rpi_dionaudio_loco_v2_remove, ++}; ++ ++module_platform_driver(snd_rpi_dionaudio_loco_v2_driver); ++ ++MODULE_AUTHOR("Miquel Blauw "); ++MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2"); ++MODULE_LICENSE("GPL v2"); + +From 0376755222b69df9cca27cd54d32f979ecb0cc00 Mon Sep 17 00:00:00 2001 +From: Fe-Pi +Date: Wed, 1 Mar 2017 04:42:43 -0700 +Subject: [PATCH 086/150] Add support for Fe-Pi audio sound card. (#1867) + +Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec. +Mechanical specification of the board is the same the Raspberry Pi Zero. +3.5mm jacks for Headphone/Mic, Line In, and Line Out. + +Signed-off-by: Henry Kupis +--- + sound/soc/bcm/Kconfig | 7 ++ + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/fe-pi-audio.c | 158 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 167 insertions(+) + create mode 100644 sound/soc/bcm/fe-pi-audio.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 3e1ee13ef8ec31849e29e551026ba427f8e44fe6..7473efd6f400a1a1618aac830753fce39d203b89 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -148,6 +148,13 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC + help + Say Y or M if you want to add support for Allo Piano DAC. + ++config SND_BCM2708_SOC_FE_PI_AUDIO ++ tristate "Support for Fe-Pi-Audio" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_SGTL5000 ++ help ++ Say Y or M if you want to add support for Fe-Pi-Audio. ++ + config SND_PISOUND + tristate "Support for Blokas Labs pisound" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 4d8adf691021a974310589e92e599924811f22cb..8d2d2073dc2cede9fbd9eb8b49083650ba0a8172 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -28,6 +28,7 @@ snd-soc-dionaudio-loco-objs := dionaudio_loco.o + snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o + snd-soc-allo-piano-dac-objs := allo-piano-dac.o + snd-soc-pisound-objs := pisound.o ++snd-soc-fe-pi-audio-objs := fe-pi-audio.o + + obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o + obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o +@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o + obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o + obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o ++obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o +diff --git a/sound/soc/bcm/fe-pi-audio.c b/sound/soc/bcm/fe-pi-audio.c +new file mode 100644 +index 0000000000000000000000000000000000000000..015b56fd73cc36be5b5eecd17548fd036eb64d61 +--- /dev/null ++++ b/sound/soc/bcm/fe-pi-audio.c +@@ -0,0 +1,158 @@ ++/* ++ * ASoC Driver for Fe-Pi Audio Sound Card ++ * ++ * Author: Henry Kupis ++ * Copyright 2016 ++ * based on code by Florian Meier ++ * based on code by Shawn Guo ++ * ++ * 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 "../codecs/sgtl5000.h" ++ ++static int snd_fe_pi_audio_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ struct snd_soc_card *card = rtd->card; ++ struct snd_soc_codec *codec = rtd->codec; ++ ++ snd_soc_dapm_force_enable_pin(&card->dapm, "LO"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "ADC"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "DAC"); ++ snd_soc_dapm_force_enable_pin(&card->dapm, "HP"); ++ snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, ++ SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); ++ ++ return 0; ++} ++ ++static int snd_fe_pi_audio_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct device *dev = rtd->card->dev; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ ++ int ret; ++ ++ /* Set SGTL5000's SYSCLK */ ++ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, 12288000, SND_SOC_CLOCK_IN); ++ if (ret) { ++ dev_err(dev, "could not set codec driver clock params\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++ ++static struct snd_soc_ops snd_fe_pi_audio_ops = { ++ .hw_params = snd_fe_pi_audio_hw_params, ++}; ++ ++static struct snd_soc_dai_link snd_fe_pi_audio_dai[] = { ++ { ++ .name = "FE-PI", ++ .stream_name = "Fe-Pi HiFi", ++ .cpu_dai_name = "bcm2708-i2s.0", ++ .codec_dai_name = "sgtl5000", ++ .platform_name = "bcm2708-i2s.0", ++ .codec_name = "sgtl5000.1-000a", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM, ++ .ops = &snd_fe_pi_audio_ops, ++ .init = snd_fe_pi_audio_init, ++ }, ++}; ++ ++static const struct snd_soc_dapm_route fe_pi_audio_dapm_routes[] = { ++ {"ADC", NULL, "Mic Bias"}, ++}; ++ ++ ++static struct snd_soc_card fe_pi_audio = { ++ .name = "Fe-Pi Audio", ++ .owner = THIS_MODULE, ++ .dai_link = snd_fe_pi_audio_dai, ++ .num_links = ARRAY_SIZE(snd_fe_pi_audio_dai), ++ ++ .dapm_routes = fe_pi_audio_dapm_routes, ++ .num_dapm_routes = ARRAY_SIZE(fe_pi_audio_dapm_routes), ++}; ++ ++static int snd_fe_pi_audio_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct snd_soc_card *card = &fe_pi_audio; ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *i2s_node; ++ struct snd_soc_dai_link *dai = &snd_fe_pi_audio_dai[0]; ++ ++ fe_pi_audio.dev = &pdev->dev; ++ ++ i2s_node = of_parse_phandle(np, "i2s-controller", 0); ++ if (!i2s_node) { ++ dev_err(&pdev->dev, "i2s_node phandle missing or invalid\n"); ++ return -EINVAL; ++ } ++ ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ ++ of_node_put(i2s_node); ++ ++ card->dev = &pdev->dev; ++ platform_set_drvdata(pdev, card); ++ ++ ret = snd_soc_register_card(card); ++ if (ret && ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int snd_fe_pi_audio_remove(struct platform_device *pdev) ++{ ++ return snd_soc_unregister_card(&fe_pi_audio); ++} ++ ++static const struct of_device_id snd_fe_pi_audio_of_match[] = { ++ { .compatible = "fe-pi,fe-pi-audio", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, snd_fe_pi_audio_of_match); ++ ++static struct platform_driver snd_fe_pi_audio_driver = { ++ .driver = { ++ .name = "snd-fe-pi-audio", ++ .owner = THIS_MODULE, ++ .of_match_table = snd_fe_pi_audio_of_match, ++ }, ++ .probe = snd_fe_pi_audio_probe, ++ .remove = snd_fe_pi_audio_remove, ++}; ++ ++module_platform_driver(snd_fe_pi_audio_driver); ++ ++MODULE_AUTHOR("Henry Kupis "); ++MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio"); ++MODULE_LICENSE("GPL v2"); + +From f0f57e2ed20bfbcefec27f37fba372024594563b Mon Sep 17 00:00:00 2001 +From: Matt Flax +Date: Wed, 8 Mar 2017 20:04:13 +1100 +Subject: [PATCH 087/150] Add support for the AudioInjector.net Octo sound card + +--- + sound/soc/bcm/Kconfig | 7 + + sound/soc/bcm/Makefile | 2 + + sound/soc/bcm/audioinjector-octo-soundcard.c | 286 +++++++++++++++++++++++++++ + 3 files changed, 295 insertions(+) + create mode 100644 sound/soc/bcm/audioinjector-octo-soundcard.c + +diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig +index 7473efd6f400a1a1618aac830753fce39d203b89..706c500b5303ac3a0fd8687d23dc9f06c7d08388 100644 +--- a/sound/soc/bcm/Kconfig ++++ b/sound/soc/bcm/Kconfig +@@ -119,6 +119,13 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD + help + Say Y or M if you want to add support for audioinjector.net Pi Hat + ++config SND_AUDIOINJECTOR_OCTO_SOUNDCARD ++ tristate "Support for audioinjector.net Octo channel (Hat) soundcard" ++ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S ++ select SND_SOC_CS42XX8_I2C ++ help ++ Say Y or M if you want to add support for audioinjector.net octo add on ++ + config SND_DIGIDAC1_SOUNDCARD + tristate "Support for Red Rocks Audio DigiDAC1" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S +diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile +index 8d2d2073dc2cede9fbd9eb8b49083650ba0a8172..d448aa517bf994fc0a41580c91b5d87deec9e1b0 100644 +--- a/sound/soc/bcm/Makefile ++++ b/sound/soc/bcm/Makefile +@@ -23,6 +23,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-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o + snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o + snd-soc-dionaudio-loco-objs := dionaudio_loco.o + snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o +@@ -44,6 +45,7 @@ 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_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o + obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o + obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o +diff --git a/sound/soc/bcm/audioinjector-octo-soundcard.c b/sound/soc/bcm/audioinjector-octo-soundcard.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9effea725798640887755dfa688da45338718afc +--- /dev/null ++++ b/sound/soc/bcm/audioinjector-octo-soundcard.c +@@ -0,0 +1,286 @@ ++/* ++ * ASoC Driver for AudioInjector Pi octo channel soundcard (hat) ++ * ++ * Created on: 27-October-2016 ++ * Author: flatmax@flatmax.org ++ * based on audioinjector-pi-soundcard.c ++ * ++ * Copyright (C) 2016 Flatmax Pty. Ltd. ++ * ++ * 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 struct gpio_descs *mult_gpios; ++static unsigned int audioinjector_octo_rate; ++ ++static int audioinjector_octo_dai_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, 64); ++} ++ ++static int audioinjector_octo_startup(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ rtd->cpu_dai->driver->playback.channels_min = 8; ++ rtd->cpu_dai->driver->playback.channels_max = 8; ++ rtd->cpu_dai->driver->capture.channels_min = 8; ++ rtd->cpu_dai->driver->capture.channels_max = 8; ++ rtd->codec_dai->driver->capture.channels_max = 8; ++ return 0; ++} ++ ++static void audioinjector_octo_shutdown(struct snd_pcm_substream *substream) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ rtd->cpu_dai->driver->playback.channels_min = 2; ++ rtd->cpu_dai->driver->playback.channels_max = 2; ++ rtd->cpu_dai->driver->capture.channels_min = 2; ++ rtd->cpu_dai->driver->capture.channels_max = 2; ++ rtd->codec_dai->driver->capture.channels_max = 6; ++} ++ ++static int audioinjector_octo_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ ++ // set codec DAI configuration ++ int ret = snd_soc_dai_set_fmt(rtd->codec_dai, ++ SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_DSP_A| ++ SND_SOC_DAIFMT_NB_NF); ++ if (ret < 0) ++ return ret; ++ ++ // set cpu DAI configuration ++ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, ++ SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S| ++ SND_SOC_DAIFMT_NB_NF); ++ if (ret < 0) ++ return ret; ++ ++ audioinjector_octo_rate = params_rate(params); ++ ++ return 0; ++} ++ ++static int audioinjector_octo_trigger(struct snd_pcm_substream *substream, ++ int cmd){ ++ int mult[4]; ++ mult[0] = 0; ++ mult[1] = 0; ++ mult[2] = 0; ++ mult[3] = 0; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ switch (audioinjector_octo_rate) { ++ case 192000: ++ mult[3] = 1; ++ case 176640: ++ mult[0] = 1; ++ mult[1] = 1; ++ mult[2] = 1; ++ break; ++ case 96000: ++ mult[3] = 1; ++ case 88200: ++ mult[1] = 1; ++ mult[2] = 1; ++ break; ++ case 64000: ++ mult[3] = 1; ++ case 58800: ++ mult[0] = 1; ++ mult[2] = 1; ++ break; ++ case 48000: ++ mult[3] = 1; ++ case 44100: ++ mult[2] = 1; ++ break; ++ case 32000: ++ mult[3] = 1; ++ case 29400: ++ mult[0] = 1; ++ mult[1] = 1; ++ break; ++ case 24000: ++ mult[3] = 1; ++ case 22050: ++ mult[1] = 1; ++ break; ++ case 16000: ++ mult[3] = 1; ++ case 14700: ++ mult[0] = 1; ++ break; ++ case 8000: ++ mult[3] = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ break; ++ default: ++ return -EINVAL; ++ } ++ gpiod_set_array_value_cansleep(mult_gpios->ndescs, mult_gpios->desc, ++ mult); ++ ++ return 0; ++} ++ ++static struct snd_soc_ops audioinjector_octo_ops = { ++ .startup = audioinjector_octo_startup, ++ .shutdown = audioinjector_octo_shutdown, ++ .hw_params = audioinjector_octo_hw_params, ++ .trigger = audioinjector_octo_trigger, ++}; ++ ++static struct snd_soc_dai_link audioinjector_octo_dai[] = { ++ { ++ .name = "AudioInjector Octo", ++ .stream_name = "AudioInject-HIFI", ++ .codec_dai_name = "cs42448", ++ .ops = &audioinjector_octo_ops, ++ .init = audioinjector_octo_dai_init, ++ }, ++}; ++ ++static const struct snd_soc_dapm_widget audioinjector_octo_widgets[] = { ++ SND_SOC_DAPM_OUTPUT("OUTPUTS0"), ++ SND_SOC_DAPM_OUTPUT("OUTPUTS1"), ++ SND_SOC_DAPM_OUTPUT("OUTPUTS2"), ++ SND_SOC_DAPM_OUTPUT("OUTPUTS3"), ++ SND_SOC_DAPM_INPUT("INPUTS0"), ++ SND_SOC_DAPM_INPUT("INPUTS1"), ++ SND_SOC_DAPM_INPUT("INPUTS2"), ++}; ++ ++static const struct snd_soc_dapm_route audioinjector_octo_route[] = { ++ /* Balanced outputs */ ++ {"OUTPUTS0", NULL, "AOUT1L"}, ++ {"OUTPUTS0", NULL, "AOUT1R"}, ++ {"OUTPUTS1", NULL, "AOUT2L"}, ++ {"OUTPUTS1", NULL, "AOUT2R"}, ++ {"OUTPUTS2", NULL, "AOUT3L"}, ++ {"OUTPUTS2", NULL, "AOUT3R"}, ++ {"OUTPUTS3", NULL, "AOUT4L"}, ++ {"OUTPUTS3", NULL, "AOUT4R"}, ++ ++ /* Balanced inputs */ ++ {"AIN1L", NULL, "INPUTS0"}, ++ {"AIN1R", NULL, "INPUTS0"}, ++ {"AIN2L", NULL, "INPUTS1"}, ++ {"AIN2R", NULL, "INPUTS1"}, ++ {"AIN3L", NULL, "INPUTS2"}, ++ {"AIN3R", NULL, "INPUTS2"}, ++}; ++ ++static struct snd_soc_card snd_soc_audioinjector_octo = { ++ .name = "audioinjector-octo-soundcard", ++ .dai_link = audioinjector_octo_dai, ++ .num_links = ARRAY_SIZE(audioinjector_octo_dai), ++ ++ .dapm_widgets = audioinjector_octo_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(audioinjector_octo_widgets), ++ .dapm_routes = audioinjector_octo_route, ++ .num_dapm_routes = ARRAY_SIZE(audioinjector_octo_route), ++}; ++ ++static int audioinjector_octo_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &snd_soc_audioinjector_octo; ++ int ret; ++ ++ card->dev = &pdev->dev; ++ ++ if (pdev->dev.of_node) { ++ struct snd_soc_dai_link *dai = &audioinjector_octo_dai[0]; ++ struct device_node *i2s_node = ++ of_parse_phandle(pdev->dev.of_node, ++ "i2s-controller", 0); ++ struct device_node *codec_node = ++ of_parse_phandle(pdev->dev.of_node, ++ "codec", 0); ++ ++ mult_gpios = devm_gpiod_get_array_optional(&pdev->dev, "mult", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(mult_gpios)) ++ return PTR_ERR(mult_gpios); ++ ++ if (i2s_node && codec_node) { ++ dai->cpu_dai_name = NULL; ++ dai->cpu_of_node = i2s_node; ++ dai->platform_name = NULL; ++ dai->platform_of_node = i2s_node; ++ dai->codec_name = NULL; ++ dai->codec_of_node = codec_node; ++ } else ++ if (!dai->cpu_of_node) { ++ dev_err(&pdev->dev, ++ "i2s-controller missing or invalid in DT\n"); ++ return -EINVAL; ++ } else { ++ dev_err(&pdev->dev, ++ "Property 'codec' missing or invalid\n"); ++ return -EINVAL; ++ } ++ } ++ ++ ret = snd_soc_register_card(card); ++ if (ret != 0) ++ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); ++ return ret; ++} ++ ++static int audioinjector_octo_remove(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = platform_get_drvdata(pdev); ++ ++ return snd_soc_unregister_card(card); ++} ++ ++static const struct of_device_id audioinjector_octo_of_match[] = { ++ { .compatible = "ai,audioinjector-octo-soundcard", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, audioinjector_octo_of_match); ++ ++static struct platform_driver audioinjector_octo_driver = { ++ .driver = { ++ .name = "audioinjector-audio", ++ .owner = THIS_MODULE, ++ .of_match_table = audioinjector_octo_of_match, ++ }, ++ .probe = audioinjector_octo_probe, ++ .remove = audioinjector_octo_remove, ++}; ++ ++module_platform_driver(audioinjector_octo_driver); ++MODULE_AUTHOR("Matt Flax "); ++MODULE_DESCRIPTION("AudioInjector.net octo Soundcard"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:audioinjector-octo-soundcard"); + +From d7f19796cf4d8fbabe08e0e779ace4b513b30829 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 21 Oct 2015 14:55:21 +0100 -Subject: [PATCH 081/216] rpi_display: add backlight driver and overlay +Subject: [PATCH 088/150] 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 @@ -117138,10 +105952,10 @@ index 0000000000000000000000000000000000000000..14a0d9b037395497c1fdae2961feccd5 +MODULE_DESCRIPTION("Raspberry Pi mailbox based Backlight Driver"); +MODULE_LICENSE("GPL"); -From 731695a02ea2c5890add56ae879d7372c030da9d Mon Sep 17 00:00:00 2001 +From 712257d81b5d923d9292739401a624cbe14313b4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 23 Feb 2016 19:56:04 +0000 -Subject: [PATCH 082/216] bcm2835-virtgpio: Virtual GPIO driver +Subject: [PATCH 089/150] bcm2835-virtgpio: Virtual GPIO driver Add a virtual GPIO driver that uses the firmware mailbox interface to request that the VPU toggles LEDs. @@ -117154,7 +105968,7 @@ request that the VPU toggles LEDs. create mode 100644 drivers/gpio/gpio-bcm-virt.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index d5d36549ecc1ecea2c53cddea2a209e54ab94b56..ade9f7dd8f973fd44031a0a6d42c28f01b424d1b 100644 +index 05043071fc9805e1b9595090450f405ab28c22db..11f6e8466018783f8478a4f4e0e9050aae5d62f0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -134,6 +134,12 @@ config GPIO_BCM_KONA @@ -117171,7 +105985,7 @@ index d5d36549ecc1ecea2c53cddea2a209e54ab94b56..ade9f7dd8f973fd44031a0a6d42c28f0 tristate "BRCMSTB GPIO support" default y if (ARCH_BRCMSTB || BMIPS_GENERIC) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index a7676b82de6f4accd75d57817fb2f0c4f5407bd1..dec0669a5f030023288047f2abe68b0f2e0946d7 100644 +index becb96c724fef59bf770c89268771c10acf6e48f..fcdfb8e3c19e1c74e4e4c1a8881955fcbcd6a659 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o @@ -117415,10 +106229,341 @@ index 4a3d79d3b48eb483a4e4bf498f617515e3ad158f..5f34e1257117fb48013c9926a8a223d6 RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, -From 73802d49475dc1b014ced68b23724a1be74f8fd9 Mon Sep 17 00:00:00 2001 +From b1176c31fd12cf6bcd755eda12ea4eebe89d47c5 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Mon, 20 Feb 2017 17:01:21 +0000 +Subject: [PATCH 090/150] bcm2835-gpio-exp: Driver for GPIO expander via + mailbox service + +Pi3 and Compute Module 3 have a GPIO expander that the +VPU communicates with. +There is a mailbox service that now allows control of this +expander, so add a kernel driver that can make use of it. + +Pwr_led node added to device-tree for Pi3. + +Signed-off-by: Dave Stevenson +--- + drivers/gpio/Kconfig | 7 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-bcm-exp.c | 256 +++++++++++++++++++++++++++++ + include/soc/bcm2835/raspberrypi-firmware.h | 4 + + 4 files changed, 268 insertions(+) + create mode 100644 drivers/gpio/gpio-bcm-exp.c + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index 11f6e8466018783f8478a4f4e0e9050aae5d62f0..2c0028656eda108b16b0d51820c3cee74121f5f9 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -128,6 +128,13 @@ config GPIO_AXP209 + help + Say yes to enable GPIO support for the AXP209 PMIC + ++config GPIO_BCM_EXP ++ bool "Broadcom Exp GPIO" ++ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) ++ help ++ Turn on GPIO support for Broadcom chips using the firmware mailbox ++ to communicate with VideoCore on BCM283x chips. ++ + config GPIO_BCM_KONA + bool "Broadcom Kona GPIO" + depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) +diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile +index fcdfb8e3c19e1c74e4e4c1a8881955fcbcd6a659..a376f2b1012a3c1236094c8e9b1f5a3f6ed599fe 100644 +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o + obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o + obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o + obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o ++obj-$(CONFIG_GPIO_BCM_EXP) += gpio-bcm-exp.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 +diff --git a/drivers/gpio/gpio-bcm-exp.c b/drivers/gpio/gpio-bcm-exp.c +new file mode 100644 +index 0000000000000000000000000000000000000000..681a91492d4c33bdfd42416e069218e8611cc4d9 +--- /dev/null ++++ b/drivers/gpio/gpio-bcm-exp.c +@@ -0,0 +1,256 @@ ++/* ++ * Broadcom expander GPIO driver ++ * ++ * Uses the firmware mailbox service to communicate with the ++ * GPIO expander on the VPU. ++ * ++ * Copyright (C) 2017 Raspberry Pi Trading Ltd. ++ * ++ * Author: Dave Stevenson ++ * Based on gpio-bcm-virt.c by Dom Cobley ++ * ++ * 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 ++ ++#define MODULE_NAME "brcmexp-gpio" ++#define NUM_GPIO 8 ++ ++struct brcmexp_gpio { ++ struct gpio_chip gc; ++ struct device *dev; ++ struct rpi_firmware *fw; ++}; ++ ++struct gpio_set_config { ++ u32 gpio, direction, polarity, term_en, term_pull_up, state; ++}; ++ ++struct gpio_get_config { ++ u32 gpio, direction, polarity, term_en, term_pull_up; ++}; ++ ++struct gpio_get_set_state { ++ u32 gpio, state; ++}; ++ ++static int brcmexp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_config get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u config (%d)\n", off, ret); ++ return ret; ++ } ++ return get.polarity; ++} ++ ++static int brcmexp_gpio_dir_in(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_set_config set_in; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ set_in.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set_in.direction = 0; /* Input */ ++ set_in.polarity = brcmexp_gpio_get_polarity(gc, off); ++ /* Retain existing setting */ ++ set_in.term_en = 0; /* termination disabled */ ++ set_in.term_pull_up = 0; /* n/a as termination disabled */ ++ set_in.state = 0; /* n/a as configured as an input */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, ++ &set_in, sizeof(set_in)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u to input (%d)\n", ++ off, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++static int brcmexp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_set_config set_out; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ set_out.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set_out.direction = 1; /* Output */ ++ set_out.polarity = brcmexp_gpio_get_polarity(gc, off); ++ /* Retain existing setting */ ++ set_out.term_en = 0; /* n/a as an output */ ++ set_out.term_pull_up = 0; /* n/a as termination disabled */ ++ set_out.state = val; /* Output state */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, ++ &set_out, sizeof(set_out)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u to output (%d)\n", off, ret); ++ return ret; ++ } ++ return 0; ++} ++ ++static int brcmexp_gpio_get_direction(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_config get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u config (%d)\n", off, ret); ++ return ret; ++ } ++ return get.direction ? GPIOF_DIR_OUT : GPIOF_DIR_IN; ++} ++ ++static int brcmexp_gpio_get(struct gpio_chip *gc, unsigned int off) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_set_state get; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ get.gpio = off + gpio->gc.base; /* GPIO to update */ ++ get.state = 0; /* storage for returned value */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE, ++ &get, sizeof(get)); ++ if (ret) { ++ dev_err(gpio->dev, ++ "Failed to get GPIO %u state (%d)\n", off, ret); ++ return ret; ++ } ++ return !!get.state; ++} ++ ++static void brcmexp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) ++{ ++ struct brcmexp_gpio *gpio; ++ struct gpio_get_set_state set; ++ int ret; ++ ++ gpio = container_of(gc, struct brcmexp_gpio, gc); ++ ++ off += gpio->gc.base; ++ ++ set.gpio = off + gpio->gc.base; /* GPIO to update */ ++ set.state = val; /* Output state */ ++ ++ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE, ++ &set, sizeof(set)); ++ if (ret) ++ dev_err(gpio->dev, ++ "Failed to set GPIO %u state (%d)\n", off, ret); ++} ++ ++static int brcmexp_gpio_probe(struct platform_device *pdev) ++{ ++ int err = 0; ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct brcmexp_gpio *ucb; ++ ++ 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; ++ ++ ucb = devm_kzalloc(dev, sizeof(*ucb), GFP_KERNEL); ++ if (!ucb) ++ return -EINVAL; ++ ++ ucb->fw = fw; ++ ucb->dev = dev; ++ ucb->gc.label = MODULE_NAME; ++ ucb->gc.owner = THIS_MODULE; ++ ucb->gc.of_node = np; ++ ucb->gc.base = 128; ++ ucb->gc.ngpio = NUM_GPIO; ++ ++ ucb->gc.direction_input = brcmexp_gpio_dir_in; ++ ucb->gc.direction_output = brcmexp_gpio_dir_out; ++ ucb->gc.get_direction = brcmexp_gpio_get_direction; ++ ucb->gc.get = brcmexp_gpio_get; ++ ucb->gc.set = brcmexp_gpio_set; ++ ucb->gc.can_sleep = true; ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ return err; ++ ++ platform_set_drvdata(pdev, ucb); ++ ++ return 0; ++} ++ ++static int brcmexp_gpio_remove(struct platform_device *pdev) ++{ ++ struct brcmexp_gpio *ucb = platform_get_drvdata(pdev); ++ ++ gpiochip_remove(&ucb->gc); ++ ++ return 0; ++} ++ ++static const struct of_device_id __maybe_unused brcmexp_gpio_ids[] = { ++ { .compatible = "brcm,bcm2835-expgpio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, brcmexp_gpio_ids); ++ ++static struct platform_driver brcmexp_gpio_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(brcmexp_gpio_ids), ++ }, ++ .probe = brcmexp_gpio_probe, ++ .remove = brcmexp_gpio_remove, ++}; ++module_platform_driver(brcmexp_gpio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Dave Stevenson "); ++MODULE_DESCRIPTION("brcm-exp GPIO driver"); ++MODULE_ALIAS("platform:brcmexp-gpio"); +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index 5f34e1257117fb48013c9926a8a223d64a598ab7..c819c21b0158a59c1308882e5a40e3f3fe73cbdf 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -81,7 +81,11 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_SET_TURBO = 0x00038009, + RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, + RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, ++ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, ++ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, + RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, ++ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, ++ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, + +From 419172a262c4c982a893c17d398036a72213c46f Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 23 Feb 2016 17:26:48 +0000 -Subject: [PATCH 083/216] amba_pl011: Don't use DT aliases for numbering +Subject: [PATCH 091/150] 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 @@ -117430,10 +106575,10 @@ use the same logic. 1 file changed, 5 insertions(+) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index d4171d71a258f2696ab2ab2109376ee5a516bfba..6beb6233a0b6132b933cf8d85d8501dc1ce2fe4c 100644 +index b0a377725d636c11cddad62470d821a31f1fff96..5c18e1c2851cd8b20f7a32328def14b209490d9a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c -@@ -2497,7 +2497,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, +@@ -2567,7 +2567,12 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, if (IS_ERR(base)) return PTR_ERR(base); @@ -117447,10 +106592,99 @@ index d4171d71a258f2696ab2ab2109376ee5a516bfba..6beb6233a0b6132b933cf8d85d8501dc uap->old_cr = 0; uap->port.dev = dev; -From b7b39173fc7d4fc71565ac9c56a53545a98abd3c Mon Sep 17 00:00:00 2001 +From 1a2cd91875178015847c0a0b99e694b55025a5af Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 1 Mar 2017 16:07:39 +0000 +Subject: [PATCH 092/150] amba_pl011: Round input clock up + +The UART clock is initialised to be as close to the requested +frequency as possible without exceeding it. Now that there is a +clock manager that returns the actual frequencies, an expected +48MHz clock is reported as 47999625. If the requested baudrate +== requested clock/16, there is no headroom and the slight +reduction in actual clock rate results in failure. + +Detect cases where it looks like a "round" clock was chosen and +adjust the reported clock to match that "round" value. As the +code comment says: + +/* + * If increasing a clock by less than 0.1% changes it + * from ..999.. to ..000.., round up. + */ + +Signed-off-by: Phil Elwell +--- + drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 5c18e1c2851cd8b20f7a32328def14b209490d9a..bf58c13d9894a8bed333c35774dcb4736970b760 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1674,6 +1674,23 @@ static void pl011_put_poll_char(struct uart_port *port, + + #endif /* CONFIG_CONSOLE_POLL */ + ++unsigned long pl011_clk_round(unsigned long clk) ++{ ++ unsigned long scaler; ++ ++ /* ++ * If increasing a clock by less than 0.1% changes it ++ * from ..999.. to ..000.., round up. ++ */ ++ scaler = 1; ++ while (scaler * 100000 < clk) ++ scaler *= 10; ++ if ((clk + scaler - 1)/scaler % 1000 == 0) ++ clk = (clk/scaler + 1) * scaler; ++ ++ return clk; ++} ++ + static int pl011_hwinit(struct uart_port *port) + { + struct uart_amba_port *uap = +@@ -1690,7 +1707,7 @@ static int pl011_hwinit(struct uart_port *port) + if (retval) + return retval; + +- uap->port.uartclk = clk_get_rate(uap->clk); ++ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); + + /* Clear pending error and receive interrupts */ + pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | +@@ -2330,7 +2347,7 @@ static int __init pl011_console_setup(struct console *co, char *options) + plat->init(); + } + +- uap->port.uartclk = clk_get_rate(uap->clk); ++ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); + + if (uap->vendor->fixed_options) { + baud = uap->fixed_baud; +@@ -2498,6 +2515,7 @@ static struct uart_driver amba_reg = { + .cons = AMBA_CONSOLE, + }; + ++#if 0 + static int pl011_probe_dt_alias(int index, struct device *dev) + { + struct device_node *np; +@@ -2529,6 +2547,7 @@ static int pl011_probe_dt_alias(int index, struct device *dev) + + return ret; + } ++#endif + + /* unregisters the driver also if no more ports are left */ + static void pl011_unregister_port(struct uart_amba_port *uap) + +From 3b145a52aef8960ee624c1083b25d11933f94022 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Wed, 3 Dec 2014 13:23:28 +0200 -Subject: [PATCH 084/216] OF: DT-Overlay configfs interface +Subject: [PATCH 093/150] 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. @@ -117882,10 +107116,10 @@ index 0000000000000000000000000000000000000000..0037e6868a6cda8706c88194c6a4454b +} +late_initcall(of_cfs_init); -From 2cb4ba99ce29b41ad90f1f8eb0bf879704248873 Mon Sep 17 00:00:00 2001 +From 00a50a6f23613422da91288be618b3654b800b92 Mon Sep 17 00:00:00 2001 From: Cheong2K Date: Fri, 26 Feb 2016 18:20:10 +0800 -Subject: [PATCH 085/216] brcm: adds support for BCM43341 wifi +Subject: [PATCH 094/150] brcm: adds support for BCM43341 wifi brcmfmac: Disable power management @@ -117931,10 +107165,10 @@ Signed-off-by: Phil Elwell 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 7ffc4aba5bab0683fe993d1d5eef9e8e3d8389d0..5dfcf16428f9c8687237c3218183d8afa66ec331 100644 +index 944b83cfc51978d06ccc82a9f23ce64472af3fc8..b285024b754c9a6eb915d4a7c9e09126e1ecbea0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2749,6 +2749,8 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, +@@ -2747,6 +2747,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 */ @@ -117943,7 +107177,7 @@ index 7ffc4aba5bab0683fe993d1d5eef9e8e3d8389d0..5dfcf16428f9c8687237c3218183d8af cfg->pwr_save = enabled; if (!check_vif_up(ifp->vif)) { -@@ -4659,12 +4661,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) +@@ -4655,12 +4657,15 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) brcmf_err("BRCMF_C_DOWN error %d\n", err); @@ -117962,7 +107196,7 @@ index 7ffc4aba5bab0683fe993d1d5eef9e8e3d8389d0..5dfcf16428f9c8687237c3218183d8af if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) brcmf_fil_iovar_int_set(ifp, "mbss", 0); brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY, -@@ -6650,12 +6655,18 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], +@@ -6687,12 +6692,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; @@ -117983,7 +107217,7 @@ index 7ffc4aba5bab0683fe993d1d5eef9e8e3d8389d0..5dfcf16428f9c8687237c3218183d8af } if ((alpha2[0] == ccreq->country_abbrev[0]) && -@@ -6679,10 +6690,14 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], +@@ -6716,10 +6727,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; } @@ -118002,7 +107236,7 @@ index 7ffc4aba5bab0683fe993d1d5eef9e8e3d8389d0..5dfcf16428f9c8687237c3218183d8af ccreq->country_abbrev[1] = alpha2[1]; ccreq->country_abbrev[2] = 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1beb79a824 100644 +index 33b133f7e63aad3b5a6bb14018fd461ec4fb90c6..6221b046bca44211e2dfac24119097f7ac09e829 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -69,7 +69,7 @@ static int brcmf_fcmode; @@ -118015,7 +107249,7 @@ index 3e15d64c64813513bc22202dd9e468588699abb0..4051780f64f44a5ce522babe6c371a1b MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c -index d2219885071f6d718f0f26320d580c66adc26e36..d13826095c09f5b4037625371fe648900c9d670a 100644 +index 65689469c5a12e2fcfd6123ca584944da79ec184..4886dc29ad36705210bed20757ce09edadbd4262 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -604,6 +604,7 @@ BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); @@ -118036,10 +107270,52 @@ index d2219885071f6d718f0f26320d580c66adc26e36..d13826095c09f5b4037625371fe64890 BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), -From 3016c023cf333b3dd9454db05c1be1147d666c85 Mon Sep 17 00:00:00 2001 +From 8a8ebc0a1b37bd58daec6ccc63d7166824fa3c98 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 17 Feb 2017 15:26:13 +0000 +Subject: [PATCH 095/150] brcmfmac: Mute expected startup 'errors' + +The brcmfmac WiFi driver always complains about the '00' country code +and the firmware version is reported as an error. Modify the driver to +ignore '00' silently and display firmware version at INFO level. + +Signed-off-by: Phil Elwell +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index b285024b754c9a6eb915d4a7c9e09126e1ecbea0..808ab269746121d35bcd175d26ecfb5a0d9c394d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6754,6 +6754,8 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, + /* ignore non-ISO3166 country codes */ + for (i = 0; i < sizeof(req->alpha2); i++) + if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { ++ if (req->alpha2[0] == '0' && req->alpha2[1] == '0') ++ return; + brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n", + req->alpha2[0], req->alpha2[1]); + return; +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +index 6221b046bca44211e2dfac24119097f7ac09e829..634602e0c44f91da06db7aa803dbee6921ae921e 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +@@ -161,7 +161,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) + strsep(&ptr, "\n"); + + /* Print fw version info */ +- brcmf_err("Firmware version = %s\n", buf); ++ pr_info("Firmware version = %s\n", buf); + + /* locate firmware version number for ethtool */ + ptr = strrchr(buf, ' ') + 1; + +From 86f421cf81c7921553471c46c9baa0ef9c1065cc Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 17 Dec 2015 13:37:07 +0000 -Subject: [PATCH 086/216] hci_h5: Don't send conf_req when ACTIVE +Subject: [PATCH 096/150] 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. @@ -118062,24 +107338,24 @@ index 90d0456b67446bcc624fab4b1542c4eaf21531b1..f9adeac3bbba6418dcca298c55706356 if (H5_HDR_LEN(hdr) > 2) h5->tx_win = (data[2] & 0x07); -From 2affbdd691394c1ba0f642fbb83fe76d7e5c8d6b Mon Sep 17 00:00:00 2001 +From e8ae5637fb688a82e30db4ce2308ba728274cd12 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 13 Apr 2015 17:16:29 +0100 -Subject: [PATCH 087/216] config: Add default configs +Subject: [PATCH 097/150] config: Add default configs --- - arch/arm/configs/bcm2709_defconfig | 1297 +++++++++++++++++++++++++++++++++++ - arch/arm/configs/bcmrpi_defconfig | 1308 ++++++++++++++++++++++++++++++++++++ - 2 files changed, 2605 insertions(+) + arch/arm/configs/bcm2709_defconfig | 1310 +++++++++++++++++++++++++++++++++++ + arch/arm/configs/bcmrpi_defconfig | 1317 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 2627 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..12e8155c175deaecea6fcf1f81ec3f6c1ddf5f7c +index 0000000000000000000000000000000000000000..4f038004cb7ae7b6d9a54d9a743686e92d0e6389 --- /dev/null +++ b/arch/arm/configs/bcm2709_defconfig -@@ -0,0 +1,1297 @@ +@@ -0,0 +1,1310 @@ +CONFIG_LOCALVERSION="-v7" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -118094,7 +107370,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +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 @@ -118181,6 +107456,8 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_BBR=m +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_INET6_AH=m @@ -118197,8 +107474,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m @@ -118261,7 +107536,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m @@ -118376,6 +107650,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m @@ -118392,6 +107667,9 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_HHF=m ++CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m @@ -118437,6 +107715,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m ++CONFIG_CAN_SLCAN=m +CONFIG_CAN_MCP251X=m +CONFIG_IRDA=m +CONFIG_IRLAN=m @@ -118486,7 +107765,9 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_CMA_SIZE_MBYTES=5 +CONFIG_MTD=m +CONFIG_MTD_BLOCK=m ++CONFIG_MTD_M25P80=m +CONFIG_MTD_NAND=m ++CONFIG_MTD_SPI_NOR=m +CONFIG_MTD_UBI=m +CONFIG_OF_CONFIGFS=y +CONFIG_ZRAM=m @@ -118616,6 +107897,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m ++CONFIG_RTL8XXXU=m +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +CONFIG_MAC80211_HWSIM=m @@ -118625,7 +107907,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set @@ -118662,11 +107944,10 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y ++CONFIG_BCM2835_DEVGPIOMEM=y +# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y @@ -118698,6 +107979,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_BCM_EXP=y +CONFIG_GPIO_BCM_VIRT=y +CONFIG_GPIO_ARIZONA=m +CONFIG_GPIO_STMPE=y @@ -118727,17 +108009,20 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_INA2XX=m +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_WM5102=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=m ++CONFIG_REGULATOR_ARIZONA=m +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y @@ -118816,7 +108101,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m @@ -118875,8 +108159,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m @@ -118905,6 +108187,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_DRM=m +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_UDL=m ++CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_VC4=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y @@ -118932,7 +108215,6 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m @@ -118944,6 +108226,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m +CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m @@ -118953,11 +108236,15 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m +CONFIG_SND_DIGIDAC1_SOUNDCARD=m +CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m +CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m +CONFIG_SND_PISOUND=m +CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_ADAU7002=m +CONFIG_SND_SOC_AK4554=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -119042,6 +108329,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m ++CONFIG_USB_DWC2=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m @@ -119114,6 +108402,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m ++CONFIG_USB_GADGET=m +CONFIG_MMC=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BCM2835=y @@ -119182,11 +108471,10 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_STAGING_MEDIA=y ++CONFIG_VIDEO_BCM2835=m +CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m +CONFIG_LIRC_RPI=m +CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m @@ -119217,6 +108505,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_SND_BCM2835=m +CONFIG_MAILBOX=y +CONFIG_BCM2835_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set @@ -119350,13 +108639,12 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y ++# CONFIG_RCU_TRACE is not set +CONFIG_LATENCYTOP=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y @@ -119370,6 +108658,7 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM_CRYPTO=y @@ -119379,10 +108668,10 @@ index 0000000000000000000000000000000000000000..12e8155c175deaecea6fcf1f81ec3f6c +CONFIG_LIBCRC32C=y diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig new file mode 100644 -index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831cda8d7b51 +index 0000000000000000000000000000000000000000..046f3e8757ef0f794c802171690528d31fee9deb --- /dev/null +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -0,0 +1,1308 @@ +@@ -0,0 +1,1317 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y @@ -119396,7 +108685,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +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 @@ -119480,6 +108768,8 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_DIAG=m ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_BBR=m +CONFIG_IPV6=m +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_INET6_AH=m @@ -119496,8 +108786,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m @@ -119560,7 +108848,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m @@ -119675,6 +108962,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m @@ -119691,6 +108979,9 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=m ++CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_HHF=m ++CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m @@ -119736,6 +109027,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m ++CONFIG_CAN_SLCAN=m +CONFIG_CAN_MCP251X=m +CONFIG_IRDA=m +CONFIG_IRLAN=m @@ -119785,7 +109077,9 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_CMA_SIZE_MBYTES=5 +CONFIG_MTD=m +CONFIG_MTD_BLOCK=m ++CONFIG_MTD_M25P80=m +CONFIG_MTD_NAND=m ++CONFIG_MTD_SPI_NOR=m +CONFIG_MTD_UBI=m +CONFIG_OF_CONFIGFS=y +CONFIG_ZRAM=m @@ -119915,6 +109209,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=m +CONFIG_RTL8192CU=m ++CONFIG_RTL8XXXU=m +CONFIG_USB_ZD1201=m +CONFIG_ZD1211RW=m +CONFIG_MAC80211_HWSIM=m @@ -119924,7 +109219,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +# CONFIG_KEYBOARD_ATKBD is not set @@ -119960,11 +109255,10 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y +CONFIG_BCM_VCIO=y +CONFIG_BCM_VC_SM=y ++CONFIG_BCM2835_DEVGPIOMEM=y +# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y @@ -120024,17 +109318,20 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_ADS1015=m +CONFIG_SENSORS_INA2XX=m +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y +CONFIG_BCM2835_WDT=y -+CONFIG_UCB1400_CORE=m +CONFIG_MFD_STMPE=y +CONFIG_STMPE_SPI=y +CONFIG_MFD_ARIZONA_I2C=m +CONFIG_MFD_ARIZONA_SPI=m +CONFIG_MFD_WM5102=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=m ++CONFIG_REGULATOR_ARIZONA=m +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y @@ -120113,7 +109410,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160_AC97=y +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m @@ -120172,8 +109468,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_BCM2835=y -+CONFIG_VIDEO_BCM2835_MMAL=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m @@ -120202,6 +109496,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_DRM=m +CONFIG_DRM_LOAD_EDID_FIRMWARE=y +CONFIG_DRM_UDL=m ++CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_VC4=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y @@ -120229,7 +109524,6 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m -+CONFIG_SND_BCM2835=m +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m @@ -120241,6 +109535,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m +CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m ++CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m +CONFIG_SND_BCM2708_SOC_RPI_DAC=m +CONFIG_SND_BCM2708_SOC_RPI_PROTO=m +CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m @@ -120250,11 +109545,15 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_SND_BCM2708_SOC_RASPIDAC3=m +CONFIG_SND_BCM2708_SOC_ADAU1977_ADC=m +CONFIG_SND_AUDIOINJECTOR_PI_SOUNDCARD=m ++CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m +CONFIG_SND_DIGIDAC1_SOUNDCARD=m +CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m ++CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m +CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m ++CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m +CONFIG_SND_PISOUND=m +CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_ADAU7002=m +CONFIG_SND_SOC_AK4554=m +CONFIG_SND_SOC_WM8804_I2C=m +CONFIG_SND_SIMPLE_CARD=m @@ -120494,11 +109793,10 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_STAGING_MEDIA=y ++CONFIG_VIDEO_BCM2835=m +CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IMON=m +CONFIG_LIRC_RPI=m +CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m +CONFIG_FB_TFT=m +CONFIG_FB_TFT_AGM1264K_FL=m +CONFIG_FB_TFT_BD663474=m @@ -120529,6 +109827,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_FB_TFT_WATTEROTT=m +CONFIG_FB_FLEX=m +CONFIG_FB_TFT_FBTFT_DEVICE=m ++CONFIG_SND_BCM2835=m +CONFIG_MAILBOX=y +CONFIG_BCM2835_MBOX=y +# CONFIG_IOMMU_SUPPORT is not set @@ -120662,13 +109961,11 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y +CONFIG_LATENCYTOP=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_STACK_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y -+# CONFIG_KPROBE_EVENT is not set +CONFIG_FUNCTION_PROFILER=y +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y @@ -120684,6 +109981,7 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_LZ4=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +# CONFIG_CRYPTO_HW is not set +CONFIG_ARM_CRYPTO=y @@ -120692,10 +109990,10 @@ index 0000000000000000000000000000000000000000..8acee9f31202ec14f2933d92dd70831c +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -From b0ae7eb190b918d20c74cf199d19e014e260d8c6 Mon Sep 17 00:00:00 2001 +From 13f4a2a2d8ee275ae22f3c50a948576a359ac15a Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Wed, 24 Aug 2016 03:35:56 -0700 -Subject: [PATCH 088/216] Add arm64 configuration and device tree differences. +Subject: [PATCH 098/150] Add arm64 configuration and device tree differences. Disable MMC_BCM2835_SDHOST and MMC_BCM2835 since these drivers are crashing at the moment. @@ -120717,7 +110015,7 @@ Tested with raspbian-jessie 2016-09-23. create mode 100644 arch/arm64/configs/bcmrpi3_defconfig diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index 715ef1256838ed4b14d21c9ee8885d10c64fb0fc..5289515a5b3bdfc85b7b6f1153e55b8ee760e96c 100644 +index 129cc5ae4091489c08eb751f3e1b85b6eaa2eb9c..f04bc208f878322d35b94afafe74a7caf7d93820 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -1,5 +1,27 @@ @@ -120749,12 +110047,12 @@ index 715ef1256838ed4b14d21c9ee8885d10c64fb0fc..5289515a5b3bdfc85b7b6f1153e55b8e bool "Allwinner sunxi 64-bit SoC Family" select GENERIC_IRQ_CHIP diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 05faf2a8a35ca5ba9049b9038dedb9be88eeb7c5..2152448c8cf5b22c573642d7ce45e85793f5fc9a 100644 +index f1caece9d3a7ae7af8f95f9b9675e935a59ace6b..db4e66ee2a455eb1ec7d49c1fcb1c6c0a7a3ad13 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile @@ -1,6 +1,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb ns2-xmc.dtb dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb +dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb @@ -122110,1116 +111408,10 @@ index 0000000000000000000000000000000000000000..e6b09fafa27eed2b762e3d53b55041f7 +CONFIG_LIBCRC32C=y +CONFIG_BCM2835_VCHIQ=n -From 91b94edb67414658dfa4ea5aa36643cca0c5191c Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 27 Dec 2016 22:13:42 +0000 -Subject: [PATCH 089/216] Revert "staging: vc04_services: remove - vchiq_copy_from_user" - -This reverts commit 49bec49fd7f273ec114e2e533c1bb8f21a654aaf. ---- - .../staging/vc04_services/interface/vchi/vchi.h | 25 +- - .../interface/vchiq_arm/vchiq_2835_arm.c | 11 + - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 103 +------- - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 269 +++++++++------------ - .../vc04_services/interface/vchiq_arm/vchiq_core.h | 3 + - .../vc04_services/interface/vchiq_arm/vchiq_if.h | 9 +- - .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 64 ++++- - 7 files changed, 197 insertions(+), 287 deletions(-) - -diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h -index d6937288210cef102e115f4265471ad9e9da7007..1b17e98f737979eef19906609bc19ecd19455618 100644 ---- a/drivers/staging/vc04_services/interface/vchi/vchi.h -+++ b/drivers/staging/vc04_services/interface/vchi/vchi.h -@@ -226,12 +226,25 @@ extern int32_t vchi_service_set_option( const VCHI_SERVICE_HANDLE_T handle, - int value); - - // Routine to send a message across a service --extern int32_t -- vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- uint32_t data_size); -+extern int32_t vchi_msg_queue( VCHI_SERVICE_HANDLE_T handle, -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// scatter-gather (vector) and send message -+int32_t vchi_msg_queuev_ex( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_EX_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); -+ -+// legacy scatter-gather (vector) and send message, only handles pointers -+int32_t vchi_msg_queuev( VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle ); - - // Routine to receive a msg from a service - // Dequeue is equivalent to hold, copy into client buffer, release -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 2b500d85cebc768373a2dd48c779063262b52570..706e7f936c1a97352f7ef3d3fbd3b4a92943165d 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -232,6 +232,17 @@ remote_event_signal(REMOTE_EVENT_T *event) - writel(0, g_regs + BELL2); /* trigger vc interrupt */ - } - -+int -+vchiq_copy_from_user(void *dst, const void *src, int size) -+{ -+ if ((uint32_t)src < TASK_SIZE) { -+ return copy_from_user(dst, src, size); -+ } else { -+ memcpy(dst, src, size); -+ return 0; -+ } -+} -+ - VCHIQ_STATUS_T - vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, - void *offset, int size, int dir) -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 0d987898b4f86abbd7d3f73046ef4ae5ffff5452..42998155eb4d7de8e49cc1ca82d84a430562a8da 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -402,107 +402,6 @@ static void close_delivered(USER_SERVICE_T *user_service) - } - } - --struct vchiq_io_copy_callback_context { -- VCHIQ_ELEMENT_T *current_element; -- size_t current_element_offset; -- unsigned long elements_to_go; -- size_t current_offset; --}; -- --static ssize_t --vchiq_ioc_copy_element_data( -- void *context, -- void *dest, -- size_t offset, -- size_t maxsize) --{ -- long res; -- size_t bytes_this_round; -- struct vchiq_io_copy_callback_context *copy_context = -- (struct vchiq_io_copy_callback_context *)context; -- -- if (offset != copy_context->current_offset) -- return 0; -- -- if (!copy_context->elements_to_go) -- return 0; -- -- /* -- * Complex logic here to handle the case of 0 size elements -- * in the middle of the array of elements. -- * -- * Need to skip over these 0 size elements. -- */ -- while (1) { -- bytes_this_round = min(copy_context->current_element->size - -- copy_context->current_element_offset, -- maxsize); -- -- if (bytes_this_round) -- break; -- -- copy_context->elements_to_go--; -- copy_context->current_element++; -- copy_context->current_element_offset = 0; -- -- if (!copy_context->elements_to_go) -- return 0; -- } -- -- res = copy_from_user(dest, -- copy_context->current_element->data + -- copy_context->current_element_offset, -- bytes_this_round); -- -- if (res != 0) -- return -EFAULT; -- -- copy_context->current_element_offset += bytes_this_round; -- copy_context->current_offset += bytes_this_round; -- -- /* -- * Check if done with current element, and if so advance to the next. -- */ -- if (copy_context->current_element_offset == -- copy_context->current_element->size) { -- copy_context->elements_to_go--; -- copy_context->current_element++; -- copy_context->current_element_offset = 0; -- } -- -- return bytes_this_round; --} -- --/************************************************************************** -- * -- * vchiq_ioc_queue_message -- * -- **************************************************************************/ --static VCHIQ_STATUS_T --vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle, -- VCHIQ_ELEMENT_T *elements, -- unsigned long count) --{ -- struct vchiq_io_copy_callback_context context; -- unsigned long i; -- size_t total_size = 0; -- -- context.current_element = elements; -- context.current_element_offset = 0; -- context.elements_to_go = count; -- context.current_offset = 0; -- -- for (i = 0; i < count; i++) { -- if (!elements[i].data && elements[i].size != 0) -- return -EFAULT; -- -- total_size += elements[i].size; -- } -- -- return vchiq_queue_message(handle, vchiq_ioc_copy_element_data, -- &context, total_size); --} -- - /**************************************************************************** - * - * vchiq_ioctl -@@ -752,7 +651,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - VCHIQ_ELEMENT_T elements[MAX_ELEMENTS]; - if (copy_from_user(elements, args.elements, - args.count * sizeof(VCHIQ_ELEMENT_T)) == 0) -- status = vchiq_ioc_queue_message -+ status = vchiq_queue_message - (args.handle, - elements, args.count); - else -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -index 028e90bc1cdcc3f305ce5b97b88dd5c6c4613a50..c5b06cc4ca53135ec9491116ca79beaa98f57bcc 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -464,8 +464,8 @@ remote_event_pollall(VCHIQ_STATE_T *state) - ** enough for a header. This relies on header size being a power of two, which - ** has been verified earlier by a static assertion. */ - --static inline size_t --calc_stride(size_t size) -+static inline unsigned int -+calc_stride(unsigned int size) - { - /* Allow room for the header */ - size += sizeof(VCHIQ_HEADER_T); -@@ -544,7 +544,7 @@ request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) - /* Called from queue_message, by the slot handler and application threads, - ** with slot_mutex held */ - static VCHIQ_HEADER_T * --reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) -+reserve_space(VCHIQ_STATE_T *state, int space, int is_blocking) - { - VCHIQ_SHARED_STATE_T *local = state->local; - int tx_pos = state->local_tx_pos; -@@ -726,66 +726,18 @@ process_free_queue(VCHIQ_STATE_T *state) - } - } - --static ssize_t --memcpy_copy_callback( -- void *context, void *dest, -- size_t offset, size_t maxsize) --{ -- void *src = context; -- -- memcpy(dest + offset, src + offset, maxsize); -- return maxsize; --} -- --static ssize_t --copy_message_data( -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- void *dest, -- size_t size) --{ -- size_t pos = 0; -- -- while (pos < size) { -- ssize_t callback_result; -- size_t max_bytes = size - pos; -- -- callback_result = -- copy_callback(context, dest + pos, -- pos, max_bytes); -- -- if (callback_result < 0) -- return callback_result; -- -- if (!callback_result) -- return -EIO; -- -- if (callback_result > max_bytes) -- return -EIO; -- -- pos += callback_result; -- } -- -- return size; --} -- - /* Called by the slot handler and application threads */ - static VCHIQ_STATUS_T - queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -- int msgid, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- size_t size, -- int flags) -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int flags) - { - VCHIQ_SHARED_STATE_T *local; - VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; - VCHIQ_HEADER_T *header; - int type = VCHIQ_MSG_TYPE(msgid); - -- size_t stride; -+ unsigned int stride; - - local = state->local; - -@@ -891,7 +843,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - } - - if (type == VCHIQ_MSG_DATA) { -- ssize_t callback_result; -+ int i, pos; - int tx_end_index; - int slot_use_count; - -@@ -905,23 +857,27 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - BUG_ON((flags & (QMFLAGS_NO_MUTEX_LOCK | - QMFLAGS_NO_MUTEX_UNLOCK)) != 0); - -- callback_result = -- copy_message_data(copy_callback, context, -- header->data, size); -- -- if (callback_result < 0) { -- mutex_unlock(&state->slot_mutex); -- VCHIQ_SERVICE_STATS_INC(service, -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->slot_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, - error_count); -- return VCHIQ_ERROR; -- } -- -- if (SRVTRACE_ENABLED(service, -- VCHIQ_LOG_INFO)) -- vchiq_log_dump_mem("Sent", 0, -- header->data, -- min((size_t)64, -- (size_t)callback_result)); -+ return VCHIQ_ERROR; -+ } -+ if (i == 0) { -+ if (SRVTRACE_ENABLED(service, -+ VCHIQ_LOG_INFO)) -+ vchiq_log_dump_mem("Sent", 0, -+ header->data + pos, -+ min(64u, -+ elements[0].size)); -+ } -+ } - - spin_lock("a_spinlock); - service_quota->message_use_count++; -@@ -963,17 +919,9 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - header, size, VCHIQ_MSG_SRCPORT(msgid), - VCHIQ_MSG_DSTPORT(msgid)); - if (size != 0) { -- /* It is assumed for now that this code path -- * only happens from calls inside this file. -- * -- * External callers are through the vchiq_queue_message -- * path which always sets the type to be VCHIQ_MSG_DATA -- * -- * At first glance this appears to be correct but -- * more review is needed. -- */ -- copy_message_data(copy_callback, context, -- header->data, size); -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); - } - VCHIQ_STATS_INC(state, ctrl_tx_count); - } -@@ -1019,16 +967,11 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - /* Called by the slot handler and application threads */ - static VCHIQ_STATUS_T - queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, -- int msgid, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- int size, -- int is_blocking) -+ int msgid, const VCHIQ_ELEMENT_T *elements, -+ int count, int size, int is_blocking) - { - VCHIQ_SHARED_STATE_T *local; - VCHIQ_HEADER_T *header; -- ssize_t callback_result; - - local = state->local; - -@@ -1051,34 +994,50 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - state->id, oldmsgid); - } - -- vchiq_log_info(vchiq_sync_log_level, -- "%d: qms %s@%pK,%x (%d->%d)", state->id, -- msg_type_str(VCHIQ_MSG_TYPE(msgid)), -- header, size, VCHIQ_MSG_SRCPORT(msgid), -- VCHIQ_MSG_DSTPORT(msgid)); -- -- callback_result = -- copy_message_data(copy_callback, context, -- header->data, size); -+ if (service) { -+ int i, pos; - -- if (callback_result < 0) { -- mutex_unlock(&state->slot_mutex); -- VCHIQ_SERVICE_STATS_INC(service, -- error_count); -- return VCHIQ_ERROR; -- } -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%pK,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ header, size, VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); - -- if (service) { -- if (SRVTRACE_ENABLED(service, -- VCHIQ_LOG_INFO)) -- vchiq_log_dump_mem("Sent", 0, -- header->data, -- min((size_t)64, -- (size_t)callback_result)); -+ for (i = 0, pos = 0; i < (unsigned int)count; -+ pos += elements[i++].size) -+ if (elements[i].size) { -+ if (vchiq_copy_from_user -+ (header->data + pos, elements[i].data, -+ (size_t) elements[i].size) != -+ VCHIQ_SUCCESS) { -+ mutex_unlock(&state->sync_mutex); -+ VCHIQ_SERVICE_STATS_INC(service, -+ error_count); -+ return VCHIQ_ERROR; -+ } -+ if (i == 0) { -+ if (vchiq_sync_log_level >= -+ VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("Sent Sync", -+ 0, header->data + pos, -+ min(64u, -+ elements[0].size)); -+ } -+ } - - VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); - } else { -+ vchiq_log_info(vchiq_sync_log_level, -+ "%d: qms %s@%pK,%x (%d->%d)", state->id, -+ msg_type_str(VCHIQ_MSG_TYPE(msgid)), -+ header, size, VCHIQ_MSG_SRCPORT(msgid), -+ VCHIQ_MSG_DSTPORT(msgid)); -+ if (size != 0) { -+ WARN_ON(!((count == 1) && (size == elements[0].size))); -+ memcpy(header->data, elements[0].data, -+ elements[0].size); -+ } - VCHIQ_STATS_INC(state, ctrl_tx_count); - } - -@@ -1191,16 +1150,11 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, - VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; - int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, - service->remoteport); -+ VCHIQ_ELEMENT_T element = { &bulk->actual, 4 }; - /* Only reply to non-dummy bulk requests */ - if (bulk->remote_data) { -- status = queue_message( -- service->state, -- NULL, -- msgid, -- memcpy_copy_callback, -- &bulk->actual, -- 4, -- 0); -+ status = queue_message(service->state, NULL, -+ msgid, &element, 1, 4, 0); - if (status != VCHIQ_SUCCESS) - break; - } -@@ -1560,6 +1514,10 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) - struct vchiq_openack_payload ack_payload = { - service->version - }; -+ VCHIQ_ELEMENT_T body = { -+ &ack_payload, -+ sizeof(ack_payload) -+ }; - - if (state->version_common < - VCHIQ_VERSION_SYNCHRONOUS_MODE) -@@ -1569,28 +1527,21 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) - if (service->sync && - (state->version_common >= - VCHIQ_VERSION_SYNCHRONOUS_MODE)) { -- if (queue_message_sync( -- state, -- NULL, -+ if (queue_message_sync(state, NULL, - VCHIQ_MAKE_MSG( - VCHIQ_MSG_OPENACK, - service->localport, - remoteport), -- memcpy_copy_callback, -- &ack_payload, -- sizeof(ack_payload), -+ &body, 1, sizeof(ack_payload), - 0) == VCHIQ_RETRY) - goto bail_not_ready; - } else { -- if (queue_message(state, -- NULL, -- VCHIQ_MAKE_MSG( -+ if (queue_message(state, NULL, -+ VCHIQ_MAKE_MSG( - VCHIQ_MSG_OPENACK, - service->localport, - remoteport), -- memcpy_copy_callback, -- &ack_payload, -- sizeof(ack_payload), -+ &body, 1, sizeof(ack_payload), - 0) == VCHIQ_RETRY) - goto bail_not_ready; - } -@@ -2680,19 +2631,14 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) - service->version, - service->version_min - }; -+ VCHIQ_ELEMENT_T body = { &payload, sizeof(payload) }; - VCHIQ_STATUS_T status = VCHIQ_SUCCESS; - - service->client_id = client_id; - vchiq_use_service_internal(service); -- status = queue_message(service->state, -- NULL, -- VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, -- service->localport, -- 0), -- memcpy_copy_callback, -- &payload, -- sizeof(payload), -- QMFLAGS_IS_BLOCKING); -+ status = queue_message(service->state, NULL, -+ VCHIQ_MAKE_MSG(VCHIQ_MSG_OPEN, service->localport, 0), -+ &body, 1, sizeof(payload), QMFLAGS_IS_BLOCKING); - if (status == VCHIQ_SUCCESS) { - /* Wait for the ACK/NAK */ - if (down_interruptible(&service->remove_event) != 0) { -@@ -3360,18 +3306,15 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, - VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); - } else { - int payload[2] = { (int)(long)bulk->data, bulk->size }; -+ VCHIQ_ELEMENT_T element = { payload, sizeof(payload) }; - -- status = queue_message(state, -- NULL, -- VCHIQ_MAKE_MSG(dir_msgtype, -- service->localport, -- service->remoteport), -- memcpy_copy_callback, -- &payload, -- sizeof(payload), -- QMFLAGS_IS_BLOCKING | -- QMFLAGS_NO_MUTEX_LOCK | -- QMFLAGS_NO_MUTEX_UNLOCK); -+ status = queue_message(state, NULL, -+ VCHIQ_MAKE_MSG(dir_msgtype, -+ service->localport, service->remoteport), -+ &element, 1, sizeof(payload), -+ QMFLAGS_IS_BLOCKING | -+ QMFLAGS_NO_MUTEX_LOCK | -+ QMFLAGS_NO_MUTEX_UNLOCK); - if (status != VCHIQ_SUCCESS) { - goto unlock_both_error_exit; - } -@@ -3417,22 +3360,26 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, - - VCHIQ_STATUS_T - vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- size_t size) -+ const VCHIQ_ELEMENT_T *elements, unsigned int count) - { - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); - VCHIQ_STATUS_T status = VCHIQ_ERROR; - -+ unsigned int size = 0; -+ unsigned int i; -+ - if (!service || - (vchiq_check_service(service) != VCHIQ_SUCCESS)) - goto error_exit; - -- if (!size) { -- VCHIQ_SERVICE_STATS_INC(service, error_count); -- goto error_exit; -- -+ for (i = 0; i < (unsigned int)count; i++) { -+ if (elements[i].size) { -+ if (elements[i].data == NULL) { -+ VCHIQ_SERVICE_STATS_INC(service, error_count); -+ goto error_exit; -+ } -+ size += elements[i].size; -+ } - } - - if (size > VCHIQ_MAX_MSG_SIZE) { -@@ -3446,14 +3393,14 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, - VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, - service->localport, - service->remoteport), -- copy_callback, context, size, 1); -+ elements, count, size, 1); - break; - case VCHIQ_SRVSTATE_OPENSYNC: - status = queue_message_sync(service->state, service, - VCHIQ_MAKE_MSG(VCHIQ_MSG_DATA, - service->localport, - service->remoteport), -- copy_callback, context, size, 1); -+ elements, count, size, 1); - break; - default: - status = VCHIQ_ERROR; -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h -index 9e164652548a42bac2646166e16961b88bc80594..1c2b1b5b8cc998f6f0490dc6460d8408e85f624b 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h -@@ -634,6 +634,9 @@ vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); - extern void - vchiq_complete_bulk(VCHIQ_BULK_T *bulk); - -+extern VCHIQ_STATUS_T -+vchiq_copy_from_user(void *dst, const void *src, int size); -+ - extern void - remote_event_signal(REMOTE_EVENT_T *event); - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h -index 377e8e48bb540465b34f2d4697504cb188d83e3b..8067bbe7ce8d70c41b2e6e0466d20a4612e39d93 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h -@@ -141,12 +141,9 @@ extern VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T service); - extern VCHIQ_STATUS_T vchiq_use_service_no_resume( - VCHIQ_SERVICE_HANDLE_T service); - extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T service); --extern VCHIQ_STATUS_T --vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- size_t size); -+ -+extern VCHIQ_STATUS_T vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T service, -+ const VCHIQ_ELEMENT_T *elements, unsigned int count); - extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, - VCHIQ_HEADER_T *header); - extern VCHIQ_STATUS_T vchiq_queue_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c -index d9771394a041bbb55daacd7744ac57758ae198d1..7694627b925c743552b093ce51d15c2f2fe71a69 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c -@@ -148,10 +148,10 @@ EXPORT_SYMBOL(vchi_msg_remove); - * Name: vchi_msg_queue - * - * Arguments: VCHI_SERVICE_HANDLE_T handle, -- * ssize_t (*copy_callback)(void *context, void *dest, -- * size_t offset, size_t maxsize), -- * void *context, -- * uint32_t data_size -+ * const void *data, -+ * uint32_t data_size, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle, - * - * Description: Thin wrapper to queue a message onto a connection - * -@@ -159,19 +159,21 @@ EXPORT_SYMBOL(vchi_msg_remove); - * - ***********************************************************/ - int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, -- ssize_t (*copy_callback)(void *context, void *dest, -- size_t offset, size_t maxsize), -- void *context, -- uint32_t data_size) -+ const void *data, -+ uint32_t data_size, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) - { - SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ VCHIQ_ELEMENT_T element = {data, data_size}; - VCHIQ_STATUS_T status; - -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ - while (1) { -- status = vchiq_queue_message(service->handle, -- copy_callback, -- context, -- data_size); -+ status = vchiq_queue_message(service->handle, &element, 1); - - /* - * vchiq_queue_message() may return VCHIQ_RETRY, so we need to -@@ -354,6 +356,44 @@ int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, - EXPORT_SYMBOL(vchi_msg_dequeue); - - /*********************************************************** -+ * Name: vchi_msg_queuev -+ * -+ * Arguments: VCHI_SERVICE_HANDLE_T handle, -+ * VCHI_MSG_VECTOR_T *vector, -+ * uint32_t count, -+ * VCHI_FLAGS_T flags, -+ * void *msg_handle -+ * -+ * Description: Thin wrapper to queue a message onto a connection -+ * -+ * Returns: int32_t - success == 0 -+ * -+ ***********************************************************/ -+ -+vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == -+ offsetof(VCHIQ_ELEMENT_T, data)); -+vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == -+ offsetof(VCHIQ_ELEMENT_T, size)); -+ -+int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, -+ VCHI_MSG_VECTOR_T *vector, -+ uint32_t count, -+ VCHI_FLAGS_T flags, -+ void *msg_handle) -+{ -+ SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; -+ -+ (void)msg_handle; -+ -+ WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); -+ -+ return vchiq_status_to_vchi(vchiq_queue_message(service->handle, -+ (const VCHIQ_ELEMENT_T *)vector, count)); -+} -+EXPORT_SYMBOL(vchi_msg_queuev); -+ -+/*********************************************************** - * Name: vchi_held_msg_release - * - * Arguments: VCHI_HELD_MSG_T *message - -From e74024d6d404818587b7fdcd7f14dccf0fb68635 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Mar 2016 14:16:25 +0000 -Subject: [PATCH 090/216] vchiq_arm: Access the dequeue_pending flag locked - -Reading through this code looking for another problem (now found in userland) -the use of dequeue_pending outside a lock didn't seem safe. - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 42998155eb4d7de8e49cc1ca82d84a430562a8da..74f1569097c7dd120cc68fb8d09d8c3d63d56977 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -279,6 +279,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, - USER_SERVICE_T *user_service; - VCHIQ_SERVICE_T *service; - VCHIQ_INSTANCE_T instance; -+ int skip_completion = 0; - DEBUG_INITIALISE(g_state.local) - - DEBUG_TRACE(SERVICE_CALLBACK_LINE); -@@ -345,9 +346,6 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, - user_service->msg_queue[user_service->msg_insert & - (MSG_QUEUE_SIZE - 1)] = header; - user_service->msg_insert++; -- spin_unlock(&msg_queue_spinlock); -- -- up(&user_service->insert_event); - - /* If there is a thread waiting in DEQUEUE_MESSAGE, or if - ** there is a MESSAGE_AVAILABLE in the completion queue then -@@ -356,13 +354,22 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, - if (((user_service->message_available_pos - - instance->completion_remove) >= 0) || - user_service->dequeue_pending) { -- DEBUG_TRACE(SERVICE_CALLBACK_LINE); - user_service->dequeue_pending = 0; -- return VCHIQ_SUCCESS; -+ skip_completion = 1; - } - -+ spin_unlock(&msg_queue_spinlock); -+ -+ up(&user_service->insert_event); -+ - header = NULL; - } -+ -+ if (skip_completion) { -+ DEBUG_TRACE(SERVICE_CALLBACK_LINE); -+ return VCHIQ_SUCCESS; -+ } -+ - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - - return add_completion(instance, reason, header, user_service, - -From 6fd2d8850ce225f7a1f574149fdf0c9e3969d769 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 23 Mar 2016 20:53:47 +0000 -Subject: [PATCH 091/216] vchiq_arm: Service callbacks must not fail - -Service callbacks are not allowed to return an error. The internal callback -that delivers events and messages to user tasks does not enqueue them if -the service is closing, but this is not an error and should not be -reported as such. - -Signed-off-by: Phil Elwell ---- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 74f1569097c7dd120cc68fb8d09d8c3d63d56977..3ba6485f0c7b32de9f2aa75164e8b1b901aa74ea 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -224,7 +224,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - } else if (instance->closing) { - vchiq_log_info(vchiq_arm_log_level, - "service_callback closing"); -- return VCHIQ_ERROR; -+ return VCHIQ_SUCCESS; - } - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - } - -From c7b0604dee67918f2a51d545637304446821d044 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 21 Apr 2016 13:49:32 +0100 -Subject: [PATCH 092/216] vchiq_arm: Add completion records under the mutex - -An issue was observed when flushing openmax components -which generate a large number of messages returning -buffers to host. - -We occasionally found a duplicate message from 16 -messages prior, resulting in a buffer returned twice. - -While only one thread adds completions, without the -mutex you don't get the protection of the automatic -memory barrier you get with synchronisation objects. - -Signed-off-by: Phil Elwell ---- - .../staging/vc04_services/interface/vchiq_arm/vchiq_arm.c | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 3ba6485f0c7b32de9f2aa75164e8b1b901aa74ea..07d8eadd2aa2dc997db13c80dc303673792b96c9 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -210,6 +210,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - VCHIQ_COMPLETION_DATA_T *completion; - DEBUG_INITIALISE(g_state.local) - -+ mutex_lock(&instance->completion_mutex); -+ - while (instance->completion_insert == - (instance->completion_remove + MAX_COMPLETIONS)) { - /* Out of space - wait for the client */ -@@ -217,11 +219,17 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - 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; -- } else if (instance->closing) { -+ } -+ -+ 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; -@@ -254,8 +262,11 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - if (reason == VCHIQ_MESSAGE_AVAILABLE) - user_service->message_available_pos = - instance->completion_insert; -+ - instance->completion_insert++; - -+ mutex_unlock(&instance->completion_mutex); -+ - up(&instance->insert_event); - - return VCHIQ_SUCCESS; - -From 881dc11c8b2387dae302ff13bab3ca5926b85318 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 20 Jun 2016 13:51:44 +0100 -Subject: [PATCH 093/216] vchiq_arm: Avoid use of mutex in add_completion - -Claiming the completion_mutex within add_completion did prevent some -messages appearing twice, but provokes a deadlock caused by vcsm using -vchiq within a page fault handler. - -Revert the use of completion_mutex, and instead fix the original -problem using more memory barriers. - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 55 +++++++++++----------- - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 14 ++++-- - 2 files changed, 37 insertions(+), 32 deletions(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -index 07d8eadd2aa2dc997db13c80dc303673792b96c9..a593c9df8128292525f6f1b89a351e1ded02977f 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -64,10 +64,10 @@ - #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 -@@ -208,28 +208,24 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - 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; -@@ -237,9 +233,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - 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; -@@ -260,12 +254,9 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - 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); - -@@ -795,6 +786,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - instance->completion_insert) - && !instance->closing) { - int rc; -+ - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - mutex_unlock(&instance->completion_mutex); - rc = down_interruptible(&instance->insert_event); -@@ -809,24 +801,29 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - } - 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; -@@ -901,7 +898,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - 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) { -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -index c5b06cc4ca53135ec9491116ca79beaa98f57bcc..d6757ee263fb61a689c0d38c0dbb65c57a8e39bb 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -607,15 +607,15 @@ process_free_queue(VCHIQ_STATE_T *state) - 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++ & -@@ -623,6 +623,8 @@ process_free_queue(VCHIQ_STATE_T *state) - 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=%pK %x %x", - state->id, slot_index, data, - local->slot_queue_recycle, slot_queue_available); -@@ -721,6 +723,8 @@ process_free_queue(VCHIQ_STATE_T *state) - up(&state->data_quota_event); - } - -+ mb(); -+ - state->slot_queue_available = slot_queue_available; - up(&state->slot_available_event); - } - -From d8d42f82473d95e278feda5c9076125fc7cb1cdd Mon Sep 17 00:00:00 2001 +From 0174ff8893ec2735faf31817b7d45f3e9388d57c Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:18:09 +0100 -Subject: [PATCH 094/216] raspberrypi-firmware: Define the MBOX channel in the +Subject: [PATCH 099/150] raspberrypi-firmware: Define the MBOX channel in the header. Signed-off-by: Eric Anholt @@ -123228,7 +111420,7 @@ Signed-off-by: Eric Anholt 1 file changed, 2 insertions(+) diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 5f34e1257117fb48013c9926a8a223d64a598ab7..7f0da0727422c690947e46e891a754de13dc1fea 100644 +index c819c21b0158a59c1308882e5a40e3f3fe73cbdf..de2a3dcd562beb752266eaf0070e55861d553f5f 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h @@ -12,6 +12,8 @@ @@ -123241,972 +111433,10 @@ index 5f34e1257117fb48013c9926a8a223d64a598ab7..7f0da0727422c690947e46e891a754de enum rpi_firmware_property_status { -From bcced95a7e4f2b3223e9b8670971c6d1a9d0bac0 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 14 Sep 2016 08:39:33 +0100 -Subject: [PATCH 095/216] drm/vc4: Add a mode for using the closed firmware for - display. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/Makefile | 1 + - drivers/gpu/drm/vc4/vc4_crtc.c | 13 + - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 7 + - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 660 +++++++++++++++++++++++++++++++++ - 5 files changed, 682 insertions(+) - create mode 100644 drivers/gpu/drm/vc4/vc4_firmware_kms.c - -diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile -index 7757f69a8a77b355677314dbb1380c4803b5e104..3358ec8775cf6e8738ea8cdb2246dad57bd29139 100644 ---- a/drivers/gpu/drm/vc4/Makefile -+++ b/drivers/gpu/drm/vc4/Makefile -@@ -8,6 +8,7 @@ vc4-y := \ - vc4_crtc.o \ - vc4_drv.o \ - vc4_dpi.o \ -+ vc4_firmware_kms.o \ - vc4_kms.o \ - vc4_gem.o \ - vc4_hdmi.o \ -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index c7e6c9839c9abfa5b4a9086024ebe3f854b13b38..c7e478f672e184974a33bb9ca72b8aa62d76e97e 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -162,6 +162,9 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, - int vblank_lines; - int ret = 0; - -+ if (vc4->firmware_kms) -+ return 0; -+ - /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ - - /* Get optional system timestamp before query. */ -@@ -655,6 +658,11 @@ int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id) - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; - -+ if (vc4->firmware_kms) { -+ /* XXX: Can we mask the SMI interrupt? */ -+ return 0; -+ } -+ - CRTC_WRITE(PV_INTEN, PV_INT_VFP_START); - - return 0; -@@ -665,6 +673,11 @@ void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id) - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_crtc *vc4_crtc = vc4->crtc[crtc_id]; - -+ if (vc4->firmware_kms) { -+ /* XXX: Can we mask the SMI interrupt? */ -+ return; -+ } -+ - CRTC_WRITE(PV_INTEN, 0); - } - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index ac09ca7ff4308874c3772f2aad9c9c11190f3706..44cd22340d82dbd5d094806e777121951f25010a 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -298,6 +298,7 @@ static struct platform_driver *const component_drivers[] = { - &vc4_dpi_driver, - &vc4_hvs_driver, - &vc4_crtc_driver, -+ &vc4_firmware_kms_driver, - &vc4_v3d_driver, - }; - -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index b5c4bb14d0d1b87a6bbb5b25fd93d156705e851d..61a9b3e81823a3c96f36f710329844cc032e2628 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -12,6 +12,9 @@ - struct vc4_dev { - struct drm_device *dev; - -+ bool firmware_kms; -+ struct rpi_firmware *firmware; -+ - struct vc4_hdmi *hdmi; - struct vc4_hvs *hvs; - struct vc4_crtc *crtc[3]; -@@ -465,6 +468,10 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index); - extern struct platform_driver vc4_dpi_driver; - int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); - -+/* vc4_firmware_kms.c */ -+extern struct platform_driver vc4_firmware_kms_driver; -+void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); -+ - /* vc4_gem.c */ - void vc4_gem_init(struct drm_device *dev); - void vc4_gem_destroy(struct drm_device *dev); -diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -new file mode 100644 -index 0000000000000000000000000000000000000000..d18a1dae51a2275846c9826b5bf1ba57ae97b55c ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -0,0 +1,660 @@ -+/* -+ * Copyright (C) 2016 Broadcom -+ * -+ * 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. -+ */ -+ -+/** -+ * DOC: VC4 firmware KMS module. -+ * -+ * As a hack to get us from the current closed source driver world -+ * toward a totally open stack, implement KMS on top of the Raspberry -+ * Pi's firmware display stack. -+ */ -+ -+#include "drm_atomic.h" -+#include "drm_atomic_helper.h" -+#include "drm_plane_helper.h" -+#include "drm_crtc_helper.h" -+#include "linux/clk.h" -+#include "linux/debugfs.h" -+#include "drm_fb_cma_helper.h" -+#include "linux/component.h" -+#include "linux/of_device.h" -+#include "vc4_drv.h" -+#include "vc4_regs.h" -+#include -+ -+/* The firmware delivers a vblank interrupt to us through the SMI -+ * hardware, which has only this one register. -+ */ -+#define SMICS 0x0 -+#define SMICS_INTERRUPTS (BIT(9) | BIT(10) | BIT(11)) -+ -+struct vc4_crtc { -+ struct drm_crtc base; -+ struct drm_encoder *encoder; -+ struct drm_connector *connector; -+ void __iomem *regs; -+ -+ struct drm_pending_vblank_event *event; -+}; -+ -+static inline struct vc4_crtc *to_vc4_crtc(struct drm_crtc *crtc) -+{ -+ return container_of(crtc, struct vc4_crtc, base); -+} -+ -+struct vc4_fkms_encoder { -+ struct drm_encoder base; -+}; -+ -+static inline struct vc4_fkms_encoder * -+to_vc4_fkms_encoder(struct drm_encoder *encoder) -+{ -+ return container_of(encoder, struct vc4_fkms_encoder, base); -+} -+ -+/* VC4 FKMS connector KMS struct */ -+struct vc4_fkms_connector { -+ struct drm_connector base; -+ -+ /* Since the connector is attached to just the one encoder, -+ * this is the reference to it so we can do the best_encoder() -+ * hook. -+ */ -+ struct drm_encoder *encoder; -+}; -+ -+static inline struct vc4_fkms_connector * -+to_vc4_fkms_connector(struct drm_connector *connector) -+{ -+ return container_of(connector, struct vc4_fkms_connector, base); -+} -+ -+/* Firmware's structure for making an FB mbox call. */ -+struct fbinfo_s { -+ u32 xres, yres, xres_virtual, yres_virtual; -+ u32 pitch, bpp; -+ u32 xoffset, yoffset; -+ u32 base; -+ u32 screen_size; -+ u16 cmap[256]; -+}; -+ -+struct vc4_fkms_plane { -+ struct drm_plane base; -+ struct fbinfo_s *fbinfo; -+ dma_addr_t fbinfo_bus_addr; -+ u32 pitch; -+}; -+ -+static inline struct vc4_fkms_plane *to_vc4_fkms_plane(struct drm_plane *plane) -+{ -+ return (struct vc4_fkms_plane *)plane; -+} -+ -+/* Turns the display on/off. */ -+static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ -+ u32 packet = blank; -+ return rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_BLANK, -+ &packet, sizeof(packet)); -+} -+ -+static void vc4_primary_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct vc4_fkms_plane *vc4_plane = to_vc4_fkms_plane(plane); -+ struct drm_plane_state *state = plane->state; -+ struct drm_framebuffer *fb = state->fb; -+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -+ volatile struct fbinfo_s *fbinfo = vc4_plane->fbinfo; -+ u32 bpp = 32; -+ int ret; -+ -+ vc4_plane_set_primary_blank(plane, false); -+ -+ fbinfo->xres = state->crtc_w; -+ fbinfo->yres = state->crtc_h; -+ fbinfo->xres_virtual = state->crtc_w; -+ fbinfo->yres_virtual = state->crtc_h; -+ fbinfo->bpp = bpp; -+ fbinfo->xoffset = state->crtc_x; -+ fbinfo->yoffset = state->crtc_y; -+ fbinfo->base = bo->paddr + fb->offsets[0]; -+ fbinfo->pitch = fb->pitches[0]; -+ /* A bug in the firmware makes it so that if the fb->base is -+ * set to nonzero, the configured pitch gets overwritten with -+ * the previous pitch. So, to get the configured pitch -+ * recomputed, we have to make it allocate itself a new buffer -+ * in VC memory, first. -+ */ -+ if (vc4_plane->pitch != fb->pitches[0]) { -+ u32 saved_base = fbinfo->base; -+ fbinfo->base = 0; -+ -+ ret = rpi_firmware_transaction(vc4->firmware, -+ RPI_FIRMWARE_CHAN_FB, -+ vc4_plane->fbinfo_bus_addr); -+ fbinfo->base = saved_base; -+ -+ vc4_plane->pitch = fbinfo->pitch; -+ WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); -+ } -+ -+ ret = rpi_firmware_transaction(vc4->firmware, -+ RPI_FIRMWARE_CHAN_FB, -+ vc4_plane->fbinfo_bus_addr); -+ WARN_ON_ONCE(fbinfo->pitch != fb->pitches[0]); -+ WARN_ON_ONCE(fbinfo->base != bo->paddr + fb->offsets[0]); -+} -+ -+static void vc4_primary_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ vc4_plane_set_primary_blank(plane, true); -+} -+ -+static void vc4_cursor_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ struct drm_plane_state *state = plane->state; -+ struct drm_framebuffer *fb = state->fb; -+ struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); -+ int ret; -+ u32 packet_state[] = { true, state->crtc_x, state->crtc_y, 0 }; -+ u32 packet_info[] = { state->crtc_w, state->crtc_h, -+ 0, /* unused */ -+ bo->paddr + fb->offsets[0], -+ 0, 0, /* hotx, hoty */}; -+ WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); -+ WARN_ON_ONCE(fb->bits_per_pixel != 32); -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_STATE, -+ &packet_state, -+ sizeof(packet_state)); -+ if (ret || packet_state[0] != 0) -+ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_INFO, -+ &packet_info, -+ sizeof(packet_info)); -+ if (ret || packet_info[0] != 0) -+ DRM_ERROR("Failed to set cursor info: 0x%08x\n", packet_info[0]); -+} -+ -+static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane, -+ struct drm_plane_state *old_state) -+{ -+ struct vc4_dev *vc4 = to_vc4_dev(plane->dev); -+ u32 packet_state[] = { false, 0, 0, 0 }; -+ int ret; -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_SET_CURSOR_STATE, -+ &packet_state, -+ sizeof(packet_state)); -+ if (ret || packet_state[0] != 0) -+ DRM_ERROR("Failed to set cursor state: 0x%08x\n", packet_state[0]); -+} -+ -+static int vc4_plane_atomic_check(struct drm_plane *plane, -+ struct drm_plane_state *state) -+{ -+ return 0; -+} -+ -+static void vc4_plane_destroy(struct drm_plane *plane) -+{ -+ drm_plane_helper_disable(plane); -+ drm_plane_cleanup(plane); -+} -+ -+static const struct drm_plane_funcs vc4_plane_funcs = { -+ .update_plane = drm_atomic_helper_update_plane, -+ .disable_plane = drm_atomic_helper_disable_plane, -+ .destroy = vc4_plane_destroy, -+ .set_property = NULL, -+ .reset = drm_atomic_helper_plane_reset, -+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, -+}; -+ -+static const struct drm_plane_helper_funcs vc4_primary_plane_helper_funcs = { -+ .prepare_fb = NULL, -+ .cleanup_fb = NULL, -+ .atomic_check = vc4_plane_atomic_check, -+ .atomic_update = vc4_primary_plane_atomic_update, -+ .atomic_disable = vc4_primary_plane_atomic_disable, -+}; -+ -+static const struct drm_plane_helper_funcs vc4_cursor_plane_helper_funcs = { -+ .prepare_fb = NULL, -+ .cleanup_fb = NULL, -+ .atomic_check = vc4_plane_atomic_check, -+ .atomic_update = vc4_cursor_plane_atomic_update, -+ .atomic_disable = vc4_cursor_plane_atomic_disable, -+}; -+ -+static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, -+ enum drm_plane_type type) -+{ -+ struct drm_plane *plane = NULL; -+ struct vc4_fkms_plane *vc4_plane; -+ u32 xrgb8888 = DRM_FORMAT_XRGB8888; -+ u32 argb8888 = DRM_FORMAT_ARGB8888; -+ int ret = 0; -+ bool primary = (type == DRM_PLANE_TYPE_PRIMARY); -+ -+ vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane), -+ GFP_KERNEL); -+ if (!vc4_plane) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ -+ plane = &vc4_plane->base; -+ ret = drm_universal_plane_init(dev, plane, 0xff, -+ &vc4_plane_funcs, -+ primary ? &xrgb8888 : &argb8888, 1, -+ type, NULL); -+ -+ if (type == DRM_PLANE_TYPE_PRIMARY) { -+ vc4_plane->fbinfo = -+ dma_alloc_coherent(dev->dev, -+ sizeof(*vc4_plane->fbinfo), -+ &vc4_plane->fbinfo_bus_addr, -+ GFP_KERNEL); -+ memset(vc4_plane->fbinfo, 0, sizeof(*vc4_plane->fbinfo)); -+ -+ drm_plane_helper_add(plane, &vc4_primary_plane_helper_funcs); -+ } else { -+ drm_plane_helper_add(plane, &vc4_cursor_plane_helper_funcs); -+ } -+ -+ return plane; -+fail: -+ if (plane) -+ vc4_plane_destroy(plane); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) -+{ -+ /* Everyting is handled in the planes. */ -+} -+ -+static void vc4_crtc_disable(struct drm_crtc *crtc) -+{ -+} -+ -+static void vc4_crtc_enable(struct drm_crtc *crtc) -+{ -+} -+ -+static int vc4_crtc_atomic_check(struct drm_crtc *crtc, -+ struct drm_crtc_state *state) -+{ -+ return 0; -+} -+ -+static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, -+ struct drm_crtc_state *old_state) -+{ -+} -+ -+static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) -+{ -+ struct drm_crtc *crtc = &vc4_crtc->base; -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ if (vc4_crtc->event) { -+ drm_crtc_send_vblank_event(crtc, vc4_crtc->event); -+ vc4_crtc->event = NULL; -+ drm_crtc_vblank_put(crtc); -+ } -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static irqreturn_t vc4_crtc_irq_handler(int irq, void *data) -+{ -+ struct vc4_crtc *vc4_crtc = data; -+ u32 stat = readl(vc4_crtc->regs + SMICS); -+ irqreturn_t ret = IRQ_NONE; -+ -+ if (stat & SMICS_INTERRUPTS) { -+ writel(0, vc4_crtc->regs + SMICS); -+ drm_crtc_handle_vblank(&vc4_crtc->base); -+ vc4_crtc_handle_page_flip(vc4_crtc); -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+static int vc4_page_flip(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, -+ struct drm_pending_vblank_event *event, -+ uint32_t flags) -+{ -+ if (flags & DRM_MODE_PAGE_FLIP_ASYNC) { -+ DRM_ERROR("Async flips aren't allowed\n"); -+ return -EINVAL; -+ } -+ -+ return drm_atomic_helper_page_flip(crtc, fb, event, flags); -+} -+ -+static const struct drm_crtc_funcs vc4_crtc_funcs = { -+ .set_config = drm_atomic_helper_set_config, -+ .destroy = drm_crtc_cleanup, -+ .page_flip = vc4_page_flip, -+ .set_property = NULL, -+ .cursor_set = NULL, /* handled by drm_mode_cursor_universal */ -+ .cursor_move = NULL, /* handled by drm_mode_cursor_universal */ -+ .reset = drm_atomic_helper_crtc_reset, -+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, -+}; -+ -+static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = { -+ .mode_set_nofb = vc4_crtc_mode_set_nofb, -+ .disable = vc4_crtc_disable, -+ .enable = vc4_crtc_enable, -+ .atomic_check = vc4_crtc_atomic_check, -+ .atomic_flush = vc4_crtc_atomic_flush, -+}; -+ -+/* Frees the page flip event when the DRM device is closed with the -+ * event still outstanding. -+ */ -+void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -+{ -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ -+ if (vc4_crtc->event && vc4_crtc->event->base.file_priv == file) { -+ kfree(&vc4_crtc->event->base); -+ drm_crtc_vblank_put(crtc); -+ vc4_crtc->event = NULL; -+ } -+ -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+} -+ -+static const struct of_device_id vc4_firmware_kms_dt_match[] = { -+ { .compatible = "raspberrypi,rpi-firmware-kms" }, -+ {} -+}; -+ -+static enum drm_connector_status -+vc4_fkms_connector_detect(struct drm_connector *connector, bool force) -+{ -+ return connector_status_connected; -+} -+ -+static int vc4_fkms_connector_get_modes(struct drm_connector *connector) -+{ -+ struct drm_device *dev = connector->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(dev); -+ u32 wh[2] = {0, 0}; -+ int ret; -+ struct drm_display_mode *mode; -+ -+ ret = rpi_firmware_property(vc4->firmware, -+ RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT, -+ &wh, sizeof(wh)); -+ if (ret) { -+ DRM_ERROR("Failed to get screen size: %d (0x%08x 0x%08x)\n", -+ ret, wh[0], wh[1]); -+ return 0; -+ } -+ -+ mode = drm_cvt_mode(dev, wh[0], wh[1], 60 /* vrefresh */, -+ 0, 0, false); -+ drm_mode_probed_add(connector, mode); -+ -+ return 1; -+} -+ -+static struct drm_encoder * -+vc4_fkms_connector_best_encoder(struct drm_connector *connector) -+{ -+ struct vc4_fkms_connector *fkms_connector = -+ to_vc4_fkms_connector(connector); -+ return fkms_connector->encoder; -+} -+ -+static void vc4_fkms_connector_destroy(struct drm_connector *connector) -+{ -+ drm_connector_unregister(connector); -+ drm_connector_cleanup(connector); -+} -+ -+static const struct drm_connector_funcs vc4_fkms_connector_funcs = { -+ .dpms = drm_atomic_helper_connector_dpms, -+ .detect = vc4_fkms_connector_detect, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .destroy = vc4_fkms_connector_destroy, -+ .reset = drm_atomic_helper_connector_reset, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static const struct drm_connector_helper_funcs vc4_fkms_connector_helper_funcs = { -+ .get_modes = vc4_fkms_connector_get_modes, -+ .best_encoder = vc4_fkms_connector_best_encoder, -+}; -+ -+static struct drm_connector *vc4_fkms_connector_init(struct drm_device *dev, -+ struct drm_encoder *encoder) -+{ -+ struct drm_connector *connector = NULL; -+ struct vc4_fkms_connector *fkms_connector; -+ int ret = 0; -+ -+ fkms_connector = devm_kzalloc(dev->dev, sizeof(*fkms_connector), -+ GFP_KERNEL); -+ if (!fkms_connector) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ connector = &fkms_connector->base; -+ -+ fkms_connector->encoder = encoder; -+ -+ drm_connector_init(dev, connector, &vc4_fkms_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA); -+ drm_connector_helper_add(connector, &vc4_fkms_connector_helper_funcs); -+ -+ connector->polled = (DRM_CONNECTOR_POLL_CONNECT | -+ DRM_CONNECTOR_POLL_DISCONNECT); -+ -+ connector->interlace_allowed = 0; -+ connector->doublescan_allowed = 0; -+ -+ drm_mode_connector_attach_encoder(connector, encoder); -+ -+ return connector; -+ -+ fail: -+ if (connector) -+ vc4_fkms_connector_destroy(connector); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_fkms_encoder_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+} -+ -+static const struct drm_encoder_funcs vc4_fkms_encoder_funcs = { -+ .destroy = vc4_fkms_encoder_destroy, -+}; -+ -+static void vc4_fkms_encoder_enable(struct drm_encoder *encoder) -+{ -+} -+ -+static void vc4_fkms_encoder_disable(struct drm_encoder *encoder) -+{ -+} -+ -+static const struct drm_encoder_helper_funcs vc4_fkms_encoder_helper_funcs = { -+ .enable = vc4_fkms_encoder_enable, -+ .disable = vc4_fkms_encoder_disable, -+}; -+ -+static int vc4_fkms_bind(struct device *dev, struct device *master, void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct drm_device *drm = dev_get_drvdata(master); -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct vc4_crtc *vc4_crtc; -+ struct vc4_fkms_encoder *vc4_encoder; -+ struct drm_crtc *crtc; -+ struct drm_plane *primary_plane, *cursor_plane, *destroy_plane, *temp; -+ struct device_node *firmware_node; -+ int ret; -+ -+ vc4->firmware_kms = true; -+ -+ vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL); -+ if (!vc4_crtc) -+ return -ENOMEM; -+ crtc = &vc4_crtc->base; -+ -+ firmware_node = of_parse_phandle(dev->of_node, "brcm,firmware", 0); -+ vc4->firmware = rpi_firmware_get(firmware_node); -+ if (!vc4->firmware) { -+ DRM_DEBUG("Failed to get Raspberry Pi firmware reference.\n"); -+ return -EPROBE_DEFER; -+ } -+ of_node_put(firmware_node); -+ -+ /* Map the SMI interrupt reg */ -+ vc4_crtc->regs = vc4_ioremap_regs(pdev, 0); -+ if (IS_ERR(vc4_crtc->regs)) -+ return PTR_ERR(vc4_crtc->regs); -+ -+ /* For now, we create just the primary and the legacy cursor -+ * planes. We should be able to stack more planes on easily, -+ * but to do that we would need to compute the bandwidth -+ * requirement of the plane configuration, and reject ones -+ * that will take too much. -+ */ -+ primary_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_PRIMARY); -+ if (IS_ERR(primary_plane)) { -+ dev_err(dev, "failed to construct primary plane\n"); -+ ret = PTR_ERR(primary_plane); -+ goto err; -+ } -+ -+ cursor_plane = vc4_fkms_plane_init(drm, DRM_PLANE_TYPE_CURSOR); -+ if (IS_ERR(cursor_plane)) { -+ dev_err(dev, "failed to construct cursor plane\n"); -+ ret = PTR_ERR(cursor_plane); -+ goto err; -+ } -+ -+ drm_crtc_init_with_planes(drm, crtc, primary_plane, cursor_plane, -+ &vc4_crtc_funcs, NULL); -+ drm_crtc_helper_add(crtc, &vc4_crtc_helper_funcs); -+ primary_plane->crtc = crtc; -+ cursor_plane->crtc = crtc; -+ vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc; -+ -+ vc4_encoder = devm_kzalloc(dev, sizeof(*vc4_encoder), GFP_KERNEL); -+ if (!vc4_encoder) -+ return -ENOMEM; -+ vc4_crtc->encoder = &vc4_encoder->base; -+ vc4_encoder->base.possible_crtcs |= drm_crtc_mask(crtc) ; -+ drm_encoder_init(drm, &vc4_encoder->base, &vc4_fkms_encoder_funcs, -+ DRM_MODE_ENCODER_TMDS, NULL); -+ drm_encoder_helper_add(&vc4_encoder->base, -+ &vc4_fkms_encoder_helper_funcs); -+ -+ vc4_crtc->connector = vc4_fkms_connector_init(drm, &vc4_encoder->base); -+ if (IS_ERR(vc4_crtc->connector)) { -+ ret = PTR_ERR(vc4_crtc->connector); -+ goto err_destroy_encoder; -+ } -+ -+ writel(0, vc4_crtc->regs + SMICS); -+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), -+ vc4_crtc_irq_handler, 0, "vc4 firmware kms", -+ vc4_crtc); -+ if (ret) -+ goto err_destroy_connector; -+ -+ platform_set_drvdata(pdev, vc4_crtc); -+ -+ return 0; -+ -+err_destroy_connector: -+ vc4_fkms_connector_destroy(vc4_crtc->connector); -+err_destroy_encoder: -+ vc4_fkms_encoder_destroy(vc4_crtc->encoder); -+ list_for_each_entry_safe(destroy_plane, temp, -+ &drm->mode_config.plane_list, head) { -+ if (destroy_plane->possible_crtcs == 1 << drm_crtc_index(crtc)) -+ destroy_plane->funcs->destroy(destroy_plane); -+ } -+err: -+ return ret; -+} -+ -+static void vc4_fkms_unbind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev); -+ -+ vc4_fkms_connector_destroy(vc4_crtc->connector); -+ vc4_fkms_encoder_destroy(vc4_crtc->encoder); -+ drm_crtc_cleanup(&vc4_crtc->base); -+ -+ platform_set_drvdata(pdev, NULL); -+} -+ -+static const struct component_ops vc4_fkms_ops = { -+ .bind = vc4_fkms_bind, -+ .unbind = vc4_fkms_unbind, -+}; -+ -+static int vc4_fkms_probe(struct platform_device *pdev) -+{ -+ return component_add(&pdev->dev, &vc4_fkms_ops); -+} -+ -+static int vc4_fkms_remove(struct platform_device *pdev) -+{ -+ component_del(&pdev->dev, &vc4_fkms_ops); -+ return 0; -+} -+ -+struct platform_driver vc4_firmware_kms_driver = { -+ .probe = vc4_fkms_probe, -+ .remove = vc4_fkms_remove, -+ .driver = { -+ .name = "vc4_firmware_kms", -+ .of_match_table = vc4_firmware_kms_dt_match, -+ }, -+}; - -From 95b521739164da064b622f7b1f986987443708fd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= -Date: Tue, 1 Nov 2016 15:15:41 +0100 -Subject: [PATCH 096/216] i2c: bcm2835: Add debug support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This adds a debug module parameter to aid in debugging transfer issues -by printing info to the kernel log. When enabled, status values are -collected in the interrupt routine and msg info in -bcm2835_i2c_start_transfer(). This is done in a way that tries to avoid -affecting timing. Having printk in the isr can mask issues. - -debug values (additive): -1: Print info on error -2: Print info on all transfers -3: Print messages before transfer is started - -The value can be changed at runtime: -/sys/module/i2c_bcm2835/parameters/debug - -Example output, debug=3: -[ 747.114448] bcm2835_i2c_xfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.114463] bcm2835_i2c_xfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117809] start_transfer: msg(1/2) write addr=0x54, len=2 flags= [i2c1] -[ 747.117825] isr: remain=2, status=0x30000055 : TA TXW TXD TXE [i2c1] -[ 747.117839] start_transfer: msg(2/2) read addr=0x54, len=32 flags= [i2c1] -[ 747.117849] isr: remain=32, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117861] isr: remain=20, status=0xd0000039 : TA RXR TXD RXD [i2c1] -[ 747.117870] isr: remain=8, status=0x32 : DONE TXD RXD [i2c1] - -Signed-off-by: Noralf Trønnes ---- - drivers/i2c/busses/i2c-bcm2835.c | 99 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 98 insertions(+), 1 deletion(-) - -diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c -index cd07a69e2e9355540442785f95e90823b05c9d10..47167f403cc8329bd811b47c7011c299b8ecafee 100644 ---- a/drivers/i2c/busses/i2c-bcm2835.c -+++ b/drivers/i2c/busses/i2c-bcm2835.c -@@ -53,6 +53,18 @@ - #define BCM2835_I2C_CDIV_MIN 0x0002 - #define BCM2835_I2C_CDIV_MAX 0xFFFE - -+static unsigned int debug; -+module_param(debug, uint, 0644); -+MODULE_PARM_DESC(debug, "1=err, 2=isr, 3=xfer"); -+ -+#define BCM2835_DEBUG_MAX 512 -+struct bcm2835_debug { -+ struct i2c_msg *msg; -+ int msg_idx; -+ size_t remain; -+ u32 status; -+}; -+ - struct bcm2835_i2c_dev { - struct device *dev; - void __iomem *regs; -@@ -66,8 +78,78 @@ struct bcm2835_i2c_dev { - u32 msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; -+ struct bcm2835_debug debug[BCM2835_DEBUG_MAX]; -+ unsigned int debug_num; -+ unsigned int debug_num_msgs; - }; - -+static inline void bcm2835_debug_add(struct bcm2835_i2c_dev *i2c_dev, u32 s) -+{ -+ if (!i2c_dev->debug_num_msgs || i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ return; -+ -+ i2c_dev->debug[i2c_dev->debug_num].msg = i2c_dev->curr_msg; -+ i2c_dev->debug[i2c_dev->debug_num].msg_idx = -+ i2c_dev->debug_num_msgs - i2c_dev->num_msgs; -+ i2c_dev->debug[i2c_dev->debug_num].remain = i2c_dev->msg_buf_remaining; -+ i2c_dev->debug[i2c_dev->debug_num].status = s; -+ i2c_dev->debug_num++; -+} -+ -+static void bcm2835_debug_print_status(struct bcm2835_i2c_dev *i2c_dev, -+ struct bcm2835_debug *d) -+{ -+ u32 s = d->status; -+ -+ pr_info("isr: remain=%zu, status=0x%x : %s%s%s%s%s%s%s%s%s%s [i2c%d]\n", -+ d->remain, s, -+ s & BCM2835_I2C_S_TA ? "TA " : "", -+ s & BCM2835_I2C_S_DONE ? "DONE " : "", -+ s & BCM2835_I2C_S_TXW ? "TXW " : "", -+ s & BCM2835_I2C_S_RXR ? "RXR " : "", -+ s & BCM2835_I2C_S_TXD ? "TXD " : "", -+ s & BCM2835_I2C_S_RXD ? "RXD " : "", -+ s & BCM2835_I2C_S_TXE ? "TXE " : "", -+ s & BCM2835_I2C_S_RXF ? "RXF " : "", -+ s & BCM2835_I2C_S_ERR ? "ERR " : "", -+ s & BCM2835_I2C_S_CLKT ? "CLKT " : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print_msg(struct bcm2835_i2c_dev *i2c_dev, -+ struct i2c_msg *msg, int i, int total, -+ const char *fname) -+{ -+ pr_info("%s: msg(%d/%d) %s addr=0x%02x, len=%u flags=%s%s%s%s%s%s%s [i2c%d]\n", -+ fname, i, total, -+ msg->flags & I2C_M_RD ? "read" : "write", msg->addr, msg->len, -+ msg->flags & I2C_M_TEN ? "TEN" : "", -+ msg->flags & I2C_M_RECV_LEN ? "RECV_LEN" : "", -+ msg->flags & I2C_M_NO_RD_ACK ? "NO_RD_ACK" : "", -+ msg->flags & I2C_M_IGNORE_NAK ? "IGNORE_NAK" : "", -+ msg->flags & I2C_M_REV_DIR_ADDR ? "REV_DIR_ADDR" : "", -+ msg->flags & I2C_M_NOSTART ? "NOSTART" : "", -+ msg->flags & I2C_M_STOP ? "STOP" : "", -+ i2c_dev->adapter.nr); -+} -+ -+static void bcm2835_debug_print(struct bcm2835_i2c_dev *i2c_dev) -+{ -+ struct bcm2835_debug *d; -+ unsigned int i; -+ -+ for (i = 0; i < i2c_dev->debug_num; i++) { -+ d = &i2c_dev->debug[i]; -+ if (d->status == ~0) -+ bcm2835_debug_print_msg(i2c_dev, d->msg, d->msg_idx, -+ i2c_dev->debug_num_msgs, "start_transfer"); -+ else -+ bcm2835_debug_print_status(i2c_dev, d); -+ } -+ if (i2c_dev->debug_num >= BCM2835_DEBUG_MAX) -+ pr_info("BCM2835_DEBUG_MAX reached\n"); -+} -+ - static inline void bcm2835_i2c_writel(struct bcm2835_i2c_dev *i2c_dev, - u32 reg, u32 val) - { -@@ -170,6 +252,7 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev) - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len); - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c); -+ bcm2835_debug_add(i2c_dev, ~0); - } - - /* -@@ -187,6 +270,7 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data) - u32 val, err; - - val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S); -+ bcm2835_debug_add(i2c_dev, val); - - err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR); - if (err) { -@@ -253,6 +337,13 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - unsigned long time_left; - int i, ret; - -+ if (debug) -+ i2c_dev->debug_num_msgs = num; -+ -+ if (debug > 2) -+ for (i = 0; i < num; i++) -+ bcm2835_debug_print_msg(i2c_dev, &msgs[i], i + 1, num, __func__); -+ - for (i = 0; i < (num - 1); i++) - if (msgs[i].flags & I2C_M_RD) { - dev_warn_once(i2c_dev->dev, -@@ -272,6 +363,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - - time_left = wait_for_completion_timeout(&i2c_dev->completion, - adap->timeout); -+ if (debug > 1 || (debug && (!time_left || i2c_dev->msg_err))) -+ bcm2835_debug_print(i2c_dev); -+ i2c_dev->debug_num_msgs = 0; -+ i2c_dev->debug_num = 0; - if (!time_left) { - bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, - BCM2835_I2C_C_CLEAR); -@@ -282,7 +377,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - if (!i2c_dev->msg_err) - return num; - -- dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err); -+ if (debug) -+ dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", -+ i2c_dev->msg_err); - - if (i2c_dev->msg_err & BCM2835_I2C_S_ERR) - return -EREMOTEIO; - -From e459088a835db05b5a00367d5571a44ab77a5142 Mon Sep 17 00:00:00 2001 +From 4f19018f654367defc2dee4e39dd594937710091 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 14 Sep 2016 09:16:19 +0100 -Subject: [PATCH 097/216] raspberrypi-firmware: Export the general transaction +Subject: [PATCH 100/150] raspberrypi-firmware: Export the general transaction function. The vc4-firmware-kms module is going to be doing the MBOX FB call. @@ -124239,10 +111469,10 @@ index 3f070bd38a91511c986e3fb114b15bd4ac32634c..f261b64d1657c02290904d841e1f087c /** * rpi_firmware_property_list - Submit firmware property list diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 7f0da0727422c690947e46e891a754de13dc1fea..280791fb9656901392ce67e44cb742c96f090ed4 100644 +index de2a3dcd562beb752266eaf0070e55861d553f5f..dc7fd58afd5dddebf9b17065bb069a1db663362c 100644 --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -152,5 +152,6 @@ static inline struct rpi_firmware *rpi_firmware_get(struct device_node *firmware +@@ -156,5 +156,6 @@ static inline struct rpi_firmware *rpi_firmware_get(struct device_node *firmware return NULL; } #endif @@ -124250,519 +111480,10 @@ index 7f0da0727422c690947e46e891a754de13dc1fea..280791fb9656901392ce67e44cb742c9 #endif /* __SOC_RASPBERRY_FIRMWARE_H__ */ -From ec248d8eb97649b30758f02855d0fd87fe46f831 Mon Sep 17 00:00:00 2001 -From: Alex Tucker -Date: Tue, 13 Dec 2016 19:50:18 +0000 -Subject: [PATCH 098/216] Add support for Silicon Labs Si7013/20/21 - humidity/temperature sensor. - ---- - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 49 +++++++++++++---------- - 1 file changed, 28 insertions(+), 21 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -index f6d134c095af2398fc55ae7d2b0e86456c30627c..31bda8da4cb6a56bfe493a81b918900995fb0589 100644 ---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -1,34 +1,41 @@ --// Definitions for a few digital barometric pressure and temperature sensors -+// Definitions for I2C based sensors using the Industrial IO interface. - /dts-v1/; - /plugin/; - - / { -- compatible = "brcm,bcm2708"; -+ compatible = "brcm,bcm2708"; - -- fragment@0 { -- target = <&i2c_arm>; -- __overlay__ { -- #address-cells = <1>; -- #size-cells = <0>; -- status = "okay"; -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; - -- bmp085: bmp085@77 { -- compatible = "bosch,bmp085"; -- reg = <0x77>; -- default-oversampling = <3>; -- status = "disable"; -- }; -+ bmp085: bmp085@77 { -+ compatible = "bosch,bmp085"; -+ reg = <0x77>; -+ default-oversampling = <3>; -+ status = "disable"; -+ }; - -- bmp280: bmp280@76 { -- compatible = "bosch,bmp280"; -- reg = <0x76>; -- status = "disable"; -- }; -- }; -- }; -+ bmp280: bmp280@76 { -+ compatible = "bosch,bmp280"; -+ reg = <0x76>; -+ status = "disable"; -+ }; -+ -+ si7020: si7020@40 { -+ compatible = "si7020"; -+ reg = <0x40>; -+ status = "disable"; -+ }; -+ }; -+ }; - - __overrides__ { - bmp085 = <&bmp085>,"status"; - bmp280 = <&bmp280>,"status"; -+ si7020 = <&si7020>,"status"; - }; - }; - -From 375f67f7fefc9130989d17e63d555674902190ef Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 3 Jan 2017 21:27:46 +0000 -Subject: [PATCH 099/216] Document the si7020 option - ---- - arch/arm/boot/dts/overlays/README | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 81d991803be335e5a1bc3bb0a8c7a2c9f5c392bd..e8fa4ccb44c34a20485c4e6155467af99179153a 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -549,6 +549,9 @@ Params: bmp085 Select the Bosch sensortronic BMP085 - - bmp280 Select the Bosch sensortronic BMP280 - -+ si7020 Select the Silicon Labs Si7013/20/21 humidity/ -+ temperature sensor -+ - - Name: i2c0-bcm2708 - Info: Enable the i2c_bcm2708 driver for the i2c0 bus. Not all pin combinations - -From 2e9015ca8a1e347ba9e411aa262da85e5f81cc75 Mon Sep 17 00:00:00 2001 -From: Giedrius Trainavicius -Date: Thu, 5 Jan 2017 02:38:16 +0200 -Subject: [PATCH 100/216] pisound improvements: - -* Added a writable sysfs object to enable scripts / user space software -to blink MIDI activity LEDs for variable duration. -* Improved hw_param constraints setting. -* Added compatibility with S16_LE sample format. -* Exposed some simple placeholder volume controls, so the card appears -in volumealsa widget. - -Signed-off-by: Giedrius Trainavicius ---- - sound/soc/bcm/pisound.c | 175 ++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 154 insertions(+), 21 deletions(-) - -diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c -index 4b8545487d06e4ea70073a5d063fb2310b3b94d0..ba70734b89e61a11201657406223f0b37d54f74a 100644 ---- a/sound/soc/bcm/pisound.c -+++ b/sound/soc/bcm/pisound.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - static int pisnd_spi_init(struct device *dev); - static void pisnd_spi_uninit(void); -@@ -214,6 +215,9 @@ static char g_serial_num[11]; - static char g_id[25]; - static char g_version[5]; - -+static uint8_t g_ledFlashDuration; -+static bool g_ledFlashDurationChanged; -+ - DEFINE_KFIFO(spi_fifo_in, uint8_t, FIFO_SIZE); - DEFINE_KFIFO(spi_fifo_out, uint8_t, FIFO_SIZE); - -@@ -396,8 +400,13 @@ static void pisnd_work_handler(struct work_struct *work) - val = 0; - tx = 0; - -- if (kfifo_get(&spi_fifo_out, &val)) -+ if (g_ledFlashDurationChanged) { -+ tx = 0xf000 | g_ledFlashDuration; -+ g_ledFlashDuration = 0; -+ g_ledFlashDurationChanged = false; -+ } else if (kfifo_get(&spi_fifo_out, &val)) { - tx = 0x0f00 | val; -+ } - - rx = spi_transfer16(tx); - -@@ -410,6 +419,7 @@ static void pisnd_work_handler(struct work_struct *work) - } while (rx != 0 - || !kfifo_is_empty(&spi_fifo_out) - || pisnd_spi_has_more() -+ || g_ledFlashDurationChanged - ); - - if (!kfifo_is_empty(&spi_fifo_in) && g_recvCallback) -@@ -569,7 +579,7 @@ static int pisnd_spi_init(struct device *dev) - } - - /* Flash the LEDs. */ -- spi_transfer16(0xf000); -+ spi_transfer16(0xf008); - - ret = pisnd_spi_gpio_irq_init(dev); - if (ret < 0) { -@@ -610,6 +620,14 @@ static void pisnd_spi_uninit(void) - pisnd_spi_gpio_uninit(); - } - -+static void pisnd_spi_flash_leds(uint8_t duration) -+{ -+ g_ledFlashDuration = duration; -+ g_ledFlashDurationChanged = true; -+ printd("schedule from spi_flash_leds\n"); -+ pisnd_schedule_process(TASK_PROCESS); -+} -+ - static void pisnd_spi_send(uint8_t val) - { - kfifo_put(&spi_fifo_out, val); -@@ -658,6 +676,83 @@ static const struct of_device_id pisound_of_match[] = { - {}, - }; - -+enum { -+ SWITCH = 0, -+ VOLUME = 1, -+}; -+ -+static int pisnd_ctl_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ if (kcontrol->private_value == SWITCH) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 1; -+ return 0; -+ } else if (kcontrol->private_value == VOLUME) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 100; -+ return 0; -+ } -+ return -EINVAL; -+} -+ -+static int pisnd_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ if (kcontrol->private_value == SWITCH) { -+ ucontrol->value.integer.value[0] = 1; -+ return 0; -+ } else if (kcontrol->private_value == VOLUME) { -+ ucontrol->value.integer.value[0] = 100; -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static struct snd_kcontrol_new pisnd_ctl[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Switch", -+ .index = 0, -+ .private_value = SWITCH, -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .info = pisnd_ctl_info, -+ .get = pisnd_ctl_get, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Volume", -+ .index = 0, -+ .private_value = VOLUME, -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .info = pisnd_ctl_info, -+ .get = pisnd_ctl_get, -+ }, -+}; -+ -+static int pisnd_ctl_init(struct snd_card *card) -+{ -+ int err, i; -+ -+ for (i = 0; i < ARRAY_SIZE(pisnd_ctl); ++i) { -+ err = snd_ctl_add(card, snd_ctl_new1(&pisnd_ctl[i], NULL)); -+ if (err < 0) -+ return err; -+ } -+ -+ return 0; -+} -+ -+static int pisnd_ctl_uninit(void) -+{ -+ return 0; -+} -+ - static struct gpio_desc *osr0, *osr1, *osr2; - static struct gpio_desc *reset; - static struct gpio_desc *button; -@@ -667,6 +762,14 @@ static int pisnd_hw_params( - struct snd_pcm_hw_params *params - ) - { -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; -+ -+ /* pisound runs on fixed 32 clock counts per channel, -+ * as generated by the master ADC. -+ */ -+ snd_soc_dai_set_bclk_ratio(cpu_dai, 32*2); -+ - printd("rate = %d\n", params_rate(params)); - printd("ch = %d\n", params_channels(params)); - printd("bits = %u\n", -@@ -711,16 +814,6 @@ static struct snd_pcm_hw_constraint_list constraints_rates = { - .mask = 0, - }; - --static unsigned int sample_bits[] = { -- 24, 32 --}; -- --static struct snd_pcm_hw_constraint_list constraints_sample_bits = { -- .count = ARRAY_SIZE(sample_bits), -- .list = sample_bits, -- .mask = 0, --}; -- - static int pisnd_startup(struct snd_pcm_substream *substream) - { - int err = snd_pcm_hw_constraint_list( -@@ -733,11 +826,21 @@ static int pisnd_startup(struct snd_pcm_substream *substream) - if (err < 0) - return err; - -- err = snd_pcm_hw_constraint_list( -+ err = snd_pcm_hw_constraint_single( - substream->runtime, -- 0, -- SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -- &constraints_sample_bits -+ SNDRV_PCM_HW_PARAM_CHANNELS, -+ 2 -+ ); -+ -+ if (err < 0) -+ return err; -+ -+ err = snd_pcm_hw_constraint_mask64( -+ substream->runtime, -+ SNDRV_PCM_HW_PARAM_FORMAT, -+ SNDRV_PCM_FMTBIT_S16_LE | -+ SNDRV_PCM_FMTBIT_S24_LE | -+ SNDRV_PCM_FMTBIT_S32_LE - ); - - if (err < 0) -@@ -771,14 +874,23 @@ static int pisnd_card_probe(struct snd_soc_card *card) - { - int err = pisnd_midi_init(card->snd_card); - -- if (err < 0) -+ if (err < 0) { - printe("pisnd_midi_init failed: %d\n", err); -+ return err; -+ } - -- return err; -+ err = pisnd_ctl_init(card->snd_card); -+ if (err < 0) { -+ printe("pisnd_ctl_init failed: %d\n", err); -+ return err; -+ } -+ -+ return 0; - } - - static int pisnd_card_remove(struct snd_soc_card *card) - { -+ pisnd_ctl_uninit(); - pisnd_midi_uninit(); - return 0; - } -@@ -870,17 +982,38 @@ static ssize_t pisnd_version_show( - return sprintf(buf, "%s\n", pisnd_spi_get_version()); - } - -+static ssize_t pisnd_led_store( -+ struct kobject *kobj, -+ struct kobj_attribute *attr, -+ const char *buf, -+ size_t length -+ ) -+{ -+ uint32_t timeout; -+ int err; -+ -+ err = kstrtou32(buf, 10, &timeout); -+ -+ if (err == 0 && timeout <= 255) -+ pisnd_spi_flash_leds(timeout); -+ -+ return length; -+} -+ - static struct kobj_attribute pisnd_serial_attribute = -- __ATTR(serial, 0644, pisnd_serial_show, NULL); -+ __ATTR(serial, 0444, pisnd_serial_show, NULL); - static struct kobj_attribute pisnd_id_attribute = -- __ATTR(id, 0644, pisnd_id_show, NULL); -+ __ATTR(id, 0444, pisnd_id_show, NULL); - static struct kobj_attribute pisnd_version_attribute = -- __ATTR(version, 0644, pisnd_version_show, NULL); -+ __ATTR(version, 0444, pisnd_version_show, NULL); -+static struct kobj_attribute pisnd_led_attribute = -+ __ATTR(led, 0644, NULL, pisnd_led_store); - - static struct attribute *attrs[] = { - &pisnd_serial_attribute.attr, - &pisnd_id_attribute.attr, - &pisnd_version_attribute.attr, -+ &pisnd_led_attribute.attr, - NULL - }; - - -From f891adaf1d99514bf065ee250823edec1a8caff6 Mon Sep 17 00:00:00 2001 -From: Aaron Shaw -Date: Tue, 10 Jan 2017 16:05:41 +0000 -Subject: [PATCH 101/216] Add driver_name property - -Add driver name property for use with 5.1 passthrough audio in LibreElec and other Kodi based OSs ---- - sound/soc/bcm/justboom-dac.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/justboom-dac.c b/sound/soc/bcm/justboom-dac.c -index 8fd50dbe681508a2cfe8fdde1c9fedbe9a507fa7..05a224ec712d06b8b7587ab6b8bb562d19956d47 100644 ---- a/sound/soc/bcm/justboom-dac.c -+++ b/sound/soc/bcm/justboom-dac.c -@@ -98,6 +98,7 @@ static struct snd_soc_dai_link snd_rpi_justboom_dac_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_justboom_dac = { - .name = "snd_rpi_justboom_dac", -+ .driver_name = "JustBoomDac", - .owner = THIS_MODULE, - .dai_link = snd_rpi_justboom_dac_dai, - .num_links = ARRAY_SIZE(snd_rpi_justboom_dac_dai), - -From 6a4d3109ac7b72aa60d90ff7532c2aa6eb275a83 Mon Sep 17 00:00:00 2001 -From: Aaron Shaw -Date: Tue, 10 Jan 2017 16:11:04 +0000 -Subject: [PATCH 102/216] Add driver_name paramater - -Add driver_name parameter for use with 5.1 passthrough audio in LibreElec and other Kodi OSs ---- - sound/soc/bcm/justboom-digi.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sound/soc/bcm/justboom-digi.c b/sound/soc/bcm/justboom-digi.c -index 91acb666380faa3c0deb2230f8a0f8bbec59417b..abfdc5c4dd5811e6847bddda4921abe33fa02812 100644 ---- a/sound/soc/bcm/justboom-digi.c -+++ b/sound/soc/bcm/justboom-digi.c -@@ -154,6 +154,7 @@ static struct snd_soc_dai_link snd_rpi_justboom_digi_dai[] = { - /* audio machine driver */ - static struct snd_soc_card snd_rpi_justboom_digi = { - .name = "snd_rpi_justboom_digi", -+ .driver_name = "JustBoomDigi", - .owner = THIS_MODULE, - .dai_link = snd_rpi_justboom_digi_dai, - .num_links = ARRAY_SIZE(snd_rpi_justboom_digi_dai), - -From afc6ad484f2e9ae36d75b0e71bf781b074d61ee5 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 11 Jan 2017 13:01:21 +0000 -Subject: [PATCH 103/216] BCM270X_DT: Add pi3-disable-wifi overlay - -pi3-disable-wifi is a minimal overlay to disable the onboard WiFi. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 ++++++ - arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts | 13 +++++++++++++ - 3 files changed, 20 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 11dba31712840a9e4b91acd4565c2d6266315273..f1191c1ded82490be5f793ab6483bc5af5891db2 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -51,6 +51,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mz61581.dtbo \ - pi3-act-led.dtbo \ - pi3-disable-bt.dtbo \ -+ pi3-disable-wifi.dtbo \ - pi3-miniuart-bt.dtbo \ - piscreen.dtbo \ - piscreen2r.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index e8fa4ccb44c34a20485c4e6155467af99179153a..34109c69416c1caf28910895320a2b9cd539588e 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -800,6 +800,12 @@ Load: dtoverlay=pi3-disable-bt - Params: - - -+Name: pi3-disable-wifi -+Info: Disable Pi3 onboard WiFi -+Load: dtoverlay=pi3-disable-wifi -+Params: -+ -+ - Name: pi3-miniuart-bt - Info: Switch Pi3 Bluetooth function to use the mini-UART (ttyS0) and restore - UART0/ttyAMA0 over GPIOs 14 & 15. Note that this may reduce the maximum -diff --git a/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..017199554bf2f4e381efcc7bb71e750c210343e0 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/pi3-disable-wifi-overlay.dts -@@ -0,0 +1,13 @@ -+/dts-v1/; -+/plugin/; -+ -+/{ -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&mmc>; -+ __overlay__ { -+ status = "disabled"; -+ }; -+ }; -+}; - -From b25f135c724a3191904ca0f8b9da029bea1ae16a Mon Sep 17 00:00:00 2001 +From 0d6908b0f4d26a9df9e5d2ea547f3249ac43941c Mon Sep 17 00:00:00 2001 From: Electron752 Date: Thu, 12 Jan 2017 07:07:08 -0800 -Subject: [PATCH 104/216] ARM64: Make it work again on 4.9 (#1790) +Subject: [PATCH 101/150] ARM64: Make it work again on 4.9 (#1790) * Invoke the dtc compiler with the same options used in arm mode. * ARM64 now uses the bcm2835 platform just like ARM32. @@ -124778,7 +111499,7 @@ Signed-off-by: Michael Zoran create mode 120000 arch/arm64/boot/dts/overlays diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms -index 5289515a5b3bdfc85b7b6f1153e55b8ee760e96c..715ef1256838ed4b14d21c9ee8885d10c64fb0fc 100644 +index f04bc208f878322d35b94afafe74a7caf7d93820..129cc5ae4091489c08eb751f3e1b85b6eaa2eb9c 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -1,27 +1,5 @@ @@ -124810,7 +111531,7 @@ index 5289515a5b3bdfc85b7b6f1153e55b8ee760e96c..715ef1256838ed4b14d21c9ee8885d10 bool "Allwinner sunxi 64-bit SoC Family" select GENERIC_IRQ_CHIP diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile -index 2152448c8cf5b22c573642d7ce45e85793f5fc9a..7aa03be73fda08d555a13323f483e9b95398f234 100644 +index db4e66ee2a455eb1ec7d49c1fcb1c6c0a7a3ad13..6b1bd6e89c472f8f048c5a87e194567addc7ccd6 100644 --- a/arch/arm64/boot/dts/broadcom/Makefile +++ b/arch/arm64/boot/dts/broadcom/Makefile @@ -1,7 +1,15 @@ @@ -124821,7 +111542,7 @@ index 2152448c8cf5b22c573642d7ce45e85793f5fc9a..7aa03be73fda08d555a13323f483e9b9 +endif + dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb - dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb + dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb ns2-xmc.dtb dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb -dtb-$(CONFIG_ARCH_BCM2709) += bcm2710-rpi-3-b.dtb +dtb-$(CONFIG_ARCH_BCM2835) += bcm2710-rpi-3-b.dtb @@ -125166,138 +111887,10 @@ index e6b09fafa27eed2b762e3d53b55041f793683d27..c7e891d72969a388d9b135a36dbfc9c9 CONFIG_LIBCRC32C=y -CONFIG_BCM2835_VCHIQ=n -From 0b2fba92ea8d5ad4f3cd39a3affde52ba4723201 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Thu, 12 Jan 2017 18:56:54 -0800 -Subject: [PATCH 105/216] ARM64: Fix bad cast in vc04_services - -The function vchiq_copy_from_user contains a non-portable -cast to uint32_t. Convert this to a cast to unsigned long -which is portable. - -Signed-off-by: Michael Zoran ---- - drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -index 706e7f936c1a97352f7ef3d3fbd3b4a92943165d..c2108dec3096fffd68261f0eb29a37d3c5ef218c 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c -@@ -235,7 +235,7 @@ remote_event_signal(REMOTE_EVENT_T *event) - int - vchiq_copy_from_user(void *dst, const void *src, int size) - { -- if ((uint32_t)src < TASK_SIZE) { -+ if ((unsigned long)src < TASK_SIZE) { - return copy_from_user(dst, src, size); - } else { - memcpy(dst, src, size); - -From f13f9f044482de36e5a7b15c2c1c2c8860d2c089 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Thu, 12 Jan 2017 19:05:46 -0800 -Subject: [PATCH 106/216] ARM64/SND_BCM2835: Port it to arm64. - -In the messages sent to VCHIQ, SND_BCM2835 passes a callback -and a context into two 32 bit pointers. Since this -message is interpreted by the firmware, it can't be easily -changed. Luckily only one of these fields is actual used, -so on ARM64 only use one of the fields to store the upper -half of the 64 bit callback pointer. - -The Kconfig is also changed to allow ARM audio to work for ARM64 -as well. - -Signed-off-by: Michael Zoran ---- - sound/arm/Kconfig | 2 +- - sound/arm/bcm2835-vchiq.c | 11 +++++++++++ - sound/arm/vc_vchi_audioserv_defs.h | 10 ++++++++++ - 3 files changed, 22 insertions(+), 1 deletion(-) - -diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig -index 42581e2f65dfedba6207b6a377a1e1b5df4f2e4b..b427dfe35ad0427db74776dfcb43b7573d9e6e7d 100644 ---- a/sound/arm/Kconfig -+++ b/sound/arm/Kconfig -@@ -2,7 +2,7 @@ - - menuconfig SND_ARM - bool "ARM sound devices" -- depends on ARM -+ depends on (ARM || ARM64) - default y - help - Support for sound devices specific to ARM architectures. -diff --git a/sound/arm/bcm2835-vchiq.c b/sound/arm/bcm2835-vchiq.c -index 7ee436ca9fa2903d41d1bdd8f8f0774025d22ae0..246ae501b7d98498964b41f355ad65046a6ae893 100755 ---- a/sound/arm/bcm2835-vchiq.c -+++ b/sound/arm/bcm2835-vchiq.c -@@ -226,7 +226,13 @@ static void audio_vchi_callback(void *param, - complete(&instance->msg_avail_comp); - } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { - bcm2835_alsa_stream_t *alsa_stream = instance->alsa_stream; -+#if defined(CONFIG_64BIT) -+ irq_handler_t callback = -+ (irq_handler_t) (((unsigned long)m.u.complete.callbackl) | -+ ((unsigned long)m.u.complete.callbackh << 32)); -+#else - irq_handler_t callback = (irq_handler_t) m.u.complete.callback; -+#endif - LOG_DBG - (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n", - instance, m.u.complete.count); -@@ -803,8 +809,13 @@ int bcm2835_audio_write_worker(bcm2835_alsa_stream_t *alsa_stream, - m.u.write.count = count; - // old version uses bulk, new version uses control - m.u.write.max_packet = instance->peer_version < 2 || force_bulk ? 0:4000; -+#if defined(CONFIG_64BIT) -+ m.u.write.callbackl = (uint32_t)(((unsigned long)alsa_stream->fifo_irq_handler)&0xFFFFFFFF); -+ m.u.write.callbackh = (uint32_t)((((unsigned long)alsa_stream->fifo_irq_handler) >> 32)&0xFFFFFFFF); -+#else - m.u.write.callback = alsa_stream->fifo_irq_handler; - m.u.write.cookie = alsa_stream; -+#endif - m.u.write.silence = src == NULL; - - /* Send the message to the videocore */ -diff --git a/sound/arm/vc_vchi_audioserv_defs.h b/sound/arm/vc_vchi_audioserv_defs.h -index af3e6eb690113fc32ce9e06bd2f0f294da7a7f00..ede6154bc09d38469a82008174d0e35749fd9932 100644 ---- a/sound/arm/vc_vchi_audioserv_defs.h -+++ b/sound/arm/vc_vchi_audioserv_defs.h -@@ -78,8 +78,13 @@ typedef struct { - // configure the write audio samples - typedef struct { - uint32_t count; // in bytes -+#if defined(CONFIG_64BIT) -+ uint32_t callbackl; -+ uint32_t callbackh; -+#else - void *callback; - void *cookie; -+#endif - uint16_t silence; - uint16_t max_packet; - } VC_AUDIO_WRITE_T; -@@ -93,8 +98,13 @@ typedef struct { - // Generic result for a request (VC->HOST) - typedef struct { - int32_t count; // Success value -+#if defined(CONFIG_64BIT) -+ uint32_t callbackl; -+ uint32_t callbackh; -+#else - void *callback; - void *cookie; -+#endif - } VC_AUDIO_COMPLETE_T; - - // Message header for all messages in HOST->VC direction - -From 0f9c55b044c96d469c5d5e9c58ee4c637775dcb0 Mon Sep 17 00:00:00 2001 +From cebe1d060056bff98ee836be6b7faa90e7fcfa6c Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 19:10:07 -0800 -Subject: [PATCH 107/216] ARM64: Enable HDMI audio and vc04_services in +Subject: [PATCH 102/150] ARM64: Enable HDMI audio and vc04_services in bcmrpi3_defconfig Signed-off-by: Michael Zoran @@ -125326,10 +111919,10 @@ index c7e891d72969a388d9b135a36dbfc9c9cb609bf8..4b90f9b64abe9f089ba56b13d5a00de3 CONFIG_BCM2835_MBOX=y # CONFIG_IOMMU_SUPPORT is not set -From 01604bb8a60512e00f6823e925e9a1559cf42a3a Mon Sep 17 00:00:00 2001 +From ac08f600d8a937c85c2c68cef986c9235929aec6 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Thu, 12 Jan 2017 19:14:03 -0800 -Subject: [PATCH 108/216] ARM64: Run bcmrpi3_defconfig through savedefconfig. +Subject: [PATCH 103/150] ARM64: Run bcmrpi3_defconfig through savedefconfig. Signed-off-by: Michael Zoran --- @@ -125374,10 +111967,10 @@ index 4b90f9b64abe9f089ba56b13d5a00de33343bfb9..dac962ca1634662ce7d966f1ffb53b5b CONFIG_FB_TFT_AGM1264K_FL=m CONFIG_FB_TFT_BD663474=m -From 58d65a830ad9aa74d7d090d710ae6ef6f15d9b71 Mon Sep 17 00:00:00 2001 +From ff55f87bbb33fec296221f71a5bb6ac1b5b76ebf Mon Sep 17 00:00:00 2001 From: Electron752 Date: Sat, 14 Jan 2017 02:54:26 -0800 -Subject: [PATCH 109/216] ARM64: Enable Kernel Address Space Randomization +Subject: [PATCH 104/150] ARM64: Enable Kernel Address Space Randomization (#1792) Randomization allows the mapping between virtual addresses and physical @@ -125409,10 +112002,10 @@ index dac962ca1634662ce7d966f1ffb53b5bfa27c506..aae33b4b3c3e736ea7cd3ca242158ad6 CONFIG_BINFMT_MISC=y CONFIG_COMPAT=y -From 4256dd208ab17594c22ca128a25bad618abd461e Mon Sep 17 00:00:00 2001 +From 65c410c8488b1450345fc2b93886cdc2c95b0445 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sun, 15 Jan 2017 07:31:59 -0800 -Subject: [PATCH 110/216] ARM64: Enable RTL8187/RTL8192CU wifi in build config +Subject: [PATCH 105/150] ARM64: Enable RTL8187/RTL8192CU wifi in build config These drivers build now, so they can be enabled back in the build configuration just like they are for @@ -125437,264 +112030,10 @@ index aae33b4b3c3e736ea7cd3ca242158ad6ba558aff..b7d762df19b85e369a32cd823dfd0621 CONFIG_ZD1211RW=m CONFIG_MAC80211_HWSIM=m -From 6ed92f2cbbef1288d97f46ff56c339dc25812c31 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 16 Jan 2017 14:53:12 +0000 -Subject: [PATCH 111/216] BCM270X_DT: Add spi0-cs overlay - -The spi0-cs overlay allows the software chip selectts to be modified -using the cs0_pin and cs1_pin parameters. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 9 +++++++- - arch/arm/boot/dts/overlays/spi0-cs-overlay.dts | 29 ++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/overlays/spi0-cs-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index f1191c1ded82490be5f793ab6483bc5af5891db2..45fafd5c39bdc6e80b12e49d3bcd281638bec471 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -83,6 +83,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - smi-nand.dtbo \ - spi-gpio35-39.dtbo \ - spi-rtc.dtbo \ -+ spi0-cs.dtbo \ - spi0-hw-cs.dtbo \ - spi1-1cs.dtbo \ - spi1-2cs.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 34109c69416c1caf28910895320a2b9cd539588e..4992a6203a5507144b6d405e03ed2bebaa11325f 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -1138,7 +1138,7 @@ Params: - - - Name: spi-gpio35-39 --Info: move SPI function block to GPIO 35 to 39 -+Info: Move SPI function block to GPIO 35 to 39 - Load: dtoverlay=spi-gpio35-39 - Params: - -@@ -1149,6 +1149,13 @@ Load: dtoverlay=spi-rtc,= - Params: pcf2123 Select the PCF2123 device - - -+Name: spi0-cs -+Info: Allows the (software) CS pins for SPI0 to be changed -+Load: dtoverlay=spi0-cs,= -+Params: cs0_pin GPIO pin for CS0 (default 8) -+ cs1_pin GPIO pin for CS1 (default 7) -+ -+ - Name: spi0-hw-cs - Info: Re-enables hardware CS/CE (chip selects) for SPI0 - Load: dtoverlay=spi0-hw-cs -diff --git a/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..7f79029d043c04d7496c7c3480450c691dc9a5cb ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/spi0-cs-overlay.dts -@@ -0,0 +1,29 @@ -+/dts-v1/; -+/plugin/; -+ -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0_cs_pins>; -+ frag0: __overlay__ { -+ brcm,pins = <8 7>; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spi0>; -+ frag1: __overlay__ { -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -+ status = "okay"; -+ }; -+ }; -+ -+ __overrides__ { -+ cs0_pin = <&frag0>,"brcm,pins:0", -+ <&frag1>,"cs-gpios:4"; -+ cs1_pin = <&frag0>,"brcm,pins:4", -+ <&frag1>,"cs-gpios:16"; -+ }; -+}; - -From 1e4529d30944a8eefb7c2647c3cefb48d6b78b2c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 1 Jul 2016 22:09:24 +0100 -Subject: [PATCH 112/216] 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 ---- - arch/arm/boot/dts/bcm283x.dtsi | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi -index 9a44da19089717f02462c657840ae9f24fd942ba..b710a4d67b8ec8c8c18ce8efb6f270e7cfb68e52 100644 ---- a/arch/arm/boot/dts/bcm283x.dtsi -+++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -366,6 +366,7 @@ - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; - }; - - i2c0: i2c@7e205000 { - -From e5f70d78d798227412cda37aa07d54b46ff21a36 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 17 Jan 2017 11:34:58 +0000 -Subject: [PATCH 113/216] BCM270X_DT: Enable UART0 on CM3 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index 41874c25a84226c0e4af92ec4059e0a571fe6123..3ba6e621856c288ae4694f758604619f59064fdb 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -6,6 +6,10 @@ - model = "Raspberry Pi Compute Module 3"; - }; - -+&uart0 { -+ status = "okay"; -+}; -+ - &gpio { - sdhost_pins: sdhost_pins { - brcm,pins = <48 49 50 51 52 53>; - -From 430a4825d539249effcd53e193cd14fb6dd8a81d Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 17 Jan 2017 14:39:39 +0000 -Subject: [PATCH 114/216] config: Add CONFIG_MD_M25P80 and CONFIG_MD_SPI_NOR - -See: https://github.com/raspberrypi/linux/issues/1781 - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 7 ++----- - arch/arm/configs/bcmrpi_defconfig | 7 ++----- - 2 files changed, 4 insertions(+), 10 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 12e8155c175deaecea6fcf1f81ec3f6c1ddf5f7c..c36f01d28097a513b32df092ce64a7d6b974e615 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -115,8 +115,6 @@ CONFIG_NF_CONNTRACK=m - CONFIG_NF_CONNTRACK_ZONES=y - CONFIG_NF_CONNTRACK_EVENTS=y - CONFIG_NF_CONNTRACK_TIMESTAMP=y --CONFIG_NF_CT_PROTO_DCCP=m --CONFIG_NF_CT_PROTO_UDPLITE=m - CONFIG_NF_CONNTRACK_AMANDA=m - CONFIG_NF_CONNTRACK_FTP=m - CONFIG_NF_CONNTRACK_H323=m -@@ -179,7 +177,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m - CONFIG_NETFILTER_XT_MATCH_RATEEST=m - CONFIG_NETFILTER_XT_MATCH_REALM=m - CONFIG_NETFILTER_XT_MATCH_RECENT=m --CONFIG_NETFILTER_XT_MATCH_SOCKET=m - CONFIG_NETFILTER_XT_MATCH_STATE=m - CONFIG_NETFILTER_XT_MATCH_STATISTIC=m - CONFIG_NETFILTER_XT_MATCH_STRING=m -@@ -404,7 +401,9 @@ CONFIG_DMA_CMA=y - CONFIG_CMA_SIZE_MBYTES=5 - CONFIG_MTD=m - CONFIG_MTD_BLOCK=m -+CONFIG_MTD_M25P80=m - CONFIG_MTD_NAND=m -+CONFIG_MTD_SPI_NOR=m - CONFIG_MTD_UBI=m - CONFIG_OF_CONFIGFS=y - CONFIG_ZRAM=m -@@ -584,7 +583,6 @@ CONFIG_BCM_VC_CMA=y - CONFIG_BCM_VCIO=y - CONFIG_BCM_VC_SM=y - # CONFIG_LEGACY_PTYS is not set --# CONFIG_DEVKMEM is not set - CONFIG_SERIAL_8250=y - # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set - CONFIG_SERIAL_8250_CONSOLE=y -@@ -1104,7 +1102,6 @@ CONFIG_LIRC_STAGING=y - CONFIG_LIRC_IMON=m - CONFIG_LIRC_RPI=m - CONFIG_LIRC_SASEM=m --CONFIG_LIRC_SERIAL=m - CONFIG_FB_TFT=m - CONFIG_FB_TFT_AGM1264K_FL=m - CONFIG_FB_TFT_BD663474=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 8acee9f31202ec14f2933d92dd70831cda8d7b51..aca8903da3156de11ba62afa64a0693900ee3611 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -111,8 +111,6 @@ CONFIG_NF_CONNTRACK=m - CONFIG_NF_CONNTRACK_ZONES=y - CONFIG_NF_CONNTRACK_EVENTS=y - CONFIG_NF_CONNTRACK_TIMESTAMP=y --CONFIG_NF_CT_PROTO_DCCP=m --CONFIG_NF_CT_PROTO_UDPLITE=m - CONFIG_NF_CONNTRACK_AMANDA=m - CONFIG_NF_CONNTRACK_FTP=m - CONFIG_NF_CONNTRACK_H323=m -@@ -175,7 +173,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m - CONFIG_NETFILTER_XT_MATCH_RATEEST=m - CONFIG_NETFILTER_XT_MATCH_REALM=m - CONFIG_NETFILTER_XT_MATCH_RECENT=m --CONFIG_NETFILTER_XT_MATCH_SOCKET=m - CONFIG_NETFILTER_XT_MATCH_STATE=m - CONFIG_NETFILTER_XT_MATCH_STATISTIC=m - CONFIG_NETFILTER_XT_MATCH_STRING=m -@@ -400,7 +397,9 @@ CONFIG_DMA_CMA=y - CONFIG_CMA_SIZE_MBYTES=5 - CONFIG_MTD=m - CONFIG_MTD_BLOCK=m -+CONFIG_MTD_M25P80=m - CONFIG_MTD_NAND=m -+CONFIG_MTD_SPI_NOR=m - CONFIG_MTD_UBI=m - CONFIG_OF_CONFIGFS=y - CONFIG_ZRAM=m -@@ -579,7 +578,6 @@ CONFIG_BCM_VC_CMA=y - CONFIG_BCM_VCIO=y - CONFIG_BCM_VC_SM=y - # CONFIG_LEGACY_PTYS is not set --# CONFIG_DEVKMEM is not set - CONFIG_SERIAL_8250=y - # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set - CONFIG_SERIAL_8250_CONSOLE=y -@@ -1113,7 +1111,6 @@ CONFIG_LIRC_STAGING=y - CONFIG_LIRC_IMON=m - CONFIG_LIRC_RPI=m - CONFIG_LIRC_SASEM=m --CONFIG_LIRC_SERIAL=m - CONFIG_FB_TFT=m - CONFIG_FB_TFT_AGM1264K_FL=m - CONFIG_FB_TFT_BD663474=m - -From ffc9a594a62aedb1c8d8e9cba6da939371c9af74 Mon Sep 17 00:00:00 2001 +From 1c77f8fe78ddbb323a13efd25fa9ae01f8e3e021 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:33:51 -0800 -Subject: [PATCH 115/216] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 +Subject: [PATCH 106/150] ARM64/DWC_OTG: Port dwc_otg driver to ARM64 In ARM64, the FIQ mechanism used by this driver is not current implemented. As a workaround, reqular IRQ is used instead @@ -125881,7 +112220,7 @@ index e6b38ac330b72152204c2a6879c20f0ce02ac2e5..b2618c15d1f1f0b062d4146672de5ae5 extern bool microframe_schedule; diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365fde09f801 100644 +index 96ec6338bbcb8ebe69a233d21a4b9d244ff6fe95..992269d61ecf48126379a38e528f719009ee1d75 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c @@ -51,7 +51,9 @@ @@ -125908,7 +112247,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end; /** -@@ -393,14 +402,49 @@ static struct dwc_otg_hcd_function_ops hcd_fops = { +@@ -395,14 +404,49 @@ static struct dwc_otg_hcd_function_ops hcd_fops = { .get_b_hnp_enable = _get_b_hnp_enable, }; @@ -125958,7 +112297,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f struct pt_regs regs; int irq; -@@ -428,6 +472,7 @@ static void hcd_init_fiq(void *cookie) +@@ -430,6 +474,7 @@ static void hcd_init_fiq(void *cookie) // __show_regs(®s); set_fiq_regs(®s); @@ -125966,7 +112305,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f //Set the mphi periph to the required registers dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base; -@@ -446,6 +491,23 @@ static void hcd_init_fiq(void *cookie) +@@ -448,6 +493,23 @@ static void hcd_init_fiq(void *cookie) DWC_WARN("MPHI periph has NOT been enabled"); #endif // Enable FIQ interrupt from USB peripheral @@ -125990,7 +112329,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f #ifdef CONFIG_MULTI_IRQ_HANDLER irq = platform_get_irq(otg_dev->os_dep.platformdev, 1); #else -@@ -457,6 +519,8 @@ static void hcd_init_fiq(void *cookie) +@@ -459,6 +521,8 @@ static void hcd_init_fiq(void *cookie) } enable_fiq(irq); local_fiq_enable(); @@ -125999,7 +112338,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f } /** -@@ -519,6 +583,13 @@ int hcd_init(dwc_bus_dev_t *_dev) +@@ -521,6 +585,13 @@ int hcd_init(dwc_bus_dev_t *_dev) otg_dev->hcd = dwc_otg_hcd; otg_dev->hcd->otg_dev = otg_dev; @@ -126013,7 +112352,7 @@ index 74cd5fa54aed5241b61371477ef67d706477fd30..162a656501988e56c9d780b7793d365f if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { goto error2; } -@@ -531,6 +602,7 @@ int hcd_init(dwc_bus_dev_t *_dev) +@@ -533,6 +604,7 @@ int hcd_init(dwc_bus_dev_t *_dev) smp_call_function_single(0, hcd_init_fiq, otg_dev, 1); } } @@ -126037,10 +112376,10 @@ index 6b2c7d0c93f36a63863ff4b0ecc1f3eab77e058b..d7b700ff17821ad1944e36721fe6b2db /** The OS page size */ #define DWC_OS_PAGE_SIZE PAGE_SIZE -From ace5d5b94d38e57e81eb3209ac9d4579dcb43395 Mon Sep 17 00:00:00 2001 +From e26cb3242b62036bcb045f0d106be2a56201c481 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:43:57 -0800 -Subject: [PATCH 116/216] ARM64: Round-Robin dispatch IRQs between CPUs. +Subject: [PATCH 107/150] ARM64: Round-Robin dispatch IRQs between CPUs. IRQ-CPU mapping is round robined on ARM64 to increase concurrency and allow multiple interrupts to be serviced @@ -126082,7 +112421,7 @@ index 8ed457fd74bd23bee27b64a2c9e3828ce0e4fb87..a035e1ceacc0494fa293e6811ff8f7e3 static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr, diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c -index a8db33b50ad9ff83d284fa54fe4d3b65f859df0f..67dcac46cca72db4ebe2300eab04f0a867e8e14b 100644 +index c4e151451cf8c8ebde5225515eac2786d6f61d46..9a7ee04ee0d9b7aa734cf3159ed59c19a338de0d 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c @@ -145,6 +145,27 @@ static void bcm2836_arm_irqchip_unmask_gpu_irq(struct irq_data *d) @@ -126114,10 +112453,10 @@ index a8db33b50ad9ff83d284fa54fe4d3b65f859df0f..67dcac46cca72db4ebe2300eab04f0a8 .name = "bcm2836-gpu", .irq_mask = bcm2836_arm_irqchip_mask_gpu_irq, -From 4fc9e1783f873cdd1c69b97ee1852c820c2df61e Mon Sep 17 00:00:00 2001 +From 339cdc462b3a88cb9277df7ee3348e279d3c50e6 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 14 Jan 2017 21:45:03 -0800 -Subject: [PATCH 117/216] ARM64: Enable DWC_OTG Driver In ARM64 Build +Subject: [PATCH 108/150] ARM64: Enable DWC_OTG Driver In ARM64 Build Config(bcmrpi3_defconfig) Signed-off-by: Michael Zoran @@ -126138,792 +112477,10 @@ index b7d762df19b85e369a32cd823dfd062145bdefa7..4d85c231c5ea0244e1b05fb4a5e3c8fd CONFIG_USB_STORAGE=y CONFIG_USB_STORAGE_REALTEK=m -From 207779522a14d201f3f5f83762c0ab46287c696d Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Sat, 14 Jan 2017 21:46:04 -0800 -Subject: [PATCH 118/216] ARM64: Use dwc_otg driver by default for USB. - -If it breaks on anybody, they can use the standard device tree -overlays to switch back to the dwc2 driver. - -Signed-off-by: Michael Zoran ---- - arch/arm/boot/dts/bcm2710.dtsi | 7 ------- - 1 file changed, 7 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index f6def5d7e5d622cf09e8f87332c7374fe28da08b..3e134a1208610b90e2d0fc22f03c6e9f372bfcd7 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -146,10 +146,3 @@ - interrupts = <8>; - }; - --#ifdef RPI364 --&usb { -- compatible = "brcm,bcm2835-usb"; -- reg = <0x7e980000 0x10000>; -- interrupts = <1 9>; --}; --#endif - -From cca2d52f2856fc7ee2d88b17d41d98221b71b26c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 19 Jan 2017 11:18:55 +0000 -Subject: [PATCH 119/216] config: Add CONFIG_USB_DWC2 and CONFIG_USB_GADGET - -The introduction of CM3 makes gadget mode on 2709 a useful option, -so enable the building of the required modules. Note that these -modules are not loaded by default and must be enabled with a DT -overlay. - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index c36f01d28097a513b32df092ce64a7d6b974e615..2e2b88fefdf367b2d9190ca227ea6eb393faa666 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -958,6 +958,7 @@ CONFIG_USB_MICROTEK=m - CONFIG_USBIP_CORE=m - CONFIG_USBIP_VHCI_HCD=m - CONFIG_USBIP_HOST=m -+CONFIG_USB_DWC2=m - CONFIG_USB_SERIAL=m - CONFIG_USB_SERIAL_GENERIC=y - CONFIG_USB_SERIAL_AIRCABLE=m -@@ -1030,6 +1031,7 @@ CONFIG_USB_SPEEDTOUCH=m - CONFIG_USB_CXACRU=m - CONFIG_USB_UEAGLEATM=m - CONFIG_USB_XUSBATM=m -+CONFIG_USB_GADGET=m - CONFIG_MMC=y - CONFIG_MMC_BLOCK_MINORS=32 - CONFIG_MMC_BCM2835=y - -From 9761aaa82ca9f591d376350e9322515f045a0888 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 23 Jan 2017 17:36:50 +0000 -Subject: [PATCH 120/216] BCM270X_DT: Add reference to audio_pins to CM dtb - -The CM1 dtb contains an empty audio_pins node, but no reference to it. -Adding the usual pinctrl reference from the audio node enables the -audremap overlay (and others) to easily turn on audio. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2708-rpi-cm.dts | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-cm.dts b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -index eb8662f0d222b4c0a9a2bcb8bccb13e86a0006b3..10be69972bd1440f574e35d515f3d6a0505fd869 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-cm.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-cm.dts -@@ -85,6 +85,11 @@ - pinctrl-0 = <&i2s_pins>; - }; - -+&audio { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&audio_pins>; -+}; -+ - &hdmi { - hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>; - }; - -From 6263fdfc97d10d42f6b1dd0142f4ec75ca0601db Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 25 Jan 2017 11:30:38 +0000 -Subject: [PATCH 121/216] config: Add additional network scheduling modules - ---- - arch/arm/configs/bcm2709_defconfig | 4 ++++ - arch/arm/configs/bcmrpi_defconfig | 4 ++++ - 2 files changed, 8 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 2e2b88fefdf367b2d9190ca227ea6eb393faa666..ce5b564ba5fd0e152a7679747b0d252b8bb2c77a 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -291,6 +291,7 @@ CONFIG_NET_SCHED=y - CONFIG_NET_SCH_CBQ=m - CONFIG_NET_SCH_HTB=m - CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_ATM=m - CONFIG_NET_SCH_PRIO=m - CONFIG_NET_SCH_MULTIQ=m - CONFIG_NET_SCH_RED=m -@@ -307,6 +308,9 @@ CONFIG_NET_SCH_CHOKE=m - CONFIG_NET_SCH_QFQ=m - CONFIG_NET_SCH_CODEL=m - CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_FQ=m -+CONFIG_NET_SCH_HHF=m -+CONFIG_NET_SCH_PIE=m - CONFIG_NET_SCH_INGRESS=m - CONFIG_NET_SCH_PLUG=m - CONFIG_NET_CLS_BASIC=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index aca8903da3156de11ba62afa64a0693900ee3611..c8c66751f263227e86cc21ad5b23861a88a636a6 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -287,6 +287,7 @@ CONFIG_NET_SCHED=y - CONFIG_NET_SCH_CBQ=m - CONFIG_NET_SCH_HTB=m - CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_ATM=m - CONFIG_NET_SCH_PRIO=m - CONFIG_NET_SCH_MULTIQ=m - CONFIG_NET_SCH_RED=m -@@ -303,6 +304,9 @@ CONFIG_NET_SCH_CHOKE=m - CONFIG_NET_SCH_QFQ=m - CONFIG_NET_SCH_CODEL=m - CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_FQ=m -+CONFIG_NET_SCH_HHF=m -+CONFIG_NET_SCH_PIE=m - CONFIG_NET_SCH_INGRESS=m - CONFIG_NET_SCH_PLUG=m - CONFIG_NET_CLS_BASIC=m - -From 0cd76aeb0ed291efb79ca584821bb54510e6fcf4 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 16 Jan 2017 16:33:54 +0000 -Subject: [PATCH 122/216] config: Add CONFIG_TCP_CONG_BBR See: - https://github.com/raspberrypi/linux/issues/1784 - ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index ce5b564ba5fd0e152a7679747b0d252b8bb2c77a..4c0d62d91c2ad6408fbff730b08cb76b62c5e068 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -99,6 +99,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m - CONFIG_INET_XFRM_MODE_TUNNEL=m - CONFIG_INET_XFRM_MODE_BEET=m - CONFIG_INET_DIAG=m -+CONFIG_TCP_CONG_ADVANCED=y -+CONFIG_TCP_CONG_BBR=m - CONFIG_IPV6=m - CONFIG_IPV6_ROUTER_PREF=y - CONFIG_INET6_AH=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index c8c66751f263227e86cc21ad5b23861a88a636a6..e483bdb7aa869b212ef69ed779c6055ef3b70e2a 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -95,6 +95,8 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m - CONFIG_INET_XFRM_MODE_TUNNEL=m - CONFIG_INET_XFRM_MODE_BEET=m - CONFIG_INET_DIAG=m -+CONFIG_TCP_CONG_ADVANCED=y -+CONFIG_TCP_CONG_BBR=m - CONFIG_IPV6=m - CONFIG_IPV6_ROUTER_PREF=y - CONFIG_INET6_AH=m - -From 3a9787042a5eb7d839b3bfe3ba26f9ac9fd79981 Mon Sep 17 00:00:00 2001 -From: chris johnson -Date: Sun, 22 Jan 2017 03:27:31 +0000 -Subject: [PATCH 123/216] ASoC: A simple-card overlay for ADAU7002 - -Usage: `dtoverlay=adau7002-simple` ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 +++ - .../boot/dts/overlays/adau7002-simple-overlay.dts | 52 ++++++++++++++++++++++ - 3 files changed, 59 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 45fafd5c39bdc6e80b12e49d3bcd281638bec471..842098be7776ae9005528b87a13890341bb4097f 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -2,6 +2,7 @@ - - dtbo-$(CONFIG_ARCH_BCM2835) += \ - adau1977-adc.dtbo \ -+ adau7002-simple.dtbo \ - ads1015.dtbo \ - ads7846.dtbo \ - akkordion-iqdacplus.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 4992a6203a5507144b6d405e03ed2bebaa11325f..2f542a810c3f200939f5996d62b118392ae0b14e 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -168,6 +168,12 @@ Load: dtoverlay=adau1977-adc - Params: - - -+Name: adau7002-simple -+Info: Overlay for the activation of ADAU7002 stereo PDM to I2S converter. -+Load: dtoverlay=adau7002-simple,= -+Params: card-name Override the default, "adau7002", card name. -+ -+ - Name: ads1015 - Info: Overlay for activation of Texas Instruments ADS1015 ADC over I2C - Load: dtoverlay=ads1015,= -diff --git a/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..e67e6625d7967abc92cf00cb604d4c12fd76b377 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/adau7002-simple-overlay.dts -@@ -0,0 +1,52 @@ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "/"; -+ __overlay__ { -+ adau7002_codec: adau7002-codec { -+ #sound-dai-cells = <0>; -+ compatible = "adi,adau7002"; -+/* IOVDD-supply = <&supply>;*/ -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&sound>; -+ sound_overlay: __overlay__ { -+ compatible = "simple-audio-card"; -+ simple-audio-card,format = "i2s"; -+ simple-audio-card,name = "adau7002"; -+ simple-audio-card,bitclock-slave = <&dailink0_slave>; -+ simple-audio-card,frame-slave = <&dailink0_slave>; -+ simple-audio-card,widgets = -+ "Microphone", "Microphone Jack"; -+ simple-audio-card,routing = -+ "PDM_DAT", "Microphone Jack"; -+ status = "okay"; -+ simple-audio-card,cpu { -+ sound-dai = <&i2s>; -+ }; -+ dailink0_slave: simple-audio-card,codec { -+ sound-dai = <&adau7002_codec>; -+ }; -+ }; -+ }; -+ -+ -+ __overrides__ { -+ card-name = <&sound_overlay>,"simple-audio-card,name"; -+ }; -+}; - -From 67911d07fb0cce8e0310dc75df06aeb69e588d65 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 25 Jan 2017 21:17:23 +0000 -Subject: [PATCH 124/216] config: Add SND_SOC_ADAU7002 codec module - -As there is now an overlay requiring it, build the codec module. - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 4c0d62d91c2ad6408fbff730b08cb76b62c5e068..e017702a34d1e6c7df7aea26032b1fc70b330a40 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -880,6 +880,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=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 e483bdb7aa869b212ef69ed779c6055ef3b70e2a..1927b1671b6eced73e4b4d76352bb4b1301d077c 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -874,6 +874,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -+CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - -From cc3b11cd02e7296cd0bc22562a34ae485d90679d Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Fri, 27 Jan 2017 06:42:42 -0500 -Subject: [PATCH 125/216] Add overlay for mcp3008 adc (#1818) - -Some example usage: - -SPI0.0 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present - -SPI0.1 -dtparam=spi=on -dtoverlay=mcp3008:spi0-1-present - -SPI0.0 and SPI0.1 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present,spi0-1-present - -SPI1.0 -dtparam=spi=on -dtoverlay=spi1-1cs -dtoverlay=mcp3008:spi1-0-present - -SPI1.2 -dtparam=spi=on -dtoverlay=spi1-1cs:cs0_pin=16 -dtoverlay=mcp3008:spi1-0-present - -SPI1.0 and SPI1.1 -dtoverlay=spi1-2cs -dtoverlay=mcp3008:spi1-0-present,spi1-1-present - -Changing the speed - -SPI0.0 -dtparam=spi=on -dtoverlay=mcp3008:spi0-0-present,spi0-0-speed=2000000 ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 9 ++ - arch/arm/boot/dts/overlays/mcp3008-overlay.dts | 205 +++++++++++++++++++++++++ - 3 files changed, 215 insertions(+) - create mode 100755 arch/arm/boot/dts/overlays/mcp3008-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 842098be7776ae9005528b87a13890341bb4097f..e915dff8a4cdf5af3df0aa519b3ee08dd970d831 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -47,6 +47,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - mcp23s17.dtbo \ - mcp2515-can0.dtbo \ - mcp2515-can1.dtbo \ -+ mcp3008.dtbo \ - midi-uart0.dtbo \ - mmc.dtbo \ - mz61581.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 2f542a810c3f200939f5996d62b118392ae0b14e..aa9b6128c397b33e9c40eec29476d8352933c237 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -742,6 +742,15 @@ Params: oscillator Clock frequency for the CAN controller (Hz) - interrupt GPIO for interrupt signal - - -+Name: mcp3008 -+Info: Configures MCP3008 A/D converters -+ For devices on spi1 or spi2, the interfaces should be enabled -+ with one of the spi1-1/2/3cs and/or spi2-1/2/3cs overlays. -+Load: dtoverlay=mcp3008,[=] -+Params: spi--present boolean, configure device at spi, cs -+ spi--speed integer, set the spi bus speed for this device -+ -+ - Name: midi-uart0 - Info: Configures UART0 (ttyAMA0) so that a requested 38.4kbaud actually gets - 31.25kbaud, the frequency required for MIDI -diff --git a/arch/arm/boot/dts/overlays/mcp3008-overlay.dts b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts -new file mode 100755 -index 0000000000000000000000000000000000000000..06bf4264959c380d8a9f90f74e7803972d399b2a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/mcp3008-overlay.dts -@@ -0,0 +1,205 @@ -+/* -+ * Device tree overlay for Microchip mcp3008 10-Bit A/D Converters -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spidev0>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&spidev1>; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "spi1/spidev@0"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "spi1/spidev@1"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "spi1/spidev@2"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@5 { -+ target-path = "spi2/spidev@0"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@6 { -+ target-path = "spi2/spidev@1"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@7 { -+ target-path = "spi2/spidev@2"; -+ __dormant__ { -+ status = "disabled"; -+ }; -+ }; -+ -+ fragment@8 { -+ target = <&spi0>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_00: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@9 { -+ target = <&spi0>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_01: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@10 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_10: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@11 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_11: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@12 { -+ target = <&spi1>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_12: mcp3008@2 { -+ compatible = "mcp3008"; -+ reg = <2>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@13 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_20: mcp3008@0 { -+ compatible = "mcp3008"; -+ reg = <0>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@14 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_21: mcp3008@1 { -+ compatible = "mcp3008"; -+ reg = <1>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ fragment@15 { -+ target = <&spi2>; -+ __dormant__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mcp3008_22: mcp3008@2 { -+ compatible = "mcp3008"; -+ reg = <2>; -+ spi-max-frequency = <1600000>; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ spi0-0-present = <0>, "+0+8"; -+ spi0-1-present = <0>, "+1+9"; -+ spi1-0-present = <0>, "+2+10"; -+ spi1-1-present = <0>, "+3+11"; -+ spi1-2-present = <0>, "+4+12"; -+ spi2-0-present = <0>, "+5+13"; -+ spi2-1-present = <0>, "+6+14"; -+ spi2-2-present = <0>, "+7+15"; -+ spi0-0-speed = <&mcp3008_00>, "spi-max-frequency:0"; -+ spi0-1-speed = <&mcp3008_01>, "spi-max-frequency:0"; -+ spi1-0-speed = <&mcp3008_10>, "spi-max-frequency:0"; -+ spi1-1-speed = <&mcp3008_11>, "spi-max-frequency:0"; -+ spi1-2-speed = <&mcp3008_12>, "spi-max-frequency:0"; -+ spi2-0-speed = <&mcp3008_20>, "spi-max-frequency:0"; -+ spi2-1-speed = <&mcp3008_21>, "spi-max-frequency:0"; -+ spi2-2-speed = <&mcp3008_22>, "spi-max-frequency:0"; -+ }; -+}; - -From 9266b433c603b28bc4c80dfa77baed4e30424e82 Mon Sep 17 00:00:00 2001 -From: JamesH65 -Date: Mon, 6 Feb 2017 15:24:47 +0000 -Subject: [PATCH 126/216] gpio_mem: Remove unnecessary dev_info output (#1830) - -The open function was spamming syslog every time -called, so have removed call completely. ---- - drivers/char/broadcom/bcm2835-gpiomem.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/drivers/char/broadcom/bcm2835-gpiomem.c b/drivers/char/broadcom/bcm2835-gpiomem.c -index 911f5b7393ed48ceed8751f06967ae6463453f9c..f5e7f1ba8fb6f18dee77fad06a17480c6603cb4e 100644 ---- a/drivers/char/broadcom/bcm2835-gpiomem.c -+++ b/drivers/char/broadcom/bcm2835-gpiomem.c -@@ -76,8 +76,6 @@ static int bcm2835_gpiomem_open(struct inode *inode, struct file *file) - int dev = iminor(inode); - int ret = 0; - -- dev_info(inst->dev, "gpiomem device opened."); -- - if (dev != DEVICE_MINOR) { - dev_err(inst->dev, "Unknown minor device: %d", dev); - ret = -ENXIO; - -From af565fe9eaeb11fb2fd380f98ad21ff75bd31712 Mon Sep 17 00:00:00 2001 -From: Claggy3 -Date: Sat, 11 Feb 2017 14:00:30 +0000 -Subject: [PATCH 127/216] Update vfpmodule.c - -Christopher Alexander Tobias Schulze - May 2, 2015, 11:57 a.m. -This patch fixes a problem with VFP state save and restore related -to exception handling (panic with message "BUG: unsupported FP -instruction in kernel mode") present on VFP11 floating point units -(as used with ARM1176JZF-S CPUs, e.g. on first generation Raspberry -Pi boards). This patch was developed and discussed on - - https://github.com/raspberrypi/linux/issues/859 - -A precondition to see the crashes is that floating point exception -traps are enabled. In this case, the VFP11 might determine that a FPU -operation needs to trap at a point in time when it is not possible to -signal this to the ARM11 core any more. The VFP11 will then set the -FPEXC.EX bit and store the trapped opcode in FPINST. (In some cases, -a second opcode might have been accepted by the VFP11 before the -exception was detected and could be reported to the ARM11 - in this -case, the VFP11 also sets FPEXC.FP2V and stores the second opcode in -FPINST2.) - -If FPEXC.EX is set, the VFP11 will "bounce" the next FPU opcode issued -by the ARM11 CPU, which will be seen by the ARM11 as an undefined opcode -trap. The VFP support code examines the FPEXC.EX and FPEXC.FP2V bits -to decide what actions to take, i.e., whether to emulate the opcodes -found in FPINST and FPINST2, and whether to retry the bounced instruction. - -If a user space application has left the VFP11 in this "pending trap" -state, the next FPU opcode issued to the VFP11 might actually be the -VSTMIA operation vfp_save_state() uses to store the FPU registers -to memory (in our test cases, when building the signal stack frame). -In this case, the kernel crashes as described above. - -This patch fixes the problem by making sure that vfp_save_state() is -always entered with FPEXC.EX cleared. (The current value of FPEXC has -already been saved, so this does not corrupt the context. Clearing -FPEXC.EX has no effects on FPINST or FPINST2. Also note that many -callers already modify FPEXC by setting FPEXC.EN before invoking -vfp_save_state().) - -This patch also addresses a second problem related to FPEXC.EX: After -returning from signal handling, the kernel reloads the VFP context -from the user mode stack. However, the current code explicitly clears -both FPEXC.EX and FPEXC.FP2V during reload. As VFP11 requires these -bits to be preserved, this patch disables clearing them for VFP -implementations belonging to architecture 1. There should be no -negative side effects: the user can set both bits by executing FPU -opcodes anyway, and while user code may now place arbitrary values -into FPINST and FPINST2 (e.g., non-VFP ARM opcodes) the VFP support -code knows which instructions can be emulated, and rejects other -opcodes with "unhandled bounce" messages, so there should be no -security impact from allowing reloading FPEXC.EX and FPEXC.FP2V. - -Signed-off-by: Christopher Alexander Tobias Schulze ---- - arch/arm/vfp/vfpmodule.c | 25 +++++++++++++++++++------ - 1 file changed, 19 insertions(+), 6 deletions(-) - -diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c -index 569d5a650a4a2c6266ddf8fc6d38e0cd96b985f6..5822a3f60a96510201a6d88828ac5262582e0743 100644 ---- a/arch/arm/vfp/vfpmodule.c -+++ b/arch/arm/vfp/vfpmodule.c -@@ -179,8 +179,11 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v) - * case the thread migrates to a different CPU. The - * restoring is done lazily. - */ -- if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) -+ if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) { -+ /* vfp_save_state oopses on VFP11 if EX bit set */ -+ fmxr(FPEXC, fpexc & ~FPEXC_EX); - vfp_save_state(vfp_current_hw_state[cpu], fpexc); -+ } - #endif - - /* -@@ -463,13 +466,16 @@ static int vfp_pm_suspend(void) - /* if vfp is on, then save state for resumption */ - if (fpexc & FPEXC_EN) { - pr_debug("%s: saving vfp state\n", __func__); -+ /* vfp_save_state oopses on VFP11 if EX bit set */ -+ fmxr(FPEXC, fpexc & ~FPEXC_EX); - vfp_save_state(&ti->vfpstate, fpexc); - - /* disable, just in case */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); - } else if (vfp_current_hw_state[ti->cpu]) { - #ifndef CONFIG_SMP -- fmxr(FPEXC, fpexc | FPEXC_EN); -+ /* vfp_save_state oopses on VFP11 if EX bit set */ -+ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); - vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); - fmxr(FPEXC, fpexc); - #endif -@@ -532,7 +538,8 @@ void vfp_sync_hwstate(struct thread_info *thread) - /* - * Save the last VFP state on this CPU. - */ -- fmxr(FPEXC, fpexc | FPEXC_EN); -+ /* vfp_save_state oopses on VFP11 if EX bit set */ -+ fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); - vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); - fmxr(FPEXC, fpexc); - } -@@ -604,6 +611,7 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, - struct vfp_hard_struct *hwstate = &thread->vfpstate.hard; - unsigned long fpexc; - int err = 0; -+ u32 fpsid = fmrx(FPSID); - - /* Disable VFP to avoid corrupting the new thread state. */ - vfp_flush_hwstate(thread); -@@ -627,8 +635,12 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, - /* Ensure the VFP is enabled. */ - fpexc |= FPEXC_EN; - -- /* Ensure FPINST2 is invalid and the exception flag is cleared. */ -- fpexc &= ~(FPEXC_EX | FPEXC_FP2V); -+ /* Mask FPXEC_EX and FPEXC_FP2V if not required by VFP arch */ -+ if ((fpsid & FPSID_ARCH_MASK) != (1 << FPSID_ARCH_BIT)) { -+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */ -+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V); -+ } -+ - hwstate->fpexc = fpexc; - - __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err); -@@ -698,7 +710,8 @@ void kernel_neon_begin(void) - cpu = get_cpu(); - - fpexc = fmrx(FPEXC) | FPEXC_EN; -- fmxr(FPEXC, fpexc); -+ /* vfp_save_state oopses on VFP11 if EX bit set */ -+ fmxr(FPEXC, fpexc & ~FPEXC_EX); - - /* - * Save the userland NEON/VFP state. Under UP, - -From be28ef65ddfba501509d9e407eee29492b02d755 Mon Sep 17 00:00:00 2001 +From 6a50b889780771cd02cf0e89cb17f1465ce697e3 Mon Sep 17 00:00:00 2001 From: Michael Zoran Date: Sat, 11 Feb 2017 01:18:31 -0800 -Subject: [PATCH 128/216] ARM64: Force hardware emulation of deprecated +Subject: [PATCH 109/150] ARM64: Force hardware emulation of deprecated instructions. --- @@ -126931,10 +112488,10 @@ Subject: [PATCH 128/216] ARM64: Force hardware emulation of deprecated 1 file changed, 5 insertions(+) diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c -index ecf9298a12d48f11d5833dca0584d8ab028cf422..14e9146709857124891f8a3927efec872fb7be39 100644 +index 657977e77ec8fa49e55fc9cacc1415db81a7cc2d..d16c807fd8c0728262b9495aab9948b626270b5b 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c -@@ -182,10 +182,15 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops) +@@ -183,10 +183,15 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops) switch (ops->status) { case INSN_DEPRECATED: @@ -126951,4947 +112508,10 @@ index ecf9298a12d48f11d5833dca0584d8ab028cf422..14e9146709857124891f8a3927efec87 case INSN_OBSOLETE: insn->current_mode = INSN_UNDEF; -From 2f74f7131109529121a8de17576132804e7be15b Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Mon, 13 Feb 2017 15:33:47 +0000 -Subject: [PATCH 129/216] squash: fix order of sound/soc/bcm makefile - ---- - sound/soc/bcm/Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 222a7583891f632cc2297f49aa1a58ee46507875..bb1df438540193652ec5464e8bc51f636a1b844e 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -10,12 +10,12 @@ obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o - - # BCM2708 Machine Support - snd-soc-adau1977-adc-objs := adau1977-adc.o -+snd-soc-hifiberry-amp-objs := hifiberry_amp.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-justboom-dac-objs := justboom-dac.o - snd-soc-justboom-digi-objs := justboom-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 -@@ -28,12 +28,12 @@ snd-soc-allo-piano-dac-objs := allo-piano-dac.o - snd-soc-pisound-objs := pisound.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o -+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.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_JUSTBOOM_DAC) += snd-soc-justboom-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-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 - -From 0ba3816f26669247c267531d04fa213b6bdc23ff Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 130/216] config: Enable regulator support - -Signed-off-by: Matthias Reichl ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index e017702a34d1e6c7df7aea26032b1fc70b330a40..3b2abe9c203e176e7088e504a7952e9b2c96aec8 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -660,6 +660,8 @@ CONFIG_STMPE_SPI=y - CONFIG_MFD_ARIZONA_I2C=m - CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 1927b1671b6eced73e4b4d76352bb4b1301d077c..5351a59b7f670985f47fdbafa26117346cafe87d 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -654,6 +654,8 @@ CONFIG_STMPE_SPI=y - CONFIG_MFD_ARIZONA_I2C=m - CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y - -From 9172938e05e0b2dddf618eaf757360e00242988d Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 131/216] BCM270x DT: expose 3.3V and 5V system rails - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/bcm270x.dtsi | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index a46cb4a8b1419edd95e0e07c18b0f373222dc2bf..36d853715f2379e1952ce3d3be58dd670e305159 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -138,4 +138,20 @@ - status = "disabled"; - }; - }; -+ -+ vdd_5v0_reg: fixedregulator_5v0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "5v0"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ vdd_3v3_reg: fixedregulator_3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; - }; - -From d235056d965a7f73ff1e0192fbfaa7c1d6872a82 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:36 +0100 -Subject: [PATCH 132/216] BCM270x DT: Consolidate audio card overlays - -Reference 3.3V / 5V system rails instead of instantiating local -regulators. - -Add missing power supply properties for codecs where these are -required according to the DT bindings docs. - -Signed-off-by: Matthias Reichl ---- - .../arm/boot/dts/overlays/adau1977-adc-overlay.dts | 19 ++-------- - .../dts/overlays/akkordion-iqdacplus-overlay.dts | 3 ++ - .../dts/overlays/hifiberry-dacplus-overlay.dts | 3 ++ - .../boot/dts/overlays/hifiberry-digi-overlay.dts | 2 + - .../dts/overlays/hifiberry-digi-pro-overlay.dts | 2 + - arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts | 3 ++ - .../boot/dts/overlays/iqaudio-dacplus-overlay.dts | 3 ++ - .../overlays/iqaudio-digi-wm8804-audio-overlay.dts | 4 +- - .../arm/boot/dts/overlays/justboom-dac-overlay.dts | 3 ++ - .../boot/dts/overlays/justboom-digi-overlay.dts | 2 + - arch/arm/boot/dts/overlays/raspidac3-overlay.dts | 4 ++ - .../overlays/rra-digidac1-wm8741-audio-overlay.dts | 44 +++------------------- - 12 files changed, 36 insertions(+), 56 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -index 24fcd58fd1dc61d97a77def3d5d1f7c65130dde6..1aaca71c1b677e414ada9a3f94e60e5e2cf30815 100644 ---- a/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -+++ b/arch/arm/boot/dts/overlays/adau1977-adc-overlay.dts -@@ -6,19 +6,6 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -- target = <&soc>; -- -- __overlay__ { -- codec_supply: fixedregulator@0 { -- compatible = "regulator-fixed"; -- regulator-name = "AVDD"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- }; -- }; -- }; -- -- fragment@1 { - target = <&i2c>; - - __overlay__ { -@@ -30,19 +17,19 @@ - compatible = "adi,adau1977"; - reg = <0x11>; - reset-gpios = <&gpio 5 0>; -- AVDD-supply = <&codec_supply>; -+ AVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; - -- fragment@2 { -+ fragment@1 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; - -- fragment@3 { -+ fragment@2 { - target = <&sound>; - __overlay__ { - compatible = "adi,adau1977-adc"; -diff --git a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -index 208849d5c39274ed0aa557f63a19430a451a95f5..241d03b9b79ef5e833cc28819003946a9eb319fd 100644 ---- a/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/akkordion-iqdacplus-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -index 2f078d4747ccfdc5172e24b18ce65454f1219b9d..b4dc99633b9d409565c0443de378a4460c7a966a 100644 ---- a/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-dacplus-overlay.dts -@@ -34,6 +34,9 @@ - compatible = "ti,pcm5122"; - reg = <0x4d>; - clocks = <&dacpro_osc>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -index f5e41f48ba4fed92194ff5a63d13c70bb2d1c091..64cb1e00343b57e3d7dee864416e558dc3163117 100644 ---- a/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -index 2a26d9cfffb0f3d7958eb3756ca7c4ba28400e1c..d02479ca4a25c3b2da75fe737fd457b1882c20b1 100644 ---- a/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -+++ b/arch/arm/boot/dts/overlays/hifiberry-digi-pro-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -index 0d35c85382bb5766b3eeb9de1bd4a94621229e4b..f16586f05971f69b928200d212015982e388ce96 100644 ---- a/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-dac-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -index d4bad8742a985e2f15eed19ca52ef283a74fefb9..4dcf17515f95589addd5194cf825be813d1e0c98 100644 ---- a/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-dacplus-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -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 -index da4fbfdfdbbbcf2505b9eb4789ddb779ec72cea8..b86e1e5edc89fb78fd1ab8482bfff6c7ec4ec9f5 100644 ---- a/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/iqaudio-digi-wm8804-audio-overlay.dts -@@ -24,8 +24,8 @@ - compatible = "wlf,wm8804"; - reg = <0x3b>; - status = "okay"; -- // DVDD-supply = <®_3v3>; -- // PVDD-supply = <®_3v3>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ PVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -index 312632ad376d5b8c8ff1dbf31fa03d0d18181d94..2b8dba0c231b20ac7660152356a06abeacc83c2d 100644 ---- a/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -+++ b/arch/arm/boot/dts/overlays/justboom-dac-overlay.dts -@@ -23,6 +23,9 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4d>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -index cbbede9a541166ba257122918081982016e0b7eb..1212e3ff591b6071604ee4a519c89ec50ac95d00 100644 ---- a/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -+++ b/arch/arm/boot/dts/overlays/justboom-digi-overlay.dts -@@ -23,6 +23,8 @@ - #sound-dai-cells = <0>; - compatible = "wlf,wm8804"; - reg = <0x3b>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/raspidac3-overlay.dts b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -index 2fac57ca179fcf114655ea91dbef419c16aceb79..2c3c97813f22c94eff6da2193aff0920ac7c39b1 100644 ---- a/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -+++ b/arch/arm/boot/dts/overlays/raspidac3-overlay.dts -@@ -23,12 +23,16 @@ - #sound-dai-cells = <0>; - compatible = "ti,pcm5122"; - reg = <0x4c>; -+ AVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - - tpa6130a2: tpa6130a2@60 { - compatible = "ti,tpa6130a2"; - reg = <0x60>; -+ Vdd-supply = <&vdd_3v3_reg>; - status = "okay"; - }; - }; -diff --git a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -index 16b1247bfa618ff85936ddf78c3aea58075eaa67..f8d48233e28c7c18509b4a95692f6aff29ea33fd 100644 ---- a/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -+++ b/arch/arm/boot/dts/overlays/rra-digidac1-wm8741-audio-overlay.dts -@@ -6,45 +6,13 @@ - compatible = "brcm,bcm2708"; - - fragment@0 { -- target-path = "/"; -- __overlay__ { -- aliases { -- ldo0 = &ldo0; -- ldo1 = &ldo1; -- }; -- }; -- }; -- -- fragment@1 { -- target-path = "/soc"; -- __overlay__ { -- -- ldo1: ldo1 { -- compatible = "regulator-fixed"; -- regulator-name = "DC_5V"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- regulator-always-on; -- }; -- -- ldo0: ldo0 { -- compatible = "regulator-fixed"; -- regulator-name = "DC_3V3"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- }; -- }; -- -- fragment@2 { - target = <&i2s>; - __overlay__ { - status = "okay"; - }; - }; - -- fragment@3 { -+ fragment@1 { - target = <&i2c1>; - __overlay__ { - #address-cells = <1>; -@@ -56,21 +24,21 @@ - compatible = "wlf,wm8804"; - reg = <0x3b>; - status = "okay"; -- PVDD-supply = <&ldo0>; -- DVDD-supply = <&ldo0>; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - }; - - wm8742: wm8741@1a { - compatible = "wlf,wm8741"; - reg = <0x1a>; - status = "okay"; -- AVDD-supply = <&ldo1>; -- DVDD-supply = <&ldo0>; -+ AVDD-supply = <&vdd_5v0_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; - }; - }; - }; - -- fragment@4 { -+ fragment@2 { - target = <&sound>; - __overlay__ { - compatible = "rra,digidac1-soundcard"; - -From 043a72859f8026c88b6d5989eee22b927a3961a4 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH 133/216] ASoC: Add driver for Cirrus Logic Audio Card - -Note: due to problems with deferred probing of regulators -the following softdep should be added to a modprobe.d file - -softdep arizona-spi pre: arizona-ldo1 - -Signed-off-by: Matthias Reichl ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - .../dts/overlays/rpi-cirrus-wm5102-overlay.dts | 146 +++ - sound/soc/bcm/Kconfig | 9 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/rpi-cirrus.c | 1003 ++++++++++++++++++++ - 6 files changed, 1167 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts - create mode 100644 sound/soc/bcm/rpi-cirrus.c - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index e915dff8a4cdf5af3df0aa519b3ee08dd970d831..0a7d30cd573060964bb081ee6617d5b77a17b974 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -68,6 +68,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - qca7000.dtbo \ - raspidac3.dtbo \ - rpi-backlight.dtbo \ -+ rpi-cirrus-wm5102.dtbo \ - rpi-dac.dtbo \ - rpi-display.dtbo \ - rpi-ft5406.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index aa9b6128c397b33e9c40eec29476d8352933c237..46228fd324fc4c52eb0ba50316b4c02f8245bf04 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -995,6 +995,12 @@ Load: dtoverlay=rpi-backlight - Params: - - -+Name: rpi-cirrus-wm5102 -+Info: Configures the Cirrus Logic Audio Card -+Load: dtoverlay=rpi-cirrus-wm5102 -+Params: -+ -+ - Name: rpi-dac - Info: Configures the RPi DAC audio card - Load: dtoverlay=rpi-dac -diff --git a/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..cf85f0af224067cf58053a143664f0716d5ce71a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-cirrus-wm5102-overlay.dts -@@ -0,0 +1,146 @@ -+// Definitions for the Cirrus Logic Audio Card -+/dts-v1/; -+/plugin/; -+#include -+#include -+#include -+ -+/ { -+ compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&gpio>; -+ __overlay__ { -+ wlf_pins: wlf_pins { -+ brcm,pins = <17 22 27 8>; -+ brcm,function = < -+ BCM2835_FSEL_GPIO_OUT -+ BCM2835_FSEL_GPIO_OUT -+ BCM2835_FSEL_GPIO_IN -+ BCM2835_FSEL_GPIO_OUT -+ >; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "/"; -+ __overlay__ { -+ rpi_cirrus_reg_1v8: rpi_cirrus_reg_1v8 { -+ compatible = "regulator-fixed"; -+ regulator-name = "RPi-Cirrus 1v8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&spi0>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ spidev@0{ -+ status = "disabled"; -+ }; -+ -+ spidev@1{ -+ status = "disabled"; -+ }; -+ -+ wm5102@1{ -+ compatible = "wlf,wm5102"; -+ reg = <1>; -+ -+ spi-max-frequency = <500000>; -+ -+ interrupt-parent = <&gpio>; -+ interrupts = <27 8>; -+ interrupt-controller; -+ #interrupt-cells = <2>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ LDOVDD-supply = <&rpi_cirrus_reg_1v8>; -+ AVDD-supply = <&rpi_cirrus_reg_1v8>; -+ DBVDD1-supply = <&rpi_cirrus_reg_1v8>; -+ DBVDD2-supply = <&vdd_3v3_reg>; -+ DBVDD3-supply = <&vdd_3v3_reg>; -+ CPVDD-supply = <&rpi_cirrus_reg_1v8>; -+ SPKVDDL-supply = <&vdd_5v0_reg>; -+ SPKVDDR-supply = <&vdd_5v0_reg>; -+ DCVDD-supply = <&arizona_ldo1>; -+ -+ wlf,reset = <&gpio 17 GPIO_ACTIVE_HIGH>; -+ wlf,ldoena = <&gpio 22 GPIO_ACTIVE_HIGH>; -+ wlf,gpio-defaults = < -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ ARIZONA_GP_DEFAULT -+ >; -+ wlf,micd-configs = <0 1 0>; -+ wlf,dmic-ref = < -+ ARIZONA_DMIC_MICVDD -+ ARIZONA_DMIC_MICBIAS2 -+ ARIZONA_DMIC_MICVDD -+ ARIZONA_DMIC_MICVDD -+ >; -+ wlf,inmode = < -+ ARIZONA_INMODE_DIFF -+ ARIZONA_INMODE_DMIC -+ ARIZONA_INMODE_SE -+ ARIZONA_INMODE_DIFF -+ >; -+ status = "okay"; -+ -+ arizona_ldo1: ldo1 { -+ regulator-name = "LDO1"; -+ // default constraints as in -+ // arizona-ldo1.c -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1800000>; -+ }; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&i2c1>; -+ __overlay__ { -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ wm8804@3b { -+ compatible = "wlf,wm8804"; -+ reg = <0x3b>; -+ status = "okay"; -+ PVDD-supply = <&vdd_3v3_reg>; -+ DVDD-supply = <&vdd_3v3_reg>; -+ wlf,reset-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ }; -+ -+ fragment@5 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "wlf,rpi-cirrus"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+}; -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index ff4284a0000fd8dc58deb9e50be1422fd7ad6e65..c0489e591b9b8c8da004ca9e300e97f1a21e5ce1 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -46,6 +46,15 @@ config SND_BCM2708_SOC_HIFIBERRY_AMP - help - Say Y or M if you want to add support for the HifiBerry Amp amplifier board. - -+config SND_BCM2708_SOC_RPI_CIRRUS -+ tristate "Support for Cirrus Logic Audio Card" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_WM5102 -+ select SND_SOC_WM8804 -+ help -+ Say Y or M if you want to add support for the Wolfson and -+ Cirrus Logic audio cards. -+ - 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 bb1df438540193652ec5464e8bc51f636a1b844e..84c2b20ce2e51b525797ee58de95734ee7847e15 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -16,6 +16,7 @@ snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o - snd-soc-hifiberry-digi-objs := hifiberry_digi.o - snd-soc-justboom-dac-objs := justboom-dac.o - snd-soc-justboom-digi-objs := justboom-digi.o -+snd-soc-rpi-cirrus-objs := rpi-cirrus.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 -@@ -34,6 +35,7 @@ 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_JUSTBOOM_DAC) += snd-soc-justboom-dac.o - obj-$(CONFIG_SND_BCM2708_SOC_JUSTBOOM_DIGI) += snd-soc-justboom-digi.o -+obj-$(CONFIG_SND_BCM2708_SOC_RPI_CIRRUS) += snd-soc-rpi-cirrus.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-cirrus.c b/sound/soc/bcm/rpi-cirrus.c -new file mode 100644 -index 0000000000000000000000000000000000000000..ac8651ddff7bd3701dffe22c7fb88352f912dff3 ---- /dev/null -+++ b/sound/soc/bcm/rpi-cirrus.c -@@ -0,0 +1,1003 @@ -+/* -+ * ASoC machine driver for Cirrus Logic Audio Card -+ * (with WM5102 and WM8804 codecs) -+ * -+ * Copyright 2015-2017 Matthias Reichl -+ * -+ * Based on rpi-cirrus-sound-pi driver (c) Wolfson / Cirrus Logic Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "../codecs/wm5102.h" -+#include "../codecs/wm8804.h" -+ -+#define WM8804_CLKOUT_HZ 12000000 -+ -+#define RPI_CIRRUS_DEFAULT_RATE 44100 -+#define WM5102_MAX_SYSCLK_1 49152000 /* max sysclk for 4K family */ -+#define WM5102_MAX_SYSCLK_2 45158400 /* max sysclk for 11.025K family */ -+ -+static inline unsigned int calc_sysclk(unsigned int rate) -+{ -+ return (rate % 4000) ? WM5102_MAX_SYSCLK_2 : WM5102_MAX_SYSCLK_1; -+} -+ -+enum { -+ DAI_WM5102 = 0, -+ DAI_WM8804, -+}; -+ -+struct rpi_cirrus_priv { -+ /* mutex for synchronzing FLL1 access with DAPM */ -+ struct mutex lock; -+ unsigned int card_rate; -+ int sync_path_enable; -+ int fll1_freq; /* negative means RefClock in spdif rx case */ -+ -+ /* track hw params/free for substreams */ -+ unsigned int params_set; -+ unsigned int min_rate_idx, max_rate_idx; -+ unsigned char iec958_status[4]; -+}; -+ -+/* helper functions */ -+static inline struct snd_soc_pcm_runtime *get_wm5102_runtime( -+ struct snd_soc_card *card) { -+ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM5102].name); -+} -+ -+static inline struct snd_soc_pcm_runtime *get_wm8804_runtime( -+ struct snd_soc_card *card) { -+ return snd_soc_get_pcm_runtime(card, card->dai_link[DAI_WM8804].name); -+} -+ -+ -+struct rate_info { -+ unsigned int value; -+ char *text; -+}; -+ -+static struct rate_info min_rates[] = { -+ { 0, "off"}, -+ { 32000, "32kHz"}, -+ { 44100, "44.1kHz"} -+}; -+ -+#define NUM_MIN_RATES ARRAY_SIZE(min_rates) -+ -+static int rpi_cirrus_min_rate_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_MIN_RATES; -+ -+ if (uinfo->value.enumerated.item >= NUM_MIN_RATES) -+ uinfo->value.enumerated.item = NUM_MIN_RATES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ min_rates[uinfo->value.enumerated.item].text); -+ return 0; -+} -+ -+static int rpi_cirrus_min_rate_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ -+ ucontrol->value.enumerated.item[0] = priv->min_rate_idx; -+ return 0; -+} -+ -+static int rpi_cirrus_min_rate_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int changed = 0; -+ -+ if (priv->min_rate_idx != ucontrol->value.enumerated.item[0]) { -+ changed = 1; -+ priv->min_rate_idx = ucontrol->value.enumerated.item[0]; -+ } -+ -+ return changed; -+} -+ -+static struct rate_info max_rates[] = { -+ { 0, "off"}, -+ { 48000, "48kHz"}, -+ { 96000, "96kHz"} -+}; -+ -+#define NUM_MAX_RATES ARRAY_SIZE(max_rates) -+ -+static int rpi_cirrus_max_rate_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_MAX_RATES; -+ if (uinfo->value.enumerated.item >= NUM_MAX_RATES) -+ uinfo->value.enumerated.item = NUM_MAX_RATES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ max_rates[uinfo->value.enumerated.item].text); -+ return 0; -+} -+ -+static int rpi_cirrus_max_rate_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ -+ ucontrol->value.enumerated.item[0] = priv->max_rate_idx; -+ return 0; -+} -+ -+static int rpi_cirrus_max_rate_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int changed = 0; -+ -+ if (priv->max_rate_idx != ucontrol->value.enumerated.item[0]) { -+ changed = 1; -+ priv->max_rate_idx = ucontrol->value.enumerated.item[0]; -+ } -+ -+ return changed; -+} -+ -+static int rpi_cirrus_spdif_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; -+ uinfo->count = 1; -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_playback_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ int i; -+ -+ for (i = 0; i < 4; i++) -+ ucontrol->value.iec958.status[i] = priv->iec958_status[i]; -+ -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_playback_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned char *stat = priv->iec958_status; -+ unsigned char *ctrl_stat = ucontrol->value.iec958.status; -+ unsigned int mask; -+ int i, changed = 0; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ if ((ctrl_stat[i] & mask) != (stat[i] & mask)) { -+ changed = 1; -+ stat[i] = ctrl_stat[i] & mask; -+ snd_soc_update_bits(wm8804_codec, -+ WM8804_SPDTX1 + i, mask, stat[i]); -+ } -+ } -+ -+ return changed; -+} -+ -+static int rpi_cirrus_spdif_mask_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ ucontrol->value.iec958.status[0] = 0xff; -+ ucontrol->value.iec958.status[1] = 0xff; -+ ucontrol->value.iec958.status[2] = 0xff; -+ ucontrol->value.iec958.status[3] = 0x3f; -+ -+ return 0; -+} -+ -+static int rpi_cirrus_spdif_capture_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ unsigned int mask; -+ int i; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ ucontrol->value.iec958.status[i] = -+ snd_soc_read(wm8804_codec, WM8804_RXCHAN1 + i) & mask; -+ } -+ -+ return 0; -+} -+ -+#define SPDIF_FLAG_CTRL(desc, reg, bit, invert) \ -+{ \ -+ .access = SNDRV_CTL_ELEM_ACCESS_READ \ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) \ -+ desc " Flag", \ -+ .info = snd_ctl_boolean_mono_info, \ -+ .get = rpi_cirrus_spdif_status_flag_get, \ -+ .private_value = \ -+ (bit) | ((reg) << 8) | ((invert) << 16) \ -+} -+ -+static int rpi_cirrus_spdif_status_flag_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ -+ unsigned int bit = kcontrol->private_value & 0xff; -+ unsigned int reg = (kcontrol->private_value >> 8) & 0xff; -+ unsigned int invert = (kcontrol->private_value >> 16) & 0xff; -+ -+ bool flag = snd_soc_read(wm8804_codec, reg) & (1 << bit); -+ -+ ucontrol->value.integer.value[0] = invert ? !flag : flag; -+ -+ return 0; -+} -+ -+static const char * const recovered_frequency_texts[] = { -+ "176.4/192 kHz", -+ "88.2/96 kHz", -+ "44.1/48 kHz", -+ "32 kHz" -+}; -+ -+#define NUM_RECOVERED_FREQUENCIES \ -+ ARRAY_SIZE(recovered_frequency_texts) -+ -+static int rpi_cirrus_recovered_frequency_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; -+ uinfo->count = 1; -+ uinfo->value.enumerated.items = NUM_RECOVERED_FREQUENCIES; -+ if (uinfo->value.enumerated.item >= NUM_RECOVERED_FREQUENCIES) -+ uinfo->value.enumerated.item = NUM_RECOVERED_FREQUENCIES - 1; -+ strcpy(uinfo->value.enumerated.name, -+ recovered_frequency_texts[uinfo->value.enumerated.item]); -+ return 0; -+} -+ -+static int rpi_cirrus_recovered_frequency_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol); -+ struct snd_soc_codec *wm8804_codec = get_wm8804_runtime(card)->codec; -+ -+ ucontrol->value.enumerated.item[0] = -+ (snd_soc_read(wm8804_codec, WM8804_SPDSTAT) >> 4) & 0x03; -+ return 0; -+} -+ -+static const struct snd_kcontrol_new rpi_cirrus_controls[] = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Min Sample Rate", -+ .info = rpi_cirrus_min_rate_info, -+ .get = rpi_cirrus_min_rate_get, -+ .put = rpi_cirrus_min_rate_put, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "Max Sample Rate", -+ .info = rpi_cirrus_max_rate_info, -+ .get = rpi_cirrus_max_rate_get, -+ .put = rpi_cirrus_max_rate_put, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_playback_get, -+ .put = rpi_cirrus_spdif_playback_put, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_capture_get, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), -+ .info = rpi_cirrus_spdif_info, -+ .get = rpi_cirrus_spdif_mask_get, -+ }, -+ { -+ .access = SNDRV_CTL_ELEM_ACCESS_READ -+ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) -+ "Recovered Frequency", -+ .info = rpi_cirrus_recovered_frequency_info, -+ .get = rpi_cirrus_recovered_frequency_get, -+ }, -+ SPDIF_FLAG_CTRL("Audio", WM8804_SPDSTAT, 0, 1), -+ SPDIF_FLAG_CTRL("Non-PCM", WM8804_SPDSTAT, 1, 0), -+ SPDIF_FLAG_CTRL("Copyright", WM8804_SPDSTAT, 2, 1), -+ SPDIF_FLAG_CTRL("De-Emphasis", WM8804_SPDSTAT, 3, 0), -+ SPDIF_FLAG_CTRL("Lock", WM8804_SPDSTAT, 6, 1), -+ SPDIF_FLAG_CTRL("Invalid", WM8804_INTSTAT, 1, 0), -+ SPDIF_FLAG_CTRL("TransErr", WM8804_INTSTAT, 3, 0), -+}; -+ -+static const char * const linein_micbias_texts[] = { -+ "off", "on", -+}; -+ -+static SOC_ENUM_SINGLE_VIRT_DECL(linein_micbias_enum, -+ linein_micbias_texts); -+ -+static const struct snd_kcontrol_new linein_micbias_mux = -+ SOC_DAPM_ENUM("Route", linein_micbias_enum); -+ -+static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event); -+ -+const struct snd_soc_dapm_widget rpi_cirrus_dapm_widgets[] = { -+ SND_SOC_DAPM_MIC("DMIC", NULL), -+ SND_SOC_DAPM_MIC("Headset Mic", NULL), -+ SND_SOC_DAPM_INPUT("Line Input"), -+ SND_SOC_DAPM_MIC("Line Input with Micbias", NULL), -+ SND_SOC_DAPM_MUX("Line Input Micbias", SND_SOC_NOPM, 0, 0, -+ &linein_micbias_mux), -+ SND_SOC_DAPM_INPUT("dummy SPDIF in"), -+ SND_SOC_DAPM_PGA_E("dummy SPDIFRX", SND_SOC_NOPM, 0, 0, NULL, 0, -+ rpi_cirrus_spdif_rx_enable_event, -+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), -+ SND_SOC_DAPM_INPUT("Dummy Input"), -+ SND_SOC_DAPM_OUTPUT("Dummy Output"), -+}; -+ -+const struct snd_soc_dapm_route rpi_cirrus_dapm_routes[] = { -+ { "IN1L", NULL, "Headset Mic" }, -+ { "IN1R", NULL, "Headset Mic" }, -+ { "Headset Mic", NULL, "MICBIAS1" }, -+ -+ { "IN2L", NULL, "DMIC" }, -+ { "IN2R", NULL, "DMIC" }, -+ { "DMIC", NULL, "MICBIAS2" }, -+ -+ { "IN3L", NULL, "Line Input Micbias" }, -+ { "IN3R", NULL, "Line Input Micbias" }, -+ -+ { "Line Input Micbias", "off", "Line Input" }, -+ { "Line Input Micbias", "on", "Line Input with Micbias" }, -+ -+ /* Make sure MICVDD is enabled, otherwise we get noise */ -+ { "Line Input", NULL, "MICVDD" }, -+ { "Line Input with Micbias", NULL, "MICBIAS3" }, -+ -+ /* Dummy routes to check whether SPDIF RX is enabled or not */ -+ {"dummy SPDIFRX", NULL, "dummy SPDIF in"}, -+ {"AIFTX", NULL, "dummy SPDIFRX"}, -+ -+ /* -+ * Dummy routes to keep wm5102 from staying off on -+ * playback/capture if all mixers are off. -+ */ -+ { "Dummy Output", NULL, "AIF1RX1" }, -+ { "Dummy Output", NULL, "AIF1RX2" }, -+ { "AIF1TX1", NULL, "Dummy Input" }, -+ { "AIF1TX2", NULL, "Dummy Input" }, -+}; -+ -+static int rpi_cirrus_clear_flls(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec) { -+ -+ int ret1, ret2; -+ -+ ret1 = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, ARIZONA_FLL_SRC_NONE, 0, 0); -+ ret2 = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1_REFCLK, ARIZONA_FLL_SRC_NONE, 0, 0); -+ -+ if (ret1) { -+ dev_warn(card->dev, -+ "setting FLL1 to zero failed: %d\n", ret1); -+ return ret1; -+ } -+ if (ret2) { -+ dev_warn(card->dev, -+ "setting FLL1_REFCLK to zero failed: %d\n", ret2); -+ return ret2; -+ } -+ return 0; -+} -+ -+static int rpi_cirrus_set_fll(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec, unsigned int clk_freq) -+{ -+ int ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, -+ ARIZONA_CLK_SRC_MCLK1, -+ WM8804_CLKOUT_HZ, -+ clk_freq); -+ if (ret) -+ dev_err(card->dev, "Failed to set FLL1 to %d: %d\n", -+ clk_freq, ret); -+ -+ usleep_range(1000, 2000); -+ return ret; -+} -+ -+static int rpi_cirrus_set_fll_refclk(struct snd_soc_card *card, -+ struct snd_soc_codec *wm5102_codec, -+ unsigned int clk_freq, unsigned int aif2_freq) -+{ -+ int ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1_REFCLK, -+ ARIZONA_CLK_SRC_MCLK1, -+ WM8804_CLKOUT_HZ, -+ clk_freq); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set FLL1_REFCLK to %d: %d\n", -+ clk_freq, ret); -+ return ret; -+ } -+ -+ ret = snd_soc_codec_set_pll(wm5102_codec, -+ WM5102_FLL1, -+ ARIZONA_CLK_SRC_AIF2BCLK, -+ aif2_freq, clk_freq); -+ if (ret) -+ dev_err(card->dev, -+ "Failed to set FLL1 with Sync Clock %d to %d: %d\n", -+ aif2_freq, clk_freq, ret); -+ -+ usleep_range(1000, 2000); -+ return ret; -+} -+ -+static int rpi_cirrus_spdif_rx_enable_event(struct snd_soc_dapm_widget *w, -+ struct snd_kcontrol *kcontrol, int event) -+{ -+ struct snd_soc_card *card = w->dapm->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_codec *wm5102_codec = get_wm5102_runtime(card)->codec; -+ -+ unsigned int clk_freq, aif2_freq; -+ int ret = 0; -+ -+ switch (event) { -+ case SND_SOC_DAPM_POST_PMU: -+ mutex_lock(&priv->lock); -+ -+ /* Enable sync path in case of SPDIF capture use case */ -+ -+ clk_freq = calc_sysclk(priv->card_rate); -+ aif2_freq = 64 * priv->card_rate; -+ -+ dev_dbg(card->dev, -+ "spdif_rx: changing FLL1 to use Ref Clock clk: %d spdif: %d\n", -+ clk_freq, aif2_freq); -+ -+ ret = rpi_cirrus_clear_flls(card, wm5102_codec); -+ if (ret) { -+ dev_err(card->dev, "spdif_rx: failed to clear FLLs\n"); -+ goto out; -+ } -+ -+ ret = rpi_cirrus_set_fll_refclk(card, wm5102_codec, -+ clk_freq, aif2_freq); -+ -+ if (ret) { -+ dev_err(card->dev, "spdif_rx: failed to set FLLs\n"); -+ goto out; -+ } -+ -+ /* set to negative to indicate we're doing spdif rx */ -+ priv->fll1_freq = -clk_freq; -+ priv->sync_path_enable = 1; -+ break; -+ -+ case SND_SOC_DAPM_POST_PMD: -+ mutex_lock(&priv->lock); -+ priv->sync_path_enable = 0; -+ break; -+ -+ default: -+ return 0; -+ } -+ -+out: -+ mutex_unlock(&priv->lock); -+ return ret; -+} -+ -+static int rpi_cirrus_set_bias_level(struct snd_soc_card *card, -+ struct snd_soc_dapm_context *dapm, -+ enum snd_soc_bias_level level) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; -+ -+ int ret = 0; -+ unsigned int clk_freq; -+ -+ if (dapm->dev != wm5102_runtime->codec_dai->dev) -+ return 0; -+ -+ switch (level) { -+ case SND_SOC_BIAS_PREPARE: -+ if (dapm->bias_level == SND_SOC_BIAS_ON) -+ break; -+ -+ mutex_lock(&priv->lock); -+ -+ if (!priv->sync_path_enable) { -+ clk_freq = calc_sysclk(priv->card_rate); -+ -+ dev_dbg(card->dev, -+ "set_bias: changing FLL1 from %d to %d\n", -+ priv->fll1_freq, clk_freq); -+ -+ ret = rpi_cirrus_set_fll(card, wm5102_codec, clk_freq); -+ if (ret) -+ dev_err(card->dev, -+ "set_bias: Failed to set FLL1\n"); -+ else -+ priv->fll1_freq = clk_freq; -+ } -+ mutex_unlock(&priv->lock); -+ break; -+ default: -+ break; -+ } -+ -+ return ret; -+} -+ -+static int rpi_cirrus_set_bias_level_post(struct snd_soc_card *card, -+ struct snd_soc_dapm_context *dapm, -+ enum snd_soc_bias_level level) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_codec *wm5102_codec = wm5102_runtime->codec; -+ -+ if (dapm->dev != wm5102_runtime->codec_dai->dev) -+ return 0; -+ -+ switch (level) { -+ case SND_SOC_BIAS_STANDBY: -+ mutex_lock(&priv->lock); -+ -+ dev_dbg(card->dev, -+ "set_bias_post: changing FLL1 from %d to off\n", -+ priv->fll1_freq); -+ -+ if (rpi_cirrus_clear_flls(card, wm5102_codec)) -+ dev_err(card->dev, -+ "set_bias_post: failed to clear FLLs\n"); -+ else -+ priv->fll1_freq = 0; -+ -+ mutex_unlock(&priv->lock); -+ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int rpi_cirrus_set_wm8804_pll(struct snd_soc_card *card, -+ struct snd_soc_dai *wm8804_dai, unsigned int rate) -+{ -+ int ret; -+ -+ /* use 256fs */ -+ unsigned int clk_freq = rate * 256; -+ -+ ret = snd_soc_dai_set_pll(wm8804_dai, 0, 0, -+ WM8804_CLKOUT_HZ, clk_freq); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set WM8804 PLL to %d: %d\n", clk_freq, ret); -+ return ret; -+ } -+ -+ /* Set MCLK as PLL Output */ -+ ret = snd_soc_dai_set_sysclk(wm8804_dai, -+ WM8804_TX_CLKSRC_PLL, clk_freq, 0); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set MCLK as PLL Output: %d\n", ret); -+ return ret; -+ } -+ -+ return ret; -+} -+ -+static int rpi_cirrus_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned int min_rate = min_rates[priv->min_rate_idx].value; -+ unsigned int max_rate = max_rates[priv->max_rate_idx].value; -+ -+ if (min_rate || max_rate) { -+ if (max_rate == 0) -+ max_rate = UINT_MAX; -+ -+ dev_dbg(card->dev, -+ "startup: limiting rate to %u-%u\n", -+ min_rate, max_rate); -+ -+ snd_pcm_hw_constraint_minmax(substream->runtime, -+ SNDRV_PCM_HW_PARAM_RATE, min_rate, max_rate); -+ } -+ -+ return 0; -+} -+ -+static struct snd_soc_pcm_stream rpi_cirrus_dai_link2_params = { -+ .formats = SNDRV_PCM_FMTBIT_S24_LE, -+ .channels_min = 2, -+ .channels_max = 2, -+ .rate_min = RPI_CIRRUS_DEFAULT_RATE, -+ .rate_max = RPI_CIRRUS_DEFAULT_RATE, -+}; -+ -+static int rpi_cirrus_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_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_dai *bcm_i2s_dai = rtd->cpu_dai; -+ struct snd_soc_codec *wm5102_codec = rtd->codec; -+ struct snd_soc_dai *wm8804_dai = get_wm8804_runtime(card)->codec_dai; -+ -+ int ret; -+ -+ unsigned int width = snd_pcm_format_physical_width( -+ params_format(params)); -+ unsigned int rate = params_rate(params); -+ unsigned int clk_freq = calc_sysclk(rate); -+ -+ mutex_lock(&priv->lock); -+ -+ dev_dbg(card->dev, "hw_params: setting rate to %d\n", rate); -+ -+ ret = snd_soc_dai_set_bclk_ratio(bcm_i2s_dai, 2 * width); -+ if (ret) { -+ dev_err(card->dev, "set_bclk_ratio failed: %d\n", ret); -+ goto out; -+ } -+ -+ ret = snd_soc_dai_set_tdm_slot(rtd->codec_dai, 0x03, 0x03, 2, width); -+ if (ret) { -+ dev_err(card->dev, "set_tdm_slot failed: %d\n", ret); -+ goto out; -+ } -+ -+ /* WM8804 supports sample rates from 32k only */ -+ if (rate >= 32000) { -+ ret = rpi_cirrus_set_wm8804_pll(card, wm8804_dai, rate); -+ if (ret) -+ goto out; -+ } -+ -+ ret = snd_soc_codec_set_sysclk(wm5102_codec, -+ ARIZONA_CLK_SYSCLK, -+ ARIZONA_CLK_SRC_FLL1, -+ clk_freq, -+ SND_SOC_CLOCK_IN); -+ if (ret) { -+ dev_err(card->dev, "Failed to set SYSCLK: %d\n", ret); -+ goto out; -+ } -+ -+ if ((priv->fll1_freq > 0) && (priv->fll1_freq != clk_freq)) { -+ dev_dbg(card->dev, -+ "hw_params: changing FLL1 from %d to %d\n", -+ priv->fll1_freq, clk_freq); -+ -+ if (rpi_cirrus_clear_flls(card, wm5102_codec)) { -+ dev_err(card->dev, "hw_params: failed to clear FLLs\n"); -+ goto out; -+ } -+ -+ if (rpi_cirrus_set_fll(card, wm5102_codec, clk_freq)) { -+ dev_err(card->dev, "hw_params: failed to set FLL\n"); -+ goto out; -+ } -+ -+ priv->fll1_freq = clk_freq; -+ } -+ -+ priv->card_rate = rate; -+ rpi_cirrus_dai_link2_params.rate_min = rate; -+ rpi_cirrus_dai_link2_params.rate_max = rate; -+ -+ priv->params_set |= 1 << substream->stream; -+ -+out: -+ mutex_unlock(&priv->lock); -+ -+ return ret; -+} -+ -+static int rpi_cirrus_hw_free(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_codec *wm5102_codec = rtd->codec; -+ int ret; -+ unsigned int old_params_set = priv->params_set; -+ -+ priv->params_set &= ~(1 << substream->stream); -+ -+ /* disable sysclk if this was the last open stream */ -+ if (priv->params_set == 0 && old_params_set) { -+ dev_dbg(card->dev, -+ "hw_free: Setting SYSCLK to Zero\n"); -+ -+ ret = snd_soc_codec_set_sysclk(wm5102_codec, -+ ARIZONA_CLK_SYSCLK, -+ ARIZONA_CLK_SRC_FLL1, -+ 0, -+ SND_SOC_CLOCK_IN); -+ if (ret) -+ dev_err(card->dev, -+ "hw_free: Failed to set SYSCLK to Zero: %d\n", -+ ret); -+ } -+ return 0; -+} -+ -+static int rpi_cirrus_init_wm5102(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ int ret; -+ -+ /* no 32kHz input, derive it from sysclk if needed */ -+ snd_soc_update_bits(codec, -+ ARIZONA_CLOCK_32K_1, ARIZONA_CLK_32K_SRC_MASK, 2); -+ -+ if (rpi_cirrus_clear_flls(rtd->card, codec)) -+ dev_warn(rtd->card->dev, -+ "init_wm5102: failed to clear FLLs\n"); -+ -+ ret = snd_soc_codec_set_sysclk(codec, -+ ARIZONA_CLK_SYSCLK, ARIZONA_CLK_SRC_FLL1, -+ 0, SND_SOC_CLOCK_IN); -+ if (ret) { -+ dev_err(rtd->card->dev, -+ "Failed to set SYSCLK to Zero: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int rpi_cirrus_init_wm8804(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_codec *codec = rtd->codec; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ struct snd_soc_card *card = rtd->card; -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ unsigned int mask; -+ int i, ret; -+ -+ for (i = 0; i < 4; i++) { -+ mask = (i == 3) ? 0x3f : 0xff; -+ priv->iec958_status[i] = -+ snd_soc_read(codec, WM8804_SPDTX1 + i) & mask; -+ } -+ -+ /* Setup for 256fs */ -+ ret = snd_soc_dai_set_clkdiv(codec_dai, -+ WM8804_MCLK_DIV, WM8804_MCLKDIV_256FS); -+ if (ret) { -+ dev_err(card->dev, -+ "init_wm8804: Failed to set MCLK_DIV to 256fs: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Output OSC on CLKOUT */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, -+ WM8804_CLKOUT_SRC_OSCCLK, WM8804_CLKOUT_HZ, 0); -+ if (ret) -+ dev_err(card->dev, -+ "init_wm8804: Failed to set CLKOUT as OSC Frequency: %d\n", -+ ret); -+ -+ /* Init PLL with default samplerate */ -+ ret = rpi_cirrus_set_wm8804_pll(card, codec_dai, -+ RPI_CIRRUS_DEFAULT_RATE); -+ if (ret) -+ dev_err(card->dev, -+ "init_wm8804: Failed to setup PLL for %dHz: %d\n", -+ RPI_CIRRUS_DEFAULT_RATE, ret); -+ -+ return ret; -+} -+ -+static struct snd_soc_ops rpi_cirrus_ops = { -+ .startup = rpi_cirrus_startup, -+ .hw_params = rpi_cirrus_hw_params, -+ .hw_free = rpi_cirrus_hw_free, -+}; -+ -+static struct snd_soc_dai_link rpi_cirrus_dai[] = { -+ [DAI_WM5102] = { -+ .name = "WM5102", -+ .stream_name = "WM5102 AiFi", -+ .codec_dai_name = "wm5102-aif1", -+ .codec_name = "wm5102-codec", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &rpi_cirrus_ops, -+ .init = rpi_cirrus_init_wm5102, -+ }, -+ [DAI_WM8804] = { -+ .name = "WM5102 SPDIF", -+ .stream_name = "SPDIF Tx/Rx", -+ .cpu_dai_name = "wm5102-aif2", -+ .codec_dai_name = "wm8804-spdif", -+ .codec_name = "wm8804.1-003b", -+ .dai_fmt = SND_SOC_DAIFMT_I2S -+ | SND_SOC_DAIFMT_NB_NF -+ | SND_SOC_DAIFMT_CBM_CFM, -+ .ignore_suspend = 1, -+ .params = &rpi_cirrus_dai_link2_params, -+ .init = rpi_cirrus_init_wm8804, -+ }, -+}; -+ -+ -+static int rpi_cirrus_late_probe(struct snd_soc_card *card) -+{ -+ struct rpi_cirrus_priv *priv = snd_soc_card_get_drvdata(card); -+ struct snd_soc_pcm_runtime *wm5102_runtime = get_wm5102_runtime(card); -+ struct snd_soc_pcm_runtime *wm8804_runtime = get_wm8804_runtime(card); -+ int ret; -+ -+ dev_dbg(card->dev, "iec958_bits: %02x %02x %02x %02x\n", -+ priv->iec958_status[0], -+ priv->iec958_status[1], -+ priv->iec958_status[2], -+ priv->iec958_status[3]); -+ -+ ret = snd_soc_dai_set_sysclk( -+ wm5102_runtime->codec_dai, ARIZONA_CLK_SYSCLK, 0, 0); -+ if (ret) { -+ dev_err(card->dev, -+ "Failed to set WM5102 codec dai clk domain: %d\n", ret); -+ return ret; -+ } -+ -+ ret = snd_soc_dai_set_sysclk( -+ wm8804_runtime->cpu_dai, ARIZONA_CLK_SYSCLK, 0, 0); -+ if (ret) -+ dev_err(card->dev, -+ "Failed to set WM8804 codec dai clk domain: %d\n", ret); -+ -+ return ret; -+} -+ -+/* audio machine driver */ -+static struct snd_soc_card rpi_cirrus_card = { -+ .name = "RPi-Cirrus", -+ .driver_name = "RPiCirrus", -+ .owner = THIS_MODULE, -+ .dai_link = rpi_cirrus_dai, -+ .num_links = ARRAY_SIZE(rpi_cirrus_dai), -+ .late_probe = rpi_cirrus_late_probe, -+ .controls = rpi_cirrus_controls, -+ .num_controls = ARRAY_SIZE(rpi_cirrus_controls), -+ .dapm_widgets = rpi_cirrus_dapm_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(rpi_cirrus_dapm_widgets), -+ .dapm_routes = rpi_cirrus_dapm_routes, -+ .num_dapm_routes = ARRAY_SIZE(rpi_cirrus_dapm_routes), -+ .set_bias_level = rpi_cirrus_set_bias_level, -+ .set_bias_level_post = rpi_cirrus_set_bias_level_post, -+}; -+ -+static int rpi_cirrus_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct rpi_cirrus_priv *priv; -+ struct device_node *i2s_node; -+ -+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ priv->min_rate_idx = 1; /* min samplerate 32kHz */ -+ priv->card_rate = RPI_CIRRUS_DEFAULT_RATE; -+ -+ mutex_init(&priv->lock); -+ -+ snd_soc_card_set_drvdata(&rpi_cirrus_card, priv); -+ -+ if (!pdev->dev.of_node) -+ return -ENODEV; -+ -+ i2s_node = of_parse_phandle( -+ pdev->dev.of_node, "i2s-controller", 0); -+ if (!i2s_node) { -+ dev_err(&pdev->dev, "i2s-controller missing in DT\n"); -+ return -ENODEV; -+ } -+ -+ rpi_cirrus_dai[DAI_WM5102].cpu_of_node = i2s_node; -+ rpi_cirrus_dai[DAI_WM5102].platform_of_node = i2s_node; -+ -+ rpi_cirrus_card.dev = &pdev->dev; -+ -+ ret = devm_snd_soc_register_card(&pdev->dev, &rpi_cirrus_card); -+ if (ret) { -+ if (ret == -EPROBE_DEFER) -+ dev_dbg(&pdev->dev, -+ "register card requested probe deferral\n"); -+ else -+ dev_err(&pdev->dev, -+ "Failed to register card: %d\n", ret); -+ } -+ -+ return ret; -+} -+ -+static const struct of_device_id rpi_cirrus_of_match[] = { -+ { .compatible = "wlf,rpi-cirrus", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rpi_cirrus_of_match); -+ -+static struct platform_driver rpi_cirrus_driver = { -+ .driver = { -+ .name = "snd-rpi-cirrus", -+ .of_match_table = of_match_ptr(rpi_cirrus_of_match), -+ }, -+ .probe = rpi_cirrus_probe, -+}; -+ -+module_platform_driver(rpi_cirrus_driver); -+ -+MODULE_AUTHOR("Matthias Reichl "); -+MODULE_DESCRIPTION("ASoC driver for Cirrus Logic Audio Card"); -+MODULE_LICENSE("GPL"); - -From df45b209128930b0847ffb34d0b2a64d23d40477 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Sun, 22 Jan 2017 12:49:37 +0100 -Subject: [PATCH 134/216] config: enable Cirrus Logic Audio Card - -Signed-off-by: Matthias Reichl ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 3b2abe9c203e176e7088e504a7952e9b2c96aec8..59f58450f4f7932dbfe051d7431c227737902b37 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -662,6 +662,7 @@ CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y - CONFIG_REGULATOR=y - CONFIG_REGULATOR_FIXED_VOLTAGE=m -+CONFIG_REGULATOR_ARIZONA=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -@@ -868,6 +869,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m - CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 5351a59b7f670985f47fdbafa26117346cafe87d..062a89f0e5fc723559ddc5739e19eb20c030f0f1 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -656,6 +656,7 @@ CONFIG_MFD_ARIZONA_SPI=m - CONFIG_MFD_WM5102=y - CONFIG_REGULATOR=y - CONFIG_REGULATOR_FIXED_VOLTAGE=m -+CONFIG_REGULATOR_ARIZONA=m - CONFIG_MEDIA_SUPPORT=m - CONFIG_MEDIA_CAMERA_SUPPORT=y - CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -@@ -862,6 +863,7 @@ CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m - CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP=m -+CONFIG_SND_BCM2708_SOC_RPI_CIRRUS=m - CONFIG_SND_BCM2708_SOC_RPI_DAC=m - CONFIG_SND_BCM2708_SOC_RPI_PROTO=m - CONFIG_SND_BCM2708_SOC_JUSTBOOM_DAC=m - -From 6a15ab8874c599819f17002ab7408305ddc53e8d Mon Sep 17 00:00:00 2001 -From: Martin Cerveny -Date: Mon, 13 Feb 2017 17:23:47 +0100 -Subject: [PATCH 135/216] dwc_otg: fix summarize urb->actual_length for - isochronous transfers - -Kernel does not copy input data of ISO transfers to userspace -if actual_length is set only in ISO transfers and not summarized -in urb->actual_length. Fixes raspberrypi/linux#903 ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 162a656501988e56c9d780b7793d365fde09f801..992269d61ecf48126379a38e528f719009ee1d75 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -334,10 +334,12 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - int i; - - urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); -+ urb->actual_length = 0; - for (i = 0; i < urb->number_of_packets; ++i) { - urb->iso_frame_desc[i].actual_length = - dwc_otg_hcd_urb_get_iso_desc_actual_length - (dwc_otg_urb, i); -+ urb->actual_length += urb->iso_frame_desc[i].actual_length; - urb->iso_frame_desc[i].status = - dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); - } - -From 6e3a68dafb26bf4270d11e23a2e5d7ebb07056c9 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Feb 2017 17:20:08 +0000 -Subject: [PATCH 136/216] clk-bcm2835: Mark used PLLs and dividers CRITICAL - -The VPU configures and relies on several PLLs and dividers. Mark all -enabled dividers and their PLLs as CRITICAL to prevent the kernel from -switching them off. - -Signed-off-by: Phil Elwell ---- - drivers/clk/bcm/clk-bcm2835.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 093694e00caec6e133eb26712f890691cad999aa..33bfa2008479153402d188d71d382f0274c104ea 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1266,6 +1266,11 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, - divider->div.hw.init = &init; - divider->div.table = NULL; - -+ if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { -+ init.flags |= CLK_IS_CRITICAL; -+ divider->div.flags |= CLK_IS_CRITICAL; -+ } -+ - divider->cprman = cprman; - divider->data = data; - - -From f98f18a21e82e612c9e47558dad1c0417ddcbfbe Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 9 Feb 2017 14:33:30 +0000 -Subject: [PATCH 137/216] irq-bcm2836: Avoid "Invalid trigger warning" - -Initialise the level for each IRQ to avoid a warning from the -arm arch timer code. - -Signed-off-by: Phil Elwell ---- - drivers/irqchip/irq-bcm2836.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c -index 67dcac46cca72db4ebe2300eab04f0a867e8e14b..9a7ee04ee0d9b7aa734cf3159ed59c19a338de0d 100644 ---- a/drivers/irqchip/irq-bcm2836.c -+++ b/drivers/irqchip/irq-bcm2836.c -@@ -178,7 +178,7 @@ static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip) - - irq_set_percpu_devid(irq); - irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq); -- irq_set_status_flags(irq, IRQ_NOAUTOEN); -+ irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_TYPE_LEVEL_LOW); - } - - static void - -From ab319528c75ea254a4db55410da7c4afd2127a21 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 9 Feb 2017 14:36:44 +0000 -Subject: [PATCH 138/216] sound: Demote deferral errors to INFO level - -At present there is no mechanism to specify driver load order, -which can lead to deferrals and repeated retries until successful. -Since this situation is expected, reduce the dmesg level to -INFO and mention that the operation will be retried. - -Signed-off-by: Phil Elwell ---- - sound/soc/soc-core.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c -index baa1afa41e3dd57fdc36655b7d3bbd147ade820f..0ddeffcc48d6c14f275ea6409d1a7de8f1f64183 100644 ---- a/sound/soc/soc-core.c -+++ b/sound/soc/soc-core.c -@@ -1056,7 +1056,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, - cpu_dai_component.dai_name = dai_link->cpu_dai_name; - rtd->cpu_dai = snd_soc_find_dai(&cpu_dai_component); - if (!rtd->cpu_dai) { -- dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", -+ dev_info(card->dev, "ASoC: CPU DAI %s not registered - will retry\n", - dai_link->cpu_dai_name); - goto _err_defer; - } -@@ -1068,7 +1068,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, - for (i = 0; i < rtd->num_codecs; i++) { - codec_dais[i] = snd_soc_find_dai(&codecs[i]); - if (!codec_dais[i]) { -- dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", -+ dev_info(card->dev, "ASoC: CODEC DAI %s not registered - will retry\n", - codecs[i].dai_name); - goto _err_defer; - } - -From 794ecc86f25bfb6e2cbbe2b7065d41363fe59da8 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Thu, 9 Feb 2017 14:40:33 +0000 -Subject: [PATCH 139/216] sound: Suppress error message about deferrals - -Since driver load deferrals are expected and will already -have resulted in a kernel message, suppress an essentially -duplicate error message from the RPi audio board drivers. - -Signed-off-by: Phil Elwell ---- - sound/soc/bcm/adau1977-adc.c | 2 +- - sound/soc/bcm/allo-piano-dac.c | 2 +- - sound/soc/bcm/digidac1-soundcard.c | 4 ++-- - sound/soc/bcm/dionaudio_loco.c | 2 +- - sound/soc/bcm/hifiberry_amp.c | 3 +-- - sound/soc/bcm/hifiberry_dac.c | 2 +- - sound/soc/bcm/hifiberry_dacplus.c | 2 +- - sound/soc/bcm/hifiberry_digi.c | 2 +- - sound/soc/bcm/iqaudio-dac.c | 5 +++-- - sound/soc/bcm/iqaudio_digi.c | 2 +- - sound/soc/bcm/justboom-dac.c | 2 +- - sound/soc/bcm/justboom-digi.c | 2 +- - sound/soc/bcm/pisound.c | 3 ++- - sound/soc/bcm/raspidac3.c | 2 +- - sound/soc/bcm/rpi-dac.c | 2 +- - sound/soc/bcm/rpi-proto.c | 3 +-- - 16 files changed, 20 insertions(+), 20 deletions(-) - -diff --git a/sound/soc/bcm/adau1977-adc.c b/sound/soc/bcm/adau1977-adc.c -index 6e2ee027926ee63c89222f75ceb89e3d2434b0e1..f3d7e5db7bb912e1d7ca6f8e8d42df5f59c9edb8 100644 ---- a/sound/soc/bcm/adau1977-adc.c -+++ b/sound/soc/bcm/adau1977-adc.c -@@ -90,7 +90,7 @@ static int snd_adau1977_adc_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_adau1977_adc); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - - return ret; -diff --git a/sound/soc/bcm/allo-piano-dac.c b/sound/soc/bcm/allo-piano-dac.c -index 8e8e62e5a36a279b425ed4655cfbac99ecd7e4cf..eaf50fb6dbca1970ae1c6f8662088b0f1573fecb 100644 ---- a/sound/soc/bcm/allo-piano-dac.c -+++ b/sound/soc/bcm/allo-piano-dac.c -@@ -109,7 +109,7 @@ static int snd_allo_piano_dac_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_allo_piano_dac); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); - -diff --git a/sound/soc/bcm/digidac1-soundcard.c b/sound/soc/bcm/digidac1-soundcard.c -index 446796e7e4c14a7d95b2f2a01211d9a0b151f1f3..f200688bb4ae32b90a0ced555aed94b0add0ac8a 100644 ---- a/sound/soc/bcm/digidac1-soundcard.c -+++ b/sound/soc/bcm/digidac1-soundcard.c -@@ -387,9 +387,9 @@ static int digidac1_soundcard_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&digidac1_soundcard); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -- ret); -+ ret); - - return ret; - } -diff --git a/sound/soc/bcm/dionaudio_loco.c b/sound/soc/bcm/dionaudio_loco.c -index 89e65317512bc774453ac8d0d5b0ff98aacb740a..65e03741d349a2dc5bd91f69855ea952d9cf87a2 100644 ---- a/sound/soc/bcm/dionaudio_loco.c -+++ b/sound/soc/bcm/dionaudio_loco.c -@@ -86,7 +86,7 @@ static int snd_rpi_dionaudio_loco_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_dionaudio_loco); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - -diff --git a/sound/soc/bcm/hifiberry_amp.c b/sound/soc/bcm/hifiberry_amp.c -index d17c29780507dc31c50f1d567ff5cea7c8241ff5..221c6c38e6465ffe5d5ad77fa80a0b146d0b6841 100644 ---- a/sound/soc/bcm/hifiberry_amp.c -+++ b/sound/soc/bcm/hifiberry_amp.c -@@ -96,9 +96,8 @@ static int snd_rpi_hifiberry_amp_probe(struct platform_device *pdev) - - ret = snd_soc_register_card(&snd_rpi_hifiberry_amp); - -- if (ret != 0) { -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -- } - - return ret; - } -diff --git a/sound/soc/bcm/hifiberry_dac.c b/sound/soc/bcm/hifiberry_dac.c -index 45f2b770ad9e67728ca599a7445d6ae9a01c0c29..ee9f133953544629282631e5ef3f73fec857a7c5 100644 ---- a/sound/soc/bcm/hifiberry_dac.c -+++ b/sound/soc/bcm/hifiberry_dac.c -@@ -90,7 +90,7 @@ static int snd_rpi_hifiberry_dac_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_hifiberry_dac); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - - return ret; -diff --git a/sound/soc/bcm/hifiberry_dacplus.c b/sound/soc/bcm/hifiberry_dacplus.c -index bdc35e7e6bc12dc1cf04f5ffad8f9ab49a0b0266..b7b401cbe2b0d510d8b12d2dda6d5ff1fff42eb0 100644 ---- a/sound/soc/bcm/hifiberry_dacplus.c -+++ b/sound/soc/bcm/hifiberry_dacplus.c -@@ -324,7 +324,7 @@ static int snd_rpi_hifiberry_dacplus_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_hifiberry_dacplus); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); - -diff --git a/sound/soc/bcm/hifiberry_digi.c b/sound/soc/bcm/hifiberry_digi.c -index 19dc953b7227ba86123fc7a2ba654499e0c581c5..7620dd02de40b6d644ff038b445d375d8f632def 100644 ---- a/sound/soc/bcm/hifiberry_digi.c -+++ b/sound/soc/bcm/hifiberry_digi.c -@@ -242,7 +242,7 @@ static int snd_rpi_hifiberry_digi_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_hifiberry_digi); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - - return ret; -diff --git a/sound/soc/bcm/iqaudio-dac.c b/sound/soc/bcm/iqaudio-dac.c -index aa15bc4b49ca95edec905fddd8fd0a6d839ca627..1ee4097c846376666775272ed692ca330881b0cb 100644 ---- a/sound/soc/bcm/iqaudio-dac.c -+++ b/sound/soc/bcm/iqaudio-dac.c -@@ -197,8 +197,9 @@ static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev) - - ret = snd_soc_register_card(&snd_rpi_iqaudio_dac); - if (ret) { -- dev_err(&pdev->dev, -- "snd_soc_register_card() failed: %d\n", ret); -+ if (ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, -+ "snd_soc_register_card() failed: %d\n", ret); - return ret; - } - -diff --git a/sound/soc/bcm/iqaudio_digi.c b/sound/soc/bcm/iqaudio_digi.c -index 9b6e829bcb5b1762a853775e7816319639e39d65..33aa2be8a43a12a12cfb5d844dd9732c2393d510 100644 ---- a/sound/soc/bcm/iqaudio_digi.c -+++ b/sound/soc/bcm/iqaudio_digi.c -@@ -204,7 +204,7 @@ static int snd_rpi_iqaudio_digi_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(card); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", - ret); - -diff --git a/sound/soc/bcm/justboom-dac.c b/sound/soc/bcm/justboom-dac.c -index 05a224ec712d06b8b7587ab6b8bb562d19956d47..9bab6cf063d3d450d96b4ee2196a7384e071cbdb 100644 ---- a/sound/soc/bcm/justboom-dac.c -+++ b/sound/soc/bcm/justboom-dac.c -@@ -128,7 +128,7 @@ static int snd_rpi_justboom_dac_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_justboom_dac); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); - -diff --git a/sound/soc/bcm/justboom-digi.c b/sound/soc/bcm/justboom-digi.c -index abfdc5c4dd5811e6847bddda4921abe33fa02812..909cf8928f2f4313982316f9c5b8a709c1d47ab8 100644 ---- a/sound/soc/bcm/justboom-digi.c -+++ b/sound/soc/bcm/justboom-digi.c -@@ -181,7 +181,7 @@ static int snd_rpi_justboom_digi_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_justboom_digi); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); - -diff --git a/sound/soc/bcm/pisound.c b/sound/soc/bcm/pisound.c -index ba70734b89e61a11201657406223f0b37d54f74a..06ff1e53dc9d860946965b6303577762f958fae2 100644 ---- a/sound/soc/bcm/pisound.c -+++ b/sound/soc/bcm/pisound.c -@@ -1076,7 +1076,8 @@ static int pisnd_probe(struct platform_device *pdev) - ret = snd_soc_register_card(&pisnd_card); - - if (ret < 0) { -- printe("snd_soc_register_card() failed: %d\n", ret); -+ if (ret != -EPROBE_DEFER) -+ printe("snd_soc_register_card() failed: %d\n", ret); - pisnd_uninit_gpio(); - kobject_put(pisnd_kobj); - pisnd_spi_uninit(); -diff --git a/sound/soc/bcm/raspidac3.c b/sound/soc/bcm/raspidac3.c -index dd9eeea2af0382307f437e6db09d15468c1a470a..ad2b5b89bc8213dc2e277306ef50d6e32448759c 100644 ---- a/sound/soc/bcm/raspidac3.c -+++ b/sound/soc/bcm/raspidac3.c -@@ -149,7 +149,7 @@ static int snd_rpi_raspidac3_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_raspidac3); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); - -diff --git a/sound/soc/bcm/rpi-dac.c b/sound/soc/bcm/rpi-dac.c -index 59dc89ecabc082c0a1ed8adacdc4f0f1337a1c73..38224467cbab7d5be3be731e73e2cf787cd9908a 100644 ---- a/sound/soc/bcm/rpi-dac.c -+++ b/sound/soc/bcm/rpi-dac.c -@@ -85,7 +85,7 @@ static int snd_rpi_rpi_dac_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_rpi_dac); -- if (ret) -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); - - return ret; -diff --git a/sound/soc/bcm/rpi-proto.c b/sound/soc/bcm/rpi-proto.c -index 9db678e885efd63d84d60a098a84ed6772b19a2d..fadbfade100228aaafabb0d3bdf35c01f8d10485 100644 ---- a/sound/soc/bcm/rpi-proto.c -+++ b/sound/soc/bcm/rpi-proto.c -@@ -117,10 +117,9 @@ static int snd_rpi_proto_probe(struct platform_device *pdev) - } - - ret = snd_soc_register_card(&snd_rpi_proto); -- if (ret) { -+ if (ret && ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "snd_soc_register_card() failed: %d\n", ret); -- } - - return ret; - } - -From 951a778c8d596c5947769cb37c34815ed7f1af7c Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 17 Feb 2017 09:47:11 +0000 -Subject: [PATCH 140/216] BCM270X_DT: Add SMSC ethernet controller to DT - -With an ethernet node in the DT, a suitable firmware can populate the -local-mac-address property, removing the need for a downstream patch -to the driver to read its MAC address from a module parameter. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 1 + - arch/arm/boot/dts/bcm2708-rpi-b.dts | 1 + - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 1 + - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 1 + - 4 files changed, 4 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 360da5c928dc5599b0d2a9055728087604c6b189..0b66ac9f25a5f7ae51f3d0666cfcb908f85e1d24 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -1,6 +1,7 @@ - /dts-v1/; - - #include "bcm2708.dtsi" -+#include "bcm283x-rpi-smsc9514.dtsi" - - / { - model = "Raspberry Pi Model B+"; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index 9c49659ab246bce0656f3514f3b924bc4826b421..e99e9d999e4142060c41eb47b93c8ac70a30f384 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -1,6 +1,7 @@ - /dts-v1/; - - #include "bcm2708.dtsi" -+#include "bcm283x-rpi-smsc9512.dtsi" - - / { - model = "Raspberry Pi Model B"; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 19c83823420fc3cc20a01d07091100cb8720ff4d..20674f250af922e9f9a43e3e8b13aee42e3930be 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -1,6 +1,7 @@ - /dts-v1/; - - #include "bcm2709.dtsi" -+#include "bcm283x-rpi-smsc9514.dtsi" - - / { - model = "Raspberry Pi 2 Model B"; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 12764a3495b2372ffaf47e32ea0d21326ca83686..2a5b512d3e1acb17c6a40bf9d370f22279c4d552 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -5,6 +5,7 @@ - #endif - - #include "bcm2710.dtsi" -+#include "bcm283x-rpi-smsc9514.dtsi" - - / { - model = "Raspberry Pi 3 Model B"; - -From 564bd54d2712fdd6361a52cd3970e63ed24b0aea Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Fri, 17 Feb 2017 15:26:13 +0000 -Subject: [PATCH 141/216] brcmfmac: Mute expected startup 'errors' - -The brcmfmac WiFi driver always complains about the '00' country code -and the firmware version is reported as an error. Modify the driver to -ignore '00' silently and display firmware version at INFO level. - -Signed-off-by: Phil Elwell ---- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++ - drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +- - 2 files changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -index 5dfcf16428f9c8687237c3218183d8afa66ec331..873ec96c300fa152ecf3b1c2d3b3a890de7df115 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -6717,6 +6717,8 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, - /* ignore non-ISO3166 country codes */ - for (i = 0; i < sizeof(req->alpha2); i++) - if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { -+ if (req->alpha2[0] == '0' && req->alpha2[1] == '0') -+ return; - brcmf_err("not a ISO3166 code (0x%02x 0x%02x)\n", - req->alpha2[0], req->alpha2[1]); - return; -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -index 4051780f64f44a5ce522babe6c371a1beb79a824..b081673abcb4aa72d70d8e0834b608f65fea16e8 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c -@@ -161,7 +161,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) - strsep(&ptr, "\n"); - - /* Print fw version info */ -- brcmf_err("Firmware version = %s\n", buf); -+ pr_info("Firmware version = %s\n", buf); - - /* locate firmware version number for ethtool */ - ptr = strrchr(buf, ' ') + 1; - -From 5d6f3fae2649254fc46d87e4bb65fb19cbfdfec3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Feb 2017 17:20:08 +0000 -Subject: [PATCH 142/216] clk-bcm2835: Add claim-clocks property - -The claim-clocks property can be used to prevent PLLs and dividers -from being marked as critical. It contains a vector of clock IDs, -as defined by dt-bindings/clock/bcm2835.h. - -Use this mechanism to claim PLLD_DSI0, PLLD_DSI1, PLLH_AUX and -PLLH_PIX for the vc4_kms_v3d driver. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 15 ++++++++++ - drivers/clk/bcm/clk-bcm2835.c | 34 ++++++++++++++++++++-- - 2 files changed, 47 insertions(+), 2 deletions(-) - -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 4f1cc20f90dc6780f74e08ebee00e5a1a6062c85..fb45c6456b181b047d6cff8784f7696eb75da3c7 100644 ---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -5,6 +5,8 @@ - /dts-v1/; - /plugin/; - -+#include -+ - / { - compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709"; - -@@ -126,6 +128,19 @@ - }; - }; - -+ -+ fragment@16 { -+ target = <&clocks>; -+ __overlay__ { -+ claim-clocks = < -+ BCM2835_PLLD_DSI0 -+ BCM2835_PLLD_DSI1 -+ BCM2835_PLLH_AUX -+ BCM2835_PLLH_PIX -+ >; -+ }; -+ }; -+ - __overrides__ { - cma-256 = <0>,"+0-1-2-3-4"; - cma-192 = <0>,"-0+1-2-3-4"; -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 33bfa2008479153402d188d71d382f0274c104ea..0b62d20f8b718cfd03c0346af784688e26e9dcb6 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1198,6 +1198,8 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = { - .debug_init = bcm2835_clock_debug_init, - }; - -+static bool bcm2835_clk_is_claimed(const char *name); -+ - static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, - const struct bcm2835_pll_data *data) - { -@@ -1214,6 +1216,9 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, - init.ops = &bcm2835_pll_clk_ops; - init.flags = CLK_IGNORE_UNUSED; - -+ if (!bcm2835_clk_is_claimed(data->name)) -+ init.flags |= CLK_IS_CRITICAL; -+ - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) - return NULL; -@@ -1267,8 +1272,10 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, - divider->div.table = NULL; - - if (!(cprman_read(cprman, data->cm_reg) & data->hold_mask)) { -- init.flags |= CLK_IS_CRITICAL; -- divider->div.flags |= CLK_IS_CRITICAL; -+ if (!bcm2835_clk_is_claimed(data->source_pll)) -+ init.flags |= CLK_IS_CRITICAL; -+ if (!bcm2835_clk_is_claimed(data->name)) -+ divider->div.flags |= CLK_IS_CRITICAL; - } - - divider->cprman = cprman; -@@ -1901,6 +1908,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_PERIICTL), - }; - -+static bool bcm2835_clk_claimed[ARRAY_SIZE(clk_desc_array)]; -+ - /* - * Permanently take a reference on the parent of the SDRAM clock. - * -@@ -1920,6 +1929,19 @@ static int bcm2835_mark_sdc_parent_critical(struct clk *sdc) - return clk_prepare_enable(parent); - } - -+static bool bcm2835_clk_is_claimed(const char *name) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(clk_desc_array); i++) { -+ const char *clk_name = *(const char **)(clk_desc_array[i].data); -+ if (!strcmp(name, clk_name)) -+ return bcm2835_clk_claimed[i]; -+ } -+ -+ return false; -+} -+ - static int bcm2835_clk_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -@@ -1929,6 +1951,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - const struct bcm2835_clk_desc *desc; - const size_t asize = ARRAY_SIZE(clk_desc_array); - size_t i; -+ u32 clk_id; - int ret; - - cprman = devm_kzalloc(dev, sizeof(*cprman) + -@@ -1944,6 +1967,13 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - if (IS_ERR(cprman->regs)) - return PTR_ERR(cprman->regs); - -+ memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed)); -+ for (i = 0; -+ !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", -+ i, &clk_id); -+ i++) -+ bcm2835_clk_claimed[clk_id]= true; -+ - cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0); - if (!cprman->osc_name) - return -ENODEV; - -From 7e2eced086d7d83072ef6a3e575f70c45d298e47 Mon Sep 17 00:00:00 2001 -From: Matthias Reichl -Date: Mon, 20 Feb 2017 20:01:16 +0100 -Subject: [PATCH 143/216] 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 -Reviewed-by: Eric Anholt ---- - 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 80d35f760b4a4a51e60c355a84d538bac3892a4d..599c218dc8a73172dd4bd4a058fc8f95a73f982f 100644 ---- a/drivers/dma/bcm2835-dma.c -+++ b/drivers/dma/bcm2835-dma.c -@@ -253,8 +253,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 4e1fb4ee789218cfd22011c28a6b6b24e4321c0f Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Thu, 23 Feb 2017 11:56:20 -0500 -Subject: [PATCH 144/216] config: Add ads1015 driver to config - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 59f58450f4f7932dbfe051d7431c227737902b37..33f5dfda12efc3022da80982e65df09b4cf7a52e 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -649,6 +649,7 @@ CONFIG_HWMON=m - CONFIG_SENSORS_LM75=m - CONFIG_SENSORS_SHT21=m - CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_ADS1015=m - CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 062a89f0e5fc723559ddc5739e19eb20c030f0f1..97b88dcbc1e6c5b165406222227157776b162801 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -643,6 +643,7 @@ CONFIG_HWMON=m - CONFIG_SENSORS_LM75=m - CONFIG_SENSORS_SHT21=m - CONFIG_SENSORS_SHTC1=m -+CONFIG_SENSORS_ADS1015=m - CONFIG_SENSORS_INA2XX=m - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - -From 10fd5a8fe54bcc88d7ca64e793d8ff79ea7f06cc Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 27 Jan 2017 18:49:30 +0000 -Subject: [PATCH 145/216] config: add slcan kernel module - -See: https://github.com/raspberrypi/linux/issues/1819 ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 33f5dfda12efc3022da80982e65df09b4cf7a52e..6d1e9c7f30d80d28bc12bae0ee40044b31237f85 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -358,6 +358,7 @@ CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m -+CONFIG_CAN_SLCAN=m - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 97b88dcbc1e6c5b165406222227157776b162801..2cfa65bc83fd4b7e802f56965543a217e7d5ed5c 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -354,6 +354,7 @@ CONFIG_BAYCOM_SER_HDX=m - CONFIG_YAM=m - CONFIG_CAN=m - CONFIG_CAN_VCAN=m -+CONFIG_CAN_SLCAN=m - CONFIG_CAN_MCP251X=m - CONFIG_IRDA=m - CONFIG_IRLAN=m - -From 91bbfa475cfbbc9b4b1f2995b8de766588a636bb Mon Sep 17 00:00:00 2001 -From: Miquel -Date: Fri, 24 Feb 2017 20:51:06 +0100 -Subject: [PATCH 146/216] sound: Support for Dion Audio LOCO-V2 DAC-AMP HAT - -Signed-off-by: Miquel Blauw ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 19 +++ - .../dts/overlays/dionaudio-loco-v2-overlay.dts | 49 ++++++++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - sound/soc/bcm/Kconfig | 7 ++ - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/dionaudio_loco-v2.c | 140 +++++++++++++++++++++ - 8 files changed, 220 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts - create mode 100644 sound/soc/bcm/dionaudio_loco-v2.c - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 0a7d30cd573060964bb081ee6617d5b77a17b974..8856139d061472311b7cead0641b5645ef33caad 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -13,6 +13,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - bmp085_i2c-sensor.dtbo \ - dht11.dtbo \ - dionaudio-loco.dtbo \ -+ dionaudio-loco-v2.dtbo \ - dpi18.dtbo \ - dpi24.dtbo \ - dwc-otg.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 46228fd324fc4c52eb0ba50316b4c02f8245bf04..c9845ba37018b821d7e5093e15a06721318b558f 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -308,6 +308,25 @@ Load: dtoverlay=dionaudio-loco - Params: - - -+Name: dionaudio-loco-v2 -+Info: Configures the Dion Audio LOCO-V2 DAC-AMP -+Load: dtoverlay=dionaudio-loco-v2,= -+Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec -+ Digital volume control. Enable with -+ "dtoverlay=hifiberry-dacplus,24db_digital_gain" -+ (The default behaviour is that the Digital -+ volume control is limited to a maximum of -+ 0dB. ie. it can attenuate but not provide -+ gain. For most users, this will be desired -+ as it will prevent clipping. By appending -+ the 24dB_digital_gain parameter, the Digital -+ volume control will allow up to 24dB of -+ gain. If this parameter is enabled, it is the -+ responsibility of the user to ensure that -+ the Digital volume control is set to a value -+ that does not result in clipping/distortion!) -+ -+ - Name: dpi18 - Info: Overlay for a generic 18-bit DPI display - This uses GPIOs 0-21 (so no I2C, uart etc.), and activates the output -diff --git a/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..a1af93de30119734e8d14cbd454589d365a3ba10 ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/dionaudio-loco-v2-overlay.dts -@@ -0,0 +1,49 @@ -+/* -+ * Definitions for Dion Audio LOCO-V2 DAC-AMP -+ * eg. dtoverlay=dionaudio-loco-v2 -+ * -+ * PCM5242 DAC (in software mode) and TPA3255 AMP. -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&sound>; -+ frag0: __overlay__ { -+ compatible = "dionaudio,dionaudio-loco-v2"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pcm5122@4c { -+ #sound-dai-cells = <0>; -+ compatible = "ti,pcm5122"; -+ reg = <0x4d>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ 24db_digital_gain = <&frag0>,"dionaudio,24db_digital_gain?"; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 6d1e9c7f30d80d28bc12bae0ee40044b31237f85..c48df02efdf83a16ef97babc1353487dc2fcfb18 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -883,6 +883,7 @@ 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_BCM2708_SOC_DIONAUDIO_LOCO_V2=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 2cfa65bc83fd4b7e802f56965543a217e7d5ed5c..92e0536cb9d5a1fe0b7c16edae18d1b3e71e053b 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -877,6 +877,7 @@ 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_BCM2708_SOC_DIONAUDIO_LOCO_V2=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index c0489e591b9b8c8da004ca9e300e97f1a21e5ce1..3e1ee13ef8ec31849e29e551026ba427f8e44fe6 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -134,6 +134,13 @@ config SND_BCM2708_SOC_DIONAUDIO_LOCO - help - Say Y or M if you want to add support for Dion Audio LOCO. - -+config SND_BCM2708_SOC_DIONAUDIO_LOCO_V2 -+ tristate "Support for Dion Audio LOCO-V2 DAC-AMP" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_PCM5122 -+ help -+ Say Y or M if you want to add support for Dion Audio LOCO-V2. -+ - config SND_BCM2708_SOC_ALLO_PIANO_DAC - tristate "Support for Allo Piano DAC" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 84c2b20ce2e51b525797ee58de95734ee7847e15..4d8adf691021a974310589e92e599924811f22cb 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -25,6 +25,7 @@ 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 -+snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o - snd-soc-allo-piano-dac-objs := allo-piano-dac.o - snd-soc-pisound-objs := pisound.o - -@@ -44,5 +45,6 @@ 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 - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o -+obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o - obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o -diff --git a/sound/soc/bcm/dionaudio_loco-v2.c b/sound/soc/bcm/dionaudio_loco-v2.c -new file mode 100644 -index 0000000000000000000000000000000000000000..a009c49477972a9832175d86f201b0357a08f7c0 ---- /dev/null -+++ b/sound/soc/bcm/dionaudio_loco-v2.c -@@ -0,0 +1,140 @@ -+/* -+ * ASoC Driver for Dion Audio LOCO-V2 DAC-AMP -+ * -+ * Author: Miquel Blauw -+ * Copyright 2017 -+ * -+ * 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. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+static bool digital_gain_0db_limit = true; -+ -+static int snd_rpi_dionaudio_loco_v2_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_dionaudio_loco_v2_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_dionaudio_loco_v2_ops = { -+ .hw_params = snd_rpi_dionaudio_loco_v2_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_rpi_dionaudio_loco_v2_dai[] = { -+{ -+ .name = "DionAudio LOCO-V2", -+ .stream_name = "DionAudio LOCO-V2 DAC-AMP", -+ .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_dionaudio_loco_v2_ops, -+ .init = snd_rpi_dionaudio_loco_v2_init, -+},}; -+ -+/* audio machine driver */ -+static struct snd_soc_card snd_rpi_dionaudio_loco_v2 = { -+ .name = "Dion Audio LOCO-V2", -+ .dai_link = snd_rpi_dionaudio_loco_v2_dai, -+ .num_links = ARRAY_SIZE(snd_rpi_dionaudio_loco_v2_dai), -+}; -+ -+static int snd_rpi_dionaudio_loco_v2_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ -+ snd_rpi_dionaudio_loco_v2.dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = -+ &snd_rpi_dionaudio_loco_v2_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, "dionaudio,24db_digital_gain"); -+ } -+ -+ ret = snd_soc_register_card(&snd_rpi_dionaudio_loco_v2); -+ if (ret) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", -+ ret); -+ -+ return ret; -+} -+ -+static int snd_rpi_dionaudio_loco_v2_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&snd_rpi_dionaudio_loco_v2); -+} -+ -+static const struct of_device_id dionaudio_of_match[] = { -+ { .compatible = "dionaudio,dionaudio-loco-v2", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, dionaudio_of_match); -+ -+static struct platform_driver snd_rpi_dionaudio_loco_v2_driver = { -+ .driver = { -+ .name = "snd-rpi-dionaudio-loco-v2", -+ .owner = THIS_MODULE, -+ .of_match_table = dionaudio_of_match, -+ }, -+ .probe = snd_rpi_dionaudio_loco_v2_probe, -+ .remove = snd_rpi_dionaudio_loco_v2_remove, -+}; -+ -+module_platform_driver(snd_rpi_dionaudio_loco_v2_driver); -+ -+MODULE_AUTHOR("Miquel Blauw "); -+MODULE_DESCRIPTION("ASoC Driver for DionAudio LOCO-V2"); -+MODULE_LICENSE("GPL v2"); - -From b3b7a13057bc19e925c4a1d0829795868bc2918d Mon Sep 17 00:00:00 2001 -From: Fe-Pi -Date: Wed, 1 Mar 2017 04:42:43 -0700 -Subject: [PATCH 147/216] Add support for Fe-Pi audio sound card. (#1867) - -Fe-Pi Audio Sound Card is based on NXP SGTL5000 codec. -Mechanical specification of the board is the same the Raspberry Pi Zero. -3.5mm jacks for Headphone/Mic, Line In, and Line Out. - -Signed-off-by: Henry Kupis ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts | 70 +++++++++ - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/fe-pi-audio.c | 158 +++++++++++++++++++++ - 8 files changed, 246 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts - create mode 100644 sound/soc/bcm/fe-pi-audio.c - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index 8856139d061472311b7cead0641b5645ef33caad..c8825365a4129b0098abf2002e1dcd936ea1ec8c 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -20,6 +20,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - dwc2.dtbo \ - enc28j60.dtbo \ - enc28j60-spi2.dtbo \ -+ fe-pi-audio.dtbo \ - gpio-ir.dtbo \ - gpio-poweroff.dtbo \ - hifiberry-amp.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c9845ba37018b821d7e5093e15a06721318b558f..788e9e3b23f37d4c44b94b60ff2b72e2f0dbeeac 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -383,6 +383,12 @@ Params: int_pin GPIO used for INT (default 39) - speed SPI bus speed (default 12000000) - - -+Name: fe-pi-audio -+Info: Configures the Fe-Pi Audio Sound Card -+Load: dtoverlay=fe-pi-audio -+Params: -+ -+ - Name: gpio-ir - Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- - based gpio_ir_recv driver maps received keys directly to a -diff --git a/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..81a07ed5a8c7594e65f0df2176418cac57a7910c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/fe-pi-audio-overlay.dts -@@ -0,0 +1,70 @@ -+// Definitions for Fe-Pi Audio -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&clocks>; -+ __overlay__ { -+ sgtl5000_mclk: sgtl5000_mclk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <12288000>; -+ clock-output-names = "sgtl5000-mclk"; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target = <&soc>; -+ __overlay__ { -+ reg_1v8: reg_1v8@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "1V8"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&i2c1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ sgtl5000@0a { -+ #sound-dai-cells = <0>; -+ compatible = "fepi,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&sgtl5000_mclk>; -+ micbias-resistor-k-ohms = <2>; -+ micbias-voltage-m-volts = <3000>; -+ VDDA-supply = <&vdd_3v3_reg>; -+ VDDIO-supply = <&vdd_3v3_reg>; -+ VDDD-supply = <®_1v8>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target = <&i2s>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@4 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "fe-pi,fe-pi-audio"; -+ i2s-controller = <&i2s>; -+ status = "okay"; -+ }; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index c48df02efdf83a16ef97babc1353487dc2fcfb18..4ca09cf1e4e19154868b576eb3827b85789b6caf 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -885,6 +885,7 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 92e0536cb9d5a1fe0b7c16edae18d1b3e71e053b..a9c46f902eb32b364423d8bef07b6b37f798c617 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -879,6 +879,7 @@ CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m - CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m -+CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m - CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 3e1ee13ef8ec31849e29e551026ba427f8e44fe6..7473efd6f400a1a1618aac830753fce39d203b89 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -148,6 +148,13 @@ config SND_BCM2708_SOC_ALLO_PIANO_DAC - help - Say Y or M if you want to add support for Allo Piano DAC. - -+config SND_BCM2708_SOC_FE_PI_AUDIO -+ tristate "Support for Fe-Pi-Audio" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_SGTL5000 -+ help -+ Say Y or M if you want to add support for Fe-Pi-Audio. -+ - config SND_PISOUND - tristate "Support for Blokas Labs pisound" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 4d8adf691021a974310589e92e599924811f22cb..8d2d2073dc2cede9fbd9eb8b49083650ba0a8172 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -28,6 +28,7 @@ snd-soc-dionaudio-loco-objs := dionaudio_loco.o - snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o - snd-soc-allo-piano-dac-objs := allo-piano-dac.o - snd-soc-pisound-objs := pisound.o -+snd-soc-fe-pi-audio-objs := fe-pi-audio.o - - obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o - obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_AMP) += snd-soc-hifiberry-amp.o -@@ -48,3 +49,4 @@ obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o - obj-$(CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC) += snd-soc-allo-piano-dac.o - obj-$(CONFIG_SND_PISOUND) += snd-soc-pisound.o -+obj-$(CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO) += snd-soc-fe-pi-audio.o -diff --git a/sound/soc/bcm/fe-pi-audio.c b/sound/soc/bcm/fe-pi-audio.c -new file mode 100644 -index 0000000000000000000000000000000000000000..015b56fd73cc36be5b5eecd17548fd036eb64d61 ---- /dev/null -+++ b/sound/soc/bcm/fe-pi-audio.c -@@ -0,0 +1,158 @@ -+/* -+ * ASoC Driver for Fe-Pi Audio Sound Card -+ * -+ * Author: Henry Kupis -+ * Copyright 2016 -+ * based on code by Florian Meier -+ * based on code by Shawn Guo -+ * -+ * 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 "../codecs/sgtl5000.h" -+ -+static int snd_fe_pi_audio_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ struct snd_soc_card *card = rtd->card; -+ struct snd_soc_codec *codec = rtd->codec; -+ -+ snd_soc_dapm_force_enable_pin(&card->dapm, "LO"); -+ snd_soc_dapm_force_enable_pin(&card->dapm, "ADC"); -+ snd_soc_dapm_force_enable_pin(&card->dapm, "DAC"); -+ snd_soc_dapm_force_enable_pin(&card->dapm, "HP"); -+ snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, -+ SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); -+ -+ return 0; -+} -+ -+static int snd_fe_pi_audio_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ struct device *dev = rtd->card->dev; -+ struct snd_soc_dai *codec_dai = rtd->codec_dai; -+ -+ int ret; -+ -+ /* Set SGTL5000's SYSCLK */ -+ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, 12288000, SND_SOC_CLOCK_IN); -+ if (ret) { -+ dev_err(dev, "could not set codec driver clock params\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+ -+static struct snd_soc_ops snd_fe_pi_audio_ops = { -+ .hw_params = snd_fe_pi_audio_hw_params, -+}; -+ -+static struct snd_soc_dai_link snd_fe_pi_audio_dai[] = { -+ { -+ .name = "FE-PI", -+ .stream_name = "Fe-Pi HiFi", -+ .cpu_dai_name = "bcm2708-i2s.0", -+ .codec_dai_name = "sgtl5000", -+ .platform_name = "bcm2708-i2s.0", -+ .codec_name = "sgtl5000.1-000a", -+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | -+ SND_SOC_DAIFMT_CBM_CFM, -+ .ops = &snd_fe_pi_audio_ops, -+ .init = snd_fe_pi_audio_init, -+ }, -+}; -+ -+static const struct snd_soc_dapm_route fe_pi_audio_dapm_routes[] = { -+ {"ADC", NULL, "Mic Bias"}, -+}; -+ -+ -+static struct snd_soc_card fe_pi_audio = { -+ .name = "Fe-Pi Audio", -+ .owner = THIS_MODULE, -+ .dai_link = snd_fe_pi_audio_dai, -+ .num_links = ARRAY_SIZE(snd_fe_pi_audio_dai), -+ -+ .dapm_routes = fe_pi_audio_dapm_routes, -+ .num_dapm_routes = ARRAY_SIZE(fe_pi_audio_dapm_routes), -+}; -+ -+static int snd_fe_pi_audio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct snd_soc_card *card = &fe_pi_audio; -+ struct device_node *np = pdev->dev.of_node; -+ struct device_node *i2s_node; -+ struct snd_soc_dai_link *dai = &snd_fe_pi_audio_dai[0]; -+ -+ fe_pi_audio.dev = &pdev->dev; -+ -+ i2s_node = of_parse_phandle(np, "i2s-controller", 0); -+ if (!i2s_node) { -+ dev_err(&pdev->dev, "i2s_node phandle missing or invalid\n"); -+ return -EINVAL; -+ } -+ -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ -+ of_node_put(i2s_node); -+ -+ card->dev = &pdev->dev; -+ platform_set_drvdata(pdev, card); -+ -+ ret = snd_soc_register_card(card); -+ if (ret && ret != -EPROBE_DEFER) -+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret); -+ -+ return ret; -+} -+ -+static int snd_fe_pi_audio_remove(struct platform_device *pdev) -+{ -+ return snd_soc_unregister_card(&fe_pi_audio); -+} -+ -+static const struct of_device_id snd_fe_pi_audio_of_match[] = { -+ { .compatible = "fe-pi,fe-pi-audio", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, snd_fe_pi_audio_of_match); -+ -+static struct platform_driver snd_fe_pi_audio_driver = { -+ .driver = { -+ .name = "snd-fe-pi-audio", -+ .owner = THIS_MODULE, -+ .of_match_table = snd_fe_pi_audio_of_match, -+ }, -+ .probe = snd_fe_pi_audio_probe, -+ .remove = snd_fe_pi_audio_remove, -+}; -+ -+module_platform_driver(snd_fe_pi_audio_driver); -+ -+MODULE_AUTHOR("Henry Kupis "); -+MODULE_DESCRIPTION("ASoC Driver for Fe-Pi Audio"); -+MODULE_LICENSE("GPL v2"); - -From cd5eb3b6dfaa6e356371752418ce010b03897a2e Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Wed, 1 Mar 2017 07:22:24 -0500 -Subject: [PATCH 148/216] Add overlay for ads1115 ADCs (#1864) - ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 22 ++++++ - arch/arm/boot/dts/overlays/ads1115-overlay.dts | 103 +++++++++++++++++++++++++ - 3 files changed, 126 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/ads1115-overlay.dts - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c8825365a4129b0098abf2002e1dcd936ea1ec8c..c890e5ddb0e2eec982597a851023b539d318d6ce 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -4,6 +4,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - adau1977-adc.dtbo \ - adau7002-simple.dtbo \ - ads1015.dtbo \ -+ ads1115.dtbo \ - ads7846.dtbo \ - akkordion-iqdacplus.dtbo \ - allo-piano-dac-pcm512x-audio.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 788e9e3b23f37d4c44b94b60ff2b72e2f0dbeeac..970c9c9b5c74467a3014a77039fa765d8f8c4e6f 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -196,6 +196,28 @@ Params: addr I2C bus address of device. Set based on how the - http://www.ti.com/lit/ds/symlink/ads1015.pdf - - -+Name: ads1115 -+Info: Texas Instruments ADS1115 ADC -+Load: dtoverlay=ads1115,[=] -+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. -+ 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=7 sets 860 sps) -+ cha_gain Set the gain of the Programmable Gain -+ Amplifier for this channel. (Default 1 sets the -+ full scale of the channel to 4.096 Volts) -+ -+ Channel 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/ads1115.pdf -+ -+ - Name: ads7846 - Info: ADS7846 Touch controller - Load: dtoverlay=ads7846,= -diff --git a/arch/arm/boot/dts/overlays/ads1115-overlay.dts b/arch/arm/boot/dts/overlays/ads1115-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..7c16a1af3172d14e1a976b1776b9f1677278beed ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/ads1115-overlay.dts -@@ -0,0 +1,103 @@ -+/* -+ * TI ADS1115 multi-channel ADC overlay -+ */ -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708"; -+ -+ fragment@0 { -+ target = <&i2c_arm>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ ads1115: ads1115 { -+ compatible = "ti,ads1115"; -+ status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ reg = <0x48>; -+ }; -+ }; -+ }; -+ -+ fragment@1 { -+ target-path = "i2c_arm/ads1115"; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ channel_a: channel_a { -+ reg = <4>; -+ ti,gain = <1>; -+ ti,datarate = <7>; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target-path = "i2c_arm/ads1115"; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ channel_b: channel_b { -+ reg = <5>; -+ ti,gain = <1>; -+ ti,datarate = <7>; -+ }; -+ }; -+ }; -+ -+ fragment@3 { -+ target-path = "i2c_arm/ads1115"; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ channel_c: channel_c { -+ reg = <6>; -+ ti,gain = <1>; -+ ti,datarate = <7>; -+ }; -+ }; -+ }; -+ -+ fragment@4 { -+ target-path = "i2c_arm/ads1115"; -+ __dormant__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ channel_d: channel_d { -+ reg = <7>; -+ ti,gain = <1>; -+ ti,datarate = <7>; -+ }; -+ }; -+ }; -+ -+ __overrides__ { -+ addr = <&ads1115>,"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"; -+ }; -+}; - -From 752ce7d8394036cbba0bd13c08280606c00544d3 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 1 Mar 2017 16:06:53 +0000 -Subject: [PATCH 149/216] clk-bcm2835: Correct the prediv logic - -If a clock has the prediv flag set, both the integer and fractional -parts must be scaled when calculating the resulting frequency. - -Signed-off-by: Phil Elwell ---- - drivers/clk/bcm/clk-bcm2835.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 0b62d20f8b718cfd03c0346af784688e26e9dcb6..ef0d05c58573f62de3632a920dfc19888c019d18 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -535,8 +535,10 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, - using_prediv = cprman_read(cprman, data->ana_reg_base + 4) & - data->ana->fb_prediv_mask; - -- if (using_prediv) -+ if (using_prediv) { - ndiv *= 2; -+ fdiv *= 2; -+ } - - return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv); - } - -From 8ad8e5110573d2cc6e1c160f60dc7727adadbdb6 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 1 Mar 2017 16:07:39 +0000 -Subject: [PATCH 150/216] amba_pl011: Round input clock up - -The UART clock is initialised to be as close to the requested -frequency as possible without exceeding it. Now that there is a -clock manager that returns the actual frequencies, an expected -48MHz clock is reported as 47999625. If the requested baudrate -== requested clock/16, there is no headroom and the slight -reduction in actual clock rate results in failure. - -Detect cases where it looks like a "round" clock was chosen and -adjust the reported clock to match that "round" value. As the -code comment says: - -/* - * If increasing a clock by less than 0.1% changes it - * from ..999.. to ..000.., round up. - */ - -Signed-off-by: Phil Elwell ---- - drivers/tty/serial/amba-pl011.c | 23 +++++++++++++++++++++-- - 1 file changed, 21 insertions(+), 2 deletions(-) - -diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c -index 6beb6233a0b6132b933cf8d85d8501dc1ce2fe4c..50792f9fa8fc530e2ecbc90f92adb11bada79cb2 100644 ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -1646,6 +1646,23 @@ static void pl011_put_poll_char(struct uart_port *port, - - #endif /* CONFIG_CONSOLE_POLL */ - -+unsigned long pl011_clk_round(unsigned long clk) -+{ -+ unsigned long scaler; -+ -+ /* -+ * If increasing a clock by less than 0.1% changes it -+ * from ..999.. to ..000.., round up. -+ */ -+ scaler = 1; -+ while (scaler * 100000 < clk) -+ scaler *= 10; -+ if ((clk + scaler - 1)/scaler % 1000 == 0) -+ clk = (clk/scaler + 1) * scaler; -+ -+ return clk; -+} -+ - static int pl011_hwinit(struct uart_port *port) - { - struct uart_amba_port *uap = -@@ -1662,7 +1679,7 @@ static int pl011_hwinit(struct uart_port *port) - if (retval) - return retval; - -- uap->port.uartclk = clk_get_rate(uap->clk); -+ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); - - /* Clear pending error and receive interrupts */ - pl011_write(UART011_OEIS | UART011_BEIS | UART011_PEIS | -@@ -2300,7 +2317,7 @@ static int __init pl011_console_setup(struct console *co, char *options) - plat->init(); - } - -- uap->port.uartclk = clk_get_rate(uap->clk); -+ uap->port.uartclk = pl011_clk_round(clk_get_rate(uap->clk)); - - if (uap->vendor->fixed_options) { - baud = uap->fixed_baud; -@@ -2428,6 +2445,7 @@ static struct uart_driver amba_reg = { - .cons = AMBA_CONSOLE, - }; - -+#if 0 - static int pl011_probe_dt_alias(int index, struct device *dev) - { - struct device_node *np; -@@ -2459,6 +2477,7 @@ static int pl011_probe_dt_alias(int index, struct device *dev) - - return ret; - } -+#endif - - /* unregisters the driver also if no more ports are left */ - static void pl011_unregister_port(struct uart_amba_port *uap) - -From 4d59781491ce4dda4135512b3edb47860bf261c0 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 13 Feb 2017 11:10:50 +0000 -Subject: [PATCH 151/216] BCM2835-V4L2: Ensure H264 header bytes get a sensible - timestamp - -H264 header come off VC with 0 timestamps, which means they get a -strange timestamp when processed with VC/kernel start times, -particularly if used with the inline header option. -Remember the last frame timestamp and use that if set, or otherwise -use the kernel start time. - -https://github.com/raspberrypi/linux/issues/1836 - -Signed-off-by: Dave Stevenson ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 30 ++++++++++++++++++++++--- - drivers/media/platform/bcm2835/bcm2835-camera.h | 2 ++ - 2 files changed, 29 insertions(+), 3 deletions(-) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index 4f03949aecf3afbf2e04df38289447195a8847a6..e69731320f4e59249933bc21843913deab4a1209 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -356,8 +356,13 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, - } - } else { - if (dev->capture.frame_count) { -- if (dev->capture.vc_start_timestamp != -1 && -- pts != 0) { -+ if (dev->capture.vc_start_timestamp == -1) { -+ buf->vb.vb2_buf.timestamp = ktime_get_ns(); -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Buffer time set as current time - %lld", -+ buf->vb.vb2_buf.timestamp); -+ -+ } else if(pts != 0) { - struct timeval timestamp; - s64 runtime_us = pts - - dev->capture.vc_start_timestamp; -@@ -390,10 +395,27 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, - buf->vb.vb2_buf.timestamp = timestamp.tv_sec * 1000000000ULL + - timestamp.tv_usec * 1000ULL; - } else { -- buf->vb.vb2_buf.timestamp = ktime_get_ns(); -+ if (dev->capture.last_timestamp) { -+ buf->vb.vb2_buf.timestamp = dev->capture.last_timestamp; -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Buffer time set as last timestamp - %lld", -+ buf->vb.vb2_buf.timestamp); -+ } -+ else { -+ buf->vb.vb2_buf.timestamp = -+ dev->capture.kernel_start_ts.tv_sec * 1000000000ULL + -+ dev->capture.kernel_start_ts.tv_usec * 1000ULL; -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Buffer time set as start timestamp - %lld", -+ buf->vb.vb2_buf.timestamp); -+ } - } -+ dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp; - - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); -+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, -+ "Buffer has ts %llu", -+ dev->capture.last_timestamp); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - - if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && -@@ -559,6 +581,8 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) - "Start time %lld size %d\n", - dev->capture.vc_start_timestamp, parameter_size); - -+ dev->capture.last_timestamp = 0; -+ - v4l2_get_timestamp(&dev->capture.kernel_start_ts); - - /* enable the camera port */ -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.h b/drivers/media/platform/bcm2835/bcm2835-camera.h -index e6aeb7e7e381de65d6c6586205069a4c5cd33274..7f8a68916a67001bc9241bce2928519a2ce1ba78 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.h -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.h -@@ -93,6 +93,8 @@ struct bm2835_mmal_dev { - s64 vc_start_timestamp; - /* Kernel start timestamp for streaming */ - struct timeval kernel_start_ts; -+ /* Timestamp of last frame */ -+ u64 last_timestamp; - - struct vchiq_mmal_port *port; /* port being used for capture */ - /* camera port being used for capture */ - -From e92d1d22c46d40e5b4fdd7ac235d346535d98483 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 13 Feb 2017 13:11:41 +0000 -Subject: [PATCH 152/216] BCM2835-V4L2: Correctly denote key frames in encoded - data - -Forward MMAL key frame flags to the V4L2 buffers. - -Signed-off-by: Dave Stevenson ---- - drivers/media/platform/bcm2835/bcm2835-camera.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/media/platform/bcm2835/bcm2835-camera.c b/drivers/media/platform/bcm2835/bcm2835-camera.c -index e69731320f4e59249933bc21843913deab4a1209..6bdec0806126044cf7146d53326e4da5b4269884 100644 ---- a/drivers/media/platform/bcm2835/bcm2835-camera.c -+++ b/drivers/media/platform/bcm2835/bcm2835-camera.c -@@ -413,6 +413,9 @@ static void buffer_cb(struct vchiq_mmal_instance *instance, - dev->capture.last_timestamp = buf->vb.vb2_buf.timestamp; - - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, length); -+ if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) -+ buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME; -+ - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Buffer has ts %llu", - dev->capture.last_timestamp); - -From e161104862401b9649bd2f7b65d1acd4710189b7 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Mon, 20 Feb 2017 17:01:21 +0000 -Subject: [PATCH 153/216] bcm2835-gpio-exp: Driver for GPIO expander via - mailbox service - -Pi3 and Compute Module 3 have a GPIO expander that the -VPU communicates with. -There is a mailbox service that now allows control of this -expander, so add a kernel driver that can make use of it. - -Pwr_led node added to device-tree for Pi3. - -Signed-off-by: Dave Stevenson ---- - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 22 +++ - arch/arm/boot/dts/bcm2710-rpi-cm3.dts | 10 +- - arch/arm/configs/bcm2709_defconfig | 1 + - drivers/gpio/Kconfig | 7 + - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-bcm-exp.c | 256 +++++++++++++++++++++++++++++ - include/soc/bcm2835/raspberrypi-firmware.h | 4 + - 7 files changed, 300 insertions(+), 1 deletion(-) - create mode 100644 drivers/gpio/gpio-bcm-exp.c - -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 2a5b512d3e1acb17c6a40bf9d370f22279c4d552..616cfd5c7094596b497101e8feca25e25e77c3e8 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -96,6 +96,14 @@ - firmware = <&firmware>; - status = "okay"; - }; -+ -+ expgpio: expgpio { -+ compatible = "brcm,bcm2835-expgpio"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ firmware = <&firmware>; -+ status = "okay"; -+ }; - }; - - &fb { -@@ -163,6 +171,16 @@ - linux,default-trigger = "mmc0"; - gpios = <&virtgpio 0 0>; - }; -+ -+ pwr_led: pwr { -+ label = "led1"; -+ linux,default-trigger = "input"; -+ gpios = <&expgpio 7 GPIO_ACTIVE_LOW>; -+ }; -+}; -+ -+&hdmi { -+ hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>; - }; - - &audio { -@@ -193,6 +211,10 @@ - act_led_activelow = <&act_led>,"gpios:8"; - act_led_trigger = <&act_led>,"linux,default-trigger"; - -+ pwr_led_gpio = <&pwr_led>,"gpios:4"; -+ pwr_led_activelow = <&pwr_led>,"gpios:8"; -+ pwr_led_trigger = <&pwr_led>,"linux,default-trigger"; -+ - audio = <&audio>,"status"; - watchdog = <&watchdog>,"status"; - random = <&random>,"status"; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -index 3ba6e621856c288ae4694f758604619f59064fdb..fe402e84cdda884583336422289ac8b3cc12fb28 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-cm3.dts -@@ -65,6 +65,14 @@ - firmware = <&firmware>; - status = "okay"; - }; -+ -+ expgpio: expgpio { -+ compatible = "brcm,bcm2835-expgpio"; -+ gpio-controller; -+ #gpio-cells = <2>; -+ firmware = <&firmware>; -+ status = "okay"; -+ }; - }; - - &fb { -@@ -123,7 +131,7 @@ - }; - - &hdmi { -- hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; -+ hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>; - }; - - &audio { -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 4ca09cf1e4e19154868b576eb3827b85789b6caf..0ee1ff698a5571f80da89a1067025b32fe546136 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -621,6 +621,7 @@ CONFIG_PPS=m - CONFIG_PPS_CLIENT_LDISC=m - CONFIG_PPS_CLIENT_GPIO=m - CONFIG_GPIO_SYSFS=y -+CONFIG_GPIO_BCM_EXP=y - CONFIG_GPIO_BCM_VIRT=y - CONFIG_GPIO_ARIZONA=m - CONFIG_GPIO_STMPE=y -diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig -index ade9f7dd8f973fd44031a0a6d42c28f01b424d1b..a6a8caa2c803c4c4a119d5d4b6d0acd2d9f2083c 100644 ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -128,6 +128,13 @@ config GPIO_AXP209 - help - Say yes to enable GPIO support for the AXP209 PMIC - -+config GPIO_BCM_EXP -+ bool "Broadcom Exp GPIO" -+ depends on OF_GPIO && RASPBERRYPI_FIRMWARE && (ARCH_BCM2835 || COMPILE_TEST) -+ help -+ Turn on GPIO support for Broadcom chips using the firmware mailbox -+ to communicate with VideoCore on BCM283x chips. -+ - config GPIO_BCM_KONA - bool "Broadcom Kona GPIO" - depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index dec0669a5f030023288047f2abe68b0f2e0946d7..73392801474433668c05442dc391af91b262b76e 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o - obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o - obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o - obj-$(CONFIG_GPIO_AXP209) += gpio-axp209.o -+obj-$(CONFIG_GPIO_BCM_EXP) += gpio-bcm-exp.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 -diff --git a/drivers/gpio/gpio-bcm-exp.c b/drivers/gpio/gpio-bcm-exp.c -new file mode 100644 -index 0000000000000000000000000000000000000000..681a91492d4c33bdfd42416e069218e8611cc4d9 ---- /dev/null -+++ b/drivers/gpio/gpio-bcm-exp.c -@@ -0,0 +1,256 @@ -+/* -+ * Broadcom expander GPIO driver -+ * -+ * Uses the firmware mailbox service to communicate with the -+ * GPIO expander on the VPU. -+ * -+ * Copyright (C) 2017 Raspberry Pi Trading Ltd. -+ * -+ * Author: Dave Stevenson -+ * Based on gpio-bcm-virt.c by Dom Cobley -+ * -+ * 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 -+ -+#define MODULE_NAME "brcmexp-gpio" -+#define NUM_GPIO 8 -+ -+struct brcmexp_gpio { -+ struct gpio_chip gc; -+ struct device *dev; -+ struct rpi_firmware *fw; -+}; -+ -+struct gpio_set_config { -+ u32 gpio, direction, polarity, term_en, term_pull_up, state; -+}; -+ -+struct gpio_get_config { -+ u32 gpio, direction, polarity, term_en, term_pull_up; -+}; -+ -+struct gpio_get_set_state { -+ u32 gpio, state; -+}; -+ -+static int brcmexp_gpio_get_polarity(struct gpio_chip *gc, unsigned int off) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_get_config get; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ get.gpio = off + gpio->gc.base; /* GPIO to update */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, -+ &get, sizeof(get)); -+ if (ret) { -+ dev_err(gpio->dev, -+ "Failed to get GPIO %u config (%d)\n", off, ret); -+ return ret; -+ } -+ return get.polarity; -+} -+ -+static int brcmexp_gpio_dir_in(struct gpio_chip *gc, unsigned int off) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_set_config set_in; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ set_in.gpio = off + gpio->gc.base; /* GPIO to update */ -+ set_in.direction = 0; /* Input */ -+ set_in.polarity = brcmexp_gpio_get_polarity(gc, off); -+ /* Retain existing setting */ -+ set_in.term_en = 0; /* termination disabled */ -+ set_in.term_pull_up = 0; /* n/a as termination disabled */ -+ set_in.state = 0; /* n/a as configured as an input */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, -+ &set_in, sizeof(set_in)); -+ if (ret) { -+ dev_err(gpio->dev, -+ "Failed to set GPIO %u to input (%d)\n", -+ off, ret); -+ return ret; -+ } -+ return 0; -+} -+ -+static int brcmexp_gpio_dir_out(struct gpio_chip *gc, unsigned int off, int val) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_set_config set_out; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ set_out.gpio = off + gpio->gc.base; /* GPIO to update */ -+ set_out.direction = 1; /* Output */ -+ set_out.polarity = brcmexp_gpio_get_polarity(gc, off); -+ /* Retain existing setting */ -+ set_out.term_en = 0; /* n/a as an output */ -+ set_out.term_pull_up = 0; /* n/a as termination disabled */ -+ set_out.state = val; /* Output state */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_CONFIG, -+ &set_out, sizeof(set_out)); -+ if (ret) { -+ dev_err(gpio->dev, -+ "Failed to set GPIO %u to output (%d)\n", off, ret); -+ return ret; -+ } -+ return 0; -+} -+ -+static int brcmexp_gpio_get_direction(struct gpio_chip *gc, unsigned int off) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_get_config get; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ get.gpio = off + gpio->gc.base; /* GPIO to update */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_CONFIG, -+ &get, sizeof(get)); -+ if (ret) { -+ dev_err(gpio->dev, -+ "Failed to get GPIO %u config (%d)\n", off, ret); -+ return ret; -+ } -+ return get.direction ? GPIOF_DIR_OUT : GPIOF_DIR_IN; -+} -+ -+static int brcmexp_gpio_get(struct gpio_chip *gc, unsigned int off) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_get_set_state get; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ get.gpio = off + gpio->gc.base; /* GPIO to update */ -+ get.state = 0; /* storage for returned value */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_GET_GPIO_STATE, -+ &get, sizeof(get)); -+ if (ret) { -+ dev_err(gpio->dev, -+ "Failed to get GPIO %u state (%d)\n", off, ret); -+ return ret; -+ } -+ return !!get.state; -+} -+ -+static void brcmexp_gpio_set(struct gpio_chip *gc, unsigned int off, int val) -+{ -+ struct brcmexp_gpio *gpio; -+ struct gpio_get_set_state set; -+ int ret; -+ -+ gpio = container_of(gc, struct brcmexp_gpio, gc); -+ -+ off += gpio->gc.base; -+ -+ set.gpio = off + gpio->gc.base; /* GPIO to update */ -+ set.state = val; /* Output state */ -+ -+ ret = rpi_firmware_property(gpio->fw, RPI_FIRMWARE_SET_GPIO_STATE, -+ &set, sizeof(set)); -+ if (ret) -+ dev_err(gpio->dev, -+ "Failed to set GPIO %u state (%d)\n", off, ret); -+} -+ -+static int brcmexp_gpio_probe(struct platform_device *pdev) -+{ -+ int err = 0; -+ struct device *dev = &pdev->dev; -+ struct device_node *np = dev->of_node; -+ struct device_node *fw_node; -+ struct rpi_firmware *fw; -+ struct brcmexp_gpio *ucb; -+ -+ 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; -+ -+ ucb = devm_kzalloc(dev, sizeof(*ucb), GFP_KERNEL); -+ if (!ucb) -+ return -EINVAL; -+ -+ ucb->fw = fw; -+ ucb->dev = dev; -+ ucb->gc.label = MODULE_NAME; -+ ucb->gc.owner = THIS_MODULE; -+ ucb->gc.of_node = np; -+ ucb->gc.base = 128; -+ ucb->gc.ngpio = NUM_GPIO; -+ -+ ucb->gc.direction_input = brcmexp_gpio_dir_in; -+ ucb->gc.direction_output = brcmexp_gpio_dir_out; -+ ucb->gc.get_direction = brcmexp_gpio_get_direction; -+ ucb->gc.get = brcmexp_gpio_get; -+ ucb->gc.set = brcmexp_gpio_set; -+ ucb->gc.can_sleep = true; -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ return err; -+ -+ platform_set_drvdata(pdev, ucb); -+ -+ return 0; -+} -+ -+static int brcmexp_gpio_remove(struct platform_device *pdev) -+{ -+ struct brcmexp_gpio *ucb = platform_get_drvdata(pdev); -+ -+ gpiochip_remove(&ucb->gc); -+ -+ return 0; -+} -+ -+static const struct of_device_id __maybe_unused brcmexp_gpio_ids[] = { -+ { .compatible = "brcm,bcm2835-expgpio" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, brcmexp_gpio_ids); -+ -+static struct platform_driver brcmexp_gpio_driver = { -+ .driver = { -+ .name = MODULE_NAME, -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(brcmexp_gpio_ids), -+ }, -+ .probe = brcmexp_gpio_probe, -+ .remove = brcmexp_gpio_remove, -+}; -+module_platform_driver(brcmexp_gpio_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Dave Stevenson "); -+MODULE_DESCRIPTION("brcm-exp GPIO driver"); -+MODULE_ALIAS("platform:brcmexp-gpio"); -diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h -index 280791fb9656901392ce67e44cb742c96f090ed4..dc7fd58afd5dddebf9b17065bb069a1db663362c 100644 ---- a/include/soc/bcm2835/raspberrypi-firmware.h -+++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -83,7 +83,11 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_SET_TURBO = 0x00038009, - RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, - RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, -+ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, -+ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, - RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, -+ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, -+ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, - - /* Dispmanx TAGS */ - RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, - -From 6f1b5dd500000a3eb27aa56d0532a876fa69bfd2 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 24 May 2016 16:30:05 +0100 -Subject: [PATCH 154/216] BCM270X_DT: Add bcm2708-rpi-0-w.dts - -Add DT support for the Pi Zero W. N.B. It will not be loaded -automatically without a corresponding change to the firmware. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm2708-rpi-0-w.dts | 197 ++++++++++++++++++++++++++++++++++ - 2 files changed, 198 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm2708-rpi-0-w.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 0263d6172d3af40668c02535a4f8dce022f3a93d..3c758781b9171f957b6afdd87c169795a61007a5 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ - bcm2708-rpi-b.dtb \ - bcm2708-rpi-b-plus.dtb \ - bcm2708-rpi-cm.dtb \ -+ bcm2708-rpi-0-w.dtb \ - bcm2709-rpi-2-b.dtb \ - bcm2710-rpi-3-b.dtb \ - bcm2710-rpi-cm3.dtb -diff --git a/arch/arm/boot/dts/bcm2708-rpi-0-w.dts b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..db0f99ddf2f46e83827d56e21c4846dd0b414c63 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm2708-rpi-0-w.dts -@@ -0,0 +1,197 @@ -+/dts-v1/; -+ -+#include "bcm2708.dtsi" -+ -+/ { -+ model = "Raspberry Pi Zero W"; -+}; -+ -+&gpio { -+ sdhost_pins: sdhost_pins { -+ brcm,pins = <48 49 50 51 52 53>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ spi0_pins: spi0_pins { -+ brcm,pins = <9 10 11>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ spi0_cs_pins: spi0_cs_pins { -+ brcm,pins = <8 7>; -+ brcm,function = <1>; /* output */ -+ }; -+ -+ i2c0_pins: i2c0 { -+ brcm,pins = <0 1>; -+ brcm,function = <4>; -+ }; -+ -+ i2c1_pins: i2c1 { -+ brcm,pins = <2 3>; -+ brcm,function = <4>; -+ }; -+ -+ i2s_pins: i2s { -+ brcm,pins = <18 19 20 21>; -+ brcm,function = <4>; /* alt0 */ -+ }; -+ -+ sdio_pins: sdio_pins { -+ brcm,pins = <34 35 36 37 38 39>; -+ brcm,function = <7>; /* ALT3 = SD1 */ -+ brcm,pull = <0 2 2 2 2 2>; -+ }; -+ -+ bt_pins: bt_pins { -+ brcm,pins = <43>; -+ brcm,function = <4>; /* alt0:GPCLK2 */ -+ brcm,pull = <0>; /* none */ -+ }; -+ -+ uart0_pins: uart0_pins { -+ brcm,pins = <30 31 32 33>; -+ brcm,function = <7>; /* alt3=UART0 */ -+ brcm,pull = <2 0 0 2>; /* up none none up */ -+ }; -+ -+ uart1_pins: uart1_pins { -+ brcm,pins; -+ brcm,function; -+ brcm,pull; -+ }; -+ -+ audio_pins: audio_pins { -+ brcm,pins = <>; -+ brcm,function = <>; -+ }; -+}; -+ -+&sdhost { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdhost_pins>; -+ bus-width = <4>; -+ status = "okay"; -+}; -+ -+&mmc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sdio_pins>; -+ non-removable; -+ bus-width = <4>; -+ status = "okay"; -+}; -+ -+&fb { -+ status = "okay"; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins &bt_pins>; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>; -+ status = "okay"; -+}; -+ -+&spi0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; -+ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; -+ -+ spidev0: spidev@0{ -+ compatible = "spidev"; -+ reg = <0>; /* CE0 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+ -+ spidev1: spidev@1{ -+ compatible = "spidev"; -+ reg = <1>; /* CE1 */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ spi-max-frequency = <500000>; -+ }; -+}; -+ -+&i2c0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c0_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ clock-frequency = <100000>; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+}; -+ -+&i2s { -+ #sound-dai-cells = <0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2s_pins>; -+}; -+ -+&random { -+ status = "okay"; -+}; -+ -+&leds { -+ act_led: act { -+ label = "led0"; -+ linux,default-trigger = "mmc0"; -+ gpios = <&gpio 47 0>; -+ }; -+}; -+ -+&hdmi { -+ hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>; -+}; -+ -+&audio { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&audio_pins>; -+}; -+ -+/ { -+ chosen { -+ bootargs = "8250.nr_uarts=1"; -+ }; -+}; -+ -+/ { -+ __overrides__ { -+ uart0 = <&uart0>,"status"; -+ uart1 = <&uart1>,"status"; -+ i2s = <&i2s>,"status"; -+ spi = <&spi0>,"status"; -+ i2c0 = <&i2c0>,"status"; -+ i2c1 = <&i2c1>,"status"; -+ i2c2_iknowwhatimdoing = <&i2c2>,"status"; -+ i2c0_baudrate = <&i2c0>,"clock-frequency:0"; -+ i2c1_baudrate = <&i2c1>,"clock-frequency:0"; -+ i2c2_baudrate = <&i2c2>,"clock-frequency:0"; -+ -+ act_led_gpio = <&act_led>,"gpios:4"; -+ act_led_activelow = <&act_led>,"gpios:8"; -+ act_led_trigger = <&act_led>,"linux,default-trigger"; -+ -+ audio = <&audio>,"status"; -+ watchdog = <&watchdog>,"status"; -+ random = <&random>,"status"; -+ sd_overclock = <&sdhost>,"brcm,overclock-50:0"; -+ sd_force_pio = <&sdhost>,"brcm,force-pio?"; -+ sd_pio_limit = <&sdhost>,"brcm,pio-limit:0"; -+ sd_debug = <&sdhost>,"brcm,debug"; -+ }; -+}; - -From 04643b351f0dc437b09d91823af5de17543852ed Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 6 Mar 2017 09:06:18 +0000 -Subject: [PATCH 155/216] clk-bcm2835: Read max core clock from firmware - -The VPU is responsible for managing the core clock, usually under -direction from the bcm2835-cpufreq driver but not via the clk-bcm2835 -driver. Since the core frequency can change without warning, it is -safer to report the maximum clock rate to users of the core clock - -I2C, SPI and the mini UART - to err on the safe side when calculating -clock divisors. - -If the DT node for the clock driver includes a reference to the -firmware node, use the firmware API to query the maximum core clock -instead of reading the divider registers. - -Prior to this patch, a "100KHz" I2C bus was sometimes clocked at about -160KHz. In particular, switching to the 4.9 kernel was likely to break -SenseHAT usage on a Pi3. - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ++++ - drivers/clk/bcm/clk-bcm2835.c | 39 +++++++++++++++++++++++++++++++++++++- - 2 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -index 055090ace687b94e4d25de65d1b8fbf7f730be9e..ef14e9ac6cd2092efb1681682dd2d3c52b8abfd5 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -107,3 +107,7 @@ - &usb { - power-domains = <&power RPI_POWER_DOMAIN_USB>; - }; -+ -+&clocks { -+ firmware = <&firmware>; -+}; -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index ef0d05c58573f62de3632a920dfc19888c019d18..41dccc4ebe6f367054822aed11cb0cd4d985c21a 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -44,6 +44,7 @@ - #include - #include - #include -+#include - - #define CM_PASSWORD 0x5a000000 - -@@ -297,9 +298,12 @@ - #define LOCK_TIMEOUT_NS 100000000 - #define BCM2835_MAX_FB_RATE 1750000000u - -+#define VCMSG_ID_CORE_CLOCK 4 -+ - struct bcm2835_cprman { - struct device *dev; - void __iomem *regs; -+ struct rpi_firmware *fw; - spinlock_t regs_lock; /* spinlock for all clocks */ - const char *osc_name; - -@@ -936,6 +940,30 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, - return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); - } - -+static unsigned long bcm2835_clock_get_rate_vpu(struct clk_hw *hw, -+ unsigned long parent_rate) -+{ -+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); -+ struct bcm2835_cprman *cprman = clock->cprman; -+ -+ if (cprman->fw) { -+ struct { -+ u32 id; -+ u32 val; -+ } packet; -+ -+ packet.id = VCMSG_ID_CORE_CLOCK; -+ packet.val = 0; -+ -+ if (!rpi_firmware_property(cprman->fw, -+ RPI_FIRMWARE_GET_MAX_CLOCK_RATE, -+ &packet, sizeof(packet))) -+ return packet.val; -+ } -+ -+ return bcm2835_clock_get_rate(hw, parent_rate); -+} -+ - static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock) - { - struct bcm2835_cprman *cprman = clock->cprman; -@@ -1192,7 +1220,7 @@ static int bcm2835_vpu_clock_is_on(struct clk_hw *hw) - */ - static const struct clk_ops bcm2835_vpu_clock_clk_ops = { - .is_prepared = bcm2835_vpu_clock_is_on, -- .recalc_rate = bcm2835_clock_get_rate, -+ .recalc_rate = bcm2835_clock_get_rate_vpu, - .set_rate = bcm2835_clock_set_rate, - .determine_rate = bcm2835_clock_determine_rate, - .set_parent = bcm2835_clock_set_parent, -@@ -1952,6 +1980,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - struct resource *res; - const struct bcm2835_clk_desc *desc; - const size_t asize = ARRAY_SIZE(clk_desc_array); -+ struct device_node *fw_node; - size_t i; - u32 clk_id; - int ret; -@@ -1969,6 +1998,14 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - if (IS_ERR(cprman->regs)) - return PTR_ERR(cprman->regs); - -+ fw_node = of_parse_phandle(dev->of_node, "firmware", 0); -+ if (fw_node) { -+ struct rpi_firmware *fw = rpi_firmware_get(NULL); -+ if (!fw) -+ return -EPROBE_DEFER; -+ cprman->fw = fw; -+ } -+ - memset(bcm2835_clk_claimed, 0, sizeof(bcm2835_clk_claimed)); - for (i = 0; - !of_property_read_u32_index(pdev->dev.of_node, "claim-clocks", - -From 18a83a03a98f7416b477730c965f62cdbeb30249 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 7 Mar 2017 19:48:23 +0000 -Subject: [PATCH 156/216] config: Add CONFIG_CRYPTO_LZ4 - -Enabling this options allows LZ4 memory compression. - -Fixes: https://github.com/raspberrypi/linux/issues/1875 - -Signed-off-by: Phil Elwell ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 0ee1ff698a5571f80da89a1067025b32fe546136..b5260a6701e48fdfcaeae9aad7dac62b4e160986 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -1303,6 +1303,7 @@ CONFIG_CRYPTO_TGR192=m - CONFIG_CRYPTO_WP512=m - CONFIG_CRYPTO_CAST5=m - CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_LZ4=m - CONFIG_CRYPTO_USER_API_SKCIPHER=m - # CONFIG_CRYPTO_HW is not set - CONFIG_ARM_CRYPTO=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index a9c46f902eb32b364423d8bef07b6b37f798c617..e5996d77b02303c4b43e62a810e0e3e660c1e99e 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -1311,6 +1311,7 @@ CONFIG_CRYPTO_TGR192=m - CONFIG_CRYPTO_WP512=m - CONFIG_CRYPTO_CAST5=m - CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_LZ4=m - CONFIG_CRYPTO_USER_API_SKCIPHER=m - # CONFIG_CRYPTO_HW is not set - CONFIG_ARM_CRYPTO=y - -From c7a3e9f4d0825ba2fff36ab76998a5d16548e9c8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 5 Mar 2017 11:46:41 +0000 -Subject: [PATCH 157/216] config: Add RTL8XXXU wifi module - ---- - arch/arm/configs/bcm2709_defconfig | 1 + - arch/arm/configs/bcmrpi_defconfig | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index b5260a6701e48fdfcaeae9aad7dac62b4e160986..6143dfd58993aa0e5adb4808fea6987058979971 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -540,6 +540,7 @@ CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y - CONFIG_RTL8187=m - CONFIG_RTL8192CU=m -+CONFIG_RTL8XXXU=m - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e5996d77b02303c4b43e62a810e0e3e660c1e99e..a691ce8b7fb6017fcc7990cf08e8ff4a39302fba 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -536,6 +536,7 @@ CONFIG_RT2800USB_RT55XX=y - CONFIG_RT2800USB_UNKNOWN=y - CONFIG_RTL8187=m - CONFIG_RTL8192CU=m -+CONFIG_RTL8XXXU=m - CONFIG_USB_ZD1201=m - CONFIG_ZD1211RW=m - CONFIG_MAC80211_HWSIM=m - -From 7036806aefecd0f8c1789bd4d55a72ebd51a0769 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Fri, 10 Mar 2017 14:43:15 +0000 -Subject: [PATCH 158/216] bcm2835-v4l2: Fix buffer overflow problem - -https://github.com/raspberrypi/linux/issues/1447 -port_parameter_get() failed to account for the header -(u32 id and u32 size) in the size before memcpying -the response into the response buffer, so overrunning -the provided buffer by 8 bytes. - -Account for those bytes, and also a belt-and-braces -check to ensure we never copy more than *value_size -bytes into value. - -Signed-off-by: Dave Stevenson ---- - drivers/media/platform/bcm2835/mmal-vchiq.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/media/platform/bcm2835/mmal-vchiq.c b/drivers/media/platform/bcm2835/mmal-vchiq.c -index 781322542d5a8295f3d7d5a3eaaf0cac29930c30..e4b243b33f58913f3d2952c97d2a2e3fbbbd0ae8 100644 ---- a/drivers/media/platform/bcm2835/mmal-vchiq.c -+++ b/drivers/media/platform/bcm2835/mmal-vchiq.c -@@ -1315,7 +1315,12 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, - } - - ret = -rmsg->u.port_parameter_get_reply.status; -- if (ret) { -+ /* port_parameter_get_reply.size includes the header, -+ * whilst *value_size doesn't. -+ */ -+ rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32)); -+ -+ if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) { - /* Copy only as much as we have space for - * but report true size of parameter - */ - -From ea3f68726de469bdf48fc6df37df3aea5cab35f6 Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Wed, 8 Mar 2017 20:04:13 +1100 -Subject: [PATCH 159/216] Add support for the AudioInjector.net Octo sound card - ---- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 + - .../dts/overlays/audioinjector-addons-overlay.dts | 50 ++++ - arch/arm/configs/bcm2709_defconfig | 2 + - arch/arm/configs/bcmrpi_defconfig | 2 + - sound/soc/bcm/Kconfig | 7 + - sound/soc/bcm/Makefile | 2 + - sound/soc/bcm/audioinjector-octo-soundcard.c | 286 +++++++++++++++++++++ - 8 files changed, 356 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts - create mode 100644 sound/soc/bcm/audioinjector-octo-soundcard.c - -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index c890e5ddb0e2eec982597a851023b539d318d6ce..0f7340799fb465ba1fb5aaa1e970cbf6295d75c4 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -9,6 +9,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - akkordion-iqdacplus.dtbo \ - allo-piano-dac-pcm512x-audio.dtbo \ - at86rf233.dtbo \ -+ audioinjector-addons.dtbo \ - audioinjector-wm8731-audio.dtbo \ - audremap.dtbo \ - bmp085_i2c-sensor.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 970c9c9b5c74467a3014a77039fa765d8f8c4e6f..c1883bba938290f03826026651c764cfd4ac278b 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -295,6 +295,12 @@ Params: interrupt GPIO used for INT (default 23) - arrays (0=+0pF, 15=+4.5pF, default 15) - - -+Name: audioinjector-addons -+Info: Configures the audioinjector.net audio add on soundcards -+Load: dtoverlay=audioinjector-addons -+Params: -+ -+ - Name: audioinjector-wm8731-audio - Info: Configures the audioinjector.net audio add on soundcard - Load: dtoverlay=audioinjector-wm8731-audio -diff --git a/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..dbf2f3cacc2e6bf5b7116fbadd97f2781580a79c ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/audioinjector-addons-overlay.dts -@@ -0,0 +1,50 @@ -+// Definitions for audioinjector.net audio add on soundcard -+/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"; -+ -+ cs42448: cs42448@48 { -+ #sound-dai-cells = <0>; -+ compatible = "cirrus,cs42448"; -+ reg = <0x48>; -+ clocks = <&cs42448_mclk>; -+ clock-names = "mclk"; -+ status = "okay"; -+ }; -+ -+ cs42448_mclk: codec-mclk { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <49152000>; -+ }; -+ }; -+ }; -+ -+ fragment@2 { -+ target = <&sound>; -+ __overlay__ { -+ compatible = "ai,audioinjector-octo-soundcard"; -+ mult-gpios = <&gpio 27 0>, <&gpio 22 0>, <&gpio 23 0>, -+ <&gpio 24 0>; -+ i2s-controller = <&i2s>; -+ codec = <&cs42448>; -+ status = "okay"; -+ }; -+ }; -+}; -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 6143dfd58993aa0e5adb4808fea6987058979971..97375c26f2d70d0c4f3956622f839dcf04463e31 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -883,6 +883,7 @@ 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_AUDIOINJECTOR_OCTO_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m -@@ -892,6 +893,7 @@ CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m -+CONFIG_SND_SOC_CS42XX8_I2C=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index a691ce8b7fb6017fcc7990cf08e8ff4a39302fba..0e2c3679d9614d331db39cd25ae9095136d3190a 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -876,6 +876,7 @@ 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_AUDIOINJECTOR_OCTO_SOUNDCARD=m - CONFIG_SND_DIGIDAC1_SOUNDCARD=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m - CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m -@@ -885,6 +886,7 @@ CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m -+CONFIG_SND_SOC_CS42XX8_I2C=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig -index 7473efd6f400a1a1618aac830753fce39d203b89..706c500b5303ac3a0fd8687d23dc9f06c7d08388 100644 ---- a/sound/soc/bcm/Kconfig -+++ b/sound/soc/bcm/Kconfig -@@ -119,6 +119,13 @@ config SND_AUDIOINJECTOR_PI_SOUNDCARD - help - Say Y or M if you want to add support for audioinjector.net Pi Hat - -+config SND_AUDIOINJECTOR_OCTO_SOUNDCARD -+ tristate "Support for audioinjector.net Octo channel (Hat) soundcard" -+ depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -+ select SND_SOC_CS42XX8_I2C -+ help -+ Say Y or M if you want to add support for audioinjector.net octo add on -+ - config SND_DIGIDAC1_SOUNDCARD - tristate "Support for Red Rocks Audio DigiDAC1" - depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S -diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile -index 8d2d2073dc2cede9fbd9eb8b49083650ba0a8172..d448aa517bf994fc0a41580c91b5d87deec9e1b0 100644 ---- a/sound/soc/bcm/Makefile -+++ b/sound/soc/bcm/Makefile -@@ -23,6 +23,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-audioinjector-octo-soundcard-objs := audioinjector-octo-soundcard.o - snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o - snd-soc-dionaudio-loco-objs := dionaudio_loco.o - snd-soc-dionaudio-loco-v2-objs := dionaudio_loco-v2.o -@@ -44,6 +45,7 @@ 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_AUDIOINJECTOR_OCTO_SOUNDCARD) += snd-soc-audioinjector-octo-soundcard.o - obj-$(CONFIG_SND_DIGIDAC1_SOUNDCARD) += snd-soc-digidac1-soundcard.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO) += snd-soc-dionaudio-loco.o - obj-$(CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2) += snd-soc-dionaudio-loco-v2.o -diff --git a/sound/soc/bcm/audioinjector-octo-soundcard.c b/sound/soc/bcm/audioinjector-octo-soundcard.c -new file mode 100644 -index 0000000000000000000000000000000000000000..9effea725798640887755dfa688da45338718afc ---- /dev/null -+++ b/sound/soc/bcm/audioinjector-octo-soundcard.c -@@ -0,0 +1,286 @@ -+/* -+ * ASoC Driver for AudioInjector Pi octo channel soundcard (hat) -+ * -+ * Created on: 27-October-2016 -+ * Author: flatmax@flatmax.org -+ * based on audioinjector-pi-soundcard.c -+ * -+ * Copyright (C) 2016 Flatmax Pty. Ltd. -+ * -+ * 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 struct gpio_descs *mult_gpios; -+static unsigned int audioinjector_octo_rate; -+ -+static int audioinjector_octo_dai_init(struct snd_soc_pcm_runtime *rtd) -+{ -+ return snd_soc_dai_set_bclk_ratio(rtd->cpu_dai, 64); -+} -+ -+static int audioinjector_octo_startup(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ rtd->cpu_dai->driver->playback.channels_min = 8; -+ rtd->cpu_dai->driver->playback.channels_max = 8; -+ rtd->cpu_dai->driver->capture.channels_min = 8; -+ rtd->cpu_dai->driver->capture.channels_max = 8; -+ rtd->codec_dai->driver->capture.channels_max = 8; -+ return 0; -+} -+ -+static void audioinjector_octo_shutdown(struct snd_pcm_substream *substream) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ rtd->cpu_dai->driver->playback.channels_min = 2; -+ rtd->cpu_dai->driver->playback.channels_max = 2; -+ rtd->cpu_dai->driver->capture.channels_min = 2; -+ rtd->cpu_dai->driver->capture.channels_max = 2; -+ rtd->codec_dai->driver->capture.channels_max = 6; -+} -+ -+static int audioinjector_octo_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ struct snd_soc_pcm_runtime *rtd = substream->private_data; -+ -+ // set codec DAI configuration -+ int ret = snd_soc_dai_set_fmt(rtd->codec_dai, -+ SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_DSP_A| -+ SND_SOC_DAIFMT_NB_NF); -+ if (ret < 0) -+ return ret; -+ -+ // set cpu DAI configuration -+ ret = snd_soc_dai_set_fmt(rtd->cpu_dai, -+ SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S| -+ SND_SOC_DAIFMT_NB_NF); -+ if (ret < 0) -+ return ret; -+ -+ audioinjector_octo_rate = params_rate(params); -+ -+ return 0; -+} -+ -+static int audioinjector_octo_trigger(struct snd_pcm_substream *substream, -+ int cmd){ -+ int mult[4]; -+ mult[0] = 0; -+ mult[1] = 0; -+ mult[2] = 0; -+ mult[3] = 0; -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ case SNDRV_PCM_TRIGGER_RESUME: -+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: -+ switch (audioinjector_octo_rate) { -+ case 192000: -+ mult[3] = 1; -+ case 176640: -+ mult[0] = 1; -+ mult[1] = 1; -+ mult[2] = 1; -+ break; -+ case 96000: -+ mult[3] = 1; -+ case 88200: -+ mult[1] = 1; -+ mult[2] = 1; -+ break; -+ case 64000: -+ mult[3] = 1; -+ case 58800: -+ mult[0] = 1; -+ mult[2] = 1; -+ break; -+ case 48000: -+ mult[3] = 1; -+ case 44100: -+ mult[2] = 1; -+ break; -+ case 32000: -+ mult[3] = 1; -+ case 29400: -+ mult[0] = 1; -+ mult[1] = 1; -+ break; -+ case 24000: -+ mult[3] = 1; -+ case 22050: -+ mult[1] = 1; -+ break; -+ case 16000: -+ mult[3] = 1; -+ case 14700: -+ mult[0] = 1; -+ break; -+ case 8000: -+ mult[3] = 1; -+ break; -+ default: -+ return -EINVAL; -+ } -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ case SNDRV_PCM_TRIGGER_SUSPEND: -+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: -+ break; -+ default: -+ return -EINVAL; -+ } -+ gpiod_set_array_value_cansleep(mult_gpios->ndescs, mult_gpios->desc, -+ mult); -+ -+ return 0; -+} -+ -+static struct snd_soc_ops audioinjector_octo_ops = { -+ .startup = audioinjector_octo_startup, -+ .shutdown = audioinjector_octo_shutdown, -+ .hw_params = audioinjector_octo_hw_params, -+ .trigger = audioinjector_octo_trigger, -+}; -+ -+static struct snd_soc_dai_link audioinjector_octo_dai[] = { -+ { -+ .name = "AudioInjector Octo", -+ .stream_name = "AudioInject-HIFI", -+ .codec_dai_name = "cs42448", -+ .ops = &audioinjector_octo_ops, -+ .init = audioinjector_octo_dai_init, -+ }, -+}; -+ -+static const struct snd_soc_dapm_widget audioinjector_octo_widgets[] = { -+ SND_SOC_DAPM_OUTPUT("OUTPUTS0"), -+ SND_SOC_DAPM_OUTPUT("OUTPUTS1"), -+ SND_SOC_DAPM_OUTPUT("OUTPUTS2"), -+ SND_SOC_DAPM_OUTPUT("OUTPUTS3"), -+ SND_SOC_DAPM_INPUT("INPUTS0"), -+ SND_SOC_DAPM_INPUT("INPUTS1"), -+ SND_SOC_DAPM_INPUT("INPUTS2"), -+}; -+ -+static const struct snd_soc_dapm_route audioinjector_octo_route[] = { -+ /* Balanced outputs */ -+ {"OUTPUTS0", NULL, "AOUT1L"}, -+ {"OUTPUTS0", NULL, "AOUT1R"}, -+ {"OUTPUTS1", NULL, "AOUT2L"}, -+ {"OUTPUTS1", NULL, "AOUT2R"}, -+ {"OUTPUTS2", NULL, "AOUT3L"}, -+ {"OUTPUTS2", NULL, "AOUT3R"}, -+ {"OUTPUTS3", NULL, "AOUT4L"}, -+ {"OUTPUTS3", NULL, "AOUT4R"}, -+ -+ /* Balanced inputs */ -+ {"AIN1L", NULL, "INPUTS0"}, -+ {"AIN1R", NULL, "INPUTS0"}, -+ {"AIN2L", NULL, "INPUTS1"}, -+ {"AIN2R", NULL, "INPUTS1"}, -+ {"AIN3L", NULL, "INPUTS2"}, -+ {"AIN3R", NULL, "INPUTS2"}, -+}; -+ -+static struct snd_soc_card snd_soc_audioinjector_octo = { -+ .name = "audioinjector-octo-soundcard", -+ .dai_link = audioinjector_octo_dai, -+ .num_links = ARRAY_SIZE(audioinjector_octo_dai), -+ -+ .dapm_widgets = audioinjector_octo_widgets, -+ .num_dapm_widgets = ARRAY_SIZE(audioinjector_octo_widgets), -+ .dapm_routes = audioinjector_octo_route, -+ .num_dapm_routes = ARRAY_SIZE(audioinjector_octo_route), -+}; -+ -+static int audioinjector_octo_probe(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = &snd_soc_audioinjector_octo; -+ int ret; -+ -+ card->dev = &pdev->dev; -+ -+ if (pdev->dev.of_node) { -+ struct snd_soc_dai_link *dai = &audioinjector_octo_dai[0]; -+ struct device_node *i2s_node = -+ of_parse_phandle(pdev->dev.of_node, -+ "i2s-controller", 0); -+ struct device_node *codec_node = -+ of_parse_phandle(pdev->dev.of_node, -+ "codec", 0); -+ -+ mult_gpios = devm_gpiod_get_array_optional(&pdev->dev, "mult", -+ GPIOD_OUT_LOW); -+ if (IS_ERR(mult_gpios)) -+ return PTR_ERR(mult_gpios); -+ -+ if (i2s_node && codec_node) { -+ dai->cpu_dai_name = NULL; -+ dai->cpu_of_node = i2s_node; -+ dai->platform_name = NULL; -+ dai->platform_of_node = i2s_node; -+ dai->codec_name = NULL; -+ dai->codec_of_node = codec_node; -+ } else -+ if (!dai->cpu_of_node) { -+ dev_err(&pdev->dev, -+ "i2s-controller missing or invalid in DT\n"); -+ return -EINVAL; -+ } else { -+ dev_err(&pdev->dev, -+ "Property 'codec' missing or invalid\n"); -+ return -EINVAL; -+ } -+ } -+ -+ ret = snd_soc_register_card(card); -+ if (ret != 0) -+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); -+ return ret; -+} -+ -+static int audioinjector_octo_remove(struct platform_device *pdev) -+{ -+ struct snd_soc_card *card = platform_get_drvdata(pdev); -+ -+ return snd_soc_unregister_card(card); -+} -+ -+static const struct of_device_id audioinjector_octo_of_match[] = { -+ { .compatible = "ai,audioinjector-octo-soundcard", }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, audioinjector_octo_of_match); -+ -+static struct platform_driver audioinjector_octo_driver = { -+ .driver = { -+ .name = "audioinjector-audio", -+ .owner = THIS_MODULE, -+ .of_match_table = audioinjector_octo_of_match, -+ }, -+ .probe = audioinjector_octo_probe, -+ .remove = audioinjector_octo_remove, -+}; -+ -+module_platform_driver(audioinjector_octo_driver); -+MODULE_AUTHOR("Matt Flax "); -+MODULE_DESCRIPTION("AudioInjector.net octo Soundcard"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:audioinjector-octo-soundcard"); - -From 56433f080ce7adc0170d0df2b2d1695311b0260e Mon Sep 17 00:00:00 2001 -From: Matt Flax -Date: Wed, 8 Mar 2017 21:13:24 +1100 -Subject: [PATCH 160/216] ASoC: bcm2835_i2s.c: relax the ch2 register setting - for 8 channels - -This patch allows ch2 registers to be set for 8 channels of audio. ---- - 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 6ba20498202ed36906b52096893a88867a79269f..c8dd065aea8414b47aa2ea4fc04168b5e29002ad 100644 ---- a/sound/soc/bcm/bcm2835-i2s.c -+++ b/sound/soc/bcm/bcm2835-i2s.c -@@ -239,6 +239,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - unsigned int ch1pos, ch2pos, mode, format; - uint32_t csreg; - -+ - /* - * If a stream is already enabled, - * the registers are already set properly. -@@ -312,6 +313,7 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, - - switch (params_channels(params)) { - case 2: -+ case 8: - format = BCM2835_I2S_CH1(format) | BCM2835_I2S_CH2(format); - format |= BCM2835_I2S_CH1(BCM2835_I2S_CHPOS(ch1pos)); - format |= BCM2835_I2S_CH2(BCM2835_I2S_CHPOS(ch2pos)); - -From 562868585ac367c3a6ef46c78cdfcb074e924105 Mon Sep 17 00:00:00 2001 +From 617d2ad61db426cb29c450bbab85126c3cb6b3fe Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Fri, 10 Feb 2017 17:57:08 -0800 -Subject: [PATCH 161/216] build/arm64: Add rules for .dtbo files for dts +Subject: [PATCH 110/150] build/arm64: Add rules for .dtbo files for dts overlays We now create overlays as .dtbo files. @@ -131916,10 +112536,77 @@ index b9a4a934ca057623e0ea436fd9b2c7c0f675fced..54e3c38d6fd877827541cdc798de035c dtbs: prepare scripts -From e54225190a0ecdf072ed52f0392df72145c43bfb Mon Sep 17 00:00:00 2001 +From 9211fc5fc35fe77328ed0c7185a9318ff2b35f36 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 12 Mar 2017 20:34:54 +0000 +Subject: [PATCH 111/150] bcm2835-sdhost: Hack fix build + +--- + drivers/mmc/host/bcm2835-sdhost.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +index a9bc79bfdbb71807819dfe2d8f1651445997f92a..3ed754f8903bbf8ee5a810f20d96bc633168e4b3 100644 +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -53,6 +53,11 @@ + #include + #include + ++#include ++#define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */ ++#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) ++ ++ + #define DRIVER_NAME "sdhost-bcm2835" + + #define SDCMD 0x00 /* Command to SD card - 16 R/W */ + +From 5af8d437f88f917e92e867c6f18a0ad9e7bddca6 Mon Sep 17 00:00:00 2001 +From: Eric Anholt +Date: Mon, 9 May 2016 17:28:18 -0700 +Subject: [PATCH 112/150] clk: bcm2835: Mark GPIO clocks enabled at boot as + critical. + +These divide off of PLLD_PER and are used for the ethernet and wifi +PHYs source PLLs. Neither of them is currently represented by a phy +device that would grab the clock for us. + +This keeps other drivers from killing the networking PHYs when they +disable their own clocks and trigger PLLD_PER's refcount going to 0. + +v2: Skip marking as critical if they aren't on at boot. + +Signed-off-by: Eric Anholt +--- + drivers/clk/bcm/clk-bcm2835.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 39f72da6ba1f6ec6ec41d5dc1bf46344aab008da..fe3298b54cdfb96bd90fb4f39e13921d2e1d4356 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1461,6 +1461,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, + init.flags = data->flags | CLK_IGNORE_UNUSED; + + /* ++ * Some GPIO clocks for ethernet/wifi PLLs are marked as ++ * critical (since some platforms use them), but if the ++ * firmware didn't have them turned on then they clearly ++ * aren't actually critical. ++ */ ++ if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0) ++ init.flags &= ~CLK_IS_CRITICAL; ++ ++ /* + * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate + * rate changes on at least of the parents. + */ + +From d98c728510542ee2b74a664bbef167224e48c894 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 -Subject: [PATCH 162/216] pinctrl-bcm2835: Fix interrupt handling for GPIOs +Subject: [PATCH 113/150] pinctrl-bcm2835: Fix interrupt handling for GPIOs 28-31 and 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has @@ -131952,4447 +112639,10 @@ index 6351fe7f8e314ac5ebb102dd20847b383fd5b857..28745af5aadf3cb91fa7ff39118385c3 }, }; -From 2b771f5eced0afd7e71b6a0f0d0cd412b0955491 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 9 May 2016 17:28:18 -0700 -Subject: [PATCH 163/216] clk: bcm2835: Mark GPIO clocks enabled at boot as - critical. - -These divide off of PLLD_PER and are used for the ethernet and wifi -PHYs source PLLs. Neither of them is currently represented by a phy -device that would grab the clock for us. - -This keeps other drivers from killing the networking PHYs when they -disable their own clocks and trigger PLLD_PER's refcount going to 0. - -v2: Skip marking as critical if they aren't on at boot. - -Signed-off-by: Eric Anholt ---- - drivers/clk/bcm/clk-bcm2835.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 41dccc4ebe6f367054822aed11cb0cd4d985c21a..7ec0e71cbcfbcd6c86e2f6c8080e1d622ca5540a 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1357,6 +1357,15 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, - init.flags = data->flags | CLK_IGNORE_UNUSED; - - /* -+ * Some GPIO clocks for ethernet/wifi PLLs are marked as -+ * critical (since some platforms use them), but if the -+ * firmware didn't have them turned on then they clearly -+ * aren't actually critical. -+ */ -+ if ((cprman_read(cprman, data->ctl_reg) & CM_ENABLE) == 0) -+ init.flags &= ~CLK_IS_CRITICAL; -+ -+ /* - * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate - * rate changes on at least of the parents. - */ - -From ddc1ff9064f11d5dc2cf59a116f3affa8c4d986a Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 7 Mar 2016 15:05:11 +0000 -Subject: [PATCH 164/216] vchiq_arm: Tweak the logging output - -Signed-off-by: Phil Elwell ---- - .../vc04_services/interface/vchiq_arm/vchiq_core.c | 31 +++++++++------------- - 1 file changed, 13 insertions(+), 18 deletions(-) - -diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -index d6757ee263fb61a689c0d38c0dbb65c57a8e39bb..7fd63cf6800d7ec35fbcb215a283630c11120c7f 100644 ---- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c -@@ -873,16 +873,14 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - error_count); - return VCHIQ_ERROR; - } -- if (i == 0) { -- if (SRVTRACE_ENABLED(service, -- VCHIQ_LOG_INFO)) -- vchiq_log_dump_mem("Sent", 0, -- header->data + pos, -- min(64u, -- elements[0].size)); -- } - } - -+ if (SRVTRACE_ENABLED(service, -+ VCHIQ_LOG_INFO)) -+ vchiq_log_dump_mem("Sent", 0, -+ header->data, -+ min(16, pos)); -+ - spin_lock("a_spinlock); - service_quota->message_use_count++; - -@@ -1019,16 +1017,13 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - error_count); - return VCHIQ_ERROR; - } -- if (i == 0) { -- if (vchiq_sync_log_level >= -- VCHIQ_LOG_TRACE) -- vchiq_log_dump_mem("Sent Sync", -- 0, header->data + pos, -- min(64u, -- elements[0].size)); -- } - } - -+ if (vchiq_sync_log_level >= VCHIQ_LOG_TRACE) -+ vchiq_log_dump_mem("Sent Sync", -+ 0, header->data, -+ min(16, pos)); -+ - VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); - } else { -@@ -1691,7 +1686,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) - remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem("Rcvd", 0, header->data, -- min(64, size)); -+ min(16, size)); - } - - if (((unsigned long)header & VCHIQ_SLOT_MASK) + -@@ -2148,7 +2143,7 @@ sync_func(void *v) - remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem("Rcvd", 0, header->data, -- min(64, size)); -+ min(16, size)); - } - - switch (type) { - -From cdea24594f5cde9b7d80b63c4d882072607117c4 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 18 Jan 2017 07:31:55 +1100 -Subject: [PATCH 165/216] clk: bcm2835: Don't rate change PLLs on behalf of DSI - PLL dividers. - -Our core PLLs are intended to be configured once and left alone. With -the SET_RATE_PARENT, asking to set the PLLD_DSI1 clock rate would -change PLLD just to get closer to the requested DSI clock, thus -changing PLLD_PER, the UART and ethernet PHY clock rates downstream of -it, and breaking ethernet. - -We *do* want PLLH to change so that PLLH_AUX can be exactly the value -we want, though. Thus, we need to have a per-divider policy of -whether to pass rate changes up. - -Signed-off-by: Eric Anholt -Signed-off-by: Stephen Boyd -(cherry picked from commit 55486091bd1e1c5ed28c43c0d6b3392468a9adb5) ---- - drivers/clk/bcm/clk-bcm2835.c | 42 ++++++++++++++++++++++++++++-------------- - 1 file changed, 28 insertions(+), 14 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 7ec0e71cbcfbcd6c86e2f6c8080e1d622ca5540a..3acf61ddeda8c27e6da0fd7e2beb46341679eb66 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -432,6 +432,7 @@ struct bcm2835_pll_divider_data { - u32 load_mask; - u32 hold_mask; - u32 fixed_divider; -+ u32 flags; - }; - - struct bcm2835_clock_data { -@@ -1287,7 +1288,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman, - init.num_parents = 1; - init.name = divider_name; - init.ops = &bcm2835_pll_divider_clk_ops; -- init.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED; -+ init.flags = data->flags | CLK_IGNORE_UNUSED; - - divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL); - if (!divider) -@@ -1517,7 +1518,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLA_CORE, - .load_mask = CM_PLLA_LOADCORE, - .hold_mask = CM_PLLA_HOLDCORE, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLA_PER] = REGISTER_PLL_DIV( - .name = "plla_per", - .source_pll = "plla", -@@ -1525,7 +1527,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLA_PER, - .load_mask = CM_PLLA_LOADPER, - .hold_mask = CM_PLLA_HOLDPER, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV( - .name = "plla_dsi0", - .source_pll = "plla", -@@ -1541,7 +1544,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLA_CCP2, - .load_mask = CM_PLLA_LOADCCP2, - .hold_mask = CM_PLLA_HOLDCCP2, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - - /* PLLB is used for the ARM's clock. */ - [BCM2835_PLLB] = REGISTER_PLL( -@@ -1565,7 +1569,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLB_ARM, - .load_mask = CM_PLLB_LOADARM, - .hold_mask = CM_PLLB_HOLDARM, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - - /* - * PLLC is the core PLL, used to drive the core VPU clock. -@@ -1594,7 +1599,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLC_CORE0, - .load_mask = CM_PLLC_LOADCORE0, - .hold_mask = CM_PLLC_HOLDCORE0, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV( - .name = "pllc_core1", - .source_pll = "pllc", -@@ -1602,7 +1608,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLC_CORE1, - .load_mask = CM_PLLC_LOADCORE1, - .hold_mask = CM_PLLC_HOLDCORE1, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV( - .name = "pllc_core2", - .source_pll = "pllc", -@@ -1610,7 +1617,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLC_CORE2, - .load_mask = CM_PLLC_LOADCORE2, - .hold_mask = CM_PLLC_HOLDCORE2, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLC_PER] = REGISTER_PLL_DIV( - .name = "pllc_per", - .source_pll = "pllc", -@@ -1618,7 +1626,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLC_PER, - .load_mask = CM_PLLC_LOADPER, - .hold_mask = CM_PLLC_HOLDPER, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - - /* - * PLLD is the display PLL, used to drive DSI display panels. -@@ -1647,7 +1656,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLD_CORE, - .load_mask = CM_PLLD_LOADCORE, - .hold_mask = CM_PLLD_HOLDCORE, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLD_PER] = REGISTER_PLL_DIV( - .name = "plld_per", - .source_pll = "plld", -@@ -1655,7 +1665,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLD_PER, - .load_mask = CM_PLLD_LOADPER, - .hold_mask = CM_PLLD_HOLDPER, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV( - .name = "plld_dsi0", - .source_pll = "plld", -@@ -1700,7 +1711,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLH_RCAL, - .load_mask = CM_PLLH_LOADRCAL, - .hold_mask = 0, -- .fixed_divider = 10), -+ .fixed_divider = 10, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV( - .name = "pllh_aux", - .source_pll = "pllh", -@@ -1708,7 +1720,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLH_AUX, - .load_mask = CM_PLLH_LOADAUX, - .hold_mask = 0, -- .fixed_divider = 1), -+ .fixed_divider = 1, -+ .flags = CLK_SET_RATE_PARENT), - [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV( - .name = "pllh_pix", - .source_pll = "pllh", -@@ -1716,7 +1729,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .a2w_reg = A2W_PLLH_PIX, - .load_mask = CM_PLLH_LOADPIX, - .hold_mask = 0, -- .fixed_divider = 10), -+ .fixed_divider = 10, -+ .flags = CLK_SET_RATE_PARENT), - - /* the clocks */ - - -From eafb781b7125128e2cc144a11f6d83e45ca5ee14 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 18 Jan 2017 07:31:56 +1100 -Subject: [PATCH 166/216] clk: bcm2835: Register the DSI0/DSI1 pixel clocks. - -The DSI pixel clocks are muxed from clocks generated in the analog phy -by the DSI driver. In order to set them as parents, we need to do the -same name lookup dance on them as we do for our root oscillator. - -Signed-off-by: Eric Anholt -Signed-off-by: Stephen Boyd -(cherry picked from commit 8a39e9fa578229fd4604266c6ebb1a3a77d7994c) ---- - .../bindings/clock/brcm,bcm2835-cprman.txt | 15 ++- - drivers/clk/bcm/clk-bcm2835.c | 121 +++++++++++++++++++-- - include/dt-bindings/clock/bcm2835.h | 2 + - 3 files changed, 125 insertions(+), 13 deletions(-) - -diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt -index e56a1df3a9d3ca7fefbc5058072ee392c49b4cfc..dd906db34b328a581e4f4d99d11284544ff817f4 100644 ---- a/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt -+++ b/Documentation/devicetree/bindings/clock/brcm,bcm2835-cprman.txt -@@ -16,7 +16,20 @@ Required properties: - - #clock-cells: Should be <1>. The permitted clock-specifier values can be - found in include/dt-bindings/clock/bcm2835.h - - reg: Specifies base physical address and size of the registers --- clocks: The external oscillator clock phandle -+- clocks: phandles to the parent clocks used as input to the module, in -+ the following order: -+ -+ - External oscillator -+ - DSI0 byte clock -+ - DSI0 DDR2 clock -+ - DSI0 DDR clock -+ - DSI1 byte clock -+ - DSI1 DDR2 clock -+ - DSI1 DDR clock -+ -+ Only external oscillator is required. The DSI clocks may -+ not be present, in which case their children will be -+ unusable. - - Example: - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 3acf61ddeda8c27e6da0fd7e2beb46341679eb66..428e75c8b970897d881b570228eb85e8aef28999 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -300,12 +300,33 @@ - - #define VCMSG_ID_CORE_CLOCK 4 - -+/* -+ * Names of clocks used within the driver that need to be replaced -+ * with an external parent's name. This array is in the order that -+ * the clocks node in the DT references external clocks. -+ */ -+static const char *const cprman_parent_names[] = { -+ "xosc", -+ "dsi0_byte", -+ "dsi0_ddr2", -+ "dsi0_ddr", -+ "dsi1_byte", -+ "dsi1_ddr2", -+ "dsi1_ddr", -+}; -+ - struct bcm2835_cprman { - struct device *dev; - void __iomem *regs; - struct rpi_firmware *fw; - spinlock_t regs_lock; /* spinlock for all clocks */ -- const char *osc_name; -+ -+ /* -+ * Real names of cprman clock parents looked up through -+ * of_clk_get_parent_name(), which will be used in the -+ * parent_names[] arrays for clock registration. -+ */ -+ const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)]; - - /* Must be last */ - struct clk_hw_onecell_data onecell; -@@ -913,6 +934,9 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock, - const struct bcm2835_clock_data *data = clock->data; - u64 temp; - -+ if (data->int_bits == 0 && data->frac_bits == 0) -+ return parent_rate; -+ - /* - * The divisor is a 12.12 fixed point field, but only some of - * the bits are populated in any given clock. -@@ -936,7 +960,12 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); - struct bcm2835_cprman *cprman = clock->cprman; - const struct bcm2835_clock_data *data = clock->data; -- u32 div = cprman_read(cprman, data->div_reg); -+ u32 div; -+ -+ if (data->int_bits == 0 && data->frac_bits == 0) -+ return parent_rate; -+ -+ div = cprman_read(cprman, data->div_reg); - - return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); - } -@@ -1241,7 +1270,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, - memset(&init, 0, sizeof(init)); - - /* All of the PLLs derive from the external oscillator. */ -- init.parent_names = &cprman->osc_name; -+ init.parent_names = &cprman->real_parent_names[0]; - init.num_parents = 1; - init.name = data->name; - init.ops = &bcm2835_pll_clk_ops; -@@ -1337,18 +1366,22 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, - struct bcm2835_clock *clock; - struct clk_init_data init; - const char *parents[1 << CM_SRC_BITS]; -- size_t i; -+ size_t i, j; - int ret; - - /* -- * Replace our "xosc" references with the oscillator's -- * actual name. -+ * Replace our strings referencing parent clocks with the -+ * actual clock-output-name of the parent. - */ - for (i = 0; i < data->num_mux_parents; i++) { -- if (strcmp(data->parents[i], "xosc") == 0) -- parents[i] = cprman->osc_name; -- else -- parents[i] = data->parents[i]; -+ parents[i] = data->parents[i]; -+ -+ for (j = 0; j < ARRAY_SIZE(cprman_parent_names); j++) { -+ if (strcmp(parents[i], cprman_parent_names[j]) == 0) { -+ parents[i] = cprman->real_parent_names[j]; -+ break; -+ } -+ } - } - - memset(&init, 0, sizeof(init)); -@@ -1484,6 +1517,47 @@ static const char *const bcm2835_clock_vpu_parents[] = { - __VA_ARGS__) - - /* -+ * DSI parent clocks. The DSI byte/DDR/DDR2 clocks come from the DSI -+ * analog PHY. The _inv variants are generated internally to cprman, -+ * but we don't use them so they aren't hooked up. -+ */ -+static const char *const bcm2835_clock_dsi0_parents[] = { -+ "gnd", -+ "xosc", -+ "testdebug0", -+ "testdebug1", -+ "dsi0_ddr", -+ "dsi0_ddr_inv", -+ "dsi0_ddr2", -+ "dsi0_ddr2_inv", -+ "dsi0_byte", -+ "dsi0_byte_inv", -+}; -+ -+static const char *const bcm2835_clock_dsi1_parents[] = { -+ "gnd", -+ "xosc", -+ "testdebug0", -+ "testdebug1", -+ "dsi1_ddr", -+ "dsi1_ddr_inv", -+ "dsi1_ddr2", -+ "dsi1_ddr2_inv", -+ "dsi1_byte", -+ "dsi1_byte_inv", -+}; -+ -+#define REGISTER_DSI0_CLK(...) REGISTER_CLK( \ -+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents), \ -+ .parents = bcm2835_clock_dsi0_parents, \ -+ __VA_ARGS__) -+ -+#define REGISTER_DSI1_CLK(...) REGISTER_CLK( \ -+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \ -+ .parents = bcm2835_clock_dsi1_parents, \ -+ __VA_ARGS__) -+ -+/* - * the real definition of all the pll, pll_dividers and clocks - * these make use of the above REGISTER_* macros - */ -@@ -1946,6 +2020,18 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_DSI1EDIV, - .int_bits = 4, - .frac_bits = 8), -+ [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK( -+ .name = "dsi0p", -+ .ctl_reg = CM_DSI0PCTL, -+ .div_reg = CM_DSI0PDIV, -+ .int_bits = 0, -+ .frac_bits = 0), -+ [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK( -+ .name = "dsi1p", -+ .ctl_reg = CM_DSI1PCTL, -+ .div_reg = CM_DSI1PDIV, -+ .int_bits = 0, -+ .frac_bits = 0), - - /* the gates */ - -@@ -2036,8 +2122,19 @@ static int bcm2835_clk_probe(struct platform_device *pdev) - i++) - bcm2835_clk_claimed[clk_id]= true; - -- cprman->osc_name = of_clk_get_parent_name(dev->of_node, 0); -- if (!cprman->osc_name) -+ memcpy(cprman->real_parent_names, cprman_parent_names, -+ sizeof(cprman_parent_names)); -+ of_clk_parent_fill(dev->of_node, cprman->real_parent_names, -+ ARRAY_SIZE(cprman_parent_names)); -+ -+ /* -+ * Make sure the external oscillator has been registered. -+ * -+ * The other (DSI) clocks are not present on older device -+ * trees, which we still need to support for backwards -+ * compatibility. -+ */ -+ if (!cprman->real_parent_names[0]) - return -ENODEV; - - platform_set_drvdata(pdev, cprman); -diff --git a/include/dt-bindings/clock/bcm2835.h b/include/dt-bindings/clock/bcm2835.h -index 360e00cefd35679b49890234b5c369fb52b89e20..a0c812b0fa391d149b4f546db39bdc4bef207960 100644 ---- a/include/dt-bindings/clock/bcm2835.h -+++ b/include/dt-bindings/clock/bcm2835.h -@@ -64,3 +64,5 @@ - #define BCM2835_CLOCK_CAM1 46 - #define BCM2835_CLOCK_DSI0E 47 - #define BCM2835_CLOCK_DSI1E 48 -+#define BCM2835_CLOCK_DSI0P 49 -+#define BCM2835_CLOCK_DSI1P 50 - -From 57109471a499144ee37717ca517cde5bb508df4e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 18 Jan 2017 07:31:57 +1100 -Subject: [PATCH 167/216] clk: bcm2835: Add leaf clock measurement support, - disabled by default - -This proved incredibly useful during debugging of the DSI driver, to -see if our clocks were running at rate we requested. Let's leave it -here for the next person interacting with clocks on the platform (and -so that hopefully we can just hook it up to debugfs some day). - -Signed-off-by: Eric Anholt -Signed-off-by: Stephen Boyd -(cherry picked from commit 3f9195811d8d829556c4cd88d3f9e56a80d5ba60) ---- - drivers/clk/bcm/clk-bcm2835.c | 144 ++++++++++++++++++++++++++++++++++-------- - 1 file changed, 119 insertions(+), 25 deletions(-) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index 428e75c8b970897d881b570228eb85e8aef28999..fe3298b54cdfb96bd90fb4f39e13921d2e1d4356 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -99,7 +100,8 @@ - #define CM_SMIDIV 0x0b4 - /* no definition for 0x0b8 and 0x0bc */ - #define CM_TCNTCTL 0x0c0 --#define CM_TCNTDIV 0x0c4 -+# define CM_TCNT_SRC1_SHIFT 12 -+#define CM_TCNTCNT 0x0c4 - #define CM_TECCTL 0x0c8 - #define CM_TECDIV 0x0cc - #define CM_TD0CTL 0x0d0 -@@ -342,6 +344,61 @@ static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg) - return readl(cprman->regs + reg); - } - -+/* Does a cycle of measuring a clock through the TCNT clock, which may -+ * source from many other clocks in the system. -+ */ -+static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman, -+ u32 tcnt_mux) -+{ -+ u32 osccount = 19200; /* 1ms */ -+ u32 count; -+ ktime_t timeout; -+ -+ spin_lock(&cprman->regs_lock); -+ -+ cprman_write(cprman, CM_TCNTCTL, CM_KILL); -+ -+ cprman_write(cprman, CM_TCNTCTL, -+ (tcnt_mux & CM_SRC_MASK) | -+ (tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT); -+ -+ cprman_write(cprman, CM_OSCCOUNT, osccount); -+ -+ /* do a kind delay at the start */ -+ mdelay(1); -+ -+ /* Finish off whatever is left of OSCCOUNT */ -+ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); -+ while (cprman_read(cprman, CM_OSCCOUNT)) { -+ if (ktime_after(ktime_get(), timeout)) { -+ dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n"); -+ count = 0; -+ goto out; -+ } -+ cpu_relax(); -+ } -+ -+ /* Wait for BUSY to clear. */ -+ timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS); -+ while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) { -+ if (ktime_after(ktime_get(), timeout)) { -+ dev_err(cprman->dev, "timeout waiting for !BUSY\n"); -+ count = 0; -+ goto out; -+ } -+ cpu_relax(); -+ } -+ -+ count = cprman_read(cprman, CM_TCNTCNT); -+ -+ cprman_write(cprman, CM_TCNTCTL, 0); -+ -+out: -+ spin_unlock(&cprman->regs_lock); -+ -+ return count * 1000; -+} -+ - static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base, - struct debugfs_reg32 *regs, size_t nregs, - struct dentry *dentry) -@@ -477,6 +534,8 @@ struct bcm2835_clock_data { - - bool is_vpu_clock; - bool is_mash_clock; -+ -+ u32 tcnt_mux; - }; - - struct bcm2835_gate_data { -@@ -1038,6 +1097,17 @@ static int bcm2835_clock_on(struct clk_hw *hw) - CM_GATE); - spin_unlock(&cprman->regs_lock); - -+ /* Debug code to measure the clock once it's turned on to see -+ * if it's ticking at the rate we expect. -+ */ -+ if (data->tcnt_mux && false) { -+ dev_info(cprman->dev, -+ "clk %s: rate %ld, measure %ld\n", -+ data->name, -+ clk_hw_get_rate(hw), -+ bcm2835_measure_tcnt_mux(cprman, data->tcnt_mux)); -+ } -+ - return 0; - } - -@@ -1816,7 +1886,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_OTPCTL, - .div_reg = CM_OTPDIV, - .int_bits = 4, -- .frac_bits = 0), -+ .frac_bits = 0, -+ .tcnt_mux = 6), - /* - * Used for a 1Mhz clock for the system clocksource, and also used - * bythe watchdog timer and the camera pulse generator. -@@ -1850,13 +1921,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_H264CTL, - .div_reg = CM_H264DIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 1), - [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK( - .name = "isp", - .ctl_reg = CM_ISPCTL, - .div_reg = CM_ISPDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 2), - - /* - * Secondary SDRAM clock. Used for low-voltage modes when the PLL -@@ -1867,13 +1940,15 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_SDCCTL, - .div_reg = CM_SDCDIV, - .int_bits = 6, -- .frac_bits = 0), -+ .frac_bits = 0, -+ .tcnt_mux = 3), - [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK( - .name = "v3d", - .ctl_reg = CM_V3DCTL, - .div_reg = CM_V3DDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 4), - /* - * VPU clock. This doesn't have an enable bit, since it drives - * the bus for everything else, and is special so it doesn't need -@@ -1887,7 +1962,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .int_bits = 12, - .frac_bits = 8, - .flags = CLK_IS_CRITICAL, -- .is_vpu_clock = true), -+ .is_vpu_clock = true, -+ .tcnt_mux = 5), - - /* clocks with per parent mux */ - [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK( -@@ -1895,19 +1971,22 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_AVEOCTL, - .div_reg = CM_AVEODIV, - .int_bits = 4, -- .frac_bits = 0), -+ .frac_bits = 0, -+ .tcnt_mux = 38), - [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK( - .name = "cam0", - .ctl_reg = CM_CAM0CTL, - .div_reg = CM_CAM0DIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 14), - [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK( - .name = "cam1", - .ctl_reg = CM_CAM1CTL, - .div_reg = CM_CAM1DIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 15), - [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK( - .name = "dft", - .ctl_reg = CM_DFTCTL, -@@ -1919,7 +1998,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_DPICTL, - .div_reg = CM_DPIDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 17), - - /* Arasan EMMC clock */ - [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK( -@@ -1927,7 +2007,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_EMMCCTL, - .div_reg = CM_EMMCDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 39), - - /* General purpose (GPIO) clocks */ - [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK( -@@ -1936,7 +2017,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .div_reg = CM_GP0DIV, - .int_bits = 12, - .frac_bits = 12, -- .is_mash_clock = true), -+ .is_mash_clock = true, -+ .tcnt_mux = 20), - [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK( - .name = "gp1", - .ctl_reg = CM_GP1CTL, -@@ -1944,7 +2026,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .int_bits = 12, - .frac_bits = 12, - .flags = CLK_IS_CRITICAL, -- .is_mash_clock = true), -+ .is_mash_clock = true, -+ .tcnt_mux = 21), - [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK( - .name = "gp2", - .ctl_reg = CM_GP2CTL, -@@ -1959,40 +2042,46 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_HSMCTL, - .div_reg = CM_HSMDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 22), - [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK( - .name = "pcm", - .ctl_reg = CM_PCMCTL, - .div_reg = CM_PCMDIV, - .int_bits = 12, - .frac_bits = 12, -- .is_mash_clock = true), -+ .is_mash_clock = true, -+ .tcnt_mux = 23), - [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( - .name = "pwm", - .ctl_reg = CM_PWMCTL, - .div_reg = CM_PWMDIV, - .int_bits = 12, - .frac_bits = 12, -- .is_mash_clock = true), -+ .is_mash_clock = true, -+ .tcnt_mux = 24), - [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK( - .name = "slim", - .ctl_reg = CM_SLIMCTL, - .div_reg = CM_SLIMDIV, - .int_bits = 12, - .frac_bits = 12, -- .is_mash_clock = true), -+ .is_mash_clock = true, -+ .tcnt_mux = 25), - [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK( - .name = "smi", - .ctl_reg = CM_SMICTL, - .div_reg = CM_SMIDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 27), - [BCM2835_CLOCK_UART] = REGISTER_PER_CLK( - .name = "uart", - .ctl_reg = CM_UARTCTL, - .div_reg = CM_UARTDIV, - .int_bits = 10, -- .frac_bits = 12), -+ .frac_bits = 12, -+ .tcnt_mux = 28), - - /* TV encoder clock. Only operating frequency is 108Mhz. */ - [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( -@@ -2005,7 +2094,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - * Allow rate change propagation only on PLLH_AUX which is - * assigned index 7 in the parent array. - */ -- .set_rate_parent = BIT(7)), -+ .set_rate_parent = BIT(7), -+ .tcnt_mux = 29), - - /* dsi clocks */ - [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK( -@@ -2013,25 +2103,29 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .ctl_reg = CM_DSI0ECTL, - .div_reg = CM_DSI0EDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 18), - [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK( - .name = "dsi1e", - .ctl_reg = CM_DSI1ECTL, - .div_reg = CM_DSI1EDIV, - .int_bits = 4, -- .frac_bits = 8), -+ .frac_bits = 8, -+ .tcnt_mux = 19), - [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK( - .name = "dsi0p", - .ctl_reg = CM_DSI0PCTL, - .div_reg = CM_DSI0PDIV, - .int_bits = 0, -- .frac_bits = 0), -+ .frac_bits = 0, -+ .tcnt_mux = 12), - [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK( - .name = "dsi1p", - .ctl_reg = CM_DSI1PCTL, - .div_reg = CM_DSI1PDIV, - .int_bits = 0, -- .frac_bits = 0), -+ .frac_bits = 0, -+ .tcnt_mux = 13), - - /* the gates */ - - -From 09352237d4ac8eef6442331f75910363be10abe2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 26 Apr 2016 13:46:13 -0700 -Subject: [PATCH 168/216] drm/panel: Add support for the Raspberry Pi 7" - Touchscreen. - -This driver communicates with the Atmel microcontroller for sequencing -the poweron of the TC358762 DSI-DPI bridge and controlling the -backlight PWM. - -The following lines are required in config.txt, to keep the firmware -from trying to bash our I2C lines and steal the DSI interrupts: - - disable_touchscreen=1 - ignore_lcd=2 - mask_gpu_interrupt1=0x1000 - -This means that the firmware won't power on the panel at boot time (no -rainbow) and the touchscreen input won't work. The native input -driver for the touchscreen still needs to be written. - -v2: Set the same default orientation as the closed source firmware - used, which is the best for viewing angle. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/panel/Kconfig | 8 + - drivers/gpu/drm/panel/Makefile | 1 + - .../gpu/drm/panel/panel-raspberrypi-touchscreen.c | 514 +++++++++++++++++++++ - 3 files changed, 523 insertions(+) - create mode 100644 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c - -diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig -index 62aba976e744c146c26d7fedf44c54cdd480361e..de7a56ab758b8f043194391f9b9e43df65c06d0a 100644 ---- a/drivers/gpu/drm/panel/Kconfig -+++ b/drivers/gpu/drm/panel/Kconfig -@@ -52,6 +52,14 @@ config DRM_PANEL_PANASONIC_VVX10F034N00 - WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some - Xperia Z2 tablets - -+config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN -+ tristate "Raspberry Pi 7-inch touchscreen panel" -+ depends on DRM_MIPI_DSI -+ help -+ Say Y here if you want to enable support for the Raspberry -+ Pi 7" Touchscreen. To compile this driver as a module, -+ choose M here. -+ - config DRM_PANEL_SAMSUNG_S6E8AA0 - tristate "Samsung S6E8AA0 DSI video mode panel" - depends on OF -diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile -index a5c7ec0236e0174079cce0f07d46372967e9cf3b..e8a7ed280fff907e5a730a13ae9a3e5e34cacce4 100644 ---- a/drivers/gpu/drm/panel/Makefile -+++ b/drivers/gpu/drm/panel/Makefile -@@ -2,6 +2,7 @@ obj-$(CONFIG_DRM_PANEL_SIMPLE) += panel-simple.o - obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o - obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o - obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o -+obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o - obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o - obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0) += panel-samsung-s6e8aa0.o - obj-$(CONFIG_DRM_PANEL_SHARP_LQ101R1SX01) += panel-sharp-lq101r1sx01.o -diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -new file mode 100644 -index 0000000000000000000000000000000000000000..1a536fe4d040f5fafe324baee110a6225dd0be08 ---- /dev/null -+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -@@ -0,0 +1,514 @@ -+/* -+ * Copyright © 2016 Broadcom -+ * -+ * 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. -+ * -+ * Portions of this file (derived from panel-simple.c) are: -+ * -+ * Copyright (C) 2013, NVIDIA Corporation. All rights reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sub license, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the -+ * next paragraph) shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+/** -+ * DOC: Raspberry Pi 7" touchscreen panel driver. -+ * -+ * The 7" touchscreen consists of a DPI LCD panel, a Toshiba -+ * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR -+ * controlling power management, the LCD PWM, and the touchscreen. -+ * -+ * This driver presents this device as a MIPI DSI panel to the DRM -+ * driver, and should expose the touchscreen as a HID device. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* I2C registers of the Atmel microcontroller. */ -+enum REG_ADDR { -+ REG_ID = 0x80, -+ REG_PORTA, // BIT(2) for horizontal flip, BIT(3) for vertical flip -+ REG_PORTB, -+ REG_PORTC, -+ REG_PORTD, -+ REG_POWERON, -+ REG_PWM, -+ REG_DDRA, -+ REG_DDRB, -+ REG_DDRC, -+ REG_DDRD, -+ REG_TEST, -+ REG_WR_ADDRL, -+ REG_WR_ADDRH, -+ REG_READH, -+ REG_READL, -+ REG_WRITEH, -+ REG_WRITEL, -+ REG_ID2, -+}; -+ -+/* We only turn the PWM on or off, without varying values. */ -+#define RPI_TOUCHSCREEN_MAX_BRIGHTNESS 1 -+ -+/* DSI D-PHY Layer Registers */ -+#define D0W_DPHYCONTTX 0x0004 -+#define CLW_DPHYCONTRX 0x0020 -+#define D0W_DPHYCONTRX 0x0024 -+#define D1W_DPHYCONTRX 0x0028 -+#define COM_DPHYCONTRX 0x0038 -+#define CLW_CNTRL 0x0040 -+#define D0W_CNTRL 0x0044 -+#define D1W_CNTRL 0x0048 -+#define DFTMODE_CNTRL 0x0054 -+ -+/* DSI PPI Layer Registers */ -+#define PPI_STARTPPI 0x0104 -+#define PPI_BUSYPPI 0x0108 -+#define PPI_LINEINITCNT 0x0110 -+#define PPI_LPTXTIMECNT 0x0114 -+//#define PPI_LANEENABLE 0x0134 -+//#define PPI_TX_RX_TA 0x013C -+#define PPI_CLS_ATMR 0x0140 -+#define PPI_D0S_ATMR 0x0144 -+#define PPI_D1S_ATMR 0x0148 -+#define PPI_D0S_CLRSIPOCOUNT 0x0164 -+#define PPI_D1S_CLRSIPOCOUNT 0x0168 -+#define CLS_PRE 0x0180 -+#define D0S_PRE 0x0184 -+#define D1S_PRE 0x0188 -+#define CLS_PREP 0x01A0 -+#define D0S_PREP 0x01A4 -+#define D1S_PREP 0x01A8 -+#define CLS_ZERO 0x01C0 -+#define D0S_ZERO 0x01C4 -+#define D1S_ZERO 0x01C8 -+#define PPI_CLRFLG 0x01E0 -+#define PPI_CLRSIPO 0x01E4 -+#define HSTIMEOUT 0x01F0 -+#define HSTIMEOUTENABLE 0x01F4 -+ -+/* DSI Protocol Layer Registers */ -+#define DSI_STARTDSI 0x0204 -+#define DSI_BUSYDSI 0x0208 -+#define DSI_LANEENABLE 0x0210 -+# define DSI_LANEENABLE_CLOCK BIT(0) -+# define DSI_LANEENABLE_D0 BIT(1) -+# define DSI_LANEENABLE_D1 BIT(2) -+ -+#define DSI_LANESTATUS0 0x0214 -+#define DSI_LANESTATUS1 0x0218 -+#define DSI_INTSTATUS 0x0220 -+#define DSI_INTMASK 0x0224 -+#define DSI_INTCLR 0x0228 -+#define DSI_LPTXTO 0x0230 -+#define DSI_MODE 0x0260 -+#define DSI_PAYLOAD0 0x0268 -+#define DSI_PAYLOAD1 0x026C -+#define DSI_SHORTPKTDAT 0x0270 -+#define DSI_SHORTPKTREQ 0x0274 -+#define DSI_BTASTA 0x0278 -+#define DSI_BTACLR 0x027C -+ -+/* DSI General Registers */ -+#define DSIERRCNT 0x0300 -+#define DSISIGMOD 0x0304 -+ -+/* DSI Application Layer Registers */ -+#define APLCTRL 0x0400 -+#define APLSTAT 0x0404 -+#define APLERR 0x0408 -+#define PWRMOD 0x040C -+#define RDPKTLN 0x0410 -+#define PXLFMT 0x0414 -+#define MEMWRCMD 0x0418 -+ -+/* LCDC/DPI Host Registers */ -+#define LCDCTRL 0x0420 -+#define HSR 0x0424 -+#define HDISPR 0x0428 -+#define VSR 0x042C -+#define VDISPR 0x0430 -+#define VFUEN 0x0434 -+ -+/* DBI-B Host Registers */ -+#define DBIBCTRL 0x0440 -+ -+/* SPI Master Registers */ -+#define SPICMR 0x0450 -+#define SPITCR 0x0454 -+ -+/* System Controller Registers */ -+#define SYSSTAT 0x0460 -+#define SYSCTRL 0x0464 -+#define SYSPLL1 0x0468 -+#define SYSPLL2 0x046C -+#define SYSPLL3 0x0470 -+#define SYSPMCTRL 0x047C -+ -+/* GPIO Registers */ -+#define GPIOC 0x0480 -+#define GPIOO 0x0484 -+#define GPIOI 0x0488 -+ -+/* I2C Registers */ -+#define I2CCLKCTRL 0x0490 -+ -+/* Chip/Rev Registers */ -+#define IDREG 0x04A0 -+ -+/* Debug Registers */ -+#define WCMDQUEUE 0x0500 -+#define RCMDQUEUE 0x0504 -+ -+struct rpi_touchscreen { -+ struct drm_panel base; -+ struct mipi_dsi_device *dsi; -+ struct i2c_client *bridge_i2c; -+ -+ /* Version of the firmware on the bridge chip */ -+ int atmel_ver; -+}; -+ -+static const struct drm_display_mode rpi_touchscreen_modes[] = { -+ { -+ /* The DSI PLL can only integer divide from the 2Ghz -+ * PLLD, giving us few choices. We pick a divide by 3 -+ * as our DSI HS clock, giving us a pixel clock of -+ * that divided by 24 bits. Pad out HFP to get our -+ * panel to refresh at 60Hz, even if that doesn't -+ * match the datasheet. -+ */ -+#define PIXEL_CLOCK ((2000000000 / 3) / 24) -+#define VREFRESH 60 -+#define VTOTAL (480 + 7 + 2 + 21) -+#define HACT 800 -+#define HSW 2 -+#define HBP 46 -+#define HFP ((PIXEL_CLOCK / (VTOTAL * VREFRESH)) - (HACT + HSW + HBP)) -+ -+ .clock = PIXEL_CLOCK / 1000, -+ .hdisplay = HACT, -+ .hsync_start = HACT + HFP, -+ .hsync_end = HACT + HFP + HSW, -+ .htotal = HACT + HFP + HSW + HBP, -+ .vdisplay = 480, -+ .vsync_start = 480 + 7, -+ .vsync_end = 480 + 7 + 2, -+ .vtotal = VTOTAL, -+ .vrefresh = 60, -+ }, -+}; -+ -+static struct rpi_touchscreen *panel_to_ts(struct drm_panel *panel) -+{ -+ return container_of(panel, struct rpi_touchscreen, base); -+} -+ -+static u8 rpi_touchscreen_i2c_read(struct rpi_touchscreen *ts, u8 reg) -+{ -+ return i2c_smbus_read_byte_data(ts->bridge_i2c, reg); -+} -+ -+static void rpi_touchscreen_i2c_write(struct rpi_touchscreen *ts, -+ u8 reg, u8 val) -+{ -+ int ret; -+ -+ ret = i2c_smbus_write_byte_data(ts->bridge_i2c, reg, val); -+ if (ret) -+ dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret); -+} -+ -+static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val) -+{ -+#if 0 -+ /* The firmware uses LP DSI transactions like this to bring up -+ * the hardware, which should be faster than using I2C to then -+ * pass to the Toshiba. However, I was unable to get it to -+ * work. -+ */ -+ u8 msg[] = { -+ reg, -+ reg >> 8, -+ val, -+ val >> 8, -+ val >> 16, -+ val >> 24, -+ }; -+ -+ mipi_dsi_dcs_write_buffer(ts->dsi, msg, sizeof(msg)); -+#else -+ rpi_touchscreen_i2c_write(ts, REG_WR_ADDRH, reg >> 8); -+ rpi_touchscreen_i2c_write(ts, REG_WR_ADDRL, reg); -+ rpi_touchscreen_i2c_write(ts, REG_WRITEH, val >> 8); -+ rpi_touchscreen_i2c_write(ts, REG_WRITEL, val); -+#endif -+ -+ return 0; -+} -+ -+static int rpi_touchscreen_disable(struct drm_panel *panel) -+{ -+ struct rpi_touchscreen *ts = panel_to_ts(panel); -+ -+ rpi_touchscreen_i2c_write(ts, REG_PWM, 0); -+ -+ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); -+ udelay(1); -+ -+ return 0; -+} -+ -+static int rpi_touchscreen_noop(struct drm_panel *panel) -+{ -+ return 0; -+} -+ -+static int rpi_touchscreen_enable(struct drm_panel *panel) -+{ -+ struct rpi_touchscreen *ts = panel_to_ts(panel); -+ int i; -+ -+ rpi_touchscreen_i2c_write(ts, REG_POWERON, 1); -+ /* Wait for nPWRDWN to go low to indicate poweron is done. */ -+ for (i = 0; i < 100; i++) { -+ if (rpi_touchscreen_i2c_read(ts, REG_PORTB) & 1) -+ break; -+ } -+ -+ rpi_touchscreen_write(ts, DSI_LANEENABLE, -+ DSI_LANEENABLE_CLOCK | -+ DSI_LANEENABLE_D0 | -+ (ts->dsi->lanes > 1 ? DSI_LANEENABLE_D1 : 0)); -+ rpi_touchscreen_write(ts, PPI_D0S_CLRSIPOCOUNT, 0x05); -+ rpi_touchscreen_write(ts, PPI_D1S_CLRSIPOCOUNT, 0x05); -+ rpi_touchscreen_write(ts, PPI_D0S_ATMR, 0x00); -+ rpi_touchscreen_write(ts, PPI_D1S_ATMR, 0x00); -+ rpi_touchscreen_write(ts, PPI_LPTXTIMECNT, 0x03); -+ -+ rpi_touchscreen_write(ts, SPICMR, 0x00); -+ rpi_touchscreen_write(ts, LCDCTRL, 0x00100150); -+ rpi_touchscreen_write(ts, SYSCTRL, 0x040f); -+ msleep(100); -+ -+ rpi_touchscreen_write(ts, PPI_STARTPPI, 0x01); -+ rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01); -+ msleep(100); -+ -+ /* Turn on the backlight. */ -+ rpi_touchscreen_i2c_write(ts, REG_PWM, 255); -+ -+ /* Default to the same orientation as the closed source -+ * firmware used for the panel. Runtime rotation -+ * configuration will be supported using VC4's plane -+ * orientation bits. -+ */ -+ rpi_touchscreen_i2c_write(ts, REG_PORTA, BIT(2)); -+ -+ return 0; -+} -+ -+static int rpi_touchscreen_get_modes(struct drm_panel *panel) -+{ -+ struct drm_connector *connector = panel->connector; -+ struct drm_device *drm = panel->drm; -+ unsigned int i, num = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(rpi_touchscreen_modes); i++) { -+ const struct drm_display_mode *m = &rpi_touchscreen_modes[i]; -+ struct drm_display_mode *mode; -+ -+ mode = drm_mode_duplicate(drm, m); -+ if (!mode) { -+ dev_err(drm->dev, "failed to add mode %ux%u@%u\n", -+ m->hdisplay, m->vdisplay, m->vrefresh); -+ continue; -+ } -+ -+ mode->type |= DRM_MODE_TYPE_DRIVER; -+ -+ if (i == 0) -+ mode->type |= DRM_MODE_TYPE_PREFERRED; -+ -+ drm_mode_set_name(mode); -+ -+ drm_mode_probed_add(connector, mode); -+ num++; -+ } -+ -+ connector->display_info.bpc = 8; -+ connector->display_info.width_mm = 154; -+ connector->display_info.height_mm = 86; -+ -+ return num; -+} -+ -+static const struct drm_panel_funcs rpi_touchscreen_funcs = { -+ .disable = rpi_touchscreen_disable, -+ .unprepare = rpi_touchscreen_noop, -+ .prepare = rpi_touchscreen_noop, -+ .enable = rpi_touchscreen_enable, -+ .get_modes = rpi_touchscreen_get_modes, -+}; -+ -+static struct i2c_client *rpi_touchscreen_get_i2c(struct device *dev, -+ const char *name) -+{ -+ struct device_node *node; -+ struct i2c_client *client; -+ -+ node = of_parse_phandle(dev->of_node, name, 0); -+ if (!node) -+ return ERR_PTR(-ENODEV); -+ -+ client = of_find_i2c_device_by_node(node); -+ -+ of_node_put(node); -+ -+ return client; -+} -+ -+static int rpi_touchscreen_dsi_probe(struct mipi_dsi_device *dsi) -+{ -+ struct device *dev = &dsi->dev; -+ struct rpi_touchscreen *ts; -+ int ret, ver; -+ -+ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); -+ if (!ts) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, ts); -+ -+ ts->dsi = dsi; -+ dsi->mode_flags = (MIPI_DSI_MODE_VIDEO | -+ MIPI_DSI_MODE_VIDEO_SYNC_PULSE | -+ MIPI_DSI_MODE_LPM); -+ dsi->format = MIPI_DSI_FMT_RGB888; -+ dsi->lanes = 1; -+ -+ ts->bridge_i2c = -+ rpi_touchscreen_get_i2c(dev, "raspberrypi,touchscreen-bridge"); -+ if (IS_ERR(ts->bridge_i2c)) { -+ ret = -EPROBE_DEFER; -+ return ret; -+ } -+ -+ ver = rpi_touchscreen_i2c_read(ts, REG_ID); -+ if (ver < 0) { -+ dev_err(dev, "Atmel I2C read failed: %d\n", ver); -+ return -ENODEV; -+ } -+ -+ switch (ver) { -+ case 0xde: -+ ts->atmel_ver = 1; -+ break; -+ case 0xc3: -+ ts->atmel_ver = 2; -+ break; -+ default: -+ dev_err(dev, "Unknown Atmel firmware revision: 0x%02x\n", ver); -+ return -ENODEV; -+ } -+ -+ /* Turn off at boot, so we can cleanly sequence powering on. */ -+ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); -+ -+ drm_panel_init(&ts->base); -+ ts->base.dev = dev; -+ ts->base.funcs = &rpi_touchscreen_funcs; -+ -+ ret = drm_panel_add(&ts->base); -+ if (ret < 0) -+ goto err_release_bridge; -+ -+ return mipi_dsi_attach(dsi); -+ -+err_release_bridge: -+ put_device(&ts->bridge_i2c->dev); -+ return ret; -+} -+ -+static int rpi_touchscreen_dsi_remove(struct mipi_dsi_device *dsi) -+{ -+ struct device *dev = &dsi->dev; -+ struct rpi_touchscreen *ts = dev_get_drvdata(dev); -+ int ret; -+ -+ ret = mipi_dsi_detach(dsi); -+ if (ret < 0) { -+ dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); -+ return ret; -+ } -+ -+ drm_panel_detach(&ts->base); -+ drm_panel_remove(&ts->base); -+ -+ put_device(&ts->bridge_i2c->dev); -+ -+ return 0; -+} -+ -+static void rpi_touchscreen_dsi_shutdown(struct mipi_dsi_device *dsi) -+{ -+ struct device *dev = &dsi->dev; -+ struct rpi_touchscreen *ts = dev_get_drvdata(dev); -+ -+ rpi_touchscreen_i2c_write(ts, REG_POWERON, 0); -+} -+ -+static const struct of_device_id rpi_touchscreen_of_match[] = { -+ { .compatible = "raspberrypi,touchscreen" }, -+ { } /* sentinel */ -+}; -+MODULE_DEVICE_TABLE(of, rpi_touchscreen_of_match); -+ -+static struct mipi_dsi_driver rpi_touchscreen_driver = { -+ .driver = { -+ .name = "raspberrypi-touchscreen", -+ .of_match_table = rpi_touchscreen_of_match, -+ }, -+ .probe = rpi_touchscreen_dsi_probe, -+ .remove = rpi_touchscreen_dsi_remove, -+ .shutdown = rpi_touchscreen_dsi_shutdown, -+}; -+module_mipi_dsi_driver(rpi_touchscreen_driver); -+ -+MODULE_AUTHOR("Eric Anholt "); -+MODULE_DESCRIPTION("Raspberry Pi 7-inch touchscreen driver"); -+MODULE_LICENSE("GPL v2"); - -From 5ac6f3b06f20a04a35e2fe294150ebfdb1d2dbf6 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 2 Jun 2016 12:29:45 -0700 -Subject: [PATCH 169/216] BCM270X: Add the DSI panel to the defconfig. - -Signed-off-by: Eric Anholt ---- - arch/arm/configs/bcm2709_defconfig | 2 ++ - arch/arm/configs/bcmrpi_defconfig | 2 ++ - arch/arm64/configs/bcmrpi3_defconfig | 2 ++ - 3 files changed, 6 insertions(+) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 97375c26f2d70d0c4f3956622f839dcf04463e31..d3fd0252f78ec72bd6d93322e781abc3609af01c 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -833,6 +833,8 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_DRM=m - CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_PANEL_SIMPLE=m -+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m - CONFIG_DRM_UDL=m - CONFIG_DRM_VC4=m - CONFIG_FB=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 0e2c3679d9614d331db39cd25ae9095136d3190a..0768998e5cbcc96714d546f656ff59eafe2dc754 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -826,6 +826,8 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_DRM=m - CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_PANEL_SIMPLE=m -+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m - CONFIG_DRM_UDL=m - CONFIG_DRM_VC4=m - CONFIG_FB=y -diff --git a/arch/arm64/configs/bcmrpi3_defconfig b/arch/arm64/configs/bcmrpi3_defconfig -index 4d85c231c5ea0244e1b05fb4a5e3c8fd3e651ddf..baf316e3a69d421d79ec098c7ad2603c906782df 100644 ---- a/arch/arm64/configs/bcmrpi3_defconfig -+++ b/arch/arm64/configs/bcmrpi3_defconfig -@@ -812,6 +812,8 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_DRM=m - CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_PANEL_SIMPLE=m -+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m - CONFIG_DRM_UDL=m - CONFIG_DRM_VC4=m - CONFIG_FB=y - -From a1693f9a5e0575f11d1a388cc87efc128122700f Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Tue, 13 Dec 2016 15:15:10 -0800 -Subject: [PATCH 170/216] ARM: bcm2835: dt: Add the DSI module nodes and - clocks. - -The modules stay disabled by default, and if you want to enable DSI -you'll need an overlay that connects a panel to it. - -Signed-off-by: Eric Anholt ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 8 +++++++ - arch/arm/boot/dts/bcm283x.dtsi | 49 +++++++++++++++++++++++++++++++++++--- - 2 files changed, 54 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index 6ddf7dfe3f7202642cc4d595ff4763f91248c0a5..58f7d874c70a9cf965e10ae3f14fe3bb00846b71 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -87,3 +87,11 @@ - power-domains = <&power RPI_POWER_DOMAIN_HDMI>; - status = "okay"; - }; -+ -+&dsi0 { -+ power-domains = <&power RPI_POWER_DOMAIN_DSI0>; -+}; -+ -+&dsi1 { -+ power-domains = <&power RPI_POWER_DOMAIN_DSI1>; -+}; -diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi -index b710a4d67b8ec8c8c18ce8efb6f270e7cfb68e52..304dd291a9ae94700e8e628c0c9ebd3fb98abb19 100644 ---- a/arch/arm/boot/dts/bcm283x.dtsi -+++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -93,10 +93,13 @@ - #clock-cells = <1>; - reg = <0x7e101000 0x2000>; - -- /* CPRMAN derives everything from the platform's -- * oscillator. -+ /* CPRMAN derives almost everything from the -+ * platform's oscillator. However, the DSI -+ * pixel clocks come from the DSI analog PHY. - */ -- clocks = <&clk_osc>; -+ clocks = <&clk_osc>, -+ <&dsi0 0>, <&dsi0 1>, <&dsi0 2>, -+ <&dsi1 0>, <&dsi1 1>, <&dsi1 2>; - }; - - rng@7e104000 { -@@ -391,6 +394,26 @@ - interrupts = <2 14>; /* pwa1 */ - }; - -+ dsi0: dsi@7e209000 { -+ compatible = "brcm,bcm2835-dsi0"; -+ reg = <0x7e209000 0x78>; -+ interrupts = <2 4>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #clock-cells = <1>; -+ -+ clocks = <&clocks BCM2835_PLLA_DSI0>, -+ <&clocks BCM2835_CLOCK_DSI0E>, -+ <&clocks BCM2835_CLOCK_DSI0P>; -+ clock-names = "phy", "escape", "pixel"; -+ -+ clock-output-names = "dsi0_byte", -+ "dsi0_ddr2", -+ "dsi0_ddr"; -+ -+ status = "disabled"; -+ }; -+ - thermal: thermal@7e212000 { - compatible = "brcm,bcm2835-thermal"; - reg = <0x7e212000 0x8>; -@@ -457,6 +480,26 @@ - interrupts = <2 1>; - }; - -+ dsi1: dsi@7e700000 { -+ compatible = "brcm,bcm2835-dsi1"; -+ reg = <0x7e700000 0x8c>; -+ interrupts = <2 12>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ #clock-cells = <1>; -+ -+ clocks = <&clocks BCM2835_PLLD_DSI1>, -+ <&clocks BCM2835_CLOCK_DSI1E>, -+ <&clocks BCM2835_CLOCK_DSI1P>; -+ clock-names = "phy", "escape", "pixel"; -+ -+ clock-output-names = "dsi1_byte", -+ "dsi1_ddr2", -+ "dsi1_ddr"; -+ -+ status = "disabled"; -+ }; -+ - i2c1: i2c@7e804000 { - compatible = "brcm,bcm2835-i2c"; - reg = <0x7e804000 0x1000>; - -From fb5df730cb45f38aa5d98753f83d46049e90fccc Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 2 Jun 2016 15:09:35 -0700 -Subject: [PATCH 171/216] BCM270X: Enable the DSI panel node in the VC4 - overlay. - -Signed-off-by: Eric Anholt ---- - arch/arm/boot/dts/bcm2708-rpi-b-plus.dts | 5 ++++ - arch/arm/boot/dts/bcm2708-rpi-b.dts | 5 ++++ - arch/arm/boot/dts/bcm2709-rpi-2-b.dts | 5 ++++ - arch/arm/boot/dts/bcm270x.dtsi | 27 ++++++++++++++++++++++ - arch/arm/boot/dts/bcm2710-rpi-3-b.dts | 5 ++++ - arch/arm/boot/dts/bcm2710.dtsi | 1 - - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 23 +++++++++++++++++- - 7 files changed, 69 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -index 0b66ac9f25a5f7ae51f3d0666cfcb908f85e1d24..08bf838fab551638e898930fba7ba49b3aeefbb3 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b-plus.dts -@@ -155,3 +155,8 @@ - sd_debug = <&sdhost>,"brcm,debug"; - }; - }; -+ -+&i2c_dsi { -+ gpios = <&gpio 28 0 -+ &gpio 29 0>; -+}; -diff --git a/arch/arm/boot/dts/bcm2708-rpi-b.dts b/arch/arm/boot/dts/bcm2708-rpi-b.dts -index e99e9d999e4142060c41eb47b93c8ac70a30f384..4e6b4dd6a8d9c4f13bc865bb8ced68264162cb6c 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi-b.dts -+++ b/arch/arm/boot/dts/bcm2708-rpi-b.dts -@@ -145,3 +145,8 @@ - sd_debug = <&sdhost>,"brcm,debug"; - }; - }; -+ -+&i2c_dsi { -+ gpios = <&gpio 2 0 -+ &gpio 3 0>; -+}; -diff --git a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -index 20674f250af922e9f9a43e3e8b13aee42e3930be..2dc0e1204e6374bbc6924e26dc4a04b68718559a 100644 ---- a/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -+++ b/arch/arm/boot/dts/bcm2709-rpi-2-b.dts -@@ -155,3 +155,8 @@ - sd_debug = <&sdhost>,"brcm,debug"; - }; - }; -+ -+&i2c_dsi { -+ gpios = <&gpio 28 0 -+ &gpio 29 0>; -+}; -diff --git a/arch/arm/boot/dts/bcm270x.dtsi b/arch/arm/boot/dts/bcm270x.dtsi -index 36d853715f2379e1952ce3d3be58dd670e305159..caa66393518603529d284f360b2000b0ed4852ef 100644 ---- a/arch/arm/boot/dts/bcm270x.dtsi -+++ b/arch/arm/boot/dts/bcm270x.dtsi -@@ -137,6 +137,29 @@ - /* Add alias */ - status = "disabled"; - }; -+ -+ i2c_dsi: i2cdsi { -+ /* We have to use i2c-gpio because the -+ * firmware is also polling another device -+ * using the only hardware I2C bus that could -+ * connect to these pins. -+ */ -+ compatible = "i2c-gpio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ -+ pitouchscreen_bridge: bridge@45 { -+ compatible = "raspberrypi,touchscreen-bridge-i2c"; -+ reg = <0x45>; -+ }; -+ -+ pitouchscreen_touch: bridge@38 { -+ compatible = "raspberrypi,touchscreen-ts-i2c"; -+ reg = <0x38>; -+ }; -+ }; -+ - }; - - vdd_5v0_reg: fixedregulator_5v0 { -@@ -155,3 +178,7 @@ - regulator-always-on; - }; - }; -+ -+&dsi1 { -+ power-domains = <&power RPI_POWER_DOMAIN_DSI1>; -+}; -diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 616cfd5c7094596b497101e8feca25e25e77c3e8..173103aaca503833b5e29530ed94e14c7cab0444 100644 ---- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -+++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -@@ -224,3 +224,8 @@ - sd_debug = <&sdhost>,"brcm,debug"; - }; - }; -+ -+&i2c_dsi { -+ gpios = <&gpio 44 0 -+ &gpio 45 0>; -+}; -diff --git a/arch/arm/boot/dts/bcm2710.dtsi b/arch/arm/boot/dts/bcm2710.dtsi -index 3e134a1208610b90e2d0fc22f03c6e9f372bfcd7..3fabac6a93e846f678d846637c4f9a5f5b8e7922 100644 ---- a/arch/arm/boot/dts/bcm2710.dtsi -+++ b/arch/arm/boot/dts/bcm2710.dtsi -@@ -145,4 +145,3 @@ - interrupt-parent = <&local_intc>; - interrupts = <8>; - }; -- -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 fb45c6456b181b047d6cff8784f7696eb75da3c7..05faf1bfa1b7c73fd60b1efb813b969e10bbfefa 100644 ---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -128,8 +128,29 @@ - }; - }; - -- - fragment@16 { -+ target = <&dsi1>; -+ __overlay__ { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "okay"; -+ -+ pitouchscreen: panel@0 { -+ compatible = "raspberrypi,touchscreen"; -+ reg = <0>; -+ raspberrypi,touchscreen-bridge = <&pitouchscreen_bridge>; -+ }; -+ }; -+ }; -+ -+ fragment@17 { -+ target = <&i2c_dsi>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@18 { - target = <&clocks>; - __overlay__ { - claim-clocks = < - -From 85eac700f7a8218f67e3536df9bd6dea9f0a98a8 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 15 Sep 2016 15:25:23 +0100 -Subject: [PATCH 172/216] drm/vc4: Set up SCALER_DISPCTRL at boot. - -We want the HVS on, obviously, and we also want DSP3 (PV1's source) to -be muxed from HVS channel 2 like we expect in vc4_crtc.c. The -firmware wasn't setting the DSP3 mux up when both the LCD and HDMI -were disabled. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_hvs.c | 14 ++++++++++++++ - drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ - 2 files changed, 17 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c -index 6fbab1c82cb1089bde0834f3e0bf1fdf99f54221..fc68b1b4da5249ce3181d7eabb0a08bf8e4908cf 100644 ---- a/drivers/gpu/drm/vc4/vc4_hvs.c -+++ b/drivers/gpu/drm/vc4/vc4_hvs.c -@@ -170,6 +170,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) - struct vc4_dev *vc4 = drm->dev_private; - struct vc4_hvs *hvs = NULL; - int ret; -+ u32 dispctrl; - - hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL); - if (!hvs) -@@ -211,6 +212,19 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) - return ret; - - vc4->hvs = hvs; -+ -+ dispctrl = HVS_READ(SCALER_DISPCTRL); -+ -+ dispctrl |= SCALER_DISPCTRL_ENABLE; -+ -+ /* Set DSP3 (PV1) to use HVS channel 2, which would otherwise -+ * be unused. -+ */ -+ dispctrl &= ~SCALER_DISPCTRL_DSP3_MUX_MASK; -+ dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX); -+ -+ HVS_WRITE(SCALER_DISPCTRL, dispctrl); -+ - return 0; - } - -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index 39f6886b24100c43b590e47e0c7bc44846721d65..b3b297fba7097bc495fa8916292c547925720199 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -244,6 +244,9 @@ - # define SCALER_DISPCTRL_ENABLE BIT(31) - # define SCALER_DISPCTRL_DSP2EISLUR BIT(15) - # define SCALER_DISPCTRL_DSP1EISLUR BIT(14) -+# define SCALER_DISPCTRL_DSP3_MUX_MASK VC4_MASK(19, 18) -+# define SCALER_DISPCTRL_DSP3_MUX_SHIFT 18 -+ - /* Enables Display 0 short line and underrun contribution to - * SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are - * always enabled. - -From e3c71207f0a6953f357b09511b04ef5e65fd0863 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 10 Feb 2016 16:17:29 -0800 -Subject: [PATCH 173/216] drm/vc4: Add support for feeding DSI encoders from - the pixel valve. - -We have to set a different pixel format, which tells the hardware to -use the pix_width field that's fed in sideband from the DSI encoder to -divide the "pixel" clock. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_crtc.c | 33 +++++++++++++++++++-------------- - drivers/gpu/drm/vc4/vc4_regs.h | 2 ++ - 2 files changed, 21 insertions(+), 14 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c -index c7e478f672e184974a33bb9ca72b8aa62d76e97e..a4937e261202748924a5a327995b6f700afd5a97 100644 ---- a/drivers/gpu/drm/vc4/vc4_crtc.c -+++ b/drivers/gpu/drm/vc4/vc4_crtc.c -@@ -352,38 +352,40 @@ static u32 vc4_get_fifo_full_level(u32 format) - } - - /* -- * Returns the clock select bit for the connector attached to the -- * CRTC. -+ * Returns the encoder attached to the CRTC. -+ * -+ * VC4 can only scan out to one encoder at a time, while the DRM core -+ * allows drivers to push pixels to more than one encoder from the -+ * same CRTC. - */ --static int vc4_get_clock_select(struct drm_crtc *crtc) -+static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc) - { - struct drm_connector *connector; - - drm_for_each_connector(connector, crtc->dev) { - if (connector->state->crtc == crtc) { -- struct drm_encoder *encoder = connector->encoder; -- struct vc4_encoder *vc4_encoder = -- to_vc4_encoder(encoder); -- -- return vc4_encoder->clock_select; -+ return connector->encoder; - } - } - -- return -1; -+ return NULL; - } - - static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - { - struct drm_device *dev = crtc->dev; - struct vc4_dev *vc4 = to_vc4_dev(dev); -+ struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); -+ struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); - struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - struct drm_crtc_state *state = crtc->state; - struct drm_display_mode *mode = &state->adjusted_mode; - bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; - u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; -- u32 format = PV_CONTROL_FORMAT_24; -+ bool is_dsi = (vc4_encoder->type == VC4_ENCODER_TYPE_DSI0 || -+ vc4_encoder->type == VC4_ENCODER_TYPE_DSI1); -+ u32 format = is_dsi ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; - bool debug_dump_regs = false; -- int clock_select = vc4_get_clock_select(crtc); - - if (debug_dump_regs) { - DRM_INFO("CRTC %d regs before:\n", drm_crtc_index(crtc)); -@@ -439,17 +441,19 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - */ - CRTC_WRITE(PV_V_CONTROL, - PV_VCONTROL_CONTINUOUS | -+ (is_dsi ? PV_VCONTROL_DSI : 0) | - PV_VCONTROL_INTERLACE | - VC4_SET_FIELD(mode->htotal * pixel_rep / 2, - PV_VCONTROL_ODD_DELAY)); - CRTC_WRITE(PV_VSYNCD_EVEN, 0); - } else { -- CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); -+ CRTC_WRITE(PV_V_CONTROL, -+ PV_VCONTROL_CONTINUOUS | -+ (is_dsi ? PV_VCONTROL_DSI : 0)); - } - - CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); - -- - CRTC_WRITE(PV_CONTROL, - VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | - VC4_SET_FIELD(vc4_get_fifo_full_level(format), -@@ -458,7 +462,8 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) - PV_CONTROL_CLR_AT_START | - PV_CONTROL_TRIGGER_UNDERFLOW | - PV_CONTROL_WAIT_HSTART | -- VC4_SET_FIELD(clock_select, PV_CONTROL_CLK_SELECT) | -+ VC4_SET_FIELD(vc4_encoder->clock_select, -+ PV_CONTROL_CLK_SELECT) | - PV_CONTROL_FIFO_CLR | - PV_CONTROL_EN); - -diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h -index b3b297fba7097bc495fa8916292c547925720199..385405a2df05eb3dd86d4f687aa8205331bec3cc 100644 ---- a/drivers/gpu/drm/vc4/vc4_regs.h -+++ b/drivers/gpu/drm/vc4/vc4_regs.h -@@ -190,6 +190,8 @@ - # define PV_VCONTROL_ODD_DELAY_SHIFT 6 - # define PV_VCONTROL_ODD_FIRST BIT(5) - # define PV_VCONTROL_INTERLACE BIT(4) -+# define PV_VCONTROL_DSI BIT(3) -+# define PV_VCONTROL_COMMAND BIT(2) - # define PV_VCONTROL_CONTINUOUS BIT(1) - # define PV_VCONTROL_VIDEN BIT(0) - - -From 5ce7b6e477653ef8d07d1170b92f3d988a2e934f Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 10 Feb 2016 11:42:32 -0800 -Subject: [PATCH 174/216] drm/vc4: Add DSI driver - -The DSI0 and DSI1 blocks on the 2835 are related hardware blocks. -Some registers move around, and the featureset is slightly different, -as DSI1 (the 4-lane DSI) is a later version of the hardware block. -This driver doesn't yet enable DSI0, since we don't have any hardware -to test against, but it does put a lot of the register definitions and -code in place. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/Kconfig | 2 + - drivers/gpu/drm/vc4/Makefile | 1 + - drivers/gpu/drm/vc4/vc4_debugfs.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.c | 1 + - drivers/gpu/drm/vc4/vc4_drv.h | 5 + - drivers/gpu/drm/vc4/vc4_dsi.c | 1725 +++++++++++++++++++++++++++++++++++++ - 6 files changed, 1735 insertions(+) - create mode 100644 drivers/gpu/drm/vc4/vc4_dsi.c - -diff --git a/drivers/gpu/drm/vc4/Kconfig b/drivers/gpu/drm/vc4/Kconfig -index e53df59cb139f25f8e6ae916bca93abf0c49e063..e1517d07cb7d22776ca164a5d2d9b87e55a5563a 100644 ---- a/drivers/gpu/drm/vc4/Kconfig -+++ b/drivers/gpu/drm/vc4/Kconfig -@@ -2,10 +2,12 @@ config DRM_VC4 - tristate "Broadcom VC4 Graphics" - depends on ARCH_BCM2835 || COMPILE_TEST - depends on DRM -+ depends on COMMON_CLK - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - select DRM_GEM_CMA_HELPER - select DRM_PANEL -+ select DRM_MIPI_DSI - help - Choose this option if you have a system that has a Broadcom - VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835. -diff --git a/drivers/gpu/drm/vc4/Makefile b/drivers/gpu/drm/vc4/Makefile -index 3358ec8775cf6e8738ea8cdb2246dad57bd29139..897f658bee287f84f7dde8dca43090ad5541495b 100644 ---- a/drivers/gpu/drm/vc4/Makefile -+++ b/drivers/gpu/drm/vc4/Makefile -@@ -8,6 +8,7 @@ vc4-y := \ - vc4_crtc.o \ - vc4_drv.o \ - vc4_dpi.o \ -+ vc4_dsi.o \ - vc4_firmware_kms.o \ - vc4_kms.o \ - vc4_gem.o \ -diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c -index caf817bac8852c82f0d6a34b676a649c10e6e6cd..3ca476c6e0578e5fbe60d4fd623b09f8f937c0b7 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}, -+ {"dsi1_regs", vc4_dsi_debugfs_regs, 0, (void *)(uintptr_t)1}, - {"hdmi_regs", vc4_hdmi_debugfs_regs, 0}, - {"vec_regs", vc4_vec_debugfs_regs, 0}, - {"hvs_regs", vc4_hvs_debugfs_regs, 0}, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c -index 44cd22340d82dbd5d094806e777121951f25010a..8666c4f46f1fad3192613c39fbe3aeb07b86bc68 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.c -+++ b/drivers/gpu/drm/vc4/vc4_drv.c -@@ -296,6 +296,7 @@ static struct platform_driver *const component_drivers[] = { - &vc4_hdmi_driver, - &vc4_vec_driver, - &vc4_dpi_driver, -+ &vc4_dsi_driver, - &vc4_hvs_driver, - &vc4_crtc_driver, - &vc4_firmware_kms_driver, -diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h -index 61a9b3e81823a3c96f36f710329844cc032e2628..44a8e6fda2b576fed63d93ef34e076cebf90d64c 100644 ---- a/drivers/gpu/drm/vc4/vc4_drv.h -+++ b/drivers/gpu/drm/vc4/vc4_drv.h -@@ -20,6 +20,7 @@ struct vc4_dev { - struct vc4_crtc *crtc[3]; - struct vc4_v3d *v3d; - struct vc4_dpi *dpi; -+ struct vc4_dsi *dsi1; - struct vc4_vec *vec; - - struct drm_fbdev_cma *fbdev; -@@ -468,6 +469,10 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index); - extern struct platform_driver vc4_dpi_driver; - int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused); - -+/* vc4_dsi.c */ -+extern struct platform_driver vc4_dsi_driver; -+int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused); -+ - /* vc4_firmware_kms.c */ - extern struct platform_driver vc4_firmware_kms_driver; - void vc4_fkms_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); -diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c -new file mode 100644 -index 0000000000000000000000000000000000000000..17fcac381dbb37cd9a5ff210ad8578f480177039 ---- /dev/null -+++ b/drivers/gpu/drm/vc4/vc4_dsi.c -@@ -0,0 +1,1725 @@ -+/* -+ * Copyright (C) 2016 Broadcom -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program. If not, see . -+ */ -+ -+/** -+ * DOC: VC4 DSI0/DSI1 module -+ * -+ * BCM2835 contains two DSI modules, DSI0 and DSI1. DSI0 is a -+ * single-lane DSI controller, while DSI1 is a more modern 4-lane DSI -+ * controller. -+ * -+ * Most Raspberry Pi boards expose DSI1 as their "DISPLAY" connector, -+ * while the compute module brings both DSI0 and DSI1 out. -+ * -+ * This driver has been tested for DSI1 video-mode display only -+ * currently, with most of the information necessary for DSI0 -+ * hopefully present. -+ */ -+ -+#include "drm_atomic_helper.h" -+#include "drm_crtc_helper.h" -+#include "drm_edid.h" -+#include "drm_mipi_dsi.h" -+#include "drm_panel.h" -+#include "linux/clk.h" -+#include "linux/clk-provider.h" -+#include "linux/completion.h" -+#include "linux/component.h" -+#include "linux/dmaengine.h" -+#include "linux/i2c.h" -+#include "linux/of_address.h" -+#include "linux/of_platform.h" -+#include "linux/pm_runtime.h" -+#include "vc4_drv.h" -+#include "vc4_regs.h" -+ -+#define DSI_CMD_FIFO_DEPTH 16 -+#define DSI_PIX_FIFO_DEPTH 256 -+#define DSI_PIX_FIFO_WIDTH 4 -+ -+#define DSI0_CTRL 0x00 -+ -+/* Command packet control. */ -+#define DSI0_TXPKT1C 0x04 /* AKA PKTC */ -+#define DSI1_TXPKT1C 0x04 -+# define DSI_TXPKT1C_TRIG_CMD_MASK VC4_MASK(31, 24) -+# define DSI_TXPKT1C_TRIG_CMD_SHIFT 24 -+# define DSI_TXPKT1C_CMD_REPEAT_MASK VC4_MASK(23, 10) -+# define DSI_TXPKT1C_CMD_REPEAT_SHIFT 10 -+ -+# define DSI_TXPKT1C_DISPLAY_NO_MASK VC4_MASK(9, 8) -+# define DSI_TXPKT1C_DISPLAY_NO_SHIFT 8 -+/* Short, trigger, BTA, or a long packet that fits all in CMDFIFO. */ -+# define DSI_TXPKT1C_DISPLAY_NO_SHORT 0 -+/* Primary display where cmdfifo provides part of the payload and -+ * pixelvalve the rest. -+ */ -+# define DSI_TXPKT1C_DISPLAY_NO_PRIMARY 1 -+/* Secondary display where cmdfifo provides part of the payload and -+ * pixfifo the rest. -+ */ -+# define DSI_TXPKT1C_DISPLAY_NO_SECONDARY 2 -+ -+# define DSI_TXPKT1C_CMD_TX_TIME_MASK VC4_MASK(7, 6) -+# define DSI_TXPKT1C_CMD_TX_TIME_SHIFT 6 -+ -+# define DSI_TXPKT1C_CMD_CTRL_MASK VC4_MASK(5, 4) -+# define DSI_TXPKT1C_CMD_CTRL_SHIFT 4 -+/* Command only. Uses TXPKT1H and DISPLAY_NO */ -+# define DSI_TXPKT1C_CMD_CTRL_TX 0 -+/* Command with BTA for either ack or read data. */ -+# define DSI_TXPKT1C_CMD_CTRL_RX 1 -+/* Trigger according to TRIG_CMD */ -+# define DSI_TXPKT1C_CMD_CTRL_TRIG 2 -+/* BTA alone for getting error status after a command, or a TE trigger -+ * without a previous command. -+ */ -+# define DSI_TXPKT1C_CMD_CTRL_BTA 3 -+ -+# define DSI_TXPKT1C_CMD_MODE_LP BIT(3) -+# define DSI_TXPKT1C_CMD_TYPE_LONG BIT(2) -+# define DSI_TXPKT1C_CMD_TE_EN BIT(1) -+# define DSI_TXPKT1C_CMD_EN BIT(0) -+ -+/* Command packet header. */ -+#define DSI0_TXPKT1H 0x08 /* AKA PKTH */ -+#define DSI1_TXPKT1H 0x08 -+# define DSI_TXPKT1H_BC_CMDFIFO_MASK VC4_MASK(31, 24) -+# define DSI_TXPKT1H_BC_CMDFIFO_SHIFT 24 -+# define DSI_TXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) -+# define DSI_TXPKT1H_BC_PARAM_SHIFT 8 -+# define DSI_TXPKT1H_BC_DT_MASK VC4_MASK(7, 0) -+# define DSI_TXPKT1H_BC_DT_SHIFT 0 -+ -+#define DSI0_RXPKT1H 0x0c /* AKA RX1_PKTH */ -+#define DSI1_RXPKT1H 0x14 -+# define DSI_RXPKT1H_CRC_ERR BIT(31) -+# define DSI_RXPKT1H_DET_ERR BIT(30) -+# define DSI_RXPKT1H_ECC_ERR BIT(29) -+# define DSI_RXPKT1H_COR_ERR BIT(28) -+# define DSI_RXPKT1H_INCOMP_PKT BIT(25) -+# define DSI_RXPKT1H_PKT_TYPE_LONG BIT(24) -+/* Byte count if DSI_RXPKT1H_PKT_TYPE_LONG */ -+# define DSI_RXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) -+# define DSI_RXPKT1H_BC_PARAM_SHIFT 8 -+/* Short return bytes if !DSI_RXPKT1H_PKT_TYPE_LONG */ -+# define DSI_RXPKT1H_SHORT_1_MASK VC4_MASK(23, 16) -+# define DSI_RXPKT1H_SHORT_1_SHIFT 16 -+# define DSI_RXPKT1H_SHORT_0_MASK VC4_MASK(15, 8) -+# define DSI_RXPKT1H_SHORT_0_SHIFT 8 -+# define DSI_RXPKT1H_DT_LP_CMD_MASK VC4_MASK(7, 0) -+# define DSI_RXPKT1H_DT_LP_CMD_SHIFT 0 -+ -+#define DSI0_RXPKT2H 0x10 /* AKA RX2_PKTH */ -+#define DSI1_RXPKT2H 0x18 -+# define DSI_RXPKT1H_DET_ERR BIT(30) -+# define DSI_RXPKT1H_ECC_ERR BIT(29) -+# define DSI_RXPKT1H_COR_ERR BIT(28) -+# define DSI_RXPKT1H_INCOMP_PKT BIT(25) -+# define DSI_RXPKT1H_BC_PARAM_MASK VC4_MASK(23, 8) -+# define DSI_RXPKT1H_BC_PARAM_SHIFT 8 -+# define DSI_RXPKT1H_DT_MASK VC4_MASK(7, 0) -+# define DSI_RXPKT1H_DT_SHIFT 0 -+ -+#define DSI0_TXPKT_CMD_FIFO 0x14 /* AKA CMD_DATAF */ -+#define DSI1_TXPKT_CMD_FIFO 0x1c -+ -+#define DSI0_DISP0_CTRL 0x18 -+# define DSI_DISP0_PIX_CLK_DIV_MASK VC4_MASK(21, 13) -+# define DSI_DISP0_PIX_CLK_DIV_SHIFT 13 -+# define DSI_DISP0_LP_STOP_CTRL_MASK VC4_MASK(12, 11) -+# define DSI_DISP0_LP_STOP_CTRL_SHIFT 11 -+# define DSI_DISP0_LP_STOP_DISABLE 0 -+# define DSI_DISP0_LP_STOP_PERLINE 1 -+# define DSI_DISP0_LP_STOP_PERFRAME 2 -+ -+/* Transmit RGB pixels and null packets only during HACTIVE, instead -+ * of going to LP-STOP. -+ */ -+# define DSI_DISP_HACTIVE_NULL BIT(10) -+/* Transmit blanking packet only during vblank, instead of allowing LP-STOP. */ -+# define DSI_DISP_VBLP_CTRL BIT(9) -+/* Transmit blanking packet only during HFP, instead of allowing LP-STOP. */ -+# define DSI_DISP_HFP_CTRL BIT(8) -+/* Transmit blanking packet only during HBP, instead of allowing LP-STOP. */ -+# define DSI_DISP_HBP_CTRL BIT(7) -+# define DSI_DISP0_CHANNEL_MASK VC4_MASK(6, 5) -+# define DSI_DISP0_CHANNEL_SHIFT 5 -+/* Enables end events for HSYNC/VSYNC, not just start events. */ -+# define DSI_DISP0_ST_END BIT(4) -+# define DSI_DISP0_PFORMAT_MASK VC4_MASK(3, 2) -+# define DSI_DISP0_PFORMAT_SHIFT 2 -+# define DSI_PFORMAT_RGB565 0 -+# define DSI_PFORMAT_RGB666_PACKED 1 -+# define DSI_PFORMAT_RGB666 2 -+# define DSI_PFORMAT_RGB888 3 -+/* Default is VIDEO mode. */ -+# define DSI_DISP0_COMMAND_MODE BIT(1) -+# define DSI_DISP0_ENABLE BIT(0) -+ -+#define DSI0_DISP1_CTRL 0x1c -+#define DSI1_DISP1_CTRL 0x2c -+/* Format of the data written to TXPKT_PIX_FIFO. */ -+# define DSI_DISP1_PFORMAT_MASK VC4_MASK(2, 1) -+# define DSI_DISP1_PFORMAT_SHIFT 1 -+# define DSI_DISP1_PFORMAT_16BIT 0 -+# define DSI_DISP1_PFORMAT_24BIT 1 -+# define DSI_DISP1_PFORMAT_32BIT_LE 2 -+# define DSI_DISP1_PFORMAT_32BIT_BE 3 -+ -+/* DISP1 is always command mode. */ -+# define DSI_DISP1_ENABLE BIT(0) -+ -+#define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */ -+ -+#define DSI0_INT_STAT 0x24 -+#define DSI0_INT_EN 0x28 -+# define DSI1_INT_PHY_D3_ULPS BIT(30) -+# define DSI1_INT_PHY_D3_STOP BIT(29) -+# define DSI1_INT_PHY_D2_ULPS BIT(28) -+# define DSI1_INT_PHY_D2_STOP BIT(27) -+# define DSI1_INT_PHY_D1_ULPS BIT(26) -+# define DSI1_INT_PHY_D1_STOP BIT(25) -+# define DSI1_INT_PHY_D0_ULPS BIT(24) -+# define DSI1_INT_PHY_D0_STOP BIT(23) -+# define DSI1_INT_FIFO_ERR BIT(22) -+# define DSI1_INT_PHY_DIR_RTF BIT(21) -+# define DSI1_INT_PHY_RXLPDT BIT(20) -+# define DSI1_INT_PHY_RXTRIG BIT(19) -+# define DSI1_INT_PHY_D0_LPDT BIT(18) -+# define DSI1_INT_PHY_DIR_FTR BIT(17) -+ -+/* Signaled when the clock lane enters the given state. */ -+# define DSI1_INT_PHY_CLOCK_ULPS BIT(16) -+# define DSI1_INT_PHY_CLOCK_HS BIT(15) -+# define DSI1_INT_PHY_CLOCK_STOP BIT(14) -+ -+/* Signaled on timeouts */ -+# define DSI1_INT_PR_TO BIT(13) -+# define DSI1_INT_TA_TO BIT(12) -+# define DSI1_INT_LPRX_TO BIT(11) -+# define DSI1_INT_HSTX_TO BIT(10) -+ -+/* Contention on a line when trying to drive the line low */ -+# define DSI1_INT_ERR_CONT_LP1 BIT(9) -+# define DSI1_INT_ERR_CONT_LP0 BIT(8) -+ -+/* Control error: incorrect line state sequence on data lane 0. */ -+# define DSI1_INT_ERR_CONTROL BIT(7) -+/* LPDT synchronization error (bits received not a multiple of 8. */ -+ -+# define DSI1_INT_ERR_SYNC_ESC BIT(6) -+/* Signaled after receiving an error packet from the display in -+ * response to a read. -+ */ -+# define DSI1_INT_RXPKT2 BIT(5) -+/* Signaled after receiving a packet. The header and optional short -+ * response will be in RXPKT1H, and a long response will be in the -+ * RXPKT_FIFO. -+ */ -+# define DSI1_INT_RXPKT1 BIT(4) -+# define DSI1_INT_TXPKT2_DONE BIT(3) -+# define DSI1_INT_TXPKT2_END BIT(2) -+/* Signaled after all repeats of TXPKT1 are transferred. */ -+# define DSI1_INT_TXPKT1_DONE BIT(1) -+/* Signaled after each TXPKT1 repeat is scheduled. */ -+# define DSI1_INT_TXPKT1_END BIT(0) -+ -+#define DSI1_INTERRUPTS_ALWAYS_ENABLED (DSI1_INT_ERR_SYNC_ESC | \ -+ DSI1_INT_ERR_CONTROL | \ -+ DSI1_INT_ERR_CONT_LP0 | \ -+ DSI1_INT_ERR_CONT_LP1 | \ -+ DSI1_INT_HSTX_TO | \ -+ DSI1_INT_LPRX_TO | \ -+ DSI1_INT_TA_TO | \ -+ DSI1_INT_PR_TO) -+ -+#define DSI0_STAT 0x2c -+#define DSI0_HSTX_TO_CNT 0x30 -+#define DSI0_LPRX_TO_CNT 0x34 -+#define DSI0_TA_TO_CNT 0x38 -+#define DSI0_PR_TO_CNT 0x3c -+#define DSI0_PHYC 0x40 -+# define DSI1_PHYC_ESC_CLK_LPDT_MASK VC4_MASK(25, 20) -+# define DSI1_PHYC_ESC_CLK_LPDT_SHIFT 20 -+# define DSI1_PHYC_HS_CLK_CONTINUOUS BIT(18) -+# define DSI0_PHYC_ESC_CLK_LPDT_MASK VC4_MASK(17, 12) -+# define DSI0_PHYC_ESC_CLK_LPDT_SHIFT 12 -+# define DSI1_PHYC_CLANE_ULPS BIT(17) -+# define DSI1_PHYC_CLANE_ENABLE BIT(16) -+# define DSI_PHYC_DLANE3_ULPS BIT(13) -+# define DSI_PHYC_DLANE3_ENABLE BIT(12) -+# define DSI0_PHYC_HS_CLK_CONTINUOUS BIT(10) -+# define DSI0_PHYC_CLANE_ULPS BIT(9) -+# define DSI_PHYC_DLANE2_ULPS BIT(9) -+# define DSI0_PHYC_CLANE_ENABLE BIT(8) -+# define DSI_PHYC_DLANE2_ENABLE BIT(8) -+# define DSI_PHYC_DLANE1_ULPS BIT(5) -+# define DSI_PHYC_DLANE1_ENABLE BIT(4) -+# define DSI_PHYC_DLANE0_FORCE_STOP BIT(2) -+# define DSI_PHYC_DLANE0_ULPS BIT(1) -+# define DSI_PHYC_DLANE0_ENABLE BIT(0) -+ -+#define DSI0_HS_CLT0 0x44 -+#define DSI0_HS_CLT1 0x48 -+#define DSI0_HS_CLT2 0x4c -+#define DSI0_HS_DLT3 0x50 -+#define DSI0_HS_DLT4 0x54 -+#define DSI0_HS_DLT5 0x58 -+#define DSI0_HS_DLT6 0x5c -+#define DSI0_HS_DLT7 0x60 -+ -+#define DSI0_PHY_AFEC0 0x64 -+# define DSI0_PHY_AFEC0_DDR2CLK_EN BIT(26) -+# define DSI0_PHY_AFEC0_DDRCLK_EN BIT(25) -+# define DSI0_PHY_AFEC0_LATCH_ULPS BIT(24) -+# define DSI1_PHY_AFEC0_IDR_DLANE3_MASK VC4_MASK(31, 29) -+# define DSI1_PHY_AFEC0_IDR_DLANE3_SHIFT 29 -+# define DSI1_PHY_AFEC0_IDR_DLANE2_MASK VC4_MASK(28, 26) -+# define DSI1_PHY_AFEC0_IDR_DLANE2_SHIFT 26 -+# define DSI1_PHY_AFEC0_IDR_DLANE1_MASK VC4_MASK(27, 23) -+# define DSI1_PHY_AFEC0_IDR_DLANE1_SHIFT 23 -+# define DSI1_PHY_AFEC0_IDR_DLANE0_MASK VC4_MASK(22, 20) -+# define DSI1_PHY_AFEC0_IDR_DLANE0_SHIFT 20 -+# define DSI1_PHY_AFEC0_IDR_CLANE_MASK VC4_MASK(19, 17) -+# define DSI1_PHY_AFEC0_IDR_CLANE_SHIFT 17 -+# define DSI0_PHY_AFEC0_ACTRL_DLANE1_MASK VC4_MASK(23, 20) -+# define DSI0_PHY_AFEC0_ACTRL_DLANE1_SHIFT 20 -+# define DSI0_PHY_AFEC0_ACTRL_DLANE0_MASK VC4_MASK(19, 16) -+# define DSI0_PHY_AFEC0_ACTRL_DLANE0_SHIFT 16 -+# define DSI0_PHY_AFEC0_ACTRL_CLANE_MASK VC4_MASK(15, 12) -+# define DSI0_PHY_AFEC0_ACTRL_CLANE_SHIFT 12 -+# define DSI1_PHY_AFEC0_DDR2CLK_EN BIT(16) -+# define DSI1_PHY_AFEC0_DDRCLK_EN BIT(15) -+# define DSI1_PHY_AFEC0_LATCH_ULPS BIT(14) -+# define DSI1_PHY_AFEC0_RESET BIT(13) -+# define DSI1_PHY_AFEC0_PD BIT(12) -+# define DSI0_PHY_AFEC0_RESET BIT(11) -+# define DSI1_PHY_AFEC0_PD_BG BIT(11) -+# define DSI0_PHY_AFEC0_PD BIT(10) -+# define DSI1_PHY_AFEC0_PD_DLANE3 BIT(10) -+# define DSI0_PHY_AFEC0_PD_BG BIT(9) -+# define DSI1_PHY_AFEC0_PD_DLANE2 BIT(9) -+# define DSI0_PHY_AFEC0_PD_DLANE1 BIT(8) -+# define DSI1_PHY_AFEC0_PD_DLANE1 BIT(8) -+# define DSI_PHY_AFEC0_PTATADJ_MASK VC4_MASK(7, 4) -+# define DSI_PHY_AFEC0_PTATADJ_SHIFT 4 -+# define DSI_PHY_AFEC0_CTATADJ_MASK VC4_MASK(3, 0) -+# define DSI_PHY_AFEC0_CTATADJ_SHIFT 0 -+ -+#define DSI0_PHY_AFEC1 0x68 -+# define DSI0_PHY_AFEC1_IDR_DLANE1_MASK VC4_MASK(10, 8) -+# define DSI0_PHY_AFEC1_IDR_DLANE1_SHIFT 8 -+# define DSI0_PHY_AFEC1_IDR_DLANE0_MASK VC4_MASK(6, 4) -+# define DSI0_PHY_AFEC1_IDR_DLANE0_SHIFT 4 -+# define DSI0_PHY_AFEC1_IDR_CLANE_MASK VC4_MASK(2, 0) -+# define DSI0_PHY_AFEC1_IDR_CLANE_SHIFT 0 -+ -+#define DSI0_TST_SEL 0x6c -+#define DSI0_TST_MON 0x70 -+#define DSI0_ID 0x74 -+# define DSI_ID_VALUE 0x00647369 -+ -+#define DSI1_CTRL 0x00 -+# define DSI_CTRL_HS_CLKC_MASK VC4_MASK(15, 14) -+# define DSI_CTRL_HS_CLKC_SHIFT 14 -+# define DSI_CTRL_HS_CLKC_BYTE 0 -+# define DSI_CTRL_HS_CLKC_DDR2 1 -+# define DSI_CTRL_HS_CLKC_DDR 2 -+ -+# define DSI_CTRL_RX_LPDT_EOT_DISABLE BIT(13) -+# define DSI_CTRL_LPDT_EOT_DISABLE BIT(12) -+# define DSI_CTRL_HSDT_EOT_DISABLE BIT(11) -+# define DSI_CTRL_SOFT_RESET_CFG BIT(10) -+# define DSI_CTRL_CAL_BYTE BIT(9) -+# define DSI_CTRL_INV_BYTE BIT(8) -+# define DSI_CTRL_CLR_LDF BIT(7) -+# define DSI0_CTRL_CLR_PBCF BIT(6) -+# define DSI1_CTRL_CLR_RXF BIT(6) -+# define DSI0_CTRL_CLR_CPBCF BIT(5) -+# define DSI1_CTRL_CLR_PDF BIT(5) -+# define DSI0_CTRL_CLR_PDF BIT(4) -+# define DSI1_CTRL_CLR_CDF BIT(4) -+# define DSI0_CTRL_CLR_CDF BIT(3) -+# define DSI0_CTRL_CTRL2 BIT(2) -+# define DSI1_CTRL_DISABLE_DISP_CRCC BIT(2) -+# define DSI0_CTRL_CTRL1 BIT(1) -+# define DSI1_CTRL_DISABLE_DISP_ECCC BIT(1) -+# define DSI0_CTRL_CTRL0 BIT(0) -+# define DSI1_CTRL_EN BIT(0) -+# define DSI0_CTRL_RESET_FIFOS (DSI_CTRL_CLR_LDF | \ -+ DSI0_CTRL_CLR_PBCF | \ -+ DSI0_CTRL_CLR_CPBCF | \ -+ DSI0_CTRL_CLR_PDF | \ -+ DSI0_CTRL_CLR_CDF) -+# define DSI1_CTRL_RESET_FIFOS (DSI_CTRL_CLR_LDF | \ -+ DSI1_CTRL_CLR_RXF | \ -+ DSI1_CTRL_CLR_PDF | \ -+ DSI1_CTRL_CLR_CDF) -+ -+#define DSI1_TXPKT2C 0x0c -+#define DSI1_TXPKT2H 0x10 -+#define DSI1_TXPKT_PIX_FIFO 0x20 -+#define DSI1_RXPKT_FIFO 0x24 -+#define DSI1_DISP0_CTRL 0x28 -+#define DSI1_INT_STAT 0x30 -+#define DSI1_INT_EN 0x34 -+/* State reporting bits. These mostly behave like INT_STAT, where -+ * writing a 1 clears the bit. -+ */ -+#define DSI1_STAT 0x38 -+# define DSI1_STAT_PHY_D3_ULPS BIT(31) -+# define DSI1_STAT_PHY_D3_STOP BIT(30) -+# define DSI1_STAT_PHY_D2_ULPS BIT(29) -+# define DSI1_STAT_PHY_D2_STOP BIT(28) -+# define DSI1_STAT_PHY_D1_ULPS BIT(27) -+# define DSI1_STAT_PHY_D1_STOP BIT(26) -+# define DSI1_STAT_PHY_D0_ULPS BIT(25) -+# define DSI1_STAT_PHY_D0_STOP BIT(24) -+# define DSI1_STAT_FIFO_ERR BIT(23) -+# define DSI1_STAT_PHY_RXLPDT BIT(22) -+# define DSI1_STAT_PHY_RXTRIG BIT(21) -+# define DSI1_STAT_PHY_D0_LPDT BIT(20) -+/* Set when in forward direction */ -+# define DSI1_STAT_PHY_DIR BIT(19) -+# define DSI1_STAT_PHY_CLOCK_ULPS BIT(18) -+# define DSI1_STAT_PHY_CLOCK_HS BIT(17) -+# define DSI1_STAT_PHY_CLOCK_STOP BIT(16) -+# define DSI1_STAT_PR_TO BIT(15) -+# define DSI1_STAT_TA_TO BIT(14) -+# define DSI1_STAT_LPRX_TO BIT(13) -+# define DSI1_STAT_HSTX_TO BIT(12) -+# define DSI1_STAT_ERR_CONT_LP1 BIT(11) -+# define DSI1_STAT_ERR_CONT_LP0 BIT(10) -+# define DSI1_STAT_ERR_CONTROL BIT(9) -+# define DSI1_STAT_ERR_SYNC_ESC BIT(8) -+# define DSI1_STAT_RXPKT2 BIT(7) -+# define DSI1_STAT_RXPKT1 BIT(6) -+# define DSI1_STAT_TXPKT2_BUSY BIT(5) -+# define DSI1_STAT_TXPKT2_DONE BIT(4) -+# define DSI1_STAT_TXPKT2_END BIT(3) -+# define DSI1_STAT_TXPKT1_BUSY BIT(2) -+# define DSI1_STAT_TXPKT1_DONE BIT(1) -+# define DSI1_STAT_TXPKT1_END BIT(0) -+ -+#define DSI1_HSTX_TO_CNT 0x3c -+#define DSI1_LPRX_TO_CNT 0x40 -+#define DSI1_TA_TO_CNT 0x44 -+#define DSI1_PR_TO_CNT 0x48 -+#define DSI1_PHYC 0x4c -+ -+#define DSI1_HS_CLT0 0x50 -+# define DSI_HS_CLT0_CZERO_MASK VC4_MASK(26, 18) -+# define DSI_HS_CLT0_CZERO_SHIFT 18 -+# define DSI_HS_CLT0_CPRE_MASK VC4_MASK(17, 9) -+# define DSI_HS_CLT0_CPRE_SHIFT 9 -+# define DSI_HS_CLT0_CPREP_MASK VC4_MASK(8, 0) -+# define DSI_HS_CLT0_CPREP_SHIFT 0 -+ -+#define DSI1_HS_CLT1 0x54 -+# define DSI_HS_CLT1_CTRAIL_MASK VC4_MASK(17, 9) -+# define DSI_HS_CLT1_CTRAIL_SHIFT 9 -+# define DSI_HS_CLT1_CPOST_MASK VC4_MASK(8, 0) -+# define DSI_HS_CLT1_CPOST_SHIFT 0 -+ -+#define DSI1_HS_CLT2 0x58 -+# define DSI_HS_CLT2_WUP_MASK VC4_MASK(23, 0) -+# define DSI_HS_CLT2_WUP_SHIFT 0 -+ -+#define DSI1_HS_DLT3 0x5c -+# define DSI_HS_DLT3_EXIT_MASK VC4_MASK(26, 18) -+# define DSI_HS_DLT3_EXIT_SHIFT 18 -+# define DSI_HS_DLT3_ZERO_MASK VC4_MASK(17, 9) -+# define DSI_HS_DLT3_ZERO_SHIFT 9 -+# define DSI_HS_DLT3_PRE_MASK VC4_MASK(8, 0) -+# define DSI_HS_DLT3_PRE_SHIFT 0 -+ -+#define DSI1_HS_DLT4 0x60 -+# define DSI_HS_DLT4_ANLAT_MASK VC4_MASK(22, 18) -+# define DSI_HS_DLT4_ANLAT_SHIFT 18 -+# define DSI_HS_DLT4_TRAIL_MASK VC4_MASK(17, 9) -+# define DSI_HS_DLT4_TRAIL_SHIFT 9 -+# define DSI_HS_DLT4_LPX_MASK VC4_MASK(8, 0) -+# define DSI_HS_DLT4_LPX_SHIFT 0 -+ -+#define DSI1_HS_DLT5 0x64 -+# define DSI_HS_DLT5_INIT_MASK VC4_MASK(23, 0) -+# define DSI_HS_DLT5_INIT_SHIFT 0 -+ -+#define DSI1_HS_DLT6 0x68 -+# define DSI_HS_DLT6_TA_GET_MASK VC4_MASK(31, 24) -+# define DSI_HS_DLT6_TA_GET_SHIFT 24 -+# define DSI_HS_DLT6_TA_SURE_MASK VC4_MASK(23, 16) -+# define DSI_HS_DLT6_TA_SURE_SHIFT 16 -+# define DSI_HS_DLT6_TA_GO_MASK VC4_MASK(15, 8) -+# define DSI_HS_DLT6_TA_GO_SHIFT 8 -+# define DSI_HS_DLT6_LP_LPX_MASK VC4_MASK(7, 0) -+# define DSI_HS_DLT6_LP_LPX_SHIFT 0 -+ -+#define DSI1_HS_DLT7 0x6c -+# define DSI_HS_DLT7_LP_WUP_MASK VC4_MASK(23, 0) -+# define DSI_HS_DLT7_LP_WUP_SHIFT 0 -+ -+#define DSI1_PHY_AFEC0 0x70 -+ -+#define DSI1_PHY_AFEC1 0x74 -+# define DSI1_PHY_AFEC1_ACTRL_DLANE3_MASK VC4_MASK(19, 16) -+# define DSI1_PHY_AFEC1_ACTRL_DLANE3_SHIFT 16 -+# define DSI1_PHY_AFEC1_ACTRL_DLANE2_MASK VC4_MASK(15, 12) -+# define DSI1_PHY_AFEC1_ACTRL_DLANE2_SHIFT 12 -+# define DSI1_PHY_AFEC1_ACTRL_DLANE1_MASK VC4_MASK(11, 8) -+# define DSI1_PHY_AFEC1_ACTRL_DLANE1_SHIFT 8 -+# define DSI1_PHY_AFEC1_ACTRL_DLANE0_MASK VC4_MASK(7, 4) -+# define DSI1_PHY_AFEC1_ACTRL_DLANE0_SHIFT 4 -+# define DSI1_PHY_AFEC1_ACTRL_CLANE_MASK VC4_MASK(3, 0) -+# define DSI1_PHY_AFEC1_ACTRL_CLANE_SHIFT 0 -+ -+#define DSI1_TST_SEL 0x78 -+#define DSI1_TST_MON 0x7c -+#define DSI1_PHY_TST1 0x80 -+#define DSI1_PHY_TST2 0x84 -+#define DSI1_PHY_FIFO_STAT 0x88 -+/* Actually, all registers in the range that aren't otherwise claimed -+ * will return the ID. -+ */ -+#define DSI1_ID 0x8c -+ -+/* General DSI hardware state. */ -+struct vc4_dsi { -+ struct platform_device *pdev; -+ -+ struct mipi_dsi_host dsi_host; -+ struct drm_encoder *encoder; -+ struct drm_connector *connector; -+ struct drm_panel *panel; -+ -+ void __iomem *regs; -+ -+ struct dma_chan *reg_dma_chan; -+ dma_addr_t reg_dma_paddr; -+ u32 *reg_dma_mem; -+ dma_addr_t reg_paddr; -+ -+ /* Whether we're on bcm2835's DSI0 or DSI1. */ -+ int port; -+ -+ /* DSI channel for the panel we're connected to. */ -+ u32 channel; -+ u32 lanes; -+ enum mipi_dsi_pixel_format format; -+ u32 mode_flags; -+ -+ /* Input clock from CPRMAN to the digital PHY, for the DSI -+ * escape clock. -+ */ -+ struct clk *escape_clock; -+ -+ /* Input clock to the analog PHY, used to generate the DSI bit -+ * clock. -+ */ -+ struct clk *pll_phy_clock; -+ -+ /* HS Clocks generated within the DSI analog PHY. */ -+ struct clk_fixed_factor phy_clocks[3]; -+ -+ struct clk_onecell_data clk_onecell; -+ -+ /* Pixel clock output to the pixelvalve, generated from the HS -+ * clock. -+ */ -+ struct clk *pixel_clock; -+ -+ struct completion xfer_completion; -+ int xfer_result; -+}; -+ -+#define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host) -+ -+static inline void -+dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val) -+{ -+ struct dma_chan *chan = dsi->reg_dma_chan; -+ struct dma_async_tx_descriptor *tx; -+ dma_cookie_t cookie; -+ int ret; -+ -+ /* DSI0 should be able to write normally. */ -+ if (!chan) { -+ writel(val, dsi->regs + offset); -+ return; -+ } -+ -+ *dsi->reg_dma_mem = val; -+ -+ tx = chan->device->device_prep_dma_memcpy(chan, -+ dsi->reg_paddr + offset, -+ dsi->reg_dma_paddr, -+ 4, 0); -+ if (!tx) { -+ DRM_ERROR("Failed to set up DMA register write\n"); -+ return; -+ } -+ -+ cookie = tx->tx_submit(tx); -+ ret = dma_submit_error(cookie); -+ if (ret) { -+ DRM_ERROR("Failed to submit DMA: %d\n", ret); -+ return; -+ } -+ ret = dma_sync_wait(chan, cookie); -+ if (ret) -+ DRM_ERROR("Failed to wait for DMA: %d\n", ret); -+} -+ -+#define DSI_READ(offset) readl(dsi->regs + (offset)) -+#define DSI_WRITE(offset, val) dsi_dma_workaround_write(dsi, offset, val) -+#define DSI_PORT_READ(offset) \ -+ DSI_READ(dsi->port ? DSI1_##offset : DSI0_##offset) -+#define DSI_PORT_WRITE(offset, val) \ -+ DSI_WRITE(dsi->port ? DSI1_##offset : DSI0_##offset, val) -+#define DSI_PORT_BIT(bit) (dsi->port ? DSI1_##bit : DSI0_##bit) -+ -+/* VC4 DSI encoder KMS struct */ -+struct vc4_dsi_encoder { -+ struct vc4_encoder base; -+ struct vc4_dsi *dsi; -+}; -+ -+static inline struct vc4_dsi_encoder * -+to_vc4_dsi_encoder(struct drm_encoder *encoder) -+{ -+ return container_of(encoder, struct vc4_dsi_encoder, base.base); -+} -+ -+/* VC4 DSI connector KMS struct */ -+struct vc4_dsi_connector { -+ struct drm_connector base; -+ struct vc4_dsi *dsi; -+}; -+ -+static inline struct vc4_dsi_connector * -+to_vc4_dsi_connector(struct drm_connector *connector) -+{ -+ return container_of(connector, struct vc4_dsi_connector, base); -+} -+ -+#define DSI_REG(reg) { reg, #reg } -+static const struct { -+ u32 reg; -+ const char *name; -+} dsi0_regs[] = { -+ DSI_REG(DSI0_CTRL), -+ DSI_REG(DSI0_STAT), -+ DSI_REG(DSI0_HSTX_TO_CNT), -+ DSI_REG(DSI0_LPRX_TO_CNT), -+ DSI_REG(DSI0_TA_TO_CNT), -+ DSI_REG(DSI0_PR_TO_CNT), -+ DSI_REG(DSI0_DISP0_CTRL), -+ DSI_REG(DSI0_DISP1_CTRL), -+ DSI_REG(DSI0_INT_STAT), -+ DSI_REG(DSI0_INT_EN), -+ DSI_REG(DSI0_PHYC), -+ DSI_REG(DSI0_HS_CLT0), -+ DSI_REG(DSI0_HS_CLT1), -+ DSI_REG(DSI0_HS_CLT2), -+ DSI_REG(DSI0_HS_DLT3), -+ DSI_REG(DSI0_HS_DLT4), -+ DSI_REG(DSI0_HS_DLT5), -+ DSI_REG(DSI0_HS_DLT6), -+ DSI_REG(DSI0_HS_DLT7), -+ DSI_REG(DSI0_PHY_AFEC0), -+ DSI_REG(DSI0_PHY_AFEC1), -+ DSI_REG(DSI0_ID), -+}; -+ -+static const struct { -+ u32 reg; -+ const char *name; -+} dsi1_regs[] = { -+ DSI_REG(DSI1_CTRL), -+ DSI_REG(DSI1_STAT), -+ DSI_REG(DSI1_HSTX_TO_CNT), -+ DSI_REG(DSI1_LPRX_TO_CNT), -+ DSI_REG(DSI1_TA_TO_CNT), -+ DSI_REG(DSI1_PR_TO_CNT), -+ DSI_REG(DSI1_DISP0_CTRL), -+ DSI_REG(DSI1_DISP1_CTRL), -+ DSI_REG(DSI1_INT_STAT), -+ DSI_REG(DSI1_INT_EN), -+ DSI_REG(DSI1_PHYC), -+ DSI_REG(DSI1_HS_CLT0), -+ DSI_REG(DSI1_HS_CLT1), -+ DSI_REG(DSI1_HS_CLT2), -+ DSI_REG(DSI1_HS_DLT3), -+ DSI_REG(DSI1_HS_DLT4), -+ DSI_REG(DSI1_HS_DLT5), -+ DSI_REG(DSI1_HS_DLT6), -+ DSI_REG(DSI1_HS_DLT7), -+ DSI_REG(DSI1_PHY_AFEC0), -+ DSI_REG(DSI1_PHY_AFEC1), -+ DSI_REG(DSI1_ID), -+}; -+ -+static void vc4_dsi_dump_regs(struct vc4_dsi *dsi) -+{ -+ int i; -+ -+ if (dsi->port == 0) { -+ for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) { -+ DRM_INFO("0x%04x (%s): 0x%08x\n", -+ dsi0_regs[i].reg, dsi0_regs[i].name, -+ DSI_READ(dsi0_regs[i].reg)); -+ } -+ } else { -+ for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) { -+ DRM_INFO("0x%04x (%s): 0x%08x\n", -+ dsi1_regs[i].reg, dsi1_regs[i].name, -+ DSI_READ(dsi1_regs[i].reg)); -+ } -+ } -+} -+ -+#ifdef CONFIG_DEBUG_FS -+int vc4_dsi_debugfs_regs(struct seq_file *m, void *unused) -+{ -+ struct drm_info_node *node = (struct drm_info_node *)m->private; -+ struct drm_device *drm = node->minor->dev; -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ int dsi_index = (uintptr_t)node->info_ent->data; -+ struct vc4_dsi *dsi = (dsi_index == 1 ? vc4->dsi1 : NULL); -+ int i; -+ -+ if (!dsi) -+ return 0; -+ -+ if (dsi->port == 0) { -+ for (i = 0; i < ARRAY_SIZE(dsi0_regs); i++) { -+ seq_printf(m, "0x%04x (%s): 0x%08x\n", -+ dsi0_regs[i].reg, dsi0_regs[i].name, -+ DSI_READ(dsi0_regs[i].reg)); -+ } -+ } else { -+ for (i = 0; i < ARRAY_SIZE(dsi1_regs); i++) { -+ seq_printf(m, "0x%04x (%s): 0x%08x\n", -+ dsi1_regs[i].reg, dsi1_regs[i].name, -+ DSI_READ(dsi1_regs[i].reg)); -+ } -+ } -+ -+ return 0; -+} -+#endif -+ -+static enum drm_connector_status -+vc4_dsi_connector_detect(struct drm_connector *connector, bool force) -+{ -+ struct vc4_dsi_connector *vc4_connector = -+ to_vc4_dsi_connector(connector); -+ struct vc4_dsi *dsi = vc4_connector->dsi; -+ -+ if (dsi->panel) -+ return connector_status_connected; -+ else -+ return connector_status_disconnected; -+} -+ -+static void vc4_dsi_connector_destroy(struct drm_connector *connector) -+{ -+ drm_connector_unregister(connector); -+ drm_connector_cleanup(connector); -+} -+ -+static int vc4_dsi_connector_get_modes(struct drm_connector *connector) -+{ -+ struct vc4_dsi_connector *vc4_connector = -+ to_vc4_dsi_connector(connector); -+ struct vc4_dsi *dsi = vc4_connector->dsi; -+ -+ if (dsi->panel) -+ return drm_panel_get_modes(dsi->panel); -+ -+ return 0; -+} -+ -+static const struct drm_connector_funcs vc4_dsi_connector_funcs = { -+ .dpms = drm_atomic_helper_connector_dpms, -+ .detect = vc4_dsi_connector_detect, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .destroy = vc4_dsi_connector_destroy, -+ .reset = drm_atomic_helper_connector_reset, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static const struct drm_connector_helper_funcs vc4_dsi_connector_helper_funcs = { -+ .get_modes = vc4_dsi_connector_get_modes, -+}; -+ -+static struct drm_connector *vc4_dsi_connector_init(struct drm_device *dev, -+ struct vc4_dsi *dsi) -+{ -+ struct drm_connector *connector = NULL; -+ struct vc4_dsi_connector *dsi_connector; -+ int ret = 0; -+ -+ dsi_connector = devm_kzalloc(dev->dev, sizeof(*dsi_connector), -+ GFP_KERNEL); -+ if (!dsi_connector) { -+ ret = -ENOMEM; -+ goto fail; -+ } -+ connector = &dsi_connector->base; -+ -+ dsi_connector->dsi = dsi; -+ -+ drm_connector_init(dev, connector, &vc4_dsi_connector_funcs, -+ DRM_MODE_CONNECTOR_DSI); -+ drm_connector_helper_add(connector, &vc4_dsi_connector_helper_funcs); -+ -+ connector->polled = 0; -+ connector->interlace_allowed = 0; -+ connector->doublescan_allowed = 0; -+ -+ drm_mode_connector_attach_encoder(connector, dsi->encoder); -+ -+ return connector; -+ -+fail: -+ if (connector) -+ vc4_dsi_connector_destroy(connector); -+ -+ return ERR_PTR(ret); -+} -+ -+static void vc4_dsi_encoder_destroy(struct drm_encoder *encoder) -+{ -+ drm_encoder_cleanup(encoder); -+} -+ -+static const struct drm_encoder_funcs vc4_dsi_encoder_funcs = { -+ .destroy = vc4_dsi_encoder_destroy, -+}; -+ -+static void vc4_dsi_latch_ulps(struct vc4_dsi *dsi, bool latch) -+{ -+ u32 afec0 = DSI_PORT_READ(PHY_AFEC0); -+ -+ if (latch) -+ afec0 |= DSI_PORT_BIT(PHY_AFEC0_LATCH_ULPS); -+ else -+ afec0 &= ~DSI_PORT_BIT(PHY_AFEC0_LATCH_ULPS); -+ -+ DSI_PORT_WRITE(PHY_AFEC0, afec0); -+} -+ -+/* Enters or exits Ultra Low Power State. */ -+static void vc4_dsi_ulps(struct vc4_dsi *dsi, bool ulps) -+{ -+ bool continuous = dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS; -+ u32 phyc_ulps = ((continuous ? DSI_PORT_BIT(PHYC_CLANE_ULPS) : 0) | -+ DSI_PHYC_DLANE0_ULPS | -+ (dsi->lanes > 1 ? DSI_PHYC_DLANE1_ULPS : 0) | -+ (dsi->lanes > 2 ? DSI_PHYC_DLANE2_ULPS : 0) | -+ (dsi->lanes > 3 ? DSI_PHYC_DLANE3_ULPS : 0)); -+ u32 stat_ulps = ((continuous ? DSI1_STAT_PHY_CLOCK_ULPS : 0) | -+ DSI1_STAT_PHY_D0_ULPS | -+ (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_ULPS : 0) | -+ (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_ULPS : 0) | -+ (dsi->lanes > 3 ? DSI1_STAT_PHY_D3_ULPS : 0)); -+ u32 stat_stop = ((continuous ? DSI1_STAT_PHY_CLOCK_STOP : 0) | -+ DSI1_STAT_PHY_D0_STOP | -+ (dsi->lanes > 1 ? DSI1_STAT_PHY_D1_STOP : 0) | -+ (dsi->lanes > 2 ? DSI1_STAT_PHY_D2_STOP : 0) | -+ (dsi->lanes > 3 ? DSI1_STAT_PHY_D3_STOP : 0)); -+ int ret; -+ -+ DSI_PORT_WRITE(STAT, stat_ulps); -+ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) | phyc_ulps); -+ ret = wait_for((DSI_PORT_READ(STAT) & stat_ulps) == stat_ulps, 200); -+ if (ret) { -+ dev_warn(&dsi->pdev->dev, -+ "Timeout waiting for DSI ULPS entry: STAT 0x%08x", -+ DSI_PORT_READ(STAT)); -+ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); -+ vc4_dsi_latch_ulps(dsi, false); -+ return; -+ } -+ -+ /* The DSI module can't be disabled while the module is -+ * generating ULPS state. So, to be able to disable the -+ * module, we have the AFE latch the ULPS state and continue -+ * on to having the module enter STOP. -+ */ -+ vc4_dsi_latch_ulps(dsi, ulps); -+ -+ DSI_PORT_WRITE(STAT, stat_stop); -+ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); -+ ret = wait_for((DSI_PORT_READ(STAT) & stat_stop) == stat_stop, 200); -+ if (ret) { -+ dev_warn(&dsi->pdev->dev, -+ "Timeout waiting for DSI STOP entry: STAT 0x%08x", -+ DSI_PORT_READ(STAT)); -+ DSI_PORT_WRITE(PHYC, DSI_PORT_READ(PHYC) & ~phyc_ulps); -+ return; -+ } -+} -+ -+static u32 -+dsi_hs_timing(u32 ui_ns, u32 ns, u32 ui) -+{ -+ /* The HS timings have to be rounded up to a multiple of 8 -+ * because we're using the byte clock. -+ */ -+ return roundup(ui + DIV_ROUND_UP(ns, ui_ns), 8); -+} -+ -+/* ESC always runs at 100Mhz. */ -+#define ESC_TIME_NS 10 -+ -+static u32 -+dsi_esc_timing(u32 ns) -+{ -+ return DIV_ROUND_UP(ns, ESC_TIME_NS); -+} -+ -+static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) -+{ -+ struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); -+ struct vc4_dsi *dsi = vc4_encoder->dsi; -+ struct device *dev = &dsi->pdev->dev; -+ -+ drm_panel_disable(dsi->panel); -+ -+ vc4_dsi_ulps(dsi, true); -+ -+ drm_panel_unprepare(dsi->panel); -+ -+ clk_disable_unprepare(dsi->pll_phy_clock); -+ clk_disable_unprepare(dsi->escape_clock); -+ clk_disable_unprepare(dsi->pixel_clock); -+ -+ pm_runtime_put(dev); -+} -+ -+static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) -+{ -+ struct drm_display_mode *mode = &encoder->crtc->mode; -+ struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder); -+ struct vc4_dsi *dsi = vc4_encoder->dsi; -+ struct device *dev = &dsi->pdev->dev; -+ u32 format = 0, divider = 0; -+ bool debug_dump_regs = false; -+ unsigned long hs_clock; -+ u32 ui_ns; -+ /* Minimum LP state duration in escape clock cycles. */ -+ u32 lpx = dsi_esc_timing(60); -+ unsigned long pixel_clock_hz = mode->clock * 1000; -+ unsigned long dsip_clock; -+ unsigned long phy_clock; -+ int ret; -+ -+ ret = pm_runtime_get_sync(dev); -+ if (ret) { -+ DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->port); -+ return; -+ } -+ -+ ret = drm_panel_prepare(dsi->panel); -+ if (ret) { -+ DRM_ERROR("Panel failed to prepare\n"); -+ return; -+ } -+ -+ if (debug_dump_regs) { -+ DRM_INFO("DSI regs before:\n"); -+ vc4_dsi_dump_regs(dsi); -+ } -+ -+ switch (dsi->format) { -+ case MIPI_DSI_FMT_RGB888: -+ format = DSI_PFORMAT_RGB888; -+ divider = 24 / dsi->lanes; -+ break; -+ case MIPI_DSI_FMT_RGB666: -+ format = DSI_PFORMAT_RGB666; -+ divider = 24 / dsi->lanes; -+ break; -+ case MIPI_DSI_FMT_RGB666_PACKED: -+ format = DSI_PFORMAT_RGB666_PACKED; -+ divider = 18 / dsi->lanes; -+ break; -+ case MIPI_DSI_FMT_RGB565: -+ format = DSI_PFORMAT_RGB565; -+ divider = 16 / dsi->lanes; -+ break; -+ } -+ -+ phy_clock = pixel_clock_hz * divider; -+ ret = clk_set_rate(dsi->pll_phy_clock, phy_clock); -+ if (ret) { -+ dev_err(&dsi->pdev->dev, -+ "Failed to set phy clock to %ld: %d\n", phy_clock, ret); -+ } -+ -+ /* Reset the DSI and all its fifos. */ -+ DSI_PORT_WRITE(CTRL, -+ DSI_CTRL_SOFT_RESET_CFG | -+ DSI_PORT_BIT(CTRL_RESET_FIFOS)); -+ -+ DSI_PORT_WRITE(CTRL, -+ DSI_CTRL_HSDT_EOT_DISABLE | -+ DSI_CTRL_RX_LPDT_EOT_DISABLE); -+ -+ /* Clear all stat bits so we see what has happened during enable. */ -+ DSI_PORT_WRITE(STAT, DSI_PORT_READ(STAT)); -+ -+ /* Set AFE CTR00/CTR1 to release powerdown of analog. */ -+ if (dsi->port == 0) { -+ u32 afec0 = (VC4_SET_FIELD(7, DSI_PHY_AFEC0_PTATADJ) | -+ VC4_SET_FIELD(7, DSI_PHY_AFEC0_CTATADJ)); -+ -+ if (dsi->lanes < 2) -+ afec0 |= DSI0_PHY_AFEC0_PD_DLANE1; -+ -+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) -+ afec0 |= DSI0_PHY_AFEC0_RESET; -+ -+ DSI_PORT_WRITE(PHY_AFEC0, afec0); -+ -+ DSI_PORT_WRITE(PHY_AFEC1, -+ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) | -+ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) | -+ VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_CLANE)); -+ } else { -+ u32 afec0 = (VC4_SET_FIELD(7, DSI_PHY_AFEC0_PTATADJ) | -+ VC4_SET_FIELD(7, DSI_PHY_AFEC0_CTATADJ) | -+ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_CLANE) | -+ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE0) | -+ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE1) | -+ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE2) | -+ VC4_SET_FIELD(6, DSI1_PHY_AFEC0_IDR_DLANE3)); -+ -+ if (dsi->lanes < 4) -+ afec0 |= DSI1_PHY_AFEC0_PD_DLANE3; -+ if (dsi->lanes < 3) -+ afec0 |= DSI1_PHY_AFEC0_PD_DLANE2; -+ if (dsi->lanes < 2) -+ afec0 |= DSI1_PHY_AFEC0_PD_DLANE1; -+ -+ afec0 |= DSI1_PHY_AFEC0_RESET; -+ -+ DSI_PORT_WRITE(PHY_AFEC0, afec0); -+ -+ DSI_PORT_WRITE(PHY_AFEC1, 0); -+ -+ /* AFEC reset hold time */ -+ mdelay(1); -+ } -+ -+ ret = clk_prepare_enable(dsi->escape_clock); -+ if (ret) { -+ DRM_ERROR("Failed to turn on DSI escape clock: %d\n", ret); -+ return; -+ } -+ -+ ret = clk_prepare_enable(dsi->pll_phy_clock); -+ if (ret) { -+ DRM_ERROR("Failed to turn on DSI PLL: %d\n", ret); -+ return; -+ } -+ -+ hs_clock = clk_get_rate(dsi->pll_phy_clock); -+ -+ /* Yes, we set the DSI0P/DSI1P pixel clock to the byte rate, -+ * not the pixel clock rate. DSIxP take from the APHY's byte, -+ * DDR2, or DDR4 clock (we use byte) and feed into the PV at -+ * that rate. Separately, a value derived from PIX_CLK_DIV -+ * and HS_CLKC is fed into the PV to divide down to the actual -+ * pixel clock for pushing pixels into DSI. -+ */ -+ dsip_clock = phy_clock / 8; -+ ret = clk_set_rate(dsi->pixel_clock, dsip_clock); -+ if (ret) { -+ dev_err(dev, "Failed to set pixel clock to %ldHz: %d\n", -+ dsip_clock, ret); -+ } -+ -+ ret = clk_prepare_enable(dsi->pixel_clock); -+ if (ret) { -+ DRM_ERROR("Failed to turn on DSI pixel clock: %d\n", ret); -+ return; -+ } -+ -+ /* How many ns one DSI unit interval is. Note that the clock -+ * is DDR, so there's an extra divide by 2. -+ */ -+ ui_ns = DIV_ROUND_UP(500000000, hs_clock); -+ -+ DSI_PORT_WRITE(HS_CLT0, -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 262, 0), -+ DSI_HS_CLT0_CZERO) | -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 0, 8), -+ DSI_HS_CLT0_CPRE) | -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 38, 0), -+ DSI_HS_CLT0_CPREP)); -+ -+ DSI_PORT_WRITE(HS_CLT1, -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 60, 0), -+ DSI_HS_CLT1_CTRAIL) | -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 60, 52), -+ DSI_HS_CLT1_CPOST)); -+ -+ DSI_PORT_WRITE(HS_CLT2, -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 1000000, 0), -+ DSI_HS_CLT2_WUP)); -+ -+ DSI_PORT_WRITE(HS_DLT3, -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 100, 0), -+ DSI_HS_DLT3_EXIT) | -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 105, 6), -+ DSI_HS_DLT3_ZERO) | -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, 40, 4), -+ DSI_HS_DLT3_PRE)); -+ -+ DSI_PORT_WRITE(HS_DLT4, -+ VC4_SET_FIELD(dsi_hs_timing(ui_ns, lpx * ESC_TIME_NS, 0), -+ DSI_HS_DLT4_LPX) | -+ VC4_SET_FIELD(max(dsi_hs_timing(ui_ns, 0, 8), -+ dsi_hs_timing(ui_ns, 60, 4)), -+ DSI_HS_DLT4_TRAIL) | -+ VC4_SET_FIELD(0, DSI_HS_DLT4_ANLAT)); -+ -+ DSI_PORT_WRITE(HS_DLT5, VC4_SET_FIELD(dsi_hs_timing(ui_ns, 1000, 5000), -+ DSI_HS_DLT5_INIT)); -+ -+ DSI_PORT_WRITE(HS_DLT6, -+ VC4_SET_FIELD(lpx * 5, DSI_HS_DLT6_TA_GET) | -+ VC4_SET_FIELD(lpx, DSI_HS_DLT6_TA_SURE) | -+ VC4_SET_FIELD(lpx * 4, DSI_HS_DLT6_TA_GO) | -+ VC4_SET_FIELD(lpx, DSI_HS_DLT6_LP_LPX)); -+ -+ DSI_PORT_WRITE(HS_DLT7, -+ VC4_SET_FIELD(dsi_esc_timing(1000000), -+ DSI_HS_DLT7_LP_WUP)); -+ -+ DSI_PORT_WRITE(PHYC, -+ DSI_PHYC_DLANE0_ENABLE | -+ (dsi->lanes >= 2 ? DSI_PHYC_DLANE1_ENABLE : 0) | -+ (dsi->lanes >= 3 ? DSI_PHYC_DLANE2_ENABLE : 0) | -+ (dsi->lanes >= 4 ? DSI_PHYC_DLANE3_ENABLE : 0) | -+ DSI_PORT_BIT(PHYC_CLANE_ENABLE) | -+ ((dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ? -+ 0 : DSI_PORT_BIT(PHYC_HS_CLK_CONTINUOUS)) | -+ (dsi->port == 0 ? -+ VC4_SET_FIELD(lpx - 1, DSI0_PHYC_ESC_CLK_LPDT) : -+ VC4_SET_FIELD(lpx - 1, DSI1_PHYC_ESC_CLK_LPDT))); -+ -+ DSI_PORT_WRITE(CTRL, -+ DSI_PORT_READ(CTRL) | -+ DSI_CTRL_CAL_BYTE); -+ -+ /* HS timeout in HS clock cycles: disabled. */ -+ DSI_PORT_WRITE(HSTX_TO_CNT, 0); -+ /* LP receive timeout in HS clocks. */ -+ DSI_PORT_WRITE(LPRX_TO_CNT, 0xffffff); -+ /* Bus turnaround timeout */ -+ DSI_PORT_WRITE(TA_TO_CNT, 100000); -+ /* Display reset sequence timeout */ -+ DSI_PORT_WRITE(PR_TO_CNT, 100000); -+ -+ if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { -+ DSI_PORT_WRITE(DISP0_CTRL, -+ VC4_SET_FIELD(divider, DSI_DISP0_PIX_CLK_DIV) | -+ VC4_SET_FIELD(format, DSI_DISP0_PFORMAT) | -+ VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME, -+ DSI_DISP0_LP_STOP_CTRL) | -+ DSI_DISP0_ST_END | -+ DSI_DISP0_ENABLE); -+ } else { -+ DSI_PORT_WRITE(DISP0_CTRL, -+ DSI_DISP0_COMMAND_MODE | -+ DSI_DISP0_ENABLE); -+ } -+ -+ /* Set up DISP1 for transferring long command payloads through -+ * the pixfifo. -+ */ -+ DSI_PORT_WRITE(DISP1_CTRL, -+ VC4_SET_FIELD(DSI_DISP1_PFORMAT_32BIT_LE, -+ DSI_DISP1_PFORMAT) | -+ DSI_DISP1_ENABLE); -+ -+ /* Ungate the block. */ -+ if (dsi->port == 0) -+ DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI0_CTRL_CTRL0); -+ else -+ DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN); -+ -+ /* Bring AFE out of reset. */ -+ if (dsi->port == 0) { -+ } else { -+ DSI_PORT_WRITE(PHY_AFEC0, -+ DSI_PORT_READ(PHY_AFEC0) & -+ ~DSI1_PHY_AFEC0_RESET); -+ } -+ -+ vc4_dsi_ulps(dsi, false); -+ -+ if (debug_dump_regs) { -+ DRM_INFO("DSI regs after:\n"); -+ vc4_dsi_dump_regs(dsi); -+ } -+ -+ ret = drm_panel_enable(dsi->panel); -+ if (ret) { -+ DRM_ERROR("Panel failed to enable\n"); -+ drm_panel_unprepare(dsi->panel); -+ return; -+ } -+} -+ -+static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host, -+ const struct mipi_dsi_msg *msg) -+{ -+ struct vc4_dsi *dsi = host_to_dsi(host); -+ struct mipi_dsi_packet packet; -+ u32 pkth = 0, pktc = 0; -+ int i, ret; -+ bool is_long = mipi_dsi_packet_format_is_long(msg->type); -+ u32 cmd_fifo_len = 0, pix_fifo_len = 0; -+ -+ mipi_dsi_create_packet(&packet, msg); -+ -+ pkth |= VC4_SET_FIELD(packet.header[0], DSI_TXPKT1H_BC_DT); -+ pkth |= VC4_SET_FIELD(packet.header[1] | -+ (packet.header[2] << 8), -+ DSI_TXPKT1H_BC_PARAM); -+ if (is_long) { -+ /* Divide data across the various FIFOs we have available. -+ * The command FIFO takes byte-oriented data, but is of -+ * limited size. The pixel FIFO (never actually used for -+ * pixel data in reality) is word oriented, and substantially -+ * larger. So, we use the pixel FIFO for most of the data, -+ * sending the residual bytes in the command FIFO at the start. -+ * -+ * With this arrangement, the command FIFO will never get full. -+ */ -+ if (packet.payload_length <= 16) { -+ cmd_fifo_len = packet.payload_length; -+ pix_fifo_len = 0; -+ } else { -+ cmd_fifo_len = (packet.payload_length % -+ DSI_PIX_FIFO_WIDTH); -+ pix_fifo_len = ((packet.payload_length - cmd_fifo_len) / -+ DSI_PIX_FIFO_WIDTH); -+ } -+ -+ WARN_ON_ONCE(pix_fifo_len >= DSI_PIX_FIFO_DEPTH); -+ -+ pkth |= VC4_SET_FIELD(cmd_fifo_len, DSI_TXPKT1H_BC_CMDFIFO); -+ } -+ -+ if (msg->rx_len) { -+ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_CMD_CTRL_RX, -+ DSI_TXPKT1C_CMD_CTRL); -+ } else { -+ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_CMD_CTRL_TX, -+ DSI_TXPKT1C_CMD_CTRL); -+ } -+ -+ for (i = 0; i < cmd_fifo_len; i++) -+ DSI_PORT_WRITE(TXPKT_CMD_FIFO, packet.payload[i]); -+ for (i = 0; i < pix_fifo_len; i++) { -+ const u8 *pix = packet.payload + cmd_fifo_len + i * 4; -+ -+ DSI_PORT_WRITE(TXPKT_PIX_FIFO, -+ pix[0] | -+ pix[1] << 8 | -+ pix[2] << 16 | -+ pix[3] << 24); -+ } -+ -+ if (msg->flags & MIPI_DSI_MSG_USE_LPM) -+ pktc |= DSI_TXPKT1C_CMD_MODE_LP; -+ if (is_long) -+ pktc |= DSI_TXPKT1C_CMD_TYPE_LONG; -+ -+ /* Send one copy of the packet. Larger repeats are used for pixel -+ * data in command mode. -+ */ -+ pktc |= VC4_SET_FIELD(1, DSI_TXPKT1C_CMD_REPEAT); -+ -+ pktc |= DSI_TXPKT1C_CMD_EN; -+ if (pix_fifo_len) { -+ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_DISPLAY_NO_SECONDARY, -+ DSI_TXPKT1C_DISPLAY_NO); -+ } else { -+ pktc |= VC4_SET_FIELD(DSI_TXPKT1C_DISPLAY_NO_SHORT, -+ DSI_TXPKT1C_DISPLAY_NO); -+ } -+ -+ /* Enable the appropriate interrupt for the transfer completion. */ -+ dsi->xfer_result = 0; -+ reinit_completion(&dsi->xfer_completion); -+ DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF); -+ if (msg->rx_len) { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_PHY_DIR_RTF)); -+ } else { -+ DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED | -+ DSI1_INT_TXPKT1_DONE)); -+ } -+ -+ /* Send the packet. */ -+ DSI_PORT_WRITE(TXPKT1H, pkth); -+ DSI_PORT_WRITE(TXPKT1C, pktc); -+ -+ if (!wait_for_completion_timeout(&dsi->xfer_completion, -+ msecs_to_jiffies(1000))) { -+ dev_err(&dsi->pdev->dev, "transfer interrupt wait timeout"); -+ dev_err(&dsi->pdev->dev, "instat: 0x%08x\n", -+ DSI_PORT_READ(INT_STAT)); -+ ret = -ETIMEDOUT; -+ } else { -+ ret = dsi->xfer_result; -+ } -+ -+ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ -+ if (ret) -+ goto reset_fifo_and_return; -+ -+ if (ret == 0 && msg->rx_len) { -+ u32 rxpkt1h = DSI_PORT_READ(RXPKT1H); -+ u8 *msg_rx = msg->rx_buf; -+ -+ if (rxpkt1h & DSI_RXPKT1H_PKT_TYPE_LONG) { -+ u32 rxlen = VC4_GET_FIELD(rxpkt1h, -+ DSI_RXPKT1H_BC_PARAM); -+ -+ if (rxlen != msg->rx_len) { -+ DRM_ERROR("DSI returned %db, expecting %db\n", -+ rxlen, (int)msg->rx_len); -+ ret = -ENXIO; -+ goto reset_fifo_and_return; -+ } -+ -+ for (i = 0; i < msg->rx_len; i++) -+ msg_rx[i] = DSI_READ(DSI1_RXPKT_FIFO); -+ } else { -+ /* FINISHME: Handle AWER */ -+ -+ msg_rx[0] = VC4_GET_FIELD(rxpkt1h, -+ DSI_RXPKT1H_SHORT_0); -+ if (msg->rx_len > 1) { -+ msg_rx[1] = VC4_GET_FIELD(rxpkt1h, -+ DSI_RXPKT1H_SHORT_1); -+ } -+ } -+ } -+ -+ return ret; -+ -+reset_fifo_and_return: -+ DRM_ERROR("DSI transfer failed, resetting: %d\n", ret); -+ -+ DSI_PORT_WRITE(TXPKT1C, DSI_PORT_READ(TXPKT1C) & ~DSI_TXPKT1C_CMD_EN); -+ udelay(1); -+ DSI_PORT_WRITE(CTRL, -+ DSI_PORT_READ(CTRL) | -+ DSI_PORT_BIT(CTRL_RESET_FIFOS)); -+ -+ DSI_PORT_WRITE(TXPKT1C, 0); -+ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ return ret; -+} -+ -+static int vc4_dsi_host_attach(struct mipi_dsi_host *host, -+ struct mipi_dsi_device *device) -+{ -+ struct vc4_dsi *dsi = host_to_dsi(host); -+ int ret = 0; -+ -+ dsi->lanes = device->lanes; -+ dsi->channel = device->channel; -+ dsi->format = device->format; -+ dsi->mode_flags = device->mode_flags; -+ -+ if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) { -+ dev_err(&dsi->pdev->dev, -+ "Only VIDEO mode panels supported currently.\n"); -+ return 0; -+ } -+ -+ dsi->panel = of_drm_find_panel(device->dev.of_node); -+ if (!dsi->panel) -+ return 0; -+ -+ ret = drm_panel_attach(dsi->panel, dsi->connector); -+ if (ret != 0) -+ return ret; -+ -+ drm_helper_hpd_irq_event(dsi->connector->dev); -+ -+ return 0; -+} -+ -+static int vc4_dsi_host_detach(struct mipi_dsi_host *host, -+ struct mipi_dsi_device *device) -+{ -+ struct vc4_dsi *dsi = host_to_dsi(host); -+ -+ if (dsi->panel) { -+ int ret = drm_panel_detach(dsi->panel); -+ -+ if (ret) -+ return ret; -+ -+ dsi->panel = NULL; -+ -+ drm_helper_hpd_irq_event(dsi->connector->dev); -+ } -+ -+ return 0; -+} -+ -+static const struct mipi_dsi_host_ops vc4_dsi_host_ops = { -+ .attach = vc4_dsi_host_attach, -+ .detach = vc4_dsi_host_detach, -+ .transfer = vc4_dsi_host_transfer, -+}; -+ -+static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = { -+ .disable = vc4_dsi_encoder_disable, -+ .enable = vc4_dsi_encoder_enable, -+}; -+ -+static const struct of_device_id vc4_dsi_dt_match[] = { -+ { .compatible = "brcm,bcm2835-dsi1", (void *)(uintptr_t)1 }, -+ {} -+}; -+ -+static void dsi_handle_error(struct vc4_dsi *dsi, -+ irqreturn_t *ret, u32 stat, u32 bit, -+ const char *type) -+{ -+ if (!(stat & bit)) -+ return; -+ -+ DRM_ERROR("DSI%d: %s error\n", dsi->port, type); -+ *ret = IRQ_HANDLED; -+} -+ -+static irqreturn_t vc4_dsi_irq_handler(int irq, void *data) -+{ -+ struct vc4_dsi *dsi = data; -+ u32 stat = DSI_PORT_READ(INT_STAT); -+ irqreturn_t ret = IRQ_NONE; -+ -+ DSI_PORT_WRITE(INT_STAT, stat); -+ -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_ERR_SYNC_ESC, "LPDT sync"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_ERR_CONTROL, "data lane 0 sequence"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_ERR_CONT_LP0, "LP0 contention"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_ERR_CONT_LP1, "LP1 contention"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_HSTX_TO, "HSTX timeout"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_LPRX_TO, "LPRX timeout"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_TA_TO, "turnaround timeout"); -+ dsi_handle_error(dsi, &ret, stat, -+ DSI1_INT_PR_TO, "peripheral reset timeout"); -+ -+ if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) { -+ complete(&dsi->xfer_completion); -+ ret = IRQ_HANDLED; -+ } else if (stat & DSI1_INT_HSTX_TO) { -+ complete(&dsi->xfer_completion); -+ dsi->xfer_result = -ETIMEDOUT; -+ ret = IRQ_HANDLED; -+ } -+ -+ return ret; -+} -+ -+/** -+ * Exposes clocks generated by the analog PHY that are consumed by -+ * CPRMAN (clk-bcm2835.c). -+ */ -+static int -+vc4_dsi_init_phy_clocks(struct vc4_dsi *dsi) -+{ -+ struct device *dev = &dsi->pdev->dev; -+ const char *parent_name = __clk_get_name(dsi->pll_phy_clock); -+ static const struct { -+ const char *dsi0_name, *dsi1_name; -+ int div; -+ } phy_clocks[] = { -+ { "dsi0_byte", "dsi1_byte", 8 }, -+ { "dsi0_ddr2", "dsi1_ddr2", 4 }, -+ { "dsi0_ddr", "dsi1_ddr", 2 }, -+ }; -+ int i; -+ -+ dsi->clk_onecell.clk_num = ARRAY_SIZE(phy_clocks); -+ dsi->clk_onecell.clks = devm_kcalloc(dev, -+ dsi->clk_onecell.clk_num, -+ sizeof(*dsi->clk_onecell.clks), -+ GFP_KERNEL); -+ if (!dsi->clk_onecell.clks) -+ return -ENOMEM; -+ -+ for (i = 0; i < ARRAY_SIZE(phy_clocks); i++) { -+ struct clk_fixed_factor *fix = &dsi->phy_clocks[i]; -+ struct clk_init_data init; -+ struct clk *clk; -+ -+ /* We just use core fixed factor clock ops for the PHY -+ * clocks. The clocks are actually gated by the -+ * PHY_AFEC0_DDRCLK_EN bits, which we should be -+ * setting if we use the DDR/DDR2 clocks. However, -+ * vc4_dsi_encoder_enable() is setting up both AFEC0, -+ * setting both our parent DSI PLL's rate and this -+ * clock's rate, so it knows if DDR/DDR2 are going to -+ * be used and could enable the gates itself. -+ */ -+ fix->mult = 1; -+ fix->div = phy_clocks[i].div; -+ fix->hw.init = &init; -+ -+ memset(&init, 0, sizeof(init)); -+ init.parent_names = &parent_name; -+ init.num_parents = 1; -+ if (dsi->port == 1) -+ init.name = phy_clocks[i].dsi1_name; -+ else -+ init.name = phy_clocks[i].dsi0_name; -+ init.ops = &clk_fixed_factor_ops; -+ init.flags = CLK_IS_BASIC; -+ -+ clk = devm_clk_register(dev, &fix->hw); -+ if (IS_ERR(clk)) -+ return PTR_ERR(clk); -+ -+ dsi->clk_onecell.clks[i] = clk; -+ } -+ -+ return of_clk_add_provider(dev->of_node, -+ of_clk_src_onecell_get, -+ &dsi->clk_onecell); -+} -+ -+static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct drm_device *drm = dev_get_drvdata(master); -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct vc4_dsi *dsi; -+ struct vc4_dsi_encoder *vc4_dsi_encoder; -+ const struct of_device_id *match; -+ dma_cap_mask_t dma_mask; -+ int ret; -+ -+ dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL); -+ if (!dsi) -+ return -ENOMEM; -+ -+ match = of_match_device(vc4_dsi_dt_match, dev); -+ if (!match) -+ return -ENODEV; -+ -+ dsi->port = (uintptr_t)match->data; -+ -+ vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder), -+ GFP_KERNEL); -+ if (!vc4_dsi_encoder) -+ return -ENOMEM; -+ vc4_dsi_encoder->base.type = VC4_ENCODER_TYPE_DSI1; -+ vc4_dsi_encoder->dsi = dsi; -+ dsi->encoder = &vc4_dsi_encoder->base.base; -+ -+ dsi->pdev = pdev; -+ dsi->regs = vc4_ioremap_regs(pdev, 0); -+ if (IS_ERR(dsi->regs)) -+ return PTR_ERR(dsi->regs); -+ -+ if (DSI_PORT_READ(ID) != DSI_ID_VALUE) { -+ dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n", -+ DSI_PORT_READ(ID), DSI_ID_VALUE); -+ return -ENODEV; -+ } -+ -+ /* DSI1 has a broken AXI slave that doesn't respond to writes -+ * from the ARM. It does handle writes from the DMA engine, -+ * so set up a channel for talking to it. -+ */ -+ if (dsi->port == 1) { -+ dsi->reg_dma_mem = dma_alloc_coherent(dev, 4, -+ &dsi->reg_dma_paddr, -+ GFP_KERNEL); -+ if (!dsi->reg_dma_mem) { -+ DRM_ERROR("Failed to get DMA memory\n"); -+ return -ENOMEM; -+ } -+ -+ dma_cap_zero(dma_mask); -+ dma_cap_set(DMA_MEMCPY, dma_mask); -+ dsi->reg_dma_chan = dma_request_chan_by_mask(&dma_mask); -+ if (IS_ERR(dsi->reg_dma_chan)) { -+ ret = PTR_ERR(dsi->reg_dma_chan); -+ if (ret != -EPROBE_DEFER) -+ DRM_ERROR("Failed to get DMA channel: %d\n", -+ ret); -+ return ret; -+ } -+ -+ /* Get the physical address of the device's registers. The -+ * struct resource for the regs gives us the bus address -+ * instead. -+ */ -+ dsi->reg_paddr = be32_to_cpup(of_get_address(dev->of_node, -+ 0, NULL, NULL)); -+ } -+ -+ init_completion(&dsi->xfer_completion); -+ /* At startup enable error-reporting interrupts and nothing else. */ -+ DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED); -+ /* Clear any existing interrupt state. */ -+ DSI_PORT_WRITE(INT_STAT, DSI_PORT_READ(INT_STAT)); -+ -+ ret = devm_request_irq(dev, platform_get_irq(pdev, 0), -+ vc4_dsi_irq_handler, 0, "vc4 dsi", dsi); -+ if (ret) { -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get interrupt: %d\n", ret); -+ return ret; -+ } -+ -+ dsi->escape_clock = devm_clk_get(dev, "escape"); -+ if (IS_ERR(dsi->escape_clock)) { -+ ret = PTR_ERR(dsi->escape_clock); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get escape clock: %d\n", ret); -+ return ret; -+ } -+ -+ dsi->pll_phy_clock = devm_clk_get(dev, "phy"); -+ if (IS_ERR(dsi->pll_phy_clock)) { -+ ret = PTR_ERR(dsi->pll_phy_clock); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get phy clock: %d\n", ret); -+ return ret; -+ } -+ -+ dsi->pixel_clock = devm_clk_get(dev, "pixel"); -+ if (IS_ERR(dsi->pixel_clock)) { -+ ret = PTR_ERR(dsi->pixel_clock); -+ if (ret != -EPROBE_DEFER) -+ dev_err(dev, "Failed to get pixel clock: %d\n", ret); -+ return ret; -+ } -+ -+ /* The esc clock rate is supposed to always be 100Mhz. */ -+ ret = clk_set_rate(dsi->escape_clock, 100 * 1000000); -+ if (ret) { -+ dev_err(dev, "Failed to set esc clock: %d\n", ret); -+ return ret; -+ } -+ -+ ret = vc4_dsi_init_phy_clocks(dsi); -+ if (ret) -+ return ret; -+ -+ if (dsi->port == 1) -+ vc4->dsi1 = dsi; -+ -+ drm_encoder_init(drm, dsi->encoder, &vc4_dsi_encoder_funcs, -+ DRM_MODE_ENCODER_DSI, NULL); -+ drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs); -+ -+ dsi->connector = vc4_dsi_connector_init(drm, dsi); -+ if (IS_ERR(dsi->connector)) { -+ ret = PTR_ERR(dsi->connector); -+ goto err_destroy_encoder; -+ } -+ -+ dsi->dsi_host.ops = &vc4_dsi_host_ops; -+ dsi->dsi_host.dev = dev; -+ -+ mipi_dsi_host_register(&dsi->dsi_host); -+ -+ dev_set_drvdata(dev, dsi); -+ -+ pm_runtime_enable(dev); -+ -+ return 0; -+ -+err_destroy_encoder: -+ vc4_dsi_encoder_destroy(dsi->encoder); -+ -+ return ret; -+} -+ -+static void vc4_dsi_unbind(struct device *dev, struct device *master, -+ void *data) -+{ -+ struct drm_device *drm = dev_get_drvdata(master); -+ struct vc4_dev *vc4 = to_vc4_dev(drm); -+ struct vc4_dsi *dsi = dev_get_drvdata(dev); -+ -+ pm_runtime_disable(dev); -+ -+ vc4_dsi_connector_destroy(dsi->connector); -+ vc4_dsi_encoder_destroy(dsi->encoder); -+ -+ mipi_dsi_host_unregister(&dsi->dsi_host); -+ -+ clk_disable_unprepare(dsi->pll_phy_clock); -+ clk_disable_unprepare(dsi->escape_clock); -+ -+ if (dsi->port == 1) -+ vc4->dsi1 = NULL; -+} -+ -+static const struct component_ops vc4_dsi_ops = { -+ .bind = vc4_dsi_bind, -+ .unbind = vc4_dsi_unbind, -+}; -+ -+static int vc4_dsi_dev_probe(struct platform_device *pdev) -+{ -+ return component_add(&pdev->dev, &vc4_dsi_ops); -+} -+ -+static int vc4_dsi_dev_remove(struct platform_device *pdev) -+{ -+ component_del(&pdev->dev, &vc4_dsi_ops); -+ return 0; -+} -+ -+struct platform_driver vc4_dsi_driver = { -+ .probe = vc4_dsi_dev_probe, -+ .remove = vc4_dsi_dev_remove, -+ .driver = { -+ .name = "vc4_dsi", -+ .of_match_table = vc4_dsi_dt_match, -+ }, -+}; - -From 9e208dd27217d9f062788dd7ce5cc51e063e95de Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Fri, 2 Dec 2016 14:48:12 +0100 -Subject: [PATCH 175/216] ARM: dts: bcm283x: Add VEC node in bcm283x.dtsi - -Add the VEC (Video EnCoder) node definition in bcm283x.dtsi. - -Signed-off-by: Boris Brezillon -Signed-off-by: Eric Anholt -(cherry picked from commit b899c45208d6f204a6da9a1132577993eeecf0fb) ---- - arch/arm/boot/dts/bcm283x.dtsi | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi -index 304dd291a9ae94700e8e628c0c9ebd3fb98abb19..ee69fd481fabd22d8f45ecdcffacdbb185e11f55 100644 ---- a/arch/arm/boot/dts/bcm283x.dtsi -+++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -520,6 +520,14 @@ - status = "disabled"; - }; - -+ vec: vec@7e806000 { -+ compatible = "brcm,bcm2835-vec"; -+ reg = <0x7e806000 0x1000>; -+ clocks = <&clocks BCM2835_CLOCK_VEC>; -+ interrupts = <2 27>; -+ status = "disabled"; -+ }; -+ - pixelvalve@7e807000 { - compatible = "brcm,bcm2835-pixelvalve2"; - reg = <0x7e807000 0x100>; - -From b25a1418190664759efdfd000e09f4029920b70c Mon Sep 17 00:00:00 2001 -From: Boris Brezillon -Date: Fri, 2 Dec 2016 14:48:13 +0100 -Subject: [PATCH 176/216] ARM: dts: bcm283x: Enable the VEC IP on all - RaspberryPi boards - -Enable the VEC IP on all RaspberryPi boards. - -Signed-off-by: Boris Brezillon -Signed-off-by: Eric Anholt -(cherry picked from commit 5ab1a37c6027c114a87a1ae32cfc5ef303d643c5) ---- - arch/arm/boot/dts/bcm2835-rpi.dtsi | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi -index 58f7d874c70a9cf965e10ae3f14fe3bb00846b71..023630efa7c1d8601ba5e83d2fdb38a7557b6460 100644 ---- a/arch/arm/boot/dts/bcm2835-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi -@@ -95,3 +95,8 @@ - &dsi1 { - power-domains = <&power RPI_POWER_DOMAIN_DSI1>; - }; -+ -+&vec { -+ power-domains = <&power RPI_POWER_DOMAIN_VEC>; -+ status = "okay"; -+}; - -From 45933c1da08a68da2ce3f7206a1ca182bf627fd2 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 23 Jan 2017 11:41:54 -0800 -Subject: [PATCH 177/216] BCM270X: Disable VEC unless vc4-kms-v3d is present. - -Signed-off-by: Eric Anholt ---- - arch/arm/boot/dts/bcm2708-rpi.dtsi | 4 ++++ - arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts | 7 +++++++ - 2 files changed, 11 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi -index ef14e9ac6cd2092efb1681682dd2d3c52b8abfd5..8bb9ca54a36f2ac29987ecc1c2738b6758849a16 100644 ---- a/arch/arm/boot/dts/bcm2708-rpi.dtsi -+++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi -@@ -111,3 +111,7 @@ - &clocks { - firmware = <&firmware>; - }; -+ -+&vec { -+ status = "disabled"; -+}; -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 05faf1bfa1b7c73fd60b1efb813b969e10bbfefa..c57e795824e9261e0f60bcb40d6a57241019fd91 100644 ---- a/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -+++ b/arch/arm/boot/dts/overlays/vc4-kms-v3d-overlay.dts -@@ -151,6 +151,13 @@ - }; - - fragment@18 { -+ target = <&vec>; -+ __overlay__ { -+ status = "okay"; -+ }; -+ }; -+ -+ fragment@19 { - target = <&clocks>; - __overlay__ { - claim-clocks = < - -From a7ed5417f4f1ce5ad2c83ea186fde0560a89845e Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 1 Feb 2017 17:09:18 -0800 -Subject: [PATCH 178/216] drm/vc4: Name the primary and cursor planes in fkms. - -This makes debugging nicer, compared to trying to remember what the -IDs are. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -index d18a1dae51a2275846c9826b5bf1ba57ae97b55c..e49ce68b607a7ffc2329e3235362f3bc21ed5cbb 100644 ---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -267,7 +267,7 @@ static struct drm_plane *vc4_fkms_plane_init(struct drm_device *dev, - ret = drm_universal_plane_init(dev, plane, 0xff, - &vc4_plane_funcs, - primary ? &xrgb8888 : &argb8888, 1, -- type, NULL); -+ type, primary ? "primary" : "cursor"); - - if (type == DRM_PLANE_TYPE_PRIMARY) { - vc4_plane->fbinfo = - -From 328e2376e456598d9bd0de8235dcc884dbe8e043 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 1 Feb 2017 17:10:09 -0800 -Subject: [PATCH 179/216] drm/vc4: Add DRM_DEBUG_ATOMIC for the insides of - fkms. - -Trying to debug weston on fkms involved figuring out what calls I was -making to the firmware. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 26 ++++++++++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -index e49ce68b607a7ffc2329e3235362f3bc21ed5cbb..dbf065677202fbebf8e3a0cffbe880aa42daef3f 100644 ---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -102,6 +102,11 @@ static int vc4_plane_set_primary_blank(struct drm_plane *plane, bool blank) - struct vc4_dev *vc4 = to_vc4_dev(plane->dev); - - u32 packet = blank; -+ -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary plane %s", -+ plane->base.id, plane->name, -+ blank ? "blank" : "unblank"); -+ - return rpi_firmware_property(vc4->firmware, - RPI_FIRMWARE_FRAMEBUFFER_BLANK, - &packet, sizeof(packet)); -@@ -149,6 +154,16 @@ static void vc4_primary_plane_atomic_update(struct drm_plane *plane, - WARN_ON_ONCE(vc4_plane->pitch != fb->pitches[0]); - } - -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] primary update %dx%d@%d +%d,%d 0x%08x/%d\n", -+ plane->base.id, plane->name, -+ state->crtc_w, -+ state->crtc_h, -+ bpp, -+ state->crtc_x, -+ state->crtc_y, -+ bo->paddr + fb->offsets[0], -+ fb->pitches[0]); -+ - ret = rpi_firmware_transaction(vc4->firmware, - RPI_FIRMWARE_CHAN_FB, - vc4_plane->fbinfo_bus_addr); -@@ -178,6 +193,15 @@ static void vc4_cursor_plane_atomic_update(struct drm_plane *plane, - WARN_ON_ONCE(fb->pitches[0] != state->crtc_w * 4); - WARN_ON_ONCE(fb->bits_per_pixel != 32); - -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] update %dx%d cursor at %d,%d (0x%08x/%d)", -+ plane->base.id, plane->name, -+ state->crtc_w, -+ state->crtc_h, -+ state->crtc_x, -+ state->crtc_y, -+ bo->paddr + fb->offsets[0], -+ fb->pitches[0]); -+ - ret = rpi_firmware_property(vc4->firmware, - RPI_FIRMWARE_SET_CURSOR_STATE, - &packet_state, -@@ -200,6 +224,8 @@ static void vc4_cursor_plane_atomic_disable(struct drm_plane *plane, - u32 packet_state[] = { false, 0, 0, 0 }; - int ret; - -+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] disabling cursor", plane->base.id, plane->name); -+ - ret = rpi_firmware_property(vc4->firmware, - RPI_FIRMWARE_SET_CURSOR_STATE, - &packet_state, - -From 169eab65225977f26e03fe9cfe2791b1ada25fe5 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 2 Feb 2017 09:42:18 -0800 -Subject: [PATCH 180/216] drm/vc4: Fix sending of page flip completion events - in FKMS mode. - -In the rewrite of vc4_crtc.c for fkms, I dropped the part of the -CRTC's atomic flush handler that moved the completion event from the -proposed atomic state change to the CRTC's current state. That meant -that when full screen pageflipping happened (glxgears -fullscreen in -X, compton, por weston), the app would end up blocked firever waiting -to draw its next frame. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_firmware_kms.c | 15 +++++++++++++++ - 1 file changed, 15 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_firmware_kms.c b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -index dbf065677202fbebf8e3a0cffbe880aa42daef3f..da818a207bfa639b8cea48d94bcf4566f97db816 100644 ---- a/drivers/gpu/drm/vc4/vc4_firmware_kms.c -+++ b/drivers/gpu/drm/vc4/vc4_firmware_kms.c -@@ -338,6 +338,21 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, - static void vc4_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) - { -+ struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); -+ struct drm_device *dev = crtc->dev; -+ -+ if (crtc->state->event) { -+ unsigned long flags; -+ -+ crtc->state->event->pipe = drm_crtc_index(crtc); -+ -+ WARN_ON(drm_crtc_vblank_get(crtc) != 0); -+ -+ spin_lock_irqsave(&dev->event_lock, flags); -+ vc4_crtc->event = crtc->state->event; -+ crtc->state->event = NULL; -+ spin_unlock_irqrestore(&dev->event_lock, flags); -+ } - } - - static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc) - -From db8625e84e2cd8592c9b2112fd56688a4cdfaf7b Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Wed, 8 Feb 2017 15:00:54 -0800 -Subject: [PATCH 181/216] drm/vc4: Fulfill user BO creation requests from the - kernel BO cache. - -The from_cache flag was actually "the BO is invisible to userspace", -so we can repurpose to just zero out a cached BO and return it to -userspace. - -Improves wall time for a loop of 5 glsl-algebraic-add-add-1 by --1.44989% +/- 0.862891% (n=28, 1 outlier removed from each that -appeared to be other system noise) - -Note that there's an intel-gpu-tools test to check for the proper -zeroing behavior here, which we continue to pass. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_bo.c | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c -index 3f6704cf6608d7be47637c6aa585de087b7f74ee..5ec14f25625dde6fd61e10415092fa25527cc151 100644 ---- a/drivers/gpu/drm/vc4/vc4_bo.c -+++ b/drivers/gpu/drm/vc4/vc4_bo.c -@@ -208,21 +208,22 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size) - } - - struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size, -- bool from_cache) -+ bool allow_unzeroed) - { - size_t size = roundup(unaligned_size, PAGE_SIZE); - struct vc4_dev *vc4 = to_vc4_dev(dev); - struct drm_gem_cma_object *cma_obj; -+ struct vc4_bo *bo; - - if (size == 0) - return ERR_PTR(-EINVAL); - - /* First, try to get a vc4_bo from the kernel BO cache. */ -- if (from_cache) { -- struct vc4_bo *bo = vc4_bo_get_from_cache(dev, size); -- -- if (bo) -- return bo; -+ bo = vc4_bo_get_from_cache(dev, size); -+ if (bo) { -+ if (!allow_unzeroed) -+ memset(bo->base.vaddr, 0, bo->base.base.size); -+ return bo; - } - - cma_obj = drm_gem_cma_create(dev, size); - -From 65defd8ca6b5535f30816c7737403ddacad17074 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Thu, 9 Feb 2017 09:23:34 -0800 -Subject: [PATCH 182/216] drm/vc4: Fix OOPSes from trying to cache a partially - constructed BO. - -If a CMA allocation failed, the partially constructed BO would be -unreferenced through the normal path, and we might choose to put it in -the BO cache. If we then reused it before it expired from the cache, -the kernel would OOPS. - -Signed-off-by: Eric Anholt -Fixes: c826a6e10644 ("drm/vc4: Add a BO cache.") ---- - drivers/gpu/drm/vc4/vc4_bo.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c -index 5ec14f25625dde6fd61e10415092fa25527cc151..fd83a28076564b9ea5cf0f2ba29b884ee3c5af43 100644 ---- a/drivers/gpu/drm/vc4/vc4_bo.c -+++ b/drivers/gpu/drm/vc4/vc4_bo.c -@@ -314,6 +314,14 @@ void vc4_free_object(struct drm_gem_object *gem_bo) - goto out; - } - -+ /* If this object was partially constructed but CMA allocation -+ * had failed, just free it. -+ */ -+ if (!bo->base.vaddr) { -+ vc4_bo_destroy(bo); -+ goto out; -+ } -+ - cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size); - if (!cache_list) { - vc4_bo_destroy(bo); - -From a01af49cdb9b71d34c66f6228c730764659c13df Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 12 Oct 2015 08:58:08 -0700 -Subject: [PATCH 183/216] drm/vc4: Verify at boot that CMA doesn't cross a - 256MB boundary. - -I've seen lots of users cranking CMA up higher, so throw an error if -they do. - -Signed-off-by: Eric Anholt ---- - drivers/base/dma-contiguous.c | 1 + - drivers/gpu/drm/vc4/vc4_v3d.c | 18 ++++++++++++++++++ - mm/cma.c | 2 ++ - 3 files changed, 21 insertions(+) - -diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c -index e167a1e1bccb062efef2595fcd5299301a97df80..60f5c2591ccdb0202461458eab4035cfba731b8b 100644 ---- a/drivers/base/dma-contiguous.c -+++ b/drivers/base/dma-contiguous.c -@@ -35,6 +35,7 @@ - #endif - - struct cma *dma_contiguous_default_area; -+EXPORT_SYMBOL(dma_contiguous_default_area); - - /* - * Default global CMA area size can be defined in kernel's .config. -diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c -index 7cc346ad9b0baed63701d1fae8f0306aa7713129..1d9e5a6edd22c29ce8b2990c9c35627aa1af2bd8 100644 ---- a/drivers/gpu/drm/vc4/vc4_v3d.c -+++ b/drivers/gpu/drm/vc4/vc4_v3d.c -@@ -16,7 +16,10 @@ - * this program. If not, see . - */ - -+#include "linux/init.h" -+#include "linux/cma.h" - #include "linux/component.h" -+#include "linux/dma-contiguous.h" - #include "linux/pm_runtime.h" - #include "vc4_drv.h" - #include "vc4_regs.h" -@@ -185,8 +188,23 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) - struct drm_device *drm = dev_get_drvdata(master); - struct vc4_dev *vc4 = to_vc4_dev(drm); - struct vc4_v3d *v3d = NULL; -+ struct cma *cma; - int ret; - -+ cma = dev_get_cma_area(dev); -+ if (!cma) -+ return -EINVAL; -+ -+ if ((cma_get_base(cma) & 0xf0000000) != -+ ((cma_get_base(cma) + cma_get_size(cma) - 1) & 0xf0000000)) { -+ DRM_ERROR("V3D requires that the CMA area (0x%08lx - 0x%08lx) " -+ "not span a 256MB boundary, or memory corruption " -+ "would happen.\n", -+ (long)cma_get_base(cma), -+ cma_get_base(cma) + cma_get_size(cma)); -+ return -EINVAL; -+ } -+ - v3d = devm_kzalloc(&pdev->dev, sizeof(*v3d), GFP_KERNEL); - if (!v3d) - return -ENOMEM; -diff --git a/mm/cma.c b/mm/cma.c -index c960459eda7e640ea55be1d4ed80c6a9125a8877..b50245282a18bc790da0f901944c2e670ffac2d2 100644 ---- a/mm/cma.c -+++ b/mm/cma.c -@@ -47,11 +47,13 @@ phys_addr_t cma_get_base(const struct cma *cma) - { - return PFN_PHYS(cma->base_pfn); - } -+EXPORT_SYMBOL(cma_get_base); - - unsigned long cma_get_size(const struct cma *cma) - { - return cma->count << PAGE_SHIFT; - } -+EXPORT_SYMBOL(cma_get_size); - - static unsigned long cma_bitmap_aligned_mask(const struct cma *cma, - int align_order) - -From d0ec3653df341eef96192c7fcd48547cf6db0cd7 Mon Sep 17 00:00:00 2001 -From: Scott Ellis -Date: Thu, 23 Feb 2017 11:56:20 -0500 -Subject: [PATCH 184/216] Add ads1015 driver to config - ---- - arch/arm/configs/bcm2709_defconfig | 2 +- - arch/arm/configs/bcmrpi_defconfig | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index d3fd0252f78ec72bd6d93322e781abc3609af01c..1a25a016a53badcb2cd76141d035d5552a72b2f8 100644 ---- a/arch/arm/configs/bcm2709_defconfig -+++ b/arch/arm/configs/bcm2709_defconfig -@@ -833,9 +833,9 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_DRM=m - CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m - CONFIG_DRM_PANEL_SIMPLE=m - CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m --CONFIG_DRM_UDL=m - CONFIG_DRM_VC4=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index 0768998e5cbcc96714d546f656ff59eafe2dc754..efc4898aca911d5c97426a38b0f1808b3c0d4baa 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -826,9 +826,9 @@ CONFIG_VIDEO_OV7640=m - CONFIG_VIDEO_MT9V011=m - CONFIG_DRM=m - CONFIG_DRM_LOAD_EDID_FIRMWARE=y -+CONFIG_DRM_UDL=m - CONFIG_DRM_PANEL_SIMPLE=m - CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN=m --CONFIG_DRM_UDL=m - CONFIG_DRM_VC4=m - CONFIG_FB=y - CONFIG_FB_BCM2708=y - -From 019ddce57e24e2509fba98c574a63d72bbcc6066 Mon Sep 17 00:00:00 2001 -From: Michael Zoran -Date: Thu, 23 Feb 2017 17:54:31 -0800 -Subject: [PATCH 185/216] drm/vc4: Don't wait for vblank when updating the - cursor - -Commonly used desktop environments such as xfce4 and gnome -on debian sid can flood the graphics drivers with cursor -updates. Because the current implementation is waiting -for a vblank between cursor updates, this will cause the -display to hang for a long time since a typical refresh -rate is only 60Hz. - -This is unnecessary and unexpected by user mode software, -so simply swap out the cursor frame buffer without waiting. - -Signed-off-by: Michael Zoran -Reviewed-by: Eric Anholt ---- - drivers/gpu/drm/vc4/vc4_plane.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c -index 686cdd3c86f2e9178768282a0dd173850e0bf063..7bdbb0e2b50f9202efe1177df761b379f1232dbc 100644 ---- a/drivers/gpu/drm/vc4/vc4_plane.c -+++ b/drivers/gpu/drm/vc4/vc4_plane.c -@@ -20,6 +20,7 @@ - - #include "vc4_drv.h" - #include "vc4_regs.h" -+#include "drm_atomic.h" - #include "drm_atomic_helper.h" - #include "drm_fb_cma_helper.h" - #include "drm_plane_helper.h" -@@ -769,12 +770,6 @@ vc4_update_plane(struct drm_plane *plane, - if (!plane_state) - goto out; - -- /* If we're changing the cursor contents, do that in the -- * normal vblank-synced atomic path. -- */ -- if (fb != plane_state->fb) -- goto out; -- - /* No configuring new scaling in the fast path. */ - if (crtc_w != plane_state->crtc_w || - crtc_h != plane_state->crtc_h || -@@ -783,6 +778,11 @@ vc4_update_plane(struct drm_plane *plane, - goto out; - } - -+ if (fb != plane_state->fb) { -+ drm_atomic_set_fb_for_plane(plane->state, fb); -+ vc4_plane_async_set_fb(plane, fb); -+ } -+ - /* Set the cursor's position on the screen. This is the - * expected change from the drm_mode_cursor_universal() - * helper. - -From 34e1b2211ca468449b4855c02563b83a52e2a4f1 Mon Sep 17 00:00:00 2001 -From: Eric Anholt -Date: Mon, 6 Mar 2017 12:17:16 -0800 -Subject: [PATCH 186/216] panel-raspberrypi-touchscreen: Round up clk rate to - fix DSI panel. - -Commit 488f9bc8e3def93e0baef53cee2026c2cb0d8956 slightly increased the -reported rate of PLLD, so the clk driver decided that PLLD/3/8 was now -higher than our requested pixel clock rate and rejected it in favor of -PLLD/4/8, which then ran the pixel clock way out of spec. - -By bumping the requested clock rate just slightly, we get back to -PLLD/3/8 like we wanted and the panel displays content again. - -Signed-off-by: Eric Anholt ---- - drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -index 1a536fe4d040f5fafe324baee110a6225dd0be08..7f315f04b109621ca7f3861fdd8acf956e752629 100644 ---- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c -@@ -220,7 +220,12 @@ static const struct drm_display_mode rpi_touchscreen_modes[] = { - #define HBP 46 - #define HFP ((PIXEL_CLOCK / (VTOTAL * VREFRESH)) - (HACT + HSW + HBP)) - -- .clock = PIXEL_CLOCK / 1000, -+ /* Round up the pixel clock a bit (10khz), so that the -+ * "don't run things faster than the requested clock -+ * rate" rule of the clk driver doesn't reject the -+ * divide-by-3 mode due to rounding error. -+ */ -+ .clock = PIXEL_CLOCK / 1000 + 10, - .hdisplay = HACT, - .hsync_start = HACT + HFP, - .hsync_end = HACT + HFP + HSW, - -From 761f060a373dfd08bb14abdbf1167b7091f26dc0 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Mon, 13 Mar 2017 12:30:37 +0000 -Subject: [PATCH 187/216] thermal: Compatible strings for bcm2836, bcm2837 - -The upstream dt-bindings documentation for bcm2835-thermal (which -exists even though the driver isn't upstreamed) says to use -dedicated compatible strings on bcm2836 and bcm2837, even though -the downstream driver doesn't support them. The Pi2 DTB uses -"brcm,bcm2836-thermal", so the driver doesn't load. The Pi3 DTB -doesn't override the base value, but the arm64 Pi3 support uses "brcm,bcm2837-thermal". - -Solve the documentation problem by adding "brcm,bcm2836-thermal" and -"brcm,bcm2837-thermal" as alternative compatible strings for the -bcm2835-thermal driver. - -Signed-off-by: Phil Elwell ---- - drivers/thermal/bcm2835-thermal.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c -index c63fb9f9d143e19612a18fe530c7b2b3518a22a4..25b78c3eac1503fbc9e679b963a6284b673b2ed3 100644 ---- a/drivers/thermal/bcm2835-thermal.c -+++ b/drivers/thermal/bcm2835-thermal.c -@@ -89,6 +89,8 @@ static int bcm2835_thermal_remove(struct platform_device *pdev) - - static const struct of_device_id bcm2835_thermal_of_match_table[] = { - { .compatible = "brcm,bcm2835-thermal", }, -+ { .compatible = "brcm,bcm2836-thermal", }, -+ { .compatible = "brcm,bcm2837-thermal", }, - {}, - }; - MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); - -From c74d28bfe4de5e036d522d5a212252b25f215e3c Mon Sep 17 00:00:00 2001 -From: John Greb -Date: Wed, 8 Mar 2017 15:12:29 +0000 -Subject: [PATCH 188/216] Match dwc2 device-tree fifo sizes to the hardware - values. - -Since commit aa381a7259c3f53727bcaa8c5f9359e940a0e3fd was reverted with 3fa9538539ac737096c81f3315a14670b1609092 the g-tx-fifo-size array in the device-tree needs to match the preset values in the bcm2835. - -Resolves https://github.com/raspberrypi/linux/issues/1876 ---- - arch/arm/boot/dts/overlays/dwc2-overlay.dts | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/dwc2-overlay.dts b/arch/arm/boot/dts/overlays/dwc2-overlay.dts -index 527abc9f0ddf71f4dc7d58336d87684c931cc2f3..265a16bab008453edba198cf2366c423509d60d6 100644 ---- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts -+++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts -@@ -15,7 +15,7 @@ - dr_mode = "otg"; - g-np-tx-fifo-size = <32>; - g-rx-fifo-size = <256>; -- g-tx-fifo-size = <256 128 128 64 64 64 32>; -+ g-tx-fifo-size = <512 512 512 512 512 768>; - status = "okay"; - }; - }; -@@ -24,6 +24,5 @@ - dr_mode = <&dwc2_usb>, "dr_mode"; - g-np-tx-fifo-size = <&dwc2_usb>,"g-np-tx-fifo-size:0"; - g-rx-fifo-size = <&dwc2_usb>,"g-rx-fifo-size:0"; -- g-tx-fifo-size = <&dwc2_usb>,"g-tx-fifo-size:0"; - }; - }; - -From 262be820466b8326e671f1fd5b00d42e2bebc93f Mon Sep 17 00:00:00 2001 +From bdd7790b38da33f87061c06c2e5f4cfe50ddd2fe Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 7 Mar 2017 12:18:20 +0000 -Subject: [PATCH 189/216] BCM270X_DT: Invert Pi3 power LED to match fw change +Subject: [PATCH 114/150] BCM270X_DT: Invert Pi3 power LED to match fw change Firmware expgpio driver reworked due to complaint over hotplug detect. @@ -136405,7 +112655,7 @@ Signed-off-by: Dave Stevenson 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts -index 173103aaca503833b5e29530ed94e14c7cab0444..b21d2866d204adc533b46d581028f290e5c34a3d 100644 +index 616cfd5c7094596b497101e8feca25e25e77c3e8..9f001bccb8261563dcddd8dec94b056b55308c6d 100644 --- a/arch/arm/boot/dts/bcm2710-rpi-3-b.dts +++ b/arch/arm/boot/dts/bcm2710-rpi-3-b.dts @@ -175,7 +175,7 @@ @@ -136418,76 +112668,10 @@ index 173103aaca503833b5e29530ed94e14c7cab0444..b21d2866d204adc533b46d581028f290 }; -From 8c38fe2d4c4037b34b6bfcdb45d2e525f61ae6bb Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 14 Mar 2017 09:10:05 +0000 -Subject: [PATCH 190/216] BCM270X_DT: Add lm75 to i2c-sensor overlay - -See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=177236 - -Signed-off-by: Phil Elwell ---- - arch/arm/boot/dts/overlays/README | 8 +++++--- - arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 8 ++++++++ - 2 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index c1883bba938290f03826026651c764cfd4ac278b..a8853b7820cd7a333cdaa2421f770a834dc724d5 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -388,9 +388,6 @@ Params: dr_mode Dual role mode: "host", "peripheral" or "otg" - g-np-tx-fifo-size Size of non-periodic tx fifo size in gadget - mode - -- g-tx-fifo-size Size of periodic tx fifo per endpoint -- (except ep0) in gadget mode -- - - [ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] - -@@ -608,6 +605,11 @@ Params: bmp085 Select the Bosch sensortronic BMP085 - - bmp280 Select the Bosch sensortronic BMP280 - -+ lm75 Select the Maxim LM75 temperature sensor -+ -+ lm75addr Choose the address for the LM75 (0x48-0x4f - -+ default 0x4f) -+ - si7020 Select the Silicon Labs Si7013/20/21 humidity/ - temperature sensor - -diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -index 31bda8da4cb6a56bfe493a81b918900995fb0589..606b2d5012abf2e85712be631c42ea40a0b512c5 100644 ---- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -+++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts -@@ -25,6 +25,12 @@ - status = "disable"; - }; - -+ lm75: lm75@4f { -+ compatible = "lm75"; -+ reg = <0x4f>; -+ status = "disable"; -+ }; -+ - si7020: si7020@40 { - compatible = "si7020"; - reg = <0x40>; -@@ -36,6 +42,8 @@ - __overrides__ { - bmp085 = <&bmp085>,"status"; - bmp280 = <&bmp280>,"status"; -+ lm75 = <&lm75>,"status"; -+ lm75addr = <&lm75>,"reg:0"; - si7020 = <&si7020>,"status"; - }; - }; - -From 28e5b2d43852e22092442a4b0600ad31cfd6efce Mon Sep 17 00:00:00 2001 +From 2789ac0dbf80b6df42974e3bbacc723cb5a3ba39 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Tue, 14 Mar 2017 14:23:06 +0000 -Subject: [PATCH 191/216] bcm2835-gpio-exp: Copy/paste error adding base twice +Subject: [PATCH 115/150] bcm2835-gpio-exp: Copy/paste error adding base twice brcmexp_gpio_set was adding gpio->gc.base to the offset twice, so passing an invalid number to the mailbox service. @@ -136513,71 +112697,48 @@ index 681a91492d4c33bdfd42416e069218e8611cc4d9..d68adafaee4ad406f45f4ff0d6b7c1ad set.state = val; /* Output state */ -From 534fc500a20c0c5db12ba5be512821e726717d41 Mon Sep 17 00:00:00 2001 -From: Dave Stevenson -Date: Wed, 15 Mar 2017 11:12:40 +0000 -Subject: [PATCH 192/216] bcm2835-camera: Correct port_parameter_get return - value +From e72aaca7d8ef75c9335eb7e8c9aefd345f6f03c6 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 17 Mar 2017 13:40:41 +0000 +Subject: [PATCH 116/150] config: disable MMC driver temporarily for now. -The API for port_parameter_get() requires that the -filled length is returned, or if insufficient space -that the required space is returned. - -Signed-off-by: Dave Stevenson +Currently causes a breakage to sdhost driver. However when MMC is disabled Pi3 wifi will not work --- - drivers/media/platform/bcm2835/mmal-vchiq.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) + arch/arm/configs/bcm2709_defconfig | 2 -- + arch/arm/configs/bcmrpi_defconfig | 2 -- + 2 files changed, 4 deletions(-) -diff --git a/drivers/media/platform/bcm2835/mmal-vchiq.c b/drivers/media/platform/bcm2835/mmal-vchiq.c -index e4b243b33f58913f3d2952c97d2a2e3fbbbd0ae8..ec2853ba9d4b1b0cd6e07a495a424e15159208e8 100644 ---- a/drivers/media/platform/bcm2835/mmal-vchiq.c -+++ b/drivers/media/platform/bcm2835/mmal-vchiq.c -@@ -1292,6 +1292,7 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, - struct mmal_msg m; - struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; -+ u32 reply_size; - - m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET; - -@@ -1315,21 +1316,27 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, - } - - ret = -rmsg->u.port_parameter_get_reply.status; -- /* port_parameter_get_reply.size includes the header, -+ /* -+ * port_parameter_get_reply.size includes the header, - * whilst *value_size doesn't. - */ -- rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32)); -+ reply_size = rmsg->u.port_parameter_get_reply.size - (2 * sizeof(u32)); - -- if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) { -+ if (ret || (reply_size > *value_size)) { - /* Copy only as much as we have space for - * but report true size of parameter - */ - memcpy(value, &rmsg->u.port_parameter_get_reply.value, - *value_size); -- *value_size = rmsg->u.port_parameter_get_reply.size; - } else - memcpy(value, &rmsg->u.port_parameter_get_reply.value, -- rmsg->u.port_parameter_get_reply.size); -+ reply_size); -+ -+ /* -+ * Return amount of data copied if big enough, -+ * or wanted if not big enough. -+ */ -+ *value_size = reply_size; - - pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, - ret, port->component->handle, port->handle, parameter_id); +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 4f038004cb7ae7b6d9a54d9a743686e92d0e6389..324788beab7412a22fcaefc9de43b9f144f218eb 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -1047,8 +1047,6 @@ CONFIG_USB_XUSBATM=m + CONFIG_USB_GADGET=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 +-CONFIG_MMC_BCM2835=y +-CONFIG_MMC_BCM2835_DMA=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 046f3e8757ef0f794c802171690528d31fee9deb..f2e0a58a96c8550f110c5940bf65f4d022cc4548 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -1053,8 +1053,6 @@ CONFIG_USB_G_HID=m + CONFIG_USB_G_WEBCAM=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 +-CONFIG_MMC_BCM2835=y +-CONFIG_MMC_BCM2835_DMA=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y -From 51d9fbec8a2bbb958dffce48e70dd7c7653c52c4 Mon Sep 17 00:00:00 2001 +From 226d6e3cd55ed7d78155f5f42553f42ab2c07222 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 17 Mar 2017 12:24:41 +0000 -Subject: [PATCH 193/216] config: Make spidev a loadable module +Subject: [PATCH 117/150] config: Make spidev a loadable module spidev isn't required early in the boot process, and not all users need it (spi_bcm2835 is a module), so make it a loadable module. @@ -136586,15 +112747,15 @@ See: https://github.com/raspberrypi/linux/issues/1897 Signed-off-by: Phil Elwell --- - arch/arm/configs/bcm2709_defconfig | 3 +-- - arch/arm/configs/bcmrpi_defconfig | 3 +-- - 2 files changed, 2 insertions(+), 4 deletions(-) + arch/arm/configs/bcm2709_defconfig | 2 +- + arch/arm/configs/bcmrpi_defconfig | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 1a25a016a53badcb2cd76141d035d5552a72b2f8..8ce1707b537e9e21589887b93c0dbf9302cb5974 100644 +index 324788beab7412a22fcaefc9de43b9f144f218eb..f969170c4d1d693795c1662d0271eba763ddc0df 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig -@@ -617,7 +617,7 @@ CONFIG_I2C_GPIO=m +@@ -616,7 +616,7 @@ CONFIG_I2C_GPIO=m CONFIG_SPI=y CONFIG_SPI_BCM2835=m CONFIG_SPI_BCM2835AUX=m @@ -136603,19 +112764,11 @@ index 1a25a016a53badcb2cd76141d035d5552a72b2f8..8ce1707b537e9e21589887b93c0dbf93 CONFIG_PPS=m CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_GPIO=m -@@ -895,7 +895,6 @@ CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m --CONFIG_SND_SOC_CS42XX8_I2C=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index efc4898aca911d5c97426a38b0f1808b3c0d4baa..e65b2106d97ea9351c1d85166d2bff39d458ded3 100644 +index f2e0a58a96c8550f110c5940bf65f4d022cc4548..9eb7084f440c8aac0c6257ee678007c23990a8ae 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -612,7 +612,7 @@ CONFIG_I2C_GPIO=m +@@ -611,7 +611,7 @@ CONFIG_I2C_GPIO=m CONFIG_SPI=y CONFIG_SPI_BCM2835=m CONFIG_SPI_BCM2835AUX=m @@ -136624,19 +112777,11 @@ index efc4898aca911d5c97426a38b0f1808b3c0d4baa..e65b2106d97ea9351c1d85166d2bff39 CONFIG_PPS=m CONFIG_PPS_CLIENT_LDISC=m CONFIG_PPS_CLIENT_GPIO=m -@@ -888,7 +888,6 @@ CONFIG_SND_PISOUND=m - CONFIG_SND_SOC_ADAU1701=m - CONFIG_SND_SOC_ADAU7002=m - CONFIG_SND_SOC_AK4554=m --CONFIG_SND_SOC_CS42XX8_I2C=m - CONFIG_SND_SOC_WM8804_I2C=m - CONFIG_SND_SIMPLE_CARD=m - CONFIG_SOUND_PRIME=m -From 9108d5a99c10d3ef3a4635c71257f6db37264b09 Mon Sep 17 00:00:00 2001 +From 9e4faee7474a829888a11aa72bdb1c7e06730b42 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 10:06:56 +0000 -Subject: [PATCH 194/216] ASoC: Add prompt for ICS43432 codec +Subject: [PATCH 118/150] ASoC: Add prompt for ICS43432 codec Without a prompt string, a config setting can't be included in a defconfig. Give CONFIG_SND_SOC_ICS43432 a prompt so that Pi soundcards @@ -136648,10 +112793,10 @@ Signed-off-by: Phil Elwell 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig -index cd02edde708f860ba90ef7892339ef311c898746..fbcc1516af4f463e5e0a1a8ced04b82cc9cb888e 100644 +index 55812b0b884cf4fc4e86680b11fedd11c863db7a..428dc05edbb99f50560b7f89e45501c5e8a0e583 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig -@@ -547,7 +547,7 @@ config SND_SOC_HDAC_HDMI +@@ -550,7 +550,7 @@ config SND_SOC_HDAC_HDMI select HDMI config SND_SOC_ICS43432 @@ -136661,10 +112806,10 @@ index cd02edde708f860ba90ef7892339ef311c898746..fbcc1516af4f463e5e0a1a8ced04b82c config SND_SOC_INNO_RK3036 tristate "Inno codec driver for RK3036 SoC" -From 8d7dc7275a9100b38679af078312da3f5ff214cb Mon Sep 17 00:00:00 2001 +From 6a7e09fdc26bd7f00523840e15292f6af4e3e6e9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 16:34:46 +0000 -Subject: [PATCH 195/216] bcm2835-aux: Add aux interrupt controller +Subject: [PATCH 119/150] bcm2835-aux: Add aux interrupt controller The AUX block has a shared interrupt line with a register indicating which devices have active IRQs. Expose this as a nested interrupt @@ -136828,10 +112973,10 @@ index bd750cf2238d61489811e7d7bd3b5f9950ed53c8..41e0702fae4692221980b0d02aed1ba6 BCM2835_AUX_CLOCK_COUNT, GFP_KERNEL); if (!onecell) -From d8953351ac3bb251d4b052ea361b5e2d14004cb5 Mon Sep 17 00:00:00 2001 +From be8eaf036332239887bfad01d222b487008877ed Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 23 Mar 2017 17:08:44 +0000 -Subject: [PATCH 196/216] BCM270X_DT: Enable AUX interrupt controller in DT +Subject: [PATCH 120/150] BCM270X_DT: Enable AUX interrupt controller in DT See: https://github.com/raspberrypi/linux/issues/1484 https://github.com/raspberrypi/linux/issues/1573 @@ -136842,10 +112987,10 @@ Signed-off-by: Phil Elwell 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi -index ee69fd481fabd22d8f45ecdcffacdbb185e11f55..278e7a94a79d01e600f85daa6ec86cd0e9653db8 100644 +index 72cb9dc60ca9ad9aa2813972a299c50dcea7cd89..ca47b23ffbcd06063e0fb7072dc8a843b20256e3 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi -@@ -426,12 +426,16 @@ +@@ -403,12 +403,16 @@ #clock-cells = <1>; reg = <0x7e215000 0x8>; clocks = <&clocks BCM2835_CLOCK_VPU>; @@ -136863,7 +113008,7 @@ index ee69fd481fabd22d8f45ecdcffacdbb185e11f55..278e7a94a79d01e600f85daa6ec86cd0 clocks = <&aux BCM2835_AUX_CLOCK_UART>; status = "disabled"; }; -@@ -439,7 +443,8 @@ +@@ -416,7 +420,8 @@ spi1: spi@7e215080 { compatible = "brcm,bcm2835-aux-spi"; reg = <0x7e215080 0x40>; @@ -136873,7 +113018,7 @@ index ee69fd481fabd22d8f45ecdcffacdbb185e11f55..278e7a94a79d01e600f85daa6ec86cd0 clocks = <&aux BCM2835_AUX_CLOCK_SPI1>; #address-cells = <1>; #size-cells = <0>; -@@ -449,7 +454,8 @@ +@@ -426,7 +431,8 @@ spi2: spi@7e2150c0 { compatible = "brcm,bcm2835-aux-spi"; reg = <0x7e2150c0 0x40>; @@ -136884,10 +113029,515 @@ index ee69fd481fabd22d8f45ecdcffacdbb185e11f55..278e7a94a79d01e600f85daa6ec86cd0 #address-cells = <1>; #size-cells = <0>; -From 9d39f5f53c902a6eb4540a9ebd60aa1fda8b7ffc Mon Sep 17 00:00:00 2001 +From d5d03ebbdedd9932ca36d53b66ad281014677734 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 27 Mar 2017 17:40:45 +0100 +Subject: [PATCH 121/150] mkknlimg: Find some more downstream-only strings + +See: https://github.com/raspberrypi/linux/issues/1920 + +Signed-off-by: Phil Elwell +--- + scripts/mkknlimg | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/scripts/mkknlimg b/scripts/mkknlimg +index 60206de7fa9a49bd027c635306674a29a568652f..84be2593ec1de8f97b0167ff06b3e05d231c4ba0 100755 +--- a/scripts/mkknlimg ++++ b/scripts/mkknlimg +@@ -68,7 +68,7 @@ if (! -r $kernel_file) + + my $wanted_strings = + { +- 'bcm2708_fb' => FLAG_PI, ++ 'bcm2708_fb' => FLAG_PI | FLAG_270X, + 'brcm,bcm2835-mmc' => FLAG_PI, + 'brcm,bcm2835-sdhost' => FLAG_PI, + 'brcm,bcm2708-pinctrl' => FLAG_PI | FLAG_DTOK, +@@ -79,6 +79,7 @@ my $wanted_strings = + 'brcm,bcm2836' => FLAG_PI | FLAG_DTOK | FLAG_283X, + 'of_cfs_init' => FLAG_DTOK | FLAG_DDTK, + 'vc_cma_init' => FLAG_PI | FLAG_270X, ++ 'vc-mem' => FLAG_PI | FLAG_270X, + }; + + my $res = try_extract($kernel_file, $tmpfile1); + +From a9d358fb540f0651536eb9f1b33d32a87157fca6 Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Fri, 29 Apr 2016 10:32:17 -0700 +Subject: [PATCH 122/150] mmc: read mmc alias from device tree + +To get the SD/MMC host device ID, read the alias from the device +tree. + +This is useful in case a SoC has multipe SD/MMC host controllers while +the second controller should logically be the first device (e.g. if +the second controller is connected to an internal eMMC). Combined +with block device numbering using MMC/SD host device ID, this +results in predictable name assignment of the internal eMMC block +device. + +Signed-off-by: Stefan Agner +Signed-off-by: Dmitry Torokhov +[dianders: rebase + roll in http://crosreview.com/259916] +Signed-off-by: Douglas Anderson +--- + drivers/mmc/core/host.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c +index 3f8c85d5aa094b43666904c7dbbe5e62c9763c19..4dbd0e8e27a496bfbe67d188cf795ecc7c89413c 100644 +--- a/drivers/mmc/core/host.c ++++ b/drivers/mmc/core/host.c +@@ -345,15 +345,30 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) + { + int err; + struct mmc_host *host; ++ int id; + + host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); + if (!host) + return NULL; + ++ /* If OF aliases exist, start dynamic assignment after highest */ ++ id = of_alias_get_highest_id("mmc"); ++ id = (id < 0) ? 0 : id + 1; ++ ++ /* If this devices has OF node, maybe it has an alias */ ++ if (dev->of_node) { ++ int of_id = of_alias_get_id(dev->of_node, "mmc"); ++ ++ if (of_id < 0) ++ dev_warn(dev, "/aliases ID not available\n"); ++ else ++ id = of_id; ++ } ++ + /* scanning will be enabled when we're ready */ + host->rescan_disable = 1; + +- err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL); ++ err = ida_simple_get(&mmc_host_ida, id, 0, GFP_KERNEL); + if (err < 0) { + kfree(host); + return NULL; + +From 713dc34bfd04c1e490fa139ae729198a9db8a41c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 29 Mar 2017 14:30:42 +0100 +Subject: [PATCH 123/150] BCM270X_DT: Add numbered aliases for SD/MMC devices + +In order to force a specific ID assignment to SD/MMC devices, add +numbered aliases to the DT: sdhost -> mmc0, mmc -> mmc1 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/bcm2708-rpi.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/dts/bcm2708-rpi.dtsi b/arch/arm/boot/dts/bcm2708-rpi.dtsi +index ef14e9ac6cd2092efb1681682dd2d3c52b8abfd5..693d4c04a36d2a7883cc3d8916bf0efbd6b782b5 100644 +--- a/arch/arm/boot/dts/bcm2708-rpi.dtsi ++++ b/arch/arm/boot/dts/bcm2708-rpi.dtsi +@@ -21,6 +21,7 @@ + gpio = &gpio; + uart0 = &uart0; + sdhost = &sdhost; ++ mmc0 = &sdhost; + i2s = &i2s; + spi0 = &spi0; + i2c0 = &i2c0; +@@ -28,6 +29,7 @@ + spi1 = &spi1; + spi2 = &spi2; + mmc = &mmc; ++ mmc1 = &mmc; + i2c1 = &i2c1; + i2c2 = &i2c2; + usb = &usb; + +From b226cc10d1e62ca1d0b82d24392a14a5b2c69cce Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 29 Mar 2017 14:28:53 +0100 +Subject: [PATCH 124/150] config: Re-enable the bcm2835-mmc driver + +With the patch to assign mmc device IDs based on DT aliases and +appropriate aliases in the rpi DTBs, it is now safe to re-enable +the bcm2835-mmc driver. + +Signed-off-by: Phil Elwell +--- + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index f969170c4d1d693795c1662d0271eba763ddc0df..1940c88c303dd644163195e13e865877d3cfe830 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -1047,6 +1047,7 @@ CONFIG_USB_XUSBATM=m + CONFIG_USB_GADGET=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 9eb7084f440c8aac0c6257ee678007c23990a8ae..021c38a909e71baa135cbcd4f3fb80fad2151647 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -1053,6 +1053,7 @@ CONFIG_USB_G_HID=m + CONFIG_USB_G_WEBCAM=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_MMC_BCM2835=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y + +From 845ebe4a7a5f89fda702be8ec72ac98ce9f3a248 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 11 May 2016 12:50:33 +0100 +Subject: [PATCH 125/150] 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, +and set it for cards of that type. + +Signed-off-by: Phil Elwell + +mmc: Apply QUIRK_BROKEN_ERASE to other capacities + +Signed-off-by: Phil Elwell + +mmc: Add card_quirks module parameter, log quirks + +Use mmc_block.card_quirks to override the quirks for all SD or MMC +cards. The value is a bitfield using the bit positions defined in +include/linux/mmc/card.h. If the module parameter is placed in the +kernel command line (or bootargs) stored on the card then, assuming the +device only has one SD card interface, the override effectively becomes +card-specific. + +Signed-off-by: Phil Elwell +--- + drivers/mmc/core/block.c | 28 +++++++++++++++++++++++++--- + drivers/mmc/core/core.c | 3 ++- + drivers/mmc/core/quirks.h | 11 +++++++++++ + include/linux/mmc/card.h | 4 ++++ + 4 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c +index ff3da960c4736147b2c1348681412953508ac49b..005afc96473037242c8e7f96ade877b4772515ef 100644 +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -125,6 +125,13 @@ static DEFINE_MUTEX(open_lock); + module_param(perdev_minors, int, 0444); + MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); + ++/* ++ * Allow quirks to be overridden for the current card ++ */ ++static char *card_quirks; ++module_param(card_quirks, charp, 0644); ++MODULE_PARM_DESC(card_quirks, "Force the use of the indicated quirks (a bitfield)"); ++ + 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); +@@ -2105,6 +2112,7 @@ static int mmc_blk_probe(struct mmc_card *card) + { + struct mmc_blk_data *md, *part_md; + char cap_str[10]; ++ char quirk_str[24]; + + /* + * Check that the card supports the command class(es) we need. +@@ -2112,7 +2120,16 @@ static int mmc_blk_probe(struct mmc_card *card) + if (!(card->csd.cmdclass & CCC_BLOCK_READ)) + return -ENODEV; + +- mmc_fixup_device(card, mmc_blk_fixups); ++ if (card_quirks) { ++ unsigned long quirks; ++ if (kstrtoul(card_quirks, 0, &quirks) == 0) ++ card->quirks = (unsigned int)quirks; ++ else ++ pr_err("mmc_block: Invalid card_quirks parameter '%s'\n", ++ card_quirks); ++ } ++ else ++ mmc_fixup_device(card, mmc_blk_fixups); + + md = mmc_blk_alloc(card); + if (IS_ERR(md)) +@@ -2120,9 +2137,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)); +- pr_info("%s: %s %s %s %s\n", ++ if (card->quirks) ++ snprintf(quirk_str, sizeof(quirk_str), ++ " (quirks 0x%08x)", card->quirks); ++ else ++ quirk_str[0] = '\0'; ++ pr_info("%s: %s %s %s%s%s\n", + md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), +- cap_str, md->read_only ? "(ro)" : ""); ++ cap_str, md->read_only ? " (ro)" : "", quirk_str); + + if (mmc_blk_alloc_parts(card, md)) + goto out; +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 926e0fde07d75a441f11ade4c10457bd7dde4ad2..e033394657585325a887e0f0fdfa9e2a299bc747 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -2392,7 +2392,8 @@ EXPORT_SYMBOL(mmc_erase); + int mmc_can_erase(struct mmc_card *card) + { + if ((card->host->caps & MMC_CAP_ERASE) && +- (card->csd.cmdclass & CCC_ERASE) && card->erase_size) ++ (card->csd.cmdclass & CCC_ERASE) && card->erase_size && ++ !(card->quirks & MMC_QUIRK_ERASE_BROKEN)) + return 1; + return 0; + } +diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h +index fb725934fa21cee1b98fd7bc08227bf6d0317549..05c8d7381fff5ae88531129d9a5ddd554bddb43e 100644 +--- a/drivers/mmc/core/quirks.h ++++ b/drivers/mmc/core/quirks.h +@@ -90,6 +90,17 @@ static const struct mmc_fixup mmc_blk_fixups[] = { + MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_TRIM_BROKEN), + ++ /* ++ * 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), ++ + END_FIXUP + }; + +diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h +index 77e61e0a216a2728dd5cfecf55299402ac03c384..d12e8ddd22cb96e38b30f1ac3f9a6bd027cf9cc4 100644 +--- a/include/linux/mmc/card.h ++++ b/include/linux/mmc/card.h +@@ -267,6 +267,10 @@ struct mmc_card { + #define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */ + #define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */ + ++ ++#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */ ++ ++ + unsigned int erase_size; /* erase size in sectors */ + unsigned int erase_shift; /* if erase unit is power 2 */ + unsigned int pref_erase; /* in sectors */ + +From a9a22a98903f6f2a2f92a780ac50e536b0b46533 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 29 Mar 2017 16:03:24 +0100 +Subject: [PATCH 126/150] Revert "bcm2835-sdhost: Hack fix build" + +This reverts commit e4e60ec9ccede5e084a74e65d206daf17dc1d0b1. +--- + drivers/mmc/host/bcm2835-sdhost.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +index 3ed754f8903bbf8ee5a810f20d96bc633168e4b3..a9bc79bfdbb71807819dfe2d8f1651445997f92a 100644 +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -53,11 +53,6 @@ + #include + #include + +-#include +-#define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */ +-#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR) +- +- + #define DRIVER_NAME "sdhost-bcm2835" + + #define SDCMD 0x00 /* Command to SD card - 16 R/W */ + +From 1a015a31bf89daad820bd634d8f4338265999a1f Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 29 Mar 2017 16:08:29 +0100 +Subject: [PATCH 127/150] bcm2835-sdhost: mmc_card_blockaddr fix + +Get the definition of mmc_card_blockaddr from drivers/mmc/core/card.h. + +Signed-off-by: Phil Elwell +--- + drivers/mmc/host/bcm2835-sdhost.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c +index a9bc79bfdbb71807819dfe2d8f1651445997f92a..9c6f199a7830959f31012d86bc1f8b1a9922185f 100644 +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -51,8 +51,12 @@ + #include + #include + #include ++#include + #include + ++/* For mmc_card_blockaddr */ ++#include "../core/card.h" ++ + #define DRIVER_NAME "sdhost-bcm2835" + + #define SDCMD 0x00 /* Command to SD card - 16 R/W */ + +From 95fc4c9a9ad573f2b4e3b6ec4c9ea65602f61a6e Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 13 Mar 2017 12:30:37 +0000 +Subject: [PATCH 128/150] thermal: Compatible strings for bcm2836, bcm2837 + +The upstream dt-bindings documentation for bcm2835-thermal (which +exists even though the driver isn't upstreamed) says to use +dedicated compatible strings on bcm2836 and bcm2837, even though +the downstream driver doesn't support them. The Pi2 DTB uses +"brcm,bcm2836-thermal", so the driver doesn't load. The Pi3 DTB +doesn't override the base value, but the arm64 Pi3 support uses "brcm,bcm2837-thermal". + +Solve the documentation problem by adding "brcm,bcm2836-thermal" and +"brcm,bcm2837-thermal" as alternative compatible strings for the +bcm2835-thermal driver. + +Signed-off-by: Phil Elwell +--- + drivers/thermal/bcm2835-thermal.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/thermal/bcm2835-thermal.c b/drivers/thermal/bcm2835-thermal.c +index c63fb9f9d143e19612a18fe530c7b2b3518a22a4..25b78c3eac1503fbc9e679b963a6284b673b2ed3 100644 +--- a/drivers/thermal/bcm2835-thermal.c ++++ b/drivers/thermal/bcm2835-thermal.c +@@ -89,6 +89,8 @@ static int bcm2835_thermal_remove(struct platform_device *pdev) + + static const struct of_device_id bcm2835_thermal_of_match_table[] = { + { .compatible = "brcm,bcm2835-thermal", }, ++ { .compatible = "brcm,bcm2836-thermal", }, ++ { .compatible = "brcm,bcm2837-thermal", }, + {}, + }; + MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table); + +From c0886a1ea925fbea9d548dacadce871b731173d0 Mon Sep 17 00:00:00 2001 +From: John Greb +Date: Wed, 8 Mar 2017 15:12:29 +0000 +Subject: [PATCH 129/150] Match dwc2 device-tree fifo sizes to the hardware + values. + +Since commit aa381a7259c3f53727bcaa8c5f9359e940a0e3fd was reverted with 3fa9538539ac737096c81f3315a14670b1609092 the g-tx-fifo-size array in the device-tree needs to match the preset values in the bcm2835. + +Resolves https://github.com/raspberrypi/linux/issues/1876 +--- + arch/arm/boot/dts/overlays/dwc2-overlay.dts | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/overlays/dwc2-overlay.dts b/arch/arm/boot/dts/overlays/dwc2-overlay.dts +index 527abc9f0ddf71f4dc7d58336d87684c931cc2f3..265a16bab008453edba198cf2366c423509d60d6 100644 +--- a/arch/arm/boot/dts/overlays/dwc2-overlay.dts ++++ b/arch/arm/boot/dts/overlays/dwc2-overlay.dts +@@ -15,7 +15,7 @@ + dr_mode = "otg"; + g-np-tx-fifo-size = <32>; + g-rx-fifo-size = <256>; +- g-tx-fifo-size = <256 128 128 64 64 64 32>; ++ g-tx-fifo-size = <512 512 512 512 512 768>; + status = "okay"; + }; + }; +@@ -24,6 +24,5 @@ + dr_mode = <&dwc2_usb>, "dr_mode"; + g-np-tx-fifo-size = <&dwc2_usb>,"g-np-tx-fifo-size:0"; + g-rx-fifo-size = <&dwc2_usb>,"g-rx-fifo-size:0"; +- g-tx-fifo-size = <&dwc2_usb>,"g-tx-fifo-size:0"; + }; + }; + +From cb03323c7dad8191cf043fe69917a61a55f78574 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 14 Mar 2017 09:10:05 +0000 +Subject: [PATCH 130/150] BCM270X_DT: Add lm75 to i2c-sensor overlay + +See: https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=177236 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/README | 8 +++++--- + arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts | 8 ++++++++ + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index c1883bba938290f03826026651c764cfd4ac278b..a8853b7820cd7a333cdaa2421f770a834dc724d5 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -388,9 +388,6 @@ Params: dr_mode Dual role mode: "host", "peripheral" or "otg" + g-np-tx-fifo-size Size of non-periodic tx fifo size in gadget + mode + +- g-tx-fifo-size Size of periodic tx fifo per endpoint +- (except ep0) in gadget mode +- + + [ The ds1307-rtc overlay has been deleted. See i2c-rtc. ] + +@@ -608,6 +605,11 @@ Params: bmp085 Select the Bosch sensortronic BMP085 + + bmp280 Select the Bosch sensortronic BMP280 + ++ lm75 Select the Maxim LM75 temperature sensor ++ ++ lm75addr Choose the address for the LM75 (0x48-0x4f - ++ default 0x4f) ++ + si7020 Select the Silicon Labs Si7013/20/21 humidity/ + temperature sensor + +diff --git a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +index 31bda8da4cb6a56bfe493a81b918900995fb0589..606b2d5012abf2e85712be631c42ea40a0b512c5 100644 +--- a/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts ++++ b/arch/arm/boot/dts/overlays/i2c-sensor-overlay.dts +@@ -25,6 +25,12 @@ + status = "disable"; + }; + ++ lm75: lm75@4f { ++ compatible = "lm75"; ++ reg = <0x4f>; ++ status = "disable"; ++ }; ++ + si7020: si7020@40 { + compatible = "si7020"; + reg = <0x40>; +@@ -36,6 +42,8 @@ + __overrides__ { + bmp085 = <&bmp085>,"status"; + bmp280 = <&bmp280>,"status"; ++ lm75 = <&lm75>,"status"; ++ lm75addr = <&lm75>,"reg:0"; + si7020 = <&si7020>,"status"; + }; + }; + +From c1f3635861a33abc98a784f184a6c6f9fb1e0764 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 28 Mar 2017 14:22:20 +0100 -Subject: [PATCH 197/216] BCM270X_DT: Allow multiple instances of w1-gpio +Subject: [PATCH 131/150] BCM270X_DT: Allow multiple instances of w1-gpio overlays Upcoming firmware will modify the address portion of node names when @@ -136952,10 +113602,10 @@ index 66a98f6c9601f51483f27803995bec772bb3350e..ef8bfbcabdb31231075d5c281df3b38b <&w1_pins>,"brcm,pins:4"; pullup = <&w1>,"rpi,parasitic-power:0"; -From c237e6567967053ece4d59947b9ce9b9c13dfdf4 Mon Sep 17 00:00:00 2001 +From c974f348bff39d3b78e36401d1447d16979898f6 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 28 Mar 2017 17:41:30 +0100 -Subject: [PATCH 198/216] leds-gpio: Remove stray assignment to brightness_set +Subject: [PATCH 132/150] leds-gpio: Remove stray assignment to brightness_set The brightness_set method is intended for use cases that must not block, and can only be used if the GPIO provider can never sleep. @@ -136969,7 +113619,7 @@ Signed-off-by: Phil Elwell 1 file changed, 1 deletion(-) diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c -index 6a27a693034825de2897bb7b338b60cc10c9e59f..a6b352cb003ff5e6c87cf6d37d6502b6b7c63e89 100644 +index 934cdb1d7bc7f12a4fb06a5c458ad76727c7b7c7..a4df27f6af35ba7f7b34c2a4b7b22ee7552264f0 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -136,7 +136,6 @@ static int create_gpio_led(const struct gpio_led *template, @@ -136981,10 +113631,45 @@ index 6a27a693034825de2897bb7b338b60cc10c9e59f..a6b352cb003ff5e6c87cf6d37d6502b6 if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) { state = gpiod_get_value_cansleep(led_dat->gpiod); -From 3b18074d165629b9a81ea982304dfb846ca6ad86 Mon Sep 17 00:00:00 2001 +From 078fbe8618880de1a6790b9aafae43c55b6d1979 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 29 Mar 2017 17:41:04 +0100 +Subject: [PATCH 133/150] config: Add back MMC_BCM2835_DMA + +--- + arch/arm/configs/bcm2709_defconfig | 1 + + arch/arm/configs/bcmrpi_defconfig | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 1940c88c303dd644163195e13e865877d3cfe830..bd3ba38e69cfc0bdc70961298afb63dcd38f133b 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -1048,6 +1048,7 @@ CONFIG_USB_GADGET=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 + CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +index 021c38a909e71baa135cbcd4f3fb80fad2151647..a8fc96ef674be476d10e59aef2367def40518f03 100644 +--- a/arch/arm/configs/bcmrpi_defconfig ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -1054,6 +1054,7 @@ CONFIG_USB_G_WEBCAM=m + CONFIG_MMC=y + CONFIG_MMC_BLOCK_MINORS=32 + CONFIG_MMC_BCM2835=y ++CONFIG_MMC_BCM2835_DMA=y + CONFIG_MMC_BCM2835_SDHOST=y + CONFIG_MMC_SDHCI=y + CONFIG_MMC_SDHCI_PLTFM=y + +From f4c24637c2e582891d11511e39c25f2f1e1b6066 Mon Sep 17 00:00:00 2001 From: Matt Flax Date: Mon, 27 Mar 2017 22:26:49 +1100 -Subject: [PATCH 199/216] AudioInjector Octo: sample rates, regulators, reset +Subject: [PATCH 134/150] AudioInjector Octo: sample rates, regulators, reset This patch adds new sample rates to the Audioinjector Octo sound card. The new supported rates are (in kHz) : @@ -137150,10 +113835,10 @@ index 9effea725798640887755dfa688da45338718afc..dcf403ab37639ba79e38278d7e4b1ade dai->cpu_dai_name = NULL; dai->cpu_of_node = i2s_node; -From 9555310a6c5da03dd619a8ba67f9cd8d7efc76ed Mon Sep 17 00:00:00 2001 +From 5bcde3681658b147da8a2afebe3fc8cc7bc57e1e Mon Sep 17 00:00:00 2001 From: Peter Malkin Date: Mon, 27 Mar 2017 16:38:21 -0700 -Subject: [PATCH 200/216] Driver support for Google voiceHAT soundcard. +Subject: [PATCH 135/150] Driver support for Google voiceHAT soundcard. --- arch/arm/boot/dts/overlays/Makefile | 1 + @@ -137255,10 +113940,10 @@ index 0000000000000000000000000000000000000000..9a9e9a0ca28cf774a868b2882ae57b00 + }; +}; diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 8ce1707b537e9e21589887b93c0dbf9302cb5974..a58ef95ea4ef28946d51f717d96f9be63115de3f 100644 +index bd3ba38e69cfc0bdc70961298afb63dcd38f133b..be903e66e95c97b16399ebfac8f6bedbeeb29663 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig -@@ -884,6 +884,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +@@ -877,6 +877,7 @@ 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 @@ -137267,10 +113952,10 @@ index 8ce1707b537e9e21589887b93c0dbf9302cb5974..a58ef95ea4ef28946d51f717d96f9be6 CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m CONFIG_SND_DIGIDAC1_SOUNDCARD=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index e65b2106d97ea9351c1d85166d2bff39d458ded3..cdf52529d8b5176303a60217eb28dc0b6f2f7184 100644 +index a8fc96ef674be476d10e59aef2367def40518f03..1a9b95f1b731c48130a0b468d95d533f458cb2d6 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -877,6 +877,7 @@ CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m +@@ -870,6 +870,7 @@ 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 @@ -137658,10 +114343,10 @@ index 0000000000000000000000000000000000000000..225854b8e5298b3c3018f59a49404354 +MODULE_DESCRIPTION("ASoC Driver for Google voiceHAT SoundCard"); +MODULE_LICENSE("GPL v2"); -From 2b25e13ca836c3c936d7b53dffad8d2c10004bf9 Mon Sep 17 00:00:00 2001 +From b226f121085149815b6e1dcd13b9aebfb5615ad3 Mon Sep 17 00:00:00 2001 From: Raashid Muhammed Date: Mon, 27 Mar 2017 12:35:00 +0530 -Subject: [PATCH 201/216] Add support for Allo Piano DAC 2.1 plus add-on board +Subject: [PATCH 136/150] Add support for Allo Piano DAC 2.1 plus add-on board for Raspberry Pi. The Piano DAC 2.1 has support for 4 channels with subwoofer. @@ -138289,10 +114974,10 @@ index 0000000000000000000000000000000000000000..f66f42abadbd5f9d3fe000676e8297ed +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Piano DAC Plus"); +MODULE_LICENSE("GPL v2"); -From 8986e172411d979e42cb67684eb97ea1c0ce749d Mon Sep 17 00:00:00 2001 +From 1775bcc2f147f18b22073a324c02cb2dffd89fe8 Mon Sep 17 00:00:00 2001 From: BabuSubashChandar Date: Tue, 28 Mar 2017 20:04:42 +0530 -Subject: [PATCH 202/216] Add support for Allo Boss DAC add-on board for +Subject: [PATCH 137/150] Add support for Allo Boss DAC add-on board for Raspberry Pi. (#1924) Signed-off-by: Baswaraj K @@ -138424,7 +115109,7 @@ index 0000000000000000000000000000000000000000..7df335a3d82f7043d31ba69331cdf318 + }; +}; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index 2b6fcd8abf79da77aa85fdc53512aafd09f836cb..b1b3cf5d3a09fe8bd38dfed880dd7e6ac0ccc3d7 100644 +index c901caf8988417053d19916172cf8eb8468a59fd..50f4737abdb4fd428b9cae26a1482f7be58e03cb 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -17,6 +17,7 @@ endif @@ -139022,10 +115707,10 @@ index 0000000000000000000000000000000000000000..c080e31065d99ab309ab3bdf41a44adf +MODULE_DESCRIPTION("ALSA ASoC Machine Driver for Allo Boss DAC"); +MODULE_LICENSE("GPL v2"); -From b5f47bd86b3cd13babf9e54c2e0a2d9fbeefab48 Mon Sep 17 00:00:00 2001 +From 7f74117a6a7676dd26754cbcafea47d7066e29ee Mon Sep 17 00:00:00 2001 From: BabuSubashChandar C Date: Thu, 30 Mar 2017 20:17:27 +0530 -Subject: [PATCH 203/216] Add support for new clock rate and mute gpios. +Subject: [PATCH 138/150] Add support for new clock rate and mute gpios. Signed-off-by: Baswaraj K Reviewed-by: Deepak @@ -139055,10 +115740,10 @@ index 7df335a3d82f7043d31ba69331cdf3185264d78c..ac1cfe093d9aa8a77ef25cc62a9d8100 }; }; diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index a58ef95ea4ef28946d51f717d96f9be63115de3f..4afe1a8ee36e62f33bfef7d76f2a460e7187eaff 100644 +index be903e66e95c97b16399ebfac8f6bedbeeb29663..515369e43b2c819a82670366582971ab26eaf532 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig -@@ -890,6 +890,7 @@ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m +@@ -883,6 +883,7 @@ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m CONFIG_SND_DIGIDAC1_SOUNDCARD=m CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m @@ -139067,7 +115752,7 @@ index a58ef95ea4ef28946d51f717d96f9be63115de3f..4afe1a8ee36e62f33bfef7d76f2a460e CONFIG_SND_BCM2708_SOC_FE_PI_AUDIO=m CONFIG_SND_PISOUND=m diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile -index b1b3cf5d3a09fe8bd38dfed880dd7e6ac0ccc3d7..eb521affd5b7d30290dd6120e32c3c2a0b0b60f0 100644 +index 50f4737abdb4fd428b9cae26a1482f7be58e03cb..35c943df626731560adbd49f489aaf3b4cfa11bf 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -17,7 +17,7 @@ endif @@ -139678,10 +116363,10 @@ index c080e31065d99ab309ab3bdf41a44adfdd8f8039..203ab76c7045b081578e23bda1099dd1 } -From 160c9589a3cf98b20393f07082aa7f2540c6b02c Mon Sep 17 00:00:00 2001 +From 95f6f3118dd6c08134335e35714d2ccbfa4388dc Mon Sep 17 00:00:00 2001 From: BabuSubashChandar Date: Sat, 1 Apr 2017 00:46:52 +0530 -Subject: [PATCH 204/216] Add clock changes and mute gpios (#1938) +Subject: [PATCH 139/150] Add clock changes and mute gpios (#1938) Also improve code style and adhere to ALSA coding conventions. @@ -139752,10 +116437,10 @@ index 6943b55ca5f96097668e2d10c05f56a26be62b0a..5c1c81c427a8b396ca9e9c903e97f271 }; }; diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig -index 4afe1a8ee36e62f33bfef7d76f2a460e7187eaff..d2ed09d05f9db97fd1f8e4e12595a24521c48749 100644 +index 515369e43b2c819a82670366582971ab26eaf532..2e4b164b118e053c6d1e7d7898b60f3dd50e91dc 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig -@@ -892,6 +892,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m +@@ -885,6 +885,7 @@ CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m CONFIG_SND_BCM2708_SOC_ALLO_BOSS_DAC=m CONFIG_SND_BCM2708_SOC_ALLO_PIANO_DAC=m @@ -139764,10 +116449,10 @@ index 4afe1a8ee36e62f33bfef7d76f2a460e7187eaff..d2ed09d05f9db97fd1f8e4e12595a245 CONFIG_SND_PISOUND=m CONFIG_SND_SOC_ADAU1701=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index cdf52529d8b5176303a60217eb28dc0b6f2f7184..83f81127ac464cfd527e52d7893ce6f0c73d231a 100644 +index 1a9b95f1b731c48130a0b468d95d533f458cb2d6..db6589288b6abd6b76b934de07e8976456e14e61 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig -@@ -883,7 +883,9 @@ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m +@@ -876,7 +876,9 @@ CONFIG_SND_AUDIOINJECTOR_OCTO_SOUNDCARD=m CONFIG_SND_DIGIDAC1_SOUNDCARD=m CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO=m CONFIG_SND_BCM2708_SOC_DIONAUDIO_LOCO_V2=m @@ -140374,152 +117059,32 @@ index f66f42abadbd5f9d3fe000676e8297ed91630e47..56e43f98846b41e487b3089813f7edc3 } -From ffc9f84b0055243cdb35b3a654b2e3c0ad05e192 Mon Sep 17 00:00:00 2001 -From: Yasunari Takiguchi -Date: Thu, 22 Dec 2016 15:34:12 +0900 -Subject: [PATCH 205/216] BCM2708: Add Raspberry Pi TV HAT Device Tree Support +From c33e97a120e0d1e543568ed6d303939a1130bd76 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Sun, 2 Apr 2017 15:33:25 +0100 +Subject: [PATCH 140/150] config: remove CONFIG_TOUCHSCREEN_EKTF2127 -This is an EXAMPLE CODE of Raspberry Pi TV HAT device tree overlay. -Although this is not a part of our release code, it has been used to verify -CXD2880 device driver with TV HAT. - -Add the following line to /boot/config.txt to enable TV HAT: - -dtoverlay=rpi-tv - -Reboot Raspberry Pi and check the existance of /proc/device-tree/soc/spi@7e204000/cxd2880@0. -If exists, the installation is successful. you should be able to find the following three files. -/dev/dvb/adapter0/frontend0 -/dev/dvb/adapter0/demux0 -/dev/dvb/adapter0/dvr0 - -Signed-off-by: Yasunari Takiguchi -Signed-off-by: Masayuki Yamamoto -Signed-off-by: Hideki Nozawa -Signed-off-by: Kota Yonezawa -Signed-off-by: Toshihiko Matsumoto -Signed-off-by: Satoshi Watanabe --- - arch/arm/boot/dts/overlays/Makefile | 1 + - arch/arm/boot/dts/overlays/README | 6 ++++++ - arch/arm/boot/dts/overlays/rpi-tv-overlay.dts | 31 +++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+) - create mode 100644 arch/arm/boot/dts/overlays/rpi-tv-overlay.dts + arch/arm/configs/bcm2709_defconfig | 1 - + 1 file changed, 1 deletion(-) -diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile -index b64dd7ac0630b2b525809a9f5221420f34a58ac9..e2f66a55dc5afe13d690c2c17827054ac94b7168 100644 ---- a/arch/arm/boot/dts/overlays/Makefile -+++ b/arch/arm/boot/dts/overlays/Makefile -@@ -81,6 +81,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ - rpi-ft5406.dtbo \ - rpi-proto.dtbo \ - rpi-sense.dtbo \ -+ rpi-tv.dtbo \ - rra-digidac1-wm8741-audio.dtbo \ - sc16is750-i2c.dtbo \ - sc16is752-spi1.dtbo \ -diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README -index 1377e5b8e8363c3e0ede318ce54bd784cb70d4c9..e2a803e5180cf78d67b6723cfd2f6d3b2b54e53b 100644 ---- a/arch/arm/boot/dts/overlays/README -+++ b/arch/arm/boot/dts/overlays/README -@@ -1142,6 +1142,12 @@ Load: dtoverlay=rpi-sense - Params: - - -+Name: rpi-tv -+Info: Raspberry Pi TV HAT -+Load: dtoverlay=rpi-tv -+Params: -+ -+ - Name: rra-digidac1-wm8741-audio - Info: Configures the Red Rocks Audio DigiDAC1 soundcard - Load: dtoverlay=rra-digidac1-wm8741-audio -diff --git a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts -new file mode 100644 -index 0000000000000000000000000000000000000000..a68f6f793d8efd8b2e2adf9f2fb6426f61ff464a ---- /dev/null -+++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts -@@ -0,0 +1,31 @@ -+// rpi-tv HAT -+ -+/dts-v1/; -+/plugin/; -+ -+/ { -+ compatible = "brcm,bcm2708", "brcm,bcm2709"; -+ -+ fragment@0 { -+ target = <&spi0>; -+ __overlay__ { -+ /* needed to avoid dtc warning */ -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ status = "okay"; -+ -+ spidev@0 { -+ status = "disabled"; -+ }; -+ -+ cxd2880@0 { -+ compatible = "sony,cxd2880"; -+ reg = <0>; /* CE0 */ -+ spi-max-frequency = <50000000>; -+ status = "okay"; -+ }; -+ }; -+ }; -+ -+}; +diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig +index 2e4b164b118e053c6d1e7d7898b60f3dd50e91dc..94227b4a4f8a9b3a4627dceaf7c654da4f2f87df 100644 +--- a/arch/arm/configs/bcm2709_defconfig ++++ b/arch/arm/configs/bcm2709_defconfig +@@ -565,7 +565,6 @@ CONFIG_JOYSTICK_RPISENSE=m + CONFIG_INPUT_TOUCHSCREEN=y + CONFIG_TOUCHSCREEN_ADS7846=m + CONFIG_TOUCHSCREEN_EGALAX=m +-CONFIG_TOUCHSCREEN_EKTF2127=m + CONFIG_TOUCHSCREEN_RPI_FT5406=m + CONFIG_TOUCHSCREEN_USB_COMPOSITE=m + CONFIG_TOUCHSCREEN_STMPE=m -From 9ff80c399fc8785bfcc8e3b5bde5f2ff59e52dde Mon Sep 17 00:00:00 2001 -From: James Hughes -Date: Wed, 19 Apr 2017 11:13:40 +0100 -Subject: [PATCH 206/216] smsc95xx: Use skb_cow_head to deal with cloned skbs - -The driver was failing to check that the SKB wasn't cloned -before adding checksum data. -Replace existing handling to extend/copy the header buffer -with skb_cow_head. - -Signed-off-by: James Hughes -Acked-by: Eric Dumazet -Acked-by: Woojung Huh -Signed-off-by: David S. Miller ---- - drivers/net/usb/smsc95xx.c | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index df60c989fc229bf0aab3c27e95ccd45323367840..f6661e388f6e801c1b88e48a3b71407bd70cf56e 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -2067,13 +2067,13 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, - /* We do not advertise SG, so skbs should be already linearized */ - BUG_ON(skb_shinfo(skb)->nr_frags); - -- if (skb_headroom(skb) < overhead) { -- struct sk_buff *skb2 = skb_copy_expand(skb, -- overhead, 0, flags); -+ /* Make writable and expand header space by overhead if required */ -+ if (skb_cow_head(skb, overhead)) { -+ /* Must deallocate here as returning NULL to indicate error -+ * means the skb won't be deallocated in the caller. -+ */ - dev_kfree_skb_any(skb); -- skb = skb2; -- if (!skb) -- return NULL; -+ return NULL; - } - - if (csum) { - -From eb8dc893aa25446d9b26ae86220774d9871f220b Mon Sep 17 00:00:00 2001 +From 1e9582d8eab3bfb89c6bb771c1293f984a6ac4ae Mon Sep 17 00:00:00 2001 From: Yasunari Takiguchi Date: Fri, 14 Apr 2017 10:43:57 +0100 -Subject: [PATCH 207/216] This is the driver for Sony CXD2880 DVB-T2/T tuner + +Subject: [PATCH 141/150] This is the driver for Sony CXD2880 DVB-T2/T tuner + demodulator. It includes the CXD2880 driver and the CXD2880 SPI adapter. The current CXD2880 driver version is 1.4.1 - 1.0.1 released on April 13, 2017. @@ -140617,7 +117182,7 @@ Signed-off-by: Satoshi Watanabe create mode 100644 drivers/media/spi/cxd2880-spi.c diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig -index c841fa1770bec376559d3292f262b41b3a78d5bb..7b6dee771df2680c0db1a500a45cce2711a88991 100644 +index e8c6554a47aa13761ca8016cb0cd7d066e38927a..3a3a7129a15001a2a3134c2aafc880540899cc9f 100644 --- a/drivers/media/dvb-frontends/Kconfig +++ b/drivers/media/dvb-frontends/Kconfig @@ -518,6 +518,8 @@ config DVB_GP8PSK_FE @@ -140630,13 +117195,13 @@ index c841fa1770bec376559d3292f262b41b3a78d5bb..7b6dee771df2680c0db1a500a45cce27 depends on DVB_CORE diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile -index 93921a4eaa275997a5ed4178de1acb1a54409430..5629631ffb2f044363fd1e1d820e4df75ec41c2b 100644 +index 3fccaf34ef520acf4207710dbf15fd7c08cc62fa..d298c79546999f80a788309824fd6545b2d25ff7 100644 --- a/drivers/media/dvb-frontends/Makefile +++ b/drivers/media/dvb-frontends/Makefile -@@ -126,3 +126,4 @@ obj-$(CONFIG_DVB_TC90522) += tc90522.o - obj-$(CONFIG_DVB_HORUS3A) += horus3a.o +@@ -126,3 +126,4 @@ obj-$(CONFIG_DVB_HORUS3A) += horus3a.o obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o obj-$(CONFIG_DVB_HELENE) += helene.o + obj-$(CONFIG_DVB_ZD1301_DEMOD) += zd1301_demod.o +obj-$(CONFIG_DVB_CXD2880) += cxd2880/ diff --git a/drivers/media/dvb-frontends/cxd2880/Kconfig b/drivers/media/dvb-frontends/cxd2880/Kconfig new file mode 100644 @@ -156651,175 +133216,109 @@ index 0000000000000000000000000000000000000000..82e122349055be817eb74ed5bbcd7560 +MODULE_AUTHOR("Sony Semiconductor Solutions Corporation"); +MODULE_LICENSE("GPL v2"); -From 621b29e1be14025002f555d487689c49ef91aa7a Mon Sep 17 00:00:00 2001 -From: James Hughes -Date: Mon, 24 Apr 2017 12:40:50 +0100 -Subject: [PATCH 208/216] brcmfmac: Ensure pointer correctly set if skb data - location changes +From 7fd92d0e9cd9b95549e61fca461e85a3147837d2 Mon Sep 17 00:00:00 2001 +From: Yasunari Takiguchi +Date: Thu, 22 Dec 2016 15:34:12 +0900 +Subject: [PATCH 142/150] BCM2708: Add Raspberry Pi TV HAT Device Tree Support -The incoming skb header may be resized if header space is -insufficient, which might change the data adddress in the skb. -Ensure that a cached pointer to that data is correctly set by -moving assignment to after any possible changes. +This is an EXAMPLE CODE of Raspberry Pi TV HAT device tree overlay. +Although this is not a part of our release code, it has been used to verify +CXD2880 device driver with TV HAT. -Signed-off-by: James Hughes +Add the following line to /boot/config.txt to enable TV HAT: -Acked-by: Arend van Spriel -Signed-off-by: Kalle Valo +dtoverlay=rpi-tv + +Reboot Raspberry Pi and check the existance of /proc/device-tree/soc/spi@7e204000/cxd2880@0. +If exists, the installation is successful. you should be able to find the following three files. +/dev/dvb/adapter0/frontend0 +/dev/dvb/adapter0/demux0 +/dev/dvb/adapter0/dvr0 + +Signed-off-by: Yasunari Takiguchi +Signed-off-by: Masayuki Yamamoto +Signed-off-by: Hideki Nozawa +Signed-off-by: Kota Yonezawa +Signed-off-by: Toshihiko Matsumoto +Signed-off-by: Satoshi Watanabe --- - drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 6 ++++++ + arch/arm/boot/dts/overlays/rpi-tv-overlay.dts | 31 +++++++++++++++++++++++++++ + 3 files changed, 38 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/rpi-tv-overlay.dts -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -index 9e6f60a0ec3eac7adac493b9fb337ffae62b6b9f..073cf8e51285cba541f26308970874805dfafa55 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -198,7 +198,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, - int ret; - struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_pub *drvr = ifp->drvr; -- struct ethhdr *eh = (struct ethhdr *)(skb->data); -+ struct ethhdr *eh; +diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile +index b64dd7ac0630b2b525809a9f5221420f34a58ac9..e2f66a55dc5afe13d690c2c17827054ac94b7168 100644 +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -81,6 +81,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + rpi-ft5406.dtbo \ + rpi-proto.dtbo \ + rpi-sense.dtbo \ ++ rpi-tv.dtbo \ + rra-digidac1-wm8741-audio.dtbo \ + sc16is750-i2c.dtbo \ + sc16is752-spi1.dtbo \ +diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README +index 1377e5b8e8363c3e0ede318ce54bd784cb70d4c9..e2a803e5180cf78d67b6723cfd2f6d3b2b54e53b 100644 +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1142,6 +1142,12 @@ Load: dtoverlay=rpi-sense + Params: - brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); -@@ -236,6 +236,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, - goto done; - } - -+ eh = (struct ethhdr *)(skb->data); ++Name: rpi-tv ++Info: Raspberry Pi TV HAT ++Load: dtoverlay=rpi-tv ++Params: ++ ++ + Name: rra-digidac1-wm8741-audio + Info: Configures the Red Rocks Audio DigiDAC1 soundcard + Load: dtoverlay=rra-digidac1-wm8741-audio +diff --git a/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..a68f6f793d8efd8b2e2adf9f2fb6426f61ff464a +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/rpi-tv-overlay.dts +@@ -0,0 +1,31 @@ ++// rpi-tv HAT ++ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2708", "brcm,bcm2709"; ++ ++ fragment@0 { ++ target = <&spi0>; ++ __overlay__ { ++ /* needed to avoid dtc warning */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ ++ spidev@0 { ++ status = "disabled"; ++ }; ++ ++ cxd2880@0 { ++ compatible = "sony,cxd2880"; ++ reg = <0>; /* CE0 */ ++ spi-max-frequency = <50000000>; ++ status = "okay"; ++ }; ++ }; ++ }; + - if (eh->h_proto == htons(ETH_P_PAE)) - atomic_inc(&ifp->pend_8021x_cnt); - - -From ebc0c25d34fb375e6da0270ae9c80855c3bcc1ba Mon Sep 17 00:00:00 2001 -From: James Hughes -Date: Tue, 25 Apr 2017 10:15:06 +0100 -Subject: [PATCH 209/216] brcmfmac: Make skb header writable before use - -The driver was making changes to the skb_header without -ensuring it was writable (i.e. uncloned). -This patch also removes some boiler plate header size -checking/adjustment code as that is also handled by the -skb_cow_header function used to make header writable. - -Signed-off-by: James Hughes -Acked-by: Arend van Spriel -Signed-off-by: Kalle Valo ---- - .../net/wireless/broadcom/brcm80211/brcmfmac/core.c | 19 +++++-------------- - 1 file changed, 5 insertions(+), 14 deletions(-) - -diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -index 073cf8e51285cba541f26308970874805dfafa55..da8aad4f99126b5ac0c1da04e57c0d16b5954a8f 100644 ---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -211,22 +211,13 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, - goto done; - } - -- /* Make sure there's enough room for any header */ -- if (skb_headroom(skb) < drvr->hdrlen) { -- struct sk_buff *skb2; -- -- brcmf_dbg(INFO, "%s: insufficient headroom\n", -+ /* Make sure there's enough writable headroom*/ -+ ret = skb_cow_head(skb, drvr->hdrlen); -+ if (ret < 0) { -+ brcmf_err("%s: skb_cow_head failed\n", - brcmf_ifname(ifp)); -- drvr->bus_if->tx_realloc++; -- skb2 = skb_realloc_headroom(skb, drvr->hdrlen); - dev_kfree_skb(skb); -- skb = skb2; -- if (skb == NULL) { -- brcmf_err("%s: skb_realloc_headroom failed\n", -- brcmf_ifname(ifp)); -- ret = -ENOMEM; -- goto done; -- } -+ goto done; - } - - /* validate length for ether packet */ - -From 6c3fc19a12b8565776fa489ae3d3d2cd4d842672 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Wed, 26 Apr 2017 17:28:47 +0100 -Subject: [PATCH 210/216] clk: bcm2835: Limit PCM clock to OSC and PLLD_PER - -It is unwise to use sources other than the oscillator and PLLD_PER for -the PCM peripheral (and perhaps others - TBD) because their rate can -change and they may even be switched off, so explicitly restrict the -choice using dummy entries in the list of potential parents (item index -is significant). - -See: https://github.com/raspberrypi/linux/issues/1949 - -Signed-off-by: Phil Elwell ---- - drivers/clk/bcm/clk-bcm2835.c | 11 +++++++++++ - 1 file changed, 11 insertions(+) - -diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c -index fe3298b54cdfb96bd90fb4f39e13921d2e1d4356..c24b4defb2b046e4ecdc109befc2b22497060647 100644 ---- a/drivers/clk/bcm/clk-bcm2835.c -+++ b/drivers/clk/bcm/clk-bcm2835.c -@@ -1562,6 +1562,16 @@ static const char *const bcm2835_clock_per_parents[] = { - "pllh_aux", - }; - -+static const char *const bcm2835_pcm_per_parents[] = { -+ "-", -+ "xosc", -+ "-", -+ "-", -+ "-", -+ "-", -+ "plld_per", +}; -+ - #define REGISTER_PER_CLK(...) REGISTER_CLK( \ - .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \ - .parents = bcm2835_clock_per_parents, \ -@@ -2051,6 +2061,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { - .int_bits = 12, - .frac_bits = 12, - .is_mash_clock = true, -+ .parents = bcm2835_pcm_per_parents, - .tcnt_mux = 23), - [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK( - .name = "pwm", -From bf649450ab2094c3596146f7d6b6540f9dfc9da9 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 26 Apr 2017 16:51:48 +0100 -Subject: [PATCH 211/216] dwc_otg: Add the dependency on FIQ - -Signed-off-by: popcornmix ---- - drivers/usb/host/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index 99bc52546b8c912de72b4381ba8cf8e8ad61d7ee..e171094de214baba151ba612f8e80de618a2e06b 100644 ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -765,7 +765,7 @@ config USB_HWA_HCD - - config USB_DWCOTG - tristate "Synopsis DWC host support" -- depends on USB -+ depends on USB && FIQ - help - The Synopsis DWC controller is a dual-role - host/peripheral/OTG ("On The Go") USB controllers. - -From 25496d0594f0bad1ca11ea75889636c6feb525ef Mon Sep 17 00:00:00 2001 +From 54e1e47427d952f05c9671da9ec11aa83776dce6 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 27 Apr 2017 16:24:34 +0100 -Subject: [PATCH 212/216] dwc_otg: make nak_holdoff work as intended with empty +Subject: [PATCH 143/150] dwc_otg: make nak_holdoff work as intended with empty queues If URBs reading from non-periodic split endpoints were dequeued and @@ -156903,10 +133402,10 @@ index c2dff94e8e6edd22e4427aaa1eac7aad972cb6bd..85a6d431ca54b47dc10573aa72d1ad69 } else { uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); -From 4b2d183f339551212df70318174903b6bcbb1848 Mon Sep 17 00:00:00 2001 +From 9e758da8dc0f4b319c7907533872ff8c525064b6 Mon Sep 17 00:00:00 2001 From: P33M Date: Tue, 2 May 2017 16:31:15 +0100 -Subject: [PATCH 213/216] dwc_otg: fix split transaction data toggle handling +Subject: [PATCH 144/150] dwc_otg: fix split transaction data toggle handling around dequeues See https://github.com/raspberrypi/linux/issues/1709 @@ -156994,10 +133493,10 @@ index 608e036be2c9484465ab836de70129335d3d2d96..718a1accc0c219a1764ce53d291de6a2 } qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); -From f1860f849c3b109ede221aae0e173f840494b196 Mon Sep 17 00:00:00 2001 +From 41da1375f8be3a5feac94d6b37558258dd6b1ed6 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 May 2017 16:36:05 +0100 -Subject: [PATCH 214/216] vcsm: Treat EBUSY as success rather than SIGBUS +Subject: [PATCH 145/150] vcsm: Treat EBUSY as success rather than SIGBUS Currently if two cores access the same page concurrently one will return VM_FAULT_NOPAGE and the other VM_FAULT_SIGBUS crashing the user code. @@ -157010,10 +133509,10 @@ Signed-off-by: popcornmix 1 file changed, 9 insertions(+) diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c -index 8b6f2476769e956fb30d4c8a24789565e78444c1..f6292d82baa23ace41b20aa90dc407d1f8a23563 100644 +index fd71d9fbb400d71bb8cfb8672080e7c3053e3ae9..fd2ca788dcd56b1702454d71b7bedd4203179500 100644 --- a/drivers/char/broadcom/vc_sm/vmcs_sm.c +++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c -@@ -1181,11 +1181,20 @@ static int vcsm_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +@@ -1181,11 +1181,20 @@ static int vcsm_vma_fault(struct vm_fault *vmf) switch (ret) { case 0: case -ERESTARTSYS: @@ -157035,10 +133534,126 @@ index 8b6f2476769e956fb30d4c8a24789565e78444c1..f6292d82baa23ace41b20aa90dc407d1 } } -From 896a71b3f5ff08db0d0762302146668b5bde3214 Mon Sep 17 00:00:00 2001 +From 260c755a02f02f1294d0e32d0f0812a480c94dee Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 3 May 2017 10:34:36 +0100 +Subject: [PATCH 146/150] staging: vc04_services: Fix bulk cache maintenance + +vchiq_arm supports transfers less than one page and at arbitrary +alignment, using the dma-mapping API to perform its cache maintenance +(even though the VPU drives the DMA hardware). Read (DMA_FROM_DEVICE) +operations use cache invalidation for speed, falling back to +clean+invalidate on partial cache lines, with writes (DMA_TO_DEVICE) +using flushes. + +If a read transfer has ends which aren't page-aligned, performing cache +maintenance as if they were whole pages can lead to memory corruption +since the partial cache lines at the ends (and any cache lines before or +after the transfer area) will be invalidated. This bug was masked until +the disabling of the cache flush in flush_dcache_page(). + +Honouring the requested transfer start- and end-points prevents the +corruption. + +See: https://github.com/raspberrypi/linux/issues/1977 + +Signed-off-by: Phil Elwell +--- + .../interface/vchiq_arm/vchiq_2835_arm.c | 31 +++++++++++++--------- + 1 file changed, 19 insertions(+), 12 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 3aeffcb9c87e91d0be902bf851d38bb8b2550ebb..18f2f529687b60750a6a8e0f422d60af21be4a8f 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -501,8 +501,15 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + */ + sg_init_table(scatterlist, num_pages); + /* Now set the pages for each scatterlist */ +- for (i = 0; i < num_pages; i++) +- sg_set_page(scatterlist + i, pages[i], PAGE_SIZE, 0); ++ for (i = 0; i < num_pages; i++) { ++ unsigned int len = PAGE_SIZE - offset; ++ ++ if (len > count) ++ len = count; ++ sg_set_page(scatterlist + i, pages[i], len, offset); ++ offset = 0; ++ count -= len; ++ } + + dma_buffers = dma_map_sg(g_dev, + scatterlist, +@@ -523,20 +530,20 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + u32 addr = sg_dma_address(sg); + + /* Note: addrs is the address + page_count - 1 +- * The firmware expects the block to be page ++ * The firmware expects blocks after the first to be page- + * aligned and a multiple of the page size + */ + WARN_ON(len == 0); +- WARN_ON(len & ~PAGE_MASK); +- WARN_ON(addr & ~PAGE_MASK); ++ WARN_ON(k && (k != (dma_buffers - 1)) && (len & ~PAGE_MASK)); ++ WARN_ON(k && (addr & ~PAGE_MASK)); + if (k > 0 && +- ((addrs[k - 1] & PAGE_MASK) | +- ((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT) +- == addr) { +- addrs[k - 1] += (len >> PAGE_SHIFT); +- } else { +- addrs[k++] = addr | ((len >> PAGE_SHIFT) - 1); +- } ++ ((addrs[k - 1] & PAGE_MASK) + ++ (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT)) ++ == (addr & PAGE_MASK)) ++ addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT); ++ else ++ addrs[k++] = (addr & PAGE_MASK) | ++ (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1); + } + + /* Partial cache lines (fragments) require special measures */ + +From df03005ed1fb257c4f8a0e073d47027267bdca97 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 4 May 2017 09:55:34 +0100 +Subject: [PATCH 147/150] SQUASH: staging: vc04_services: Fix warnings + +create_pagelist uses a number of WARNs to sanity-check check the input +user pages, verifying that only the first and last entries in the +array are not integral pages. These WARNs use the output array index +when it should be input array index. Although the difference is only +significant in one instance, change all the indices for consistency. + +See: https://github.com/raspberrypi/linux/pull/1987 + +Signed-off-by: Phil Elwell +--- + drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +index 18f2f529687b60750a6a8e0f422d60af21be4a8f..02e97367cb88129793bab6b02f474a6abaeac722 100644 +--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -534,8 +534,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type, + * aligned and a multiple of the page size + */ + WARN_ON(len == 0); +- WARN_ON(k && (k != (dma_buffers - 1)) && (len & ~PAGE_MASK)); +- WARN_ON(k && (addr & ~PAGE_MASK)); ++ WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK)); ++ WARN_ON(i && (addr & ~PAGE_MASK)); + if (k > 0 && + ((addrs[k - 1] & PAGE_MASK) + + (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT)) + +From b66403cf963b8bb8dbbbc1445e475a6fbbdb2d3f Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 4 May 2017 12:58:11 +0100 -Subject: [PATCH 215/216] fiq_fsm: Use correct states when starting isoc OUT +Subject: [PATCH 148/150] fiq_fsm: Use correct states when starting isoc OUT transfers In fiq_fsm_start_next_periodic() if an isochronous OUT transfer @@ -157075,10 +133690,10 @@ index 9304279592cb5b388086ef91cb52f1e9f94868ce..208252645c09d1d17bf07673989f91b7 break; } -From ec32f020001ded7ab43025023209c7115722fe0b Mon Sep 17 00:00:00 2001 +From 5255c20a5cd584dbed1c4beb7648435f4d54547e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 4 May 2017 17:38:22 +0100 -Subject: [PATCH 216/216] bcm2708_fb: Avoid firmware mbox call in vc_mem_copy +Subject: [PATCH 149/150] bcm2708_fb: Avoid firmware mbox call in vc_mem_copy If firmware has locked up it is useful to get vcdbg log out without a firmware mbox response. Issue the mbox call at probe time instead. @@ -157141,3 +133756,27 @@ index 53c5a0bdadb4be9251affdabed66305842a08e72..612293cf9f1bd93ad2f2aefdd7ca0f5e ret = bcm2708_fb_register(fb); if (ret == 0) { platform_set_drvdata(dev, fb); + +From a4b4cfb22b78871aeb2450b043082534ee4a1d60 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Fri, 5 May 2017 13:23:56 +0100 +Subject: [PATCH 150/150] Revert "serial: 8250: Don't crash when nr_uarts is 0" + +This reverts commit 88e2058979b7b95417a05f2a3fcd637b3f1e09f8. +--- + drivers/tty/serial/8250/8250_core.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c +index 0a172c2e6fa288de1e080463e897ea85aa98399f..76e03a7de9cc3d790a230948f599ef2db4b93249 100644 +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -509,8 +509,6 @@ static void __init serial8250_isa_init_ports(void) + + if (nr_uarts > UART_NR) + nr_uarts = UART_NR; +- if (!nr_uarts) +- return; + + for (i = 0; i < nr_uarts; i++) { + struct uart_8250_port *up = &serial8250_ports[i];